为什么';在Delphi的FindDialog中,我的光标不会变成沙漏吗?

为什么';在Delphi的FindDialog中,我的光标不会变成沙漏吗?,delphi,cursor,hourglass,finddialog,Delphi,Cursor,Hourglass,Finddialog,我只是用以下方式打开我的FindDialog: FindDialog.Execute; 在FindDialog.OnFind事件中,我想将光标更改为沙漏,以便在大型文件中进行搜索,这可能需要几秒钟的时间。因此,在OnFind事件中,我执行以下操作: Screen.Cursor := crHourglass; (code that searches for the text and displays it) ... Screen.Cursor := crDefault; 搜索文本时,光标会正确

我只是用以下方式打开我的FindDialog:

FindDialog.Execute;
在FindDialog.OnFind事件中,我想将光标更改为沙漏,以便在大型文件中进行搜索,这可能需要几秒钟的时间。因此,在OnFind事件中,我执行以下操作:

Screen.Cursor := crHourglass;
(code that searches for the text and displays it) ...
Screen.Cursor := crDefault;
搜索文本时,光标会正确地变为沙漏(或Vista中的旋转圆),然后在搜索完成后返回指针

然而,这只发生在主窗体上。它不会发生在FindDialog本身上。搜索过程中,默认光标保持在FindDialog上。当搜索发生时,如果我将光标移到FindDialog上,它将更改为默认值,如果我将光标移离并移到主窗体上,它将成为沙漏

这似乎不是应该发生的事情。我是做错了什么,还是需要做一些特殊的事情才能使光标成为所有窗体上的沙漏


作为参考,我使用的是Delphi 2009。

尝试添加Application.ProcessMessages;设置光标后


如果可行,一定要打电话给你妈妈,帮助一位老太太过马路,或者种一棵树。否则,魔鬼将拥有你的另一小片灵魂。

我想这是因为发现对话不是一种形式,而是一种对话(普通对话)

您可以尝试设置类游标(对对话框的控件没有影响)



编辑

另一种方法是在搜索期间将FindDialog子类化,并用“SETCURSOR”响应WM_SETCURSOR消息。如果我们阻止进一步处理消息,对话框上的控件将不会设置自己的游标

type
  TForm1 = class(TForm)
    FindDialog1: TFindDialog;
    ...
  private
    FSaveWndProc, FWndProc: Pointer;
    procedure FindDlgProc(var Message: TMessage);
    ...
  end;

....
procedure TForm1.FormCreate(Sender: TObject);
begin
  FWndProc := classes.MakeObjectInstance(FindDlgProc);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  classes.FreeObjectInstance(FWndProc);
end;

procedure TForm1.FindDialog1Find(Sender: TObject);
begin
  FSaveWndProc := Pointer(SetWindowLong(FindDialog1.Handle, GWL_WNDPROC,
        Longint(FWndProc)));
  try
    Screen.Cursor := crHourGlass;
    try
//    (code that searches for the text and displays it) ...
    finally
      Screen.Cursor := crDefault;
    end;
  finally
    if Assigned(FWndProc) then
      SetWindowLong(FindDialog1.Handle, GWL_WNDPROC, Longint(FSaveWndProc));
//    SendMessage(FindDialog1.Handle, WM_SETCURSOR, FindDialog1.Handle,
//        MakeLong(HTNOWHERE, WM_MOUSEMOVE));
    SetCursor(Screen.Cursors[crDefault]);
  end;
end;

procedure TForm1.FindDlgProc(var Message: TMessage);
begin
  if Message.Msg = WM_SETCURSOR then begin
    SetCursor(Screen.Cursors[crHourGlass]);
    Message.Result := 1;
    Exit;
  end;
  Message.Result := CallWindowProc(FSaveWndProc, FindDialog1.Handle,
      Message.Msg, Message.WParam, Message.LParam);
end;

@克里斯。我在搜索文本代码时确实有Application.ProcessMessages,但在上面的示例中没有显示它。如果我没有它,那么光标也不会变成主窗体的沙漏。@Sertac:“几乎”可以。沙漏似乎出现在“查找”对话框的某些部分,但不是全部。很奇怪!任何看起来像是放置在对话框上的对象(例如标签、按钮、编辑框)的东西都不会显示沙漏,但它后面的窗体会显示沙漏。好吧,我想这只会更改对话框“窗体”的光标,而不会更改对话框控件的光标,而且您还需要设置所有子窗口的光标。我认为EnumChildWindows可以完成这项工作。编辑后,可以提出一种替代方法来枚举对话框上的控件。我不知道这是更少的代码还是更合适…@Sertac:这更好。沙漏现在出现在FindDialog及其控件上。但是,当查找完成时,FindDialog控件上的光标被设置回默认值,但是FindDialog中没有控件的部分上的光标仍然具有沙漏。另外,我现在注意到(以前没有)主窗体上的一些控件没有更改为沙漏。也许windows标准希望沙漏以这种方式处理,我不应该拿它胡闹(???)。@Ikessler-(1)确认,在重置窗口过程后添加了对SetCursor的调用。。。(2) -我不知道,我不知道沙漏光标使用设计指南。是否可以使用标准VCL控件进行复制?
type
  TForm1 = class(TForm)
    FindDialog1: TFindDialog;
    ...
  private
    FSaveWndProc, FWndProc: Pointer;
    procedure FindDlgProc(var Message: TMessage);
    ...
  end;

....
procedure TForm1.FormCreate(Sender: TObject);
begin
  FWndProc := classes.MakeObjectInstance(FindDlgProc);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  classes.FreeObjectInstance(FWndProc);
end;

procedure TForm1.FindDialog1Find(Sender: TObject);
begin
  FSaveWndProc := Pointer(SetWindowLong(FindDialog1.Handle, GWL_WNDPROC,
        Longint(FWndProc)));
  try
    Screen.Cursor := crHourGlass;
    try
//    (code that searches for the text and displays it) ...
    finally
      Screen.Cursor := crDefault;
    end;
  finally
    if Assigned(FWndProc) then
      SetWindowLong(FindDialog1.Handle, GWL_WNDPROC, Longint(FSaveWndProc));
//    SendMessage(FindDialog1.Handle, WM_SETCURSOR, FindDialog1.Handle,
//        MakeLong(HTNOWHERE, WM_MOUSEMOVE));
    SetCursor(Screen.Cursors[crDefault]);
  end;
end;

procedure TForm1.FindDlgProc(var Message: TMessage);
begin
  if Message.Msg = WM_SETCURSOR then begin
    SetCursor(Screen.Cursors[crHourGlass]);
    Message.Result := 1;
    Exit;
  end;
  Message.Result := CallWindowProc(FSaveWndProc, FindDialog1.Handle,
      Message.Msg, Message.WParam, Message.LParam);
end;