在表单上设置的光标不会显示在控件上
setted cursor on form wont show up on controls
我使用 Delphi xe-8 并使用线程进行查询,我想在我的线程工作时显示一个沙漏光标。
我将光标设置为沙漏,但是当我将鼠标悬停在窗体上的控件上时,例如在网格上,光标显示为默认;只有当我将鼠标悬停在表单本身上时,光标才会改变。我想要做的是仅在窗体和窗体上的任何控件上显示沙漏光标,而不是应用程序的其余部分。
我尝试将 Screen.Cursor 设置为 crHourGlass,但它适用于整个应用程序,因此即使我将鼠标悬停在另一个表单上,它也是一个沙漏。
可以吗?如果是我该怎么做?
当鼠标悬停在给定的 TWinControl
上时,OS 会向它发送一条 WM_SETCURSOR
消息,请求它设置屏幕光标图标。 VCL 对该消息的默认处理如下:
如果Screen.Cursor
不是crDefault
,就是使用的游标。
否则,如果TWinControl
鼠标下方有一个TGraphicControl
子节点,而它的Cursor
不是crDefault
,那就是光标使用过。
否则,如果TWinControl
自己的Cursor
不是crDefault
,那就是使用的光标。
否则,消息将传递给父级 window。重复步骤 2-3。
因此,为了满足您的要求,请尝试将表单的 Cursor
设置为所需的值,并确保表单上的所有子控件的 Cursor
设置为 crDefault
.
如果这不是您的选择,或者如果它不起作用,您可以让您的表单 class 覆盖它的虚拟 WndProc()
方法(或使用 message
method) 直接处理 WM_SETCURSOR
消息。先调用inherited
处理函数,如果消息的Result
是FALSE
,工作线程是运行则调用Win32的APISetCursor()
函数设置您想要的光标图标,并将消息的 Result
设置为 TRUE
,例如:
protected
procedure WndProc(var Message: TMessage); override;
...
procedure TMyForm.WndProc(var Message: TMessage);
begin
inherited;
if (Message.Msg = WM_SETCURSOR) and (Message.Result = 0) and (Thread is Running) then
begin
Windows.SetCursor(Screen.Cursors[crHourGlass]);
Message.Result := 1;
end;
end;
或
private
procedure WMSetCursor(var Message: TMessage); message WM_SETCURSOR;
...
procedure TMyForm.WMSetCursor(var Message: TMessage);
begin
inherited;
if (Message.Result = 0) and (Thread is Running) then
begin
Windows.SetCursor(Screen.Cursors[crHourGlass]);
Message.Result := 1;
end;
end;
这样,Screen.Cursor
和个别TControl.Cursor
属性仍然优先,但如果光标保持不变(即所有属性都是crDefault
),那么你可以改变光标为整个Form整体,不影响其他Form。
我使用 Delphi xe-8 并使用线程进行查询,我想在我的线程工作时显示一个沙漏光标。
我将光标设置为沙漏,但是当我将鼠标悬停在窗体上的控件上时,例如在网格上,光标显示为默认;只有当我将鼠标悬停在表单本身上时,光标才会改变。我想要做的是仅在窗体和窗体上的任何控件上显示沙漏光标,而不是应用程序的其余部分。
我尝试将 Screen.Cursor 设置为 crHourGlass,但它适用于整个应用程序,因此即使我将鼠标悬停在另一个表单上,它也是一个沙漏。
可以吗?如果是我该怎么做?
当鼠标悬停在给定的 TWinControl
上时,OS 会向它发送一条 WM_SETCURSOR
消息,请求它设置屏幕光标图标。 VCL 对该消息的默认处理如下:
如果
Screen.Cursor
不是crDefault
,就是使用的游标。否则,如果
TWinControl
鼠标下方有一个TGraphicControl
子节点,而它的Cursor
不是crDefault
,那就是光标使用过。否则,如果
TWinControl
自己的Cursor
不是crDefault
,那就是使用的光标。否则,消息将传递给父级 window。重复步骤 2-3。
因此,为了满足您的要求,请尝试将表单的 Cursor
设置为所需的值,并确保表单上的所有子控件的 Cursor
设置为 crDefault
.
如果这不是您的选择,或者如果它不起作用,您可以让您的表单 class 覆盖它的虚拟 WndProc()
方法(或使用 message
method) 直接处理 WM_SETCURSOR
消息。先调用inherited
处理函数,如果消息的Result
是FALSE
,工作线程是运行则调用Win32的APISetCursor()
函数设置您想要的光标图标,并将消息的 Result
设置为 TRUE
,例如:
protected
procedure WndProc(var Message: TMessage); override;
...
procedure TMyForm.WndProc(var Message: TMessage);
begin
inherited;
if (Message.Msg = WM_SETCURSOR) and (Message.Result = 0) and (Thread is Running) then
begin
Windows.SetCursor(Screen.Cursors[crHourGlass]);
Message.Result := 1;
end;
end;
或
private
procedure WMSetCursor(var Message: TMessage); message WM_SETCURSOR;
...
procedure TMyForm.WMSetCursor(var Message: TMessage);
begin
inherited;
if (Message.Result = 0) and (Thread is Running) then
begin
Windows.SetCursor(Screen.Cursors[crHourGlass]);
Message.Result := 1;
end;
end;
这样,Screen.Cursor
和个别TControl.Cursor
属性仍然优先,但如果光标保持不变(即所有属性都是crDefault
),那么你可以改变光标为整个Form整体,不影响其他Form。