标签: delphi-2007

Delphi - 如何在TStringGrid中设置垂直滚动条,始终可见

我正在使用Delphi 2007 for Win32并且需要在TstringGrid中设置垂直滚动条以始终可见.你是怎样做的?

delphi scrollbar delphi-2007

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

从OnTimer事件访问父窗体中的变量 - 获取异常

我在OnTimer事件处理程序(TTimer)中得到一个异常,它在执行时递增父窗体中的整数变量.定时器需要能够访问用作id的递增整数.

我的第一个问题是:如何在Delphi 2007中告诉哪个代码在哪个线程中运行?有没有办法在调试模式下检查这个,所以我可以确定?

其次,如果我需要从另一个线程访问和修改父表单中的变量,那么最好的方法是什么?似乎有时Delphi允许我"错误地"访问这些变量而不给出异常,有时它确实给出了异常.

delphi multithreading delphi-2007

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

使用复杂记录时"无效指针操作"的建议

环境:德尔福2007

<理由>我倾向于经常使用复杂的记录,因为它们几乎提供了类的所有优点,但处理起来更简单.</ Justification>

Anyhoo,我刚刚实现的一个特别复杂的记录是垃圾内存(后来导致"无效的指针操作"错误).

这是内存垃圾代码的一个例子:

sSignature := gProfiles.Profile[_stPrimary].Signature.Formatted(True);
Run Code Online (Sandbox Code Playgroud)

在我第二次调用它时,我得到"无效的指针操作"

如果我这样称呼它可以正常工作:

  AProfile    := gProfiles.Profile[_stPrimary];
  ASignature  := AProfile.Signature;
  sSignature  := ASignature.Formatted(True);
Run Code Online (Sandbox Code Playgroud)

背景代码:

  gProfiles: TProfiles;

  TProfiles = Record
  private
    FPrimaryProfileID: Integer;
    FCachedProfile: TProfile;
    ...
  public
    < much code removed >

    property Profile[ProfileType: TProfileType]: TProfile Read GetProfile;
  end;


  function TProfiles.GetProfile(ProfileType: TProfileType): TProfile;
  begin        
    case ProfileType of
      _stPrimary        : Result := ProfileByID(FPrimaryProfileID);
      ...
    end;
  end;

  function TProfiles.ProfileByID(iID: Integer): TProfile;
  begin
    <snip>
    if LoadProfileOfID(iID, FCachedProfile)  then
    begin
      Result := FCachedProfile;
    end
    else
    ...
  end;


  TProfile = …
Run Code Online (Sandbox Code Playgroud)

delphi records delphi-2007

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

如何在构造中创建枚举器销毁?

我有一个从TCollection派生的集合,实现了GetEnumerator,所以我可以在类似的结构中使用它

for lElem in lCollection do
Run Code Online (Sandbox Code Playgroud)

枚举器派生自TObject,与Delphi提供的标准枚举器完全相同,因此没有所有者.

Delphi帮助提到,如果枚举器支持IDisposable,它将被处理掉,但这只适用于.NET.

我想知道的是,枚举器实例如何以及何时以及由谁被释放?

delphi enumerator delphi-2007

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

德尔福悸动

什么是表明应用程序正在做某事的最佳解决方案?

我尝试显示进度指示器,但它没有用.

更新:-------------

进度条工作正常,但不是我想要的.

我想展示一个像Web浏览器一样使用的悸动,所以只要有东西正在更新它就会不断变换.

游标也可以处于crHourGlass模式.

delphi progress delphi-2007 throbber

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

Delphi DLL没有卸载,可能是由于仍然分配了GDI

我们编写了一个DLL来执行所有打印功能.它允许我们进行打印预览,打印,还可以生成PDF.

我们现在有一个特定的使用此DLL的模式,之后DLL无法正确卸载.结果是,当我们退出主程序时,它会消失但不会终止,我们必须手动终止该过程.

我想,罪魁祸首是一些GDI资源没有被正确地"封闭"(当我这样说时,我从GDI的无知深处说出来).我们不直接处理GDI资源,而是在使用各种Delphi组件时使用GDI资源.

有关如何找到并解决此类问题的任何提示?在我们尝试终止程序之后,我们使用GDIView确认某些GID资源仍然存在,但我不知道如何将这些Windows/Kernel句柄与底层Delphi代码相关联.我可以在程序执行期间的不同时间提供GIDView列表.

谢谢!

乔恩(德尔福2007)


我回复了所提出的建议,但没有人回复我的回复.最终,我放弃了.我最终编写了一个自杀程序,它不仅杀死了我自己的进程,而且还杀死了其他具有相同名称的进程,以解决问题.荒谬的矫枉过正,但我​​似乎别无选择.我正在使用我在某处找到的免费软件ProcessInfo工具.

procedure KillNamedProcesses(pName : String);
// used to clean up programs that hang as a result of DLLs not unloading
   var
      ProcessInfo : TProcessInfo;
      ProcessName : String;
      i : INTEGER;
      currentPID : cardinal;
   BEGIN
   currentPID := GetCurrentProcessID;
   pName := UpperCase(pName);
   ProcessInfo := TProcessInfo.Create(nil);

   // kill all old processes (not our process)
   for i := 0 to ProcessInfo.RunningProcesses.Count - 1 do begin
      ProcessName := ProcessInfo.RunningProcesses[i].ExeFile;
      IF (UpperCase(ProcessName) <> pName) THEN CONTINUE;
      IF (currentPID <> ProcessInfo.RunningProcesses[i].ProcessID) …
Run Code Online (Sandbox Code Playgroud)

delphi dll delphi-2007

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

相同的代码作为Windows服务运行速度比GUI应用程序慢

我有一些Delphi 2007代码,它运行在两个不同的应用程序中,一个是GUI应用程序,另一个是Windows服务.奇怪的是,虽然GUI应用程序在技术上似乎有更多的"待办事项",绘制GUI,计算一些统计数据等,但Windows服务在运行时始终使用更多的CPU.在GUI应用程序使用大约3-4%的CPU功率的情况下,该服务的使用范围为6-8%.

当它们一起运行时,两个应用程序的CPU负载大约加倍.

除了在Windows窗体应用程序中添加GUI代码外,两个应用程序中的基本代码相同.

这种行为有什么理由吗?Windows服务应用程序是否具有某种固有的开销,或者我是否需要查看代码以查找我的书中出现的意外行为?

编辑:

有时间仔细查看代码,我认为下面的建议是GUI应用程序花费一些时间等待重新绘制,导致CPU负载下降可能是不正确的.应用程序都是线程化的,这意味着GUI重新绘制不应影响CPU负载.

为了确保我首先尝试从应用程序中删除所有GUI组件,只留下一个空白表单.这并没有增加程序的CPU负载.然后我经历了在用于更新UI的工作线程中删除所有对Synchronize的调用.这有相同的结果:CPU负载没有变化.

服务中的代码如下所示:

procedure TLsOpcServer.ServiceExecute(Sender: TService);
begin
  // Initialize OPC server as NT Service
  dmEngine.AddToLog( sevInfo, 'Service', 'Name', Sender.Name );
  AddLocalServiceKeysToRegistry( Sender.Name );

  dmEngine.AddToLog( sevInfo, 'Service', 'Execute', 'Started' );
  dmEngine.Start( True );
  //
  while not Terminated do
  begin
    ServiceThread.ProcessRequests( True );
  end;

  dmEngine.Stop;
  dmEngine.AddToLog( sevInfo, 'Service', 'Execute', 'Stopped' );
end;
Run Code Online (Sandbox Code Playgroud)

dmEngine.Start将启动并注册OPC服务器并初始化套接字.然后它启动一个线程,它对输入的OPC信号有所帮助.在GUI应用程序的主要表单上的FormCreate中进行相同的完全调用.

我将研究GUI应用程序如何启动,我没有编写这段代码,所以试图弄清楚它是如何工作的有点冒险:)

EDIT2

这有点有趣.我运行两个应用程序各1分钟,运行AQTime来对它们进行基准测试.这是结果中最有趣的部分:

在服务中:

过程名称: TSignalList :: HandleChild

执行时间: 20.105963821084

Hitcount: 5961231

在GUI应用程序中:

过程名称: TSignalList :: HandleChild

执行时间: 7.62424101324976

命中数: 6383010

编辑3:

我终于回到了能够继续关注这个问题的位置.我发现两个程序在五分钟运行期间都具有大约相同的hitcount,但在服务中执行时间要高得多.对于HandleValue,hitcount为4 …

windows delphi performance windows-services delphi-2007

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

如何使用dbExpress处理多个结果集查询

我有这样一个sql语句:

UPDATE tbworker SET iState=2 WHERE iState=1;
UPDATE tbworker SEt iState=3 WHERE iState=0;
Run Code Online (Sandbox Code Playgroud)

我想在一个MySQL请求中执行此语句.

简单的sql请求以这种方式排除:

SQLQuery.SQL.Text := SomeSQLText;
AffectedRows := SQLQuery.ExecSQL(true);
Run Code Online (Sandbox Code Playgroud)

但是现在我需要一个像NextResultSet这样的方法,例如:

SQLQuery.SQL.Text := MultyResultSetSQLText;
ResultSetCounter := 1;
AffectedRows.Add(ResultSetCounter, SQLQuery.ExecSQL(true));
while SQLQuery.HasNextResultSets do
begin
  Inc(ResultSetCounter);
  AffectedRows.Add(ResultSetCounter, SQLQuery.GetNextResultSet);
end;
Run Code Online (Sandbox Code Playgroud)

dbExpress如何处理多个结果集?

mysql delphi dbexpress delphi-2007

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

使用临时变量格式化输出

在保留一些代码时,我遇到了这样的声明:

 sActDiln := Format('%.*f',[tdDigits.ndd, Fields[itd].AsFloat * rfc / 100]);
Run Code Online (Sandbox Code Playgroud)

为了看看发生了什么,我添加了一个DOUBLE类型的临时变量(actDiln),并修改了如下代码:

 actDiln := Fields[itd].AsFloat * rfc / 100;
 sActDiln := Format('%.*f',[tdDigits.ndd, actDiln]);
Run Code Online (Sandbox Code Playgroud)

当"Fields [itd] .AsString"为35且"rfc"为109时,计算值从38.15变为38.14999999.当小数位数为1时,则将计算值从38.2更改为38.1.这引起了其他问题.

我没想到使用这个临时变量会导致这样的问题.谁能解释一下这里发生了什么?为避免这种情况,未来的最佳做法是什么?

这证明了这个问题:

Uses DB, DBISAMTb;

procedure TForm1.FormShow(Sender: TObject);
   var
      t : TDBISAMTable;
      actDiln, rfc : double;
      actDilnE : extended;
      sActDiln1, sActDiln2, sActDiln3 : string;
   begin
   t := TDBISAMTable.Create(Application);

   WITH t DO BEGIN
      TableName := 'xxx';
      DataBaseName := 'Study';

      Active := False;
      Exclusive := False;
      IF Exists THEN DeleteTable;

      WITH FieldDefs DO BEGIN
         Clear;
         Add('fld', ftString, 10, …
Run Code Online (Sandbox Code Playgroud)

delphi delphi-2007

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

双舍入

我这是代码,它围绕62到61并在输出中显示它.为什么它决定舍入以及如何在输出中获得62?

var  d: double;
i: integer;
begin
  d:=0.62;
  i:= trunc(d*100);
  Showmessage( inttostr(i) );

end;
Run Code Online (Sandbox Code Playgroud)

delphi delphi-2007

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