我正在尝试制作事件处理程序列表,其中handler是方法引用.要删除特定的处理程序,我需要在列表中找到它.但是我如何比较两个方法引用的代码地址?
type
TEventHandler = reference to procedure;
procedure TestProc;
begin
end;
procedure TForm26.FormCreate(Sender: TObject);
var
Handlers: TList<TEventHandler>;
begin
Handlers := TList<TEventHandler>.create;
try
Handlers.Add(TestProc);
Handlers.Remove(TestProc); { doesn't work }
Assert(Handlers.Count=0); { fails }
Assert(Handlers.IndexOf(TestProc)>=0); { fails }
finally
FreeAndNil(Handlers);
end;
end;
Run Code Online (Sandbox Code Playgroud)
TList <>的默认比较器不能正确比较方法引用.我该如何比较它们?是否存在类似于TMethod的结构,但是方法参考?
我在表单上有网格控件,当前记录更改时我需要加载存储在DB中的RTF.它一般工作正常,但当我切换记录时,我可以看到鼠标光标更改为沙漏并返回常规:
function TComments.GetDocument(AID: integer; ADst: TStream):Boolean;
begin
try
SelectQuery.Close;
SelectQuery.Params.Clear;
SelectQuery.SQL.Text :=
'SELECT Dokument from Kommentarer ' +
'WHERE ID = :ID';
SelectQuery.ParamByName('ID').AsInteger := AID;
SelectQuery.Open;
Result := SelectQuery.RecordCount > 0;
if Result then
(SelectQuery.Fields[0] as TBLOBField).SaveToStream(ADst);
finally
SelectQuery.Close;
end;
end;
Run Code Online (Sandbox Code Playgroud)
如果我发表评论"SelectQuery.Open;" 那么光标不会切换.我想TFDQuery(或连接)应该有选项,但我找不到任何东西.有帮助吗?
UPDATE.正如TLama建议的那样,我将WaitCursor:TFDGUIxWaitCursor放在我的表单(app的一个地方)并以这种方式使用它:
StoredCursor := WaitCursor.ScreenCursor;
WaitCursor.ScreenCursor := gcrNone;
try
// access DB with queries
finally
WaitCursor.ScreenCursor := StoredCursor;
end;
Run Code Online (Sandbox Code Playgroud)
更新2:还有两种方法.
TFDQuery.ResourceOptions.SilentMode=True(对于特定查询禁用沙漏光标的最简单方法,属性名称不好,但根据doc它不阻止任何对话框,只更改光标).FADGUIxSilentMode=True从单元FireDAC.UI.Intf 设置全局变量(不是最好的,但可能是最简单的方法来为FireDAC全局禁用游标更改).在许多确认对话框中,有这样的选项是有用的(快速方法来禁用确认).但我无法找到如何做到这一点.我不想自己设计它,因为我需要这个对话框是标准的,不要随着Delphi的每次更新重新设计.是否有简单的方法使用Delphi标准确认对话框这样的复选框?
UPDATE2.Synopse项目推荐的SynTaskDialog库做得很好(我需要的甚至更多),我将在我的项目中使用它.谢谢!
UPDATE.所以,谢谢你们的想法.系统函数MessageBoxCheck是一个不错的解决方案,但似乎不是那么稳定.总的来说,我同意最好使用最新的API函数为用户提供现代操作系统的最佳UI体验,并为旧系统使用老式设计.目前我仍然坚持简单的解决方案(代码如下),但如果有人在现代操作系统的UI支持下共享代码,那就太好了.
function MsgDlgWithCB(const Msg,Title,CBMsg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; DefaultButton: TMsgDlgBtn;
var cbDontAskAnymore: TCheckBox): TForm;
var
i: integer;
b: TButton;
y: integer;
begin
Result := CreateMessageDialog(Msg, DlgType, Buttons, DefaultButton) ;
Result.Position := poScreenCenter;
cbDontAskAnymore := TCheckBox.Create(Result);
cbDontAskAnymore.Caption := CBMsg;
cbDontAskAnymore.Width := 130;
y := -1;
for i := 0 to result.ComponentCount-1 do
if result.Components[i] is TButton then
begin
b := TButton(result.Components[i]);
b.Left := b.Left + cbDontAskAnymore.Width + 16;
Result.ClientWidth := Max(Result.ClientWidth, b.Left+b.Width+16);
y := b.Top+b.Height-cbDontAskAnymore.Height;
end;
if y<0 …Run Code Online (Sandbox Code Playgroud) 有没有简单的方法来跟踪他的滚动条滚动TScrollbox内容?我有几个TScrollBox组件(每个组件都有一些组件),并希望保持它们同步.如果其中一个滚动框滚动(垂直或水平),我需要同步滚动其他滚动框.这就是为什么我需要知道滚动条位置何时被更改.这很奇怪,但是Delphi的TScrollbox组件没有这样的事件.
对于表单上的所有组合组件,我需要使用鼠标滚轮禁用滚动项目.最重要的是拥有或多或少的通用解决方案,因为表单的设计可能会发生变化,如果在没有任何额外的源代码工作的情况下忽略新的组合组件会更好.我有两种类型的组合:TComboBox和TcxComboBox(来自DevExpress ExpressBars Suit).我试着这样走:
procedure TSomeForm.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
var Handled: Boolean);
begin
if (Screen.ActiveControl is TComboBox) or (Screen.ActiveControl is TcxComboBox) then
Handled := True;
end;
Run Code Online (Sandbox Code Playgroud)
它适用于TComboBox,但是当TcxComboBox具有焦点时,此事件处理程序从未触发.我试图在表单的级别上捕获相应的消息,如下所示:
procedure TSomeForm.WndProc(var m: TMessage);
begin
if (m.Msg = WM_VSCROLL) or (m.Msg = WM_HSCROLL) or (m.msg = WM_Mousewheel) then
m.Msg := 0;
inherited;
end;
Run Code Online (Sandbox Code Playgroud)
但这样的消息永远不会来到这个处理程序 我试图直接禁用TcxComboBox的鼠标滚轮处理,因为它有这样的属性:
procedure TSomeForm.FormCreate(Sender: TObject);
begin
cxComboBox1.Properties.UseMouseWheel := False;
end;
Run Code Online (Sandbox Code Playgroud)
但它不起作用,仍然可以使用鼠标滚轮滚动项目.我发布了这个问题的支持票,但即使他们在下一个版本中修复它我现在需要一些解决方案.
任何想法,也许有人以某种方式解决了它?
我正在尝试获取记录字段的类型以创建正确的比较器(作为任何/几乎任何记录类型的通用解决方案).我找不到静态数组的类型信息:
TArrFieldTest = record
a: string;
b: array[0..3] of byte;
end;
procedure Test;
var
rttiContext: TRttiContext;
rttiType: TRttiType;
rttiFields: TArray<TRttiField>;
begin
rttiType := rttiContext.GetType(TypeInfo(TArrFieldTest));
rttiFields := rttiType.GetFields;
Assert(rttiFields[0].FieldType<>nil); // it's ok
Assert(rttiFields[1].FieldType<>nil); // fail here!
end;
Run Code Online (Sandbox Code Playgroud)
对于任何类型的静态数组,FieldType都是nil.任何想法在这里有什么不对?或者也许有更简单的方法来创建与TArray/TDictionary等一起使用的记录的比较器?
我需要捕获没有背景图片(壁纸)的屏幕截图。我可以尝试禁用墙纸,拍摄屏幕截图,然后重新启用它,但是:
有谁知道在哪里寻找解决方案的解决方案或想法?也许可以暂时禁用壁纸?
更新:屏幕截图是注册错误程序的一部分,因此我需要所有可能有用的信息(可见表单、任务栏等),并且非常希望将屏幕截图保持在无损格式(更易读、压缩速度更快)。选项之一是捕捉镜头以将它们存储为 AVI,因此处理时间也很重要。背景使图像更大,这是我试图删除它的唯一原因。我可以使用一些算法来减少使用的颜色,它大大提高了压缩率,但它是耗时的过程。所以最重要的是完全删除背景图片。
更新 2:为了从镜头序列生成 AVI,我使用了 François PIETTE 的单元(基于本文):
Avi := TAviFromBitmaps.CreateAviFile(
nil,
AviFilename,
MKFOURCC('S', 'C', 'L', 'S'), // msu-sc-codec
2, 1); // 2 frames per second
// called by timer
procedure TfrmSnapshot.RecordFrame;
begin
TakeSnapshot; // get snap shot to BMP:TBitmap
Avi.AppendNewFrame(Bmp.Handle);
end;
Run Code Online (Sandbox Code Playgroud)
因此,如果我能够从快照中删除背景,那么 AVI 压缩也将得到改进。
我使用的最终代码部分:
TAppRects = class
protected
FMonitor: TMonitor;
FRects: TList<TRect>;
function GetRegion(AArea: TRect): HRGN;
public
constructor Create(AMonitor: TMonitor);
destructor Destroy; override;
// fill all Area which is not …Run Code Online (Sandbox Code Playgroud) 可能我缺少了一些东西,但是找不到找到创建具有特定像素格式的FMX位图的方法。更具体地说,我需要FMX.Graphics.TBitmap使用pixel format 创建BGR_565。构造函数没有定义PixelFormat的选项。该属性PixelFormat为只读(与的VCL版本不同TBitmap)。
我有这样的网址(例如):
https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=delphi+url+parameters+
Run Code Online (Sandbox Code Playgroud)
我需要按名称(“sourceid”、“ion”、...)获取/设置参数的值。我怎样才能做到这一点?Delphi 有 TIdURI 类,它有助于解析 URL 而不是参数,它将所有参数作为单个字符串(属性参数)返回。当然我可以创建自己的解析器,但它是如此基本的功能,应该有一些标准的方式(我希望)。我很惊讶 TIdURI 没有它。
delphi ×9
bitmap ×1
combobox ×1
confirmation ×1
delphi-xe3 ×1
delphi-xe7 ×1
dialog ×1
firedac ×1
firemonkey ×1
mousewheel ×1
pixelformat ×1
rtti ×1
tscrollbox ×1
url ×1