小编Mik*_*nni的帖子

有什么方法可以加快位图画布上的绘图速度?

我的应用程序的一部分是绘制图形表单的草稿,主要是用户输入表单,有许多编辑框.我绘制位图并保存为PNG,报告过程的所有部分,因此没有任何内容被绘制到应用程序表单.我绘制所有控件,编辑框,单选按钮,复选框......

绘图的最长部分当然是绘制编辑框,因为它们数量巨大.我有一个典型的过程,在大约70K表格上绘制1M编辑框.

我画了一个非常简单的编辑框:

  1. 基本矩形,笔宽= 1
  2. 添加左侧和顶部附加线,以获得缩进控制的感觉.
  3. 如果需要,添加文本

我附加了一个简单的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)

delphi canvas bitmap delphi-xe7

2
推荐指数
1
解决办法
981
查看次数

如何在没有数组变量的情况下传递值数组?

我已经建立了非常好的系统来将列添加到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)

arrays delphi delphi-xe7

2
推荐指数
1
解决办法
291
查看次数

如果它们仅用作表单控件的指针,我是否需要"创建"/初始化局部变量?

我有一个同步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)

但我认为创建滚动框变量是不必要的,对吧?这些只是表单上控件的变量指针.

delphi compiler-warnings tscrollbox delphi-xe7

2
推荐指数
1
解决办法
112
查看次数

如何初始化局部变量使用的布尔类型?

我试图改变我如何使用布尔参数来获得有意义的名称,所以我不需要检查每个方法的真/假意味着什么.在这个例子中我使用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)

delphi boolean delphi-xe7

2
推荐指数
2
解决办法
976
查看次数

无法覆盖TCollection.Notify:Notify声明与之前的声明不同

注意:其他问题的标题不同,这使其无法识别为匹配的标题.

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不兼容的类型

题 …

delphi tcollection

2
推荐指数
1
解决办法
182
查看次数

删除IDE代码编辑器中间的垂直白线

我正在使用 2 个显示器。在第二个中,我有 Delphi IDE,使用经典的取消停靠设置。

IDE 中间有一条白色竖线贯穿源代码。我似乎无法在设置中找到删除它的选项。

图像

ide delphi delphi-10.2-tokyo

2
推荐指数
1
解决办法
2102
查看次数

为什么TForm.Handle是一个吸气剂而不是一个领域?

我最近调试了一个复杂的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()?

delphi vcl handle tform

1
推荐指数
1
解决办法
306
查看次数

如何用 ReadLn 的缓冲流版本替换 Readln?

我从 xml 文件中读取 UTF8 内容,然后需要保存并按需重新加载。我正在从 AssignFile/Writeln/Readln 转换为 David Heffernan 的缓冲流:缓冲文件(用于更快的磁盘访问)

我有简单的新 WriteLn 和 ReadLn 过程,WriteLn 可以工作,但我不能让 ReadLn 工作。

我对 ReadLn 的概念是处理:

  1. 读取缓冲区
  2. 查找换行符
  3. 从 PrevPos 获取文本到 CurrPos-1
  4. 保存缓冲区的其余部分以添加到下一个读取缓冲区的第一行

新的 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)

delphi filestream delphi-xe7

1
推荐指数
1
解决办法
840
查看次数

我如何在delphi项目中执行两个线程

我的项目包含两个执行不同任务的过程,我执行一个计时器中的每个线程.

我的问题是,当我运行项目时,计时器启动.线程不能正常工作.

为什么?

而且,我可以在同一个项目中使用两个或更多线程吗?

注意:我真的想使用线程,我需要一个带线程的解决方案.

这是我没有线程的代码.

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)

delphi multithreading delphi-xe7

0
推荐指数
1
解决办法
2591
查看次数

如何用TCheckBox中的属性替换全局变量?

我有一个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 tcheckbox delphi-10.1-berlin

0
推荐指数
1
解决办法
139
查看次数