我的应用程序的一部分是绘制图形表单的草稿,主要是用户输入表单,有许多编辑框.我绘制位图并保存为PNG,报告过程的所有部分,因此没有任何内容被绘制到应用程序表单.我绘制所有控件,编辑框,单选按钮,复选框......
绘图的最长部分当然是绘制编辑框,因为它们数量巨大.我有一个典型的过程,在大约70K表格上绘制1M编辑框.
我画了一个非常简单的编辑框:
我附加了一个简单的Edit控件的屏幕截图,其中包含Zoomed,因此可以看到额外的左侧和顶部线条.
这是DrawEdit的代码,它绘制了1M Edit框,需要20秒.反正是为了加快这个过程吗?
procedure DrawEdit(myCanvas:TCanvas; vLeft, vTop, vWidth, vHeight: integer; const vText: string; vCenterText:boolean=false);
begin
// basic rectangle
pPoint.x := vLeft; pPoint.Y := vTop;
myCanvas.Pen.Width := 1;
myCanvas.PenPos := pPoint;
myCanvas.Pen.Color := $0099A8AC;
myCanvas.LineTo(vLeft + vWidth, vTop);
myCanvas.LineTo(vLeft + vWidth, vTop + 1);
myCanvas.Pen.Color := $00E2EFF1;
myCanvas.LineTo(vLeft + vWidth, vTop + vHeight - 1);
myCanvas.LineTo(vLeft, vTop + vHeight - 1);
myCanvas.Pen.Color := $0099A8AC;
myCanvas.LineTo(vLeft, vTop);
// again top border
pPoint.x := vLeft …
Run Code Online (Sandbox Code Playgroud) 我已经建立了非常好的系统来将列添加到VirtualStringTree中,因为旧系统太笨重了.
旧系统:
procedure TForm1.Button1Click(Sender: TObject);
begin
VST.Header.Columns.Clear;
VST.Header.Columns.Add.Text:='#';
VST.Header.Columns.Add.Text:='First name';
VST.Header.Columns.Add.Text:='Last name';
VST.Header.Columns.Add.Text:='Address';
VST.Header.Columns[0].Width:=50;
VST.Header.Columns[1].Width:=200;
VST.Header.Columns[2].Width:=200;
VST.Header.Columns[3].Width:=500;
end;
Run Code Online (Sandbox Code Playgroud)
新系统有3个额外的程序,但执行它们的代码要少得多:
SetNames - 在字符串的全局数组中设置列名
SetWidths - 在全局整数数组中设置列widhs
SetColumns - 基于全局数组值创建列
var
gWidths:array of integer;
gNames:array of string;
procedure SetNames(vCount:integer; vA:string='';vB:string='';vC:string='';vD:string='';vE:string='';vF:string='';vG:string='';vH:string='';vI:string='';vJ:string='');
begin
SetLength(gNames,0);
SetLength(gNames,vCount);
If vCount>0 then gNames[0]:=vA;
If vCount>1 then gNames[1]:=vB;
If vCount>2 then gNames[2]:=vC;
If vCount>3 then gNames[3]:=vD;
If vCount>4 then gNames[4]:=vE;
If vCount>5 then gNames[5]:=vF;
If vCount>6 then gNames[6]:=vG;
If vCount>7 then gNames[7]:=vH;
If vCount>8 then gNames[8]:=vI;
If vCount>9 …
Run Code Online (Sandbox Code Playgroud) 我有一个同步Scrollboxes的简单示例,我控制哪一方通过单选按钮同步 - 同步左侧或右侧.当我编译时,我收到编译器消息:
[dcc32警告] Unit1.pas(51):W1036变量'ScrlBox1'可能尚未初始化
[dcc32警告] Unit1.pas(51):W1036变量'ScrlBox2'可能尚未初始化
这是一个简单的例子:
procedure TForm1.Button1Click(Sender: TObject);
var
ScrlBox1, ScrlBox2: TScrollBox;
begin
if radiobtn_SyncLeftSides.Checked then // Snyc Left side
begin
ScrlBox1 := ScrollBoxLeft1;
ScrlBox2 := ScrollBoxLeft2;
end
else if radiobtn_SyncrightSides.Checked then // Snyc Right side
begin
ScrlBox2 := ScrollBoxRight1;
ScrlBox1 := ScrollBoxRight2;
end;
// Sync scroll boxes
ScrlBox2.VertScrollBar.Position := ScrlBox1.VertScrollBar.Position;
ScrlBox2.HorzScrollBar.Position := ScrlBox1.HorzScrollBar.Position;
end;
Run Code Online (Sandbox Code Playgroud)
这是什么问题?
如果我在开头添加这个消息就消失了:
ScrlBox1:= TScrollBox.Create(nil);
ScrlBox2:= TScrollBox.Create(nil);
Run Code Online (Sandbox Code Playgroud)
但我认为创建滚动框变量是不必要的,对吧?这些只是表单上控件的变量指针.
我试图改变我如何使用布尔参数来获得有意义的名称,所以我不需要检查每个方法的真/假意味着什么.在这个例子中我使用True/False:
procedure ProcessData(Param1, Param2: string; CreateOnEmpty: boolean = False);
procedure TForm1.Button1Click(Sender: TObject);
begin
ProcessData(P1, P2, True); // when CreateOnEmpty should be True
ProcessData(P1, P2); // when CreateOnEmpty should be False
ProcessData(P1, P2, False); // when CreateOnEmpty should be False
end;
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,我需要查找ProcessData方法来查看True/False参数的含义.
所以,我从这个例子开始,为参数分配有意义的名字:
procedure TForm1.Button2Click(Sender: TObject);
var
vCreateWhenEmpty: boolean;
vDontCreateWhenEmpty: boolean;
begin
// Init control params
vCreateWhenEmpty := True;
vDontCreateWhenEmpty := False;
ProcessData(P1, P2, vCreateWhenEmpty); // When CreateOnEmpty should be True
ProcessData(P1, P2, vDontCreateWhenEmpty); // When CreateOnEmpty should be False
end; …
Run Code Online (Sandbox Code Playgroud) 注意:其他问题的标题不同,这使其无法识别为匹配的标题.
System.Classes
TCollection = class(TPersistent)
protected
procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); virtual;
end;
Run Code Online (Sandbox Code Playgroud)
MyUnit
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
Vcl.ExtCtrls, DB, System.Generics.Collections;
TTextDisplayLineInfos = class(TCollection)
protected
procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); override; //Here "[dcc32 Error] MyUnit.pas(85): E2037 Declaration of 'Notify' differs from previous declaration"
end;
implementation
procedure TTextDisplayLineInfos.Notify(Item: TCollectionItem;
Action: TCollectionNotification);
begin
inherited; //Here "[dcc32 Error] MyUnit.pas(475): E2008 Incompatible types"
//..............
end;
Run Code Online (Sandbox Code Playgroud)
Notify方法的签名是通过复制粘贴进行的,因此不会出现任何错误;
错误
在界面部分:
[dcc32错误] MyUnit.pas(85):E2037"通知"声明与之前的声明不同
在实施部分:
[dcc32错误] MyUnit.pas(475):E2008不兼容的类型
题 …
我最近调试了一个复杂的bug.这是由访问不存在的Form.Handle
(带状指针)引起的.这个bug以相当意想不到的方式向我揭示 - 访问Forms会Handle
导致调整大小和重新绘制.
我希望Form.Handle
通过垃圾指针访问只会返回一些垃圾THandle.期望Handle
在表单创建时创建一次并保持相同直到Form被销毁.
为什么会这样,这TForm.Handle
不是一个在表单创建时初始化并通过访问的字段
property Handle: Integer read FHandle;
Run Code Online (Sandbox Code Playgroud)
,但是是一个吸气剂
property Handle: Integer read GetHandle;
Run Code Online (Sandbox Code Playgroud)
CreateWnd
在第一次访问时创建Handle甚至Window()?
我从 xml 文件中读取 UTF8 内容,然后需要保存并按需重新加载。我正在从 AssignFile/Writeln/Readln 转换为 David Heffernan 的缓冲流:缓冲文件(用于更快的磁盘访问)
我有简单的新 WriteLn 和 ReadLn 过程,WriteLn 可以工作,但我不能让 ReadLn 工作。
我对 ReadLn 的概念是处理:
新的 WriteLn 过程:
{ * New WriteLn * }
procedure TForm1.Button2Click(Sender: TObject);
var FileOut: TWriteCachedFileStream;
vText: string;
vUTF8Text: RawByteString;
begin
FileOut := TWriteCachedFileStream.Create('c:\tmp\file.txt');
try
vText := 'Delphi';
vUTF8Text := Utf8Encode(vText + sLineBreak);
FileOut.WriteBuffer(PAnsichar(vUTF8Text)^, Length(vUTF8Text));
vText := 'VB??';
vUTF8Text := Utf8Encode(vText + sLineBreak);
FileOut.WriteBuffer(PAnsichar(vUTF8Text)^, Length(vUTF8Text));
vText := 'Java??';
vUTF8Text := Utf8Encode(vText + …
Run Code Online (Sandbox Code Playgroud) 我的项目包含两个执行不同任务的过程,我执行一个计时器中的每个线程.
我的问题是,当我运行项目时,计时器启动.线程不能正常工作.
为什么?
而且,我可以在同一个项目中使用两个或更多线程吗?
注意:我真的想使用线程,我需要一个带线程的解决方案.
这是我没有线程的代码.
procedure TForm1.Timer1Timer(Sender: TObject);
var
i : integer;
begin
for i := 0 to 50 do
begin
Memo1.Lines.Add(IntToStr(i));
sleep(500);
end;
end;
procedure TForm1.Timer2Timer(Sender: TObject);
var
k : integer;
begin
for k := 0 to 50 do
begin
Memo2.Lines.Add(IntToStr(k));
sleep(500);
end;
end;
end.
Run Code Online (Sandbox Code Playgroud)
有线程:
type
TThread_Timer2 = class(TThread)
protected
procedure Execute; override;
end;
type
TThread_Timer3 = class(TThread)
protected
procedure Execute; override;
end;
procedure TThread_Timer2.Execute;
var
i : integer;
begin
for i := 0 to 50 do …
Run Code Online (Sandbox Code Playgroud) 我有一个Checkbox1,我想自定义,当用户点击复选框的标题(文本)时,它不会改变它的状态(选中/取消选中),但只有当它点击实际的复选框时才会这样做.
这是当前代码,包含2个全局变量,一个表示何时跳过更改状态,另一个表示记住当前状态并确保它在OnClick之后保持不变 - 因为当流程处于OnClick时状态已经更改:
var
gSkipClick:boolean = false;
gPrevState:boolean;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
// Make sure previous state is assigned when Skip
if gSkipClick then
Checkbox1.Checked := gPrevState;
end;
procedure TForm1.CheckBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if (x > 12) then
begin
// Click outside checkbox square
gSkipClick := True; // skip Click
gPrevState := CheckBox1.Checked; // save current state
end
else
gSkipClick := False; // enable Click
end;
Run Code Online (Sandbox Code Playgroud)
现在我想用TCheckBox中的2个新属性来替换全局变量:
TCheckBox = class(Vcl.StdCtrls.TCustomCheckBox)
private
FSkipStateChange:Boolean;
FPrevState:Boolean; …
Run Code Online (Sandbox Code Playgroud) delphi ×10
delphi-xe7 ×6
arrays ×1
bitmap ×1
boolean ×1
canvas ×1
filestream ×1
handle ×1
ide ×1
tcheckbox ×1
tcollection ×1
tform ×1
tscrollbox ×1
vcl ×1