Por que meu cursor não muda para uma ampulheta no meu finddialog em Delphi?
-
27-09-2019 - |
Pergunta
Estou simplesmente abrindo meu finddialog com:
FindDialog.Execute;
No meu evento finddialog.onfind, quero alterar o cursor para uma ampulheta para pesquisas através de arquivos grandes, que podem levar alguns segundos. Então, no evento ONFIND, eu faço isso:
Screen.Cursor := crHourglass;
(code that searches for the text and displays it) ...
Screen.Cursor := crDefault;
O que acontece é que, ao procurar o texto, o cursor muda adequadamente para a ampulheta (ou círculo rotativo no Vista) e depois volta ao ponteiro quando a pesquisa é concluída.
No entanto, isso só acontece na forma principal. Isso não acontece no próprio finddialog. O cursor padrão permanece no finddialog durante a pesquisa. Enquanto a pesquisa está acontecendo se eu mover o cursor sobre o finddialog, ele muda para o padrão e, se eu o mover para fora e sobre a forma principal, ele se tornará a ampulheta.
Isso não parece o que deveria acontecer. Estou fazendo algo errado ou algo especial precisa ser feito para fazer com que o cursor seja a ampulheta em todas as formas?
Para referência, estou usando o Delphi 2009.
Solução
Eu acho que a razão para isso tem STH. A ver com a caixa de diálogo Localizar não sendo um formulário, mas uma caixa de diálogo (uma caixa de diálogo comum).
Você pode tentar definir o cursor da classe (não afeta os controles da caixa de diálogo);
procedure TForm1.FindDialog1Find(Sender: TObject);
begin
SetClassLong(TFindDialog(Sender).Handle, GCL_HCURSOR, Screen.Cursors[crHourGlass]);
try
Screen.Cursor := crHourglass;
try
// (code that searches for the text and displays it) ...
finally
Screen.Cursor := crDefault;
end;
finally
SetClassLong(TFindDialog(Sender).Handle, GCL_HCURSOR, Screen.Cursors[crDefault]);
end;
end;
EDITAR
Uma alternativa pode ser subclasse o FindDialog durante o tempo de pesquisa e responder às mensagens WM_SETCURSOR com "SetCursor". Se impedirmos o processamento adicional da mensagem, os controles na caixa de diálogo não definirão seus próprios cursores.
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;
Outras dicas
Tente adicionar Application.processMessages; Depois de definir o cursor.
Se isso funcionar, chame sua mãe, ajude uma velha senhora a atravessar a rua ou talvez plantar uma árvore. Caso contrário, o diabo terá outro pedacinho da sua alma.