我有一个有2个事件的TPanel:
procedure TForm1.Panel1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Panel1.Cursor := crSizeAll;
end;
procedure TForm1.Panel1MouseUp(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Panel1.Cursor := crDefault;
end;
Run Code Online (Sandbox Code Playgroud)
当我单击面板(MouseDown事件)时,光标不会更改为crSizeAll.我做错了什么,如何解决这个问题?
你做得很好.捕获鼠标输入只有一个简单的技巧.在TPanel此面板上按下鼠标左键(LMB)后,鼠标就会输出.
在那之后,您的代码Panel1.Cursor := crSizeAll;开始运行.正如您在VCL的源代码中所看到的,TControl向CM_CURSORCHANGED自身发送消息以设置所需的游标类型.由于TWinControl是基于TControl,它处理此消息并检查是否已捕获鼠标输入.如果不是这样,则TWinControl向WM_SETCURSOR自身发送消息以设置新光标.
但微软明确表示该消息WM_SETCURSOR有一点限制:
如果鼠标导致光标在窗口内移动并且未捕获鼠标输入,则发送到窗口.
因此,如果捕获了鼠标输入,则无法更改光标的类型.你可以做的一件事是打电话ReleaseCapture:
procedure TForm1.Panel1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
ReleaseCapture;
Panel1.Cursor := crSizeAll;
end;
Run Code Online (Sandbox Code Playgroud)
但我不建议这样做,因为它打破了鼠标输入的范例(在我看来,一旦按下LMB,它应该保持按下直到它被释放的重要原因(点击按钮),但你是自由的决定如何自己使用ReleaseCapture).
重要!
用户Zig执行的测试证明使用ReleaseCapture方法是不合适的,因为OnMouseUp如果鼠标光标TPanel移出LMB并且LMB已经释放,它禁止生成事件.
有用的信息:
迪马解释了为什么改变Panel1.Cursor没有你想要的效果.
作为替代方案,您可以Screen.Cursor改为:
procedure TForm1.Panel1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Screen.Cursor := crSizeAll;
end;
procedure TForm1.Panel1MouseUp(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Screen.Cursor := crDefault;
end;
Run Code Online (Sandbox Code Playgroud)
由于Dima 解释了Cursor面板设置没有效果的原因,面板无法处理WM_SETCURSOR消息,因为只要按下鼠标按钮就捕获鼠标.
要立即设置光标,您可以使用SetCursorAPI.可能的缺点是光标将保持您设置的状态,直到您释放鼠标按钮,甚至在面板外.
procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
SetCursor(Screen.Cursors[crSizeAll]);
end;
Run Code Online (Sandbox Code Playgroud)
您不需要重置光标,因为在WM_SETCURSOR释放鼠标按钮后将假定默认值(响应消息).
如果您希望光标恢复到面板外部并在再次进入面板时再次设置,则可以包含OnMouseMove事件处理程序.那是因为鼠标消息将被引导到面板,即使在面板外面,因为它捕获了鼠标:
procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if Mouse.Capture = Panel1.Handle then begin
if PtInRect(Rect(0, 0, Panel1.Width, Panel1.Height), Point(X, Y)) then
SetCursor(Screen.Cursors[crSizeAll])
else
SetCursor(Screen.Cursors[crDefault])
end;
end;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
187 次 |
| 最近记录: |