也许我错了,但是...我想模拟字符间距.我将单词(文本)分成单个字符列表,测量它们的宽度,然后在位图上一个接一个地绘制它们.我想,渲染文本的整体宽度将与整个未分割字符串的宽度相同,但有一些错误.在循环中渲染字符显示更广泛的结果.有没有办法获得共同(预期)的结果?
这是一段代码:
private struct CharWidths
{
public char Char;
public float Width;
}
private List<CharWidths> CharacterWidths = new List<CharWidths>();
Run Code Online (Sandbox Code Playgroud)
...
private void GetCharacterWidths(string Text, Bitmap BMP)
{
int i;
int l = Text.Length;
CharacterWidths.Clear();
Graphics g = Graphics.FromImage(BMP);
CharWidths cw = new CharWidths();
for (i = 0; i < l; i++)
{
Size textSize = TextRenderer.MeasureText(Text[i].ToString(), Font);
cw.Char = Text[i];
cw.Width = textSize.Width;
CharacterWidths.Add(cw);
}
}
Run Code Online (Sandbox Code Playgroud)
...
public void RenderToBitmap(Bitmap BMP)
{
//MessageBox.Show("color");
Graphics g = Graphics.FromImage(BMP);
GetCharacterWidths("Lyborko", BMP);
int …Run Code Online (Sandbox Code Playgroud) 我想做一件简单的事情:在TScrollBox后代上添加一个Canvas属性.我读过这篇文章
但我的ScrollBox后代根本不在画布上绘制.愿有人告诉我,有什么不对吗?
TfrmScrollContainer = class (TScrollBox)
private
FCanvas: TCanvas;
FControlState:TControlState;
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
protected
procedure Paint;
procedure PaintWindow(DC: HDC); override;
property Canvas: TCanvas read FCanvas;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
Run Code Online (Sandbox Code Playgroud)
...这是精确的副本,TWincontrol如何转向TCustomControl(但它在某处失败)
constructor TfrmScrollContainer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCanvas := TControlCanvas.Create;
TControlCanvas(FCanvas).Control := Self;
end;
destructor TfrmScrollContainer.Destroy;
begin
FCanvas.Free;
inherited Destroy;
end;
procedure TfrmScrollContainer.WMPaint(var Message: TWMPaint);
begin
Include(FControlState, csCustomPaint);
inherited;
Exclude(FControlState, csCustomPaint);
end;
procedure TfrmScrollContainer.PaintWindow(DC: HDC);
begin
FCanvas.Lock;
try
FCanvas.Handle := DC;
try …Run Code Online (Sandbox Code Playgroud) 最近我发现了一段代码,它从一个字符串创建一个TButton实例:'TButton'被用作参数.
我试图将任何对象的已发布属性保存到XML文件(工作正常),最近我想从XML文件中重新创建这些对象.在这个文件中编写了应该创建哪个类(例如TButton),然后是一个属性列表,这些属性应该加载到这个运行时创建的对象中.
上面的示例显示了如何执行此操作的方法,但它不适用于我自己的类.见下面的代码:
TTripple=class (TPersistent)
FFont:TFont;
public
constructor Create;
Destructor Destroy;override;
published
property Font:TFont read FFont write FFont;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
constructor TTripple.Create;
begin
inherited;
FFont:=TFont.Create;
end;
destructor TTripple.Destroy;
begin
FFont.Free;
inherited;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterClasses([TButton, TForm, TTripple]);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
CRef : TPersistentClass;
APer : TPersistent;
begin
// CRef := GetClass('TButton');
CRef := GetClass('TTripple');
if CRef<>nil then
begin
APer := TPersistent(TPersistentClass(CRef).Create);
ShowMessage(APer.ClassName); // shows TTripple, what is correct
if …Run Code Online (Sandbox Code Playgroud) 这一行代码:
ShowMessage(GetEnumName(TypeInfo(TAlign), 1));
Run Code Online (Sandbox Code Playgroud)
返回"alTop".
当我想使用字符串变量:'TAlign'而不是TAlign时,如何将枚举类型的所有值都放入stringlist?就像是:
ShowMessage(GetEnumName(TypeInfo('TAlign'), 1));
Run Code Online (Sandbox Code Playgroud)
感谢名单
令我惊讶的是,我发现在TCanvas上重复渲染文本在某种程度上是"附加的".我意识到设置Canvas.Brush.Style:=bsClear是问题的原因,但我确实需要透明地重复呈现文本(即在OnPaint事件中).执行此操作后,文本看起来不太好.
我怎么能避免这种情况?
这是一些示例代码; 如果你在被调用的TButton上点击几下,就可以看到效果btn1.
procedure TForm1.btn1Click(Sender: TObject);
begin
Form1.Canvas.Brush.Style:=bsClear; //if you omit this, everything is OK.
Form1.Canvas.Font.Color:=clRed;
Form1.Canvas.Font.Name:='Times new Roman';
Form1.Canvas.Font.Style:=[fsBold];
Form1.Canvas.Font.Size:=12;
Form1.Canvas.TextOut(50,50,'www.stackoverflow.com');
end;
Run Code Online (Sandbox Code Playgroud) 在这里,我提供简单的代码.
function GetStringList:TStringList;
var i:integer;
begin
Result:=TStringList.Create;
Result.Add('Adam');
Result.Add('Eva');
Result.Add('Kain');
Result.Add('Abel');
end;
procedure ProvideStringList(SL:TStringList);
var i:integer;
Names:TStringList;
begin
Names:=TStringList.Create;
Names.Add('Adam');
Names.Add('Eva');
Names.Add('Kain');
Names.Add('Abel');
SL.Assign(Names);
Names.Free;
end;
procedure TForm1.btn1Click(Sender: TObject);
var SL:TStringList;
i:integer;
begin
SL:=TStringList.Create;
SL.Assign(GetStringList);
for i:=0 to 3 do ShowMessage(SL[i]);
SL.Free;
end;
procedure TForm1.btn2Click(Sender: TObject);
var SL:TStringList;
i:integer;
begin
SL:=TStringList.Create;
ProvideStringList(SL);
for i:=0 to 3 do ShowMessage(SL[i]);
SL.Free;
end;
Run Code Online (Sandbox Code Playgroud)
现在的问题是:函数GetStringList中的结果对象会发生什么:Tstringlist,它被创建,但从未被释放?(我调用2次Create并且只有1次Free)是按照函数提供对象的内存安全吗?还是我应该使用过程来执行此任务,其中只是处理对象创建和销毁(过程ProvideStringlist)?我叫2次创建和2次免费.还是有其他解决方案吗?
Thanx提前
Lyborko
我开发了一个使用第三方组件的应用程序(在D7,WinXP上开发).当我在XP上部署这个应用程序时,一切正常.当我在Vista上运行它时,应用程序停止正常工作:
当我打开/关闭可见性时,工具栏上的工具按钮的大小不一致,这就是为什么(第三方)皮肤没有正确嵌套然后看起来很难看.它很烦人,这很烦人,但下一点并不致命.
第三方文本处理组件停止写入.我写了一些例程,允许在某些情况下写这个组件.发现,我无法写任何东西(可能这些例程在写作时返回false,但我没有看到任何理由,为什么在XP上应该可以正常工作,但在Vista上没有),这是一个很大的冲击.
该应用程序运行(最后),但不是在路上,就像它应该!!!!
我想调试它,但是怎么样?
注意:当我在Win98上运行相同的应用程序时,我收到有关无效浮点运算的错误消息...
有人解决了这个问题吗?
谢谢
我正在尝试创建复合组件TTreePage(后代形式TCustomControl).它应该包含3个子组件:Treeview(TTreeview)align:= alLeft,Splitter(TSplitter)align:= alLeft和Container(TPanel)align:= alClient.
这是contstructor:
constructor TTreePage.Create(AOwner: TComponent);
begin
inherited;
FTreeview := TTreeView.Create(self);
FTreeview.SetSubComponent(True);
InsertControl(FTreeview);
FSplitter := TSplitter.Create(self);
FSplitter.SetSubComponent(True);
FSplitter.Width := 3;
FSplitter.Color := clBlack;
InsertControl(FSplitter);
FContainer:= TPanel.Create(Self);
FContainer.SetSubComponent(True);
FContainer.BevelInner := bvNone;
FContainer.BevelOuter := bvNone;
FContainer.Color := clYellow;
InsertControl(FContainer);
RefreshLayout; // this performs alignment of subcomponents
end;
Run Code Online (Sandbox Code Playgroud)
这里是创建参数程序:
procedure TTreePage.CreateParams(var Params:TCreateParams);
begin
inherited;
Params.Style := Params.Style + WS_EX_CONTROLPARENT;
ControlStyle := ControlStyle + [csAcceptsControls, csCaptureMouse, csOpaque];
end;
Run Code Online (Sandbox Code Playgroud)
整个组件表现为单个块.我无法通过鼠标选择任何子组件(TTreeview,TSplitter或TPanel).是的,我可以在Object Inspector中编辑它们的属性,但是我无法编辑例如TTreeview的宽度或拖动TSplitter.对我来说最重要的是在设计时在TTreeview中添加节点,但我不能为它唤起树节点编辑器.
我该怎么办?
感谢名单
想象一下,您想要分配自己的事件过程:
procedure TSuperObject.DoSomething(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
ShowMessage('Yes, I am doing');
end;
Run Code Online (Sandbox Code Playgroud)
到表单上的任何TWinControl.通常,如果表单上有Panel1(TPanel),您可以轻松完成:
Panel1.OnMouseDown:=SuperObject1.DoSomething;
Run Code Online (Sandbox Code Playgroud)
但如果你想普遍这样做,怎么能实现呢?您无法访问TWincontrol的受保护成员,因此直观答案:
AnyWinControl.OnMouseDown:=SuperObject1.DoSomething;
Run Code Online (Sandbox Code Playgroud)
根本行不通.
可以通过RTTI完成吗?怎么样?
感谢名单
我的第一个对象是TGoodFairy(TObject),它有自己的孩子FChildren(TList).有Assign程序,制作任何TGoodFairy及其子女的副本.
第二个对象是TBadFairyTGoodFairy的后代.
我正在努力如何使用TBadFairy的Assign方法来创建TBadFairy孩子.我想将ClassType与Create结合使用,以便为TBadFairy创建合适的子项(现在只创建TGoodFairy子项)
TGoodFairy = class (TObject)
private
FChildren:TList;
FName:string;
public
constructor Create;
destructor Destroy; override;
procedure Assign(Source:TGoodFairy);
published
property Name:string read FName write FName;
end;
TBadFairy = class (TGoodFairy)
procedure Assign(Source:TBadFairy);
end;
------------------------
constructor TGoodFairy.Create;
begin
inherited;
FChildren:=TList.Create;
end;
destructor TGoodFairy.Destroy;
var i:integer;
begin
for i:=0 to FChildren.Count-1 do TGoodFairy(FChildren[i]).Free;
FChildren.Clear;
FChildren.Free;
inherited;
end;
procedure TGoodFairy.Assign(Source:TGoodFairy);
var i:integer;
f:TGoodFairy;
C:TClass;
begin
FName:=Source.Name;
for i:=0 to Source.FChildren.Count-1 do
begin
//C := Source.ClassType; …Run Code Online (Sandbox Code Playgroud)