小编Mar*_*ski的帖子

Delphi 2009中的Generic TList <>在IndexOf上崩溃

我已经看到许多提到Delphi 2009泛型中的错误,但从来没有预料到在Update 3中会出现如此基本的错误,不会少.如果列表包含一个或多个项目,则在通用TList或TObjectList上调用IndexOf会导致访问冲突:

type
  TTest = class( TObject );

procedure DoTest;
var
  list : TObjectList< TTest >;
  t : TTest;
begin
  list := TObjectList< TTest >.Create;
  try
    t := TTest.Create;
    list.IndexOf( t ); // No items in list, correct result -1
    list.Add( t );
    list.IndexOf( t ); // Access violation here
  finally
    list.Free;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

例外情况是"EAccessViolation:模块'testbed.exe'中地址0048974C的访问冲突.读取地址00000000"

使用调试DCU进行编译会导致generics.collections.pas中出现问题 - 未分配FComparer成员:

function TList<T>.IndexOf(const Value: T): Integer;
var
  i: Integer;
begin
  for i := 0 to Count - 1 do
    if FComparer.Compare(FItems[i], Value) …
Run Code Online (Sandbox Code Playgroud)

delphi generics indexof delphi-2009

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

将C++ time_t转换为Delphi TDateTime

在Delphi XE应用程序中,我正在从最初由C++程序创建的数据库中读取值.有一个日期列,存储(它会显示)为time_t,即Unix时间,自UTC时间00:00,1970年1月1日以来的秒数.我可以处理时区,但是如何从(长)time_t获得TDateTime?

c++ delphi time-t

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

在Delphi XE中将UnicodeString转换为PAnsiChar

在Delphi XE中,我使用的是BASS音频库,它包含以下功能:

function BASS_StreamCreateURL(url: PAnsiChar; offset: DWORD; flags: DWORD; 
    proc: DOWNLOADPROC; user: Pointer):HSTREAM; stdcall; external bassdll;
Run Code Online (Sandbox Code Playgroud)

'url'参数的类型为PAnsiChar,所以在我的代码中我做了一个强制转换:

FStreamHandle := BASS_StreamCreateURL(PAnsiChar( url ) [...]
Run Code Online (Sandbox Code Playgroud)

编译器在此行上发出警告:"对PAnsiChar的字符串的可疑类型转换".在试图消除警告时,我发现推荐的方法是使用双重投射:

FStreamHandle := BASS_StreamCreateURL(PAnsiChar( AnsiString( url )) [...]
Run Code Online (Sandbox Code Playgroud)

这确实消除了警告,但是BASS函数现在返回错误代码2("无法打开文件"),这告诉我它收到的URL字符串以某种方式被破坏.我无法看到低音DLL实际接收到的内容,但在调试器中使用断点时字符串看起来很好:

var
  s : PAnsiChar;
begin
  s := PAnsiChar( AnsiString( url ));
Run Code Online (Sandbox Code Playgroud)

此时字符串s显示正常,但是当我通过它时BASS功能失败.我的初始代码:PAnsiChar(url)与BASS配合良好,但会发出警告.

那么在没有警告的情况下从UnicodeString到PAnsiChar的正确方法是什么?

delphi pointers unicode-string ansistring delphi-xe

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

在SQLite WHERE子句中组合了大量条件

我需要检索与列表中存储的ID匹配的记录.在运行时生成的查询很简单:

SELECT [whatever FROM sometable] WHERE (id = 1) or (id = 5) or (id = 33).
Run Code Online (Sandbox Code Playgroud)

这相当于

SELECT [whatever FROM sometable] WHERE [id] IN (1, 5, 33);
Run Code Online (Sandbox Code Playgroud)

这很好,但如果列表包含数百或数千个ID怎么办?声明将是巨大的,并且在某些时候SQL解析器可能会呱呱叫,或者如果它没有,性能可能会非常糟糕.如何以对检索的记录数量不那么敏感的方式执行此操作?

(我不能只循环遍历列表并逐个检索记录的原因是我需要数据库为我做ORDER BY.记录必须来自特定字段排序的数据库,而列表表示由网格中的用户可以通过多种方式进行排序.是的,我可以在检索后对代码中的记录进行排序,但这是计划B,因为我甚至不需要将它们全部保存在一个数据结构中,只是为了正确订购.)

sql sqlite performance

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

如何根据需要启动/停止监控Delphi线程?

我一直在寻找一种方法来监控Delphi中特定的注册表更改.在about.com上找到了解决方案:

procedure TRegMonitorThread.Execute;
begin
  InitThread; // method omitted here
  while not Terminated do
  begin
    if WaitForSingleObject(FEvent, INFINITE) = WAIT_OBJECT_0 then
    begin
      fChangeData.RootKey := RootKey;
      fChangeData.Key := Key;
      SendMessage(Wnd, WM_REGCHANGE, RootKey, LongInt(PChar(Key)));
      ResetEvent(FEvent);

      RegNotifyChangeKeyValue(FReg.CurrentKey, 1, Filter, FEvent, 1);
    end;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,我将需要按需启动和停止此线程,但上面的代码不允许这样做.只设置Terminated标志是不行的.

以某种方式告诉线程停止等待,然后释放它并在需要时创建一个新的就足够了.如何更改此代码才能实现?

delphi multithreading ondemand

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

如何在Delphi中抑制标准的RadioButton检查行为?

我意识到这个有点奇怪,所以我会解释.对于一个简单的互联网广播播放器,我需要一个控件来指定评级(1-5"星").我没有图形设计的经验或才能,所以我绘制位图的所有尝试看起来都很荒谬/糟糕,请你选择.我找不到具有该功能的第三方控件,并且看起来符合标准VCL控件.所以...

在我看来,通过使用没有标题的标准radiobutton,我可以通过Windows UI获得良好的外观和一致性,如下所示:

不带字幕的无线电按钮作为基本额定值控制

我对GroupIndex属性进行了模糊(不正确)的回忆; 为每个单选按钮分配不同的值将允许同时检查多个单选按钮.唉,TRadioButton没有GroupIndex属性,所以就是这样.

  1. 是否可以完全覆盖自然的无线电按钮行为,以便同时显示多个按钮?要么,

  2. 我可以从系统中获取Windows用于radiobuttons的所有位图(我假设它们是位图)并直接绘制它们,包括主题支持吗?在这种情况下,我仍然希望保留radiobutton的所有效果,包括鼠标悬停"发光"等,这意味着获取所有"本机"位图并根据需要绘制它们,可能在TPaintBox上.

delphi radio-button

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

将以null结尾的内存流转换为unicode字符串

在Delphi XE中,我从剪贴板中捕获CF_UNICODETEXT数据.结果是一个以两个空字节终止的流.要获取复制到剪贴板的实际字符串,我需要删除空值.

这个类似的问题包含一个从TMemoryStream转换为Delphi的unicode字符串的好方法:

function MemoryStreamToString(M: TMemoryStream): string;
begin
  SetString(Result, M.Memory, M.Size div SizeOf(Char));
end;
Run Code Online (Sandbox Code Playgroud)

但是,在我的情况下,这将产生一个包含尾随空值的字符串.我可以通过限制大小来解决这个问题:

function ClipboardMemoryStreamToString(M: TMemoryStream): string;
begin
  SetString(Result, M.Memory, (M.Size - SizeOf(Char)) div SizeOf(Char));
end;
Run Code Online (Sandbox Code Playgroud)

......但这感觉很难看,"特殊情况".我想知道是否有更简洁的方法对此进行编码,以便后来查看代码的任何人(我!)都不会立即询问"为什么会从流中删除尾随的字符?"

编辑:预先解决问题的一种方法是添加评论.但是,除此之外?

delphi memorystream unicode-string null-terminated

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