如何停止Screen.Cursor会影响窗体上的所有控件?

问题描述 投票:4回答:1

我将尝试简化我的问题。例如,如果您丢下2 TSpeedButton并执行:

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  Screen.Cursor := crHourGlass;
  SpeedButton2.Cursor := crHandPoint; // note I'm setting other cursor than crDefault
end;

SpeedButton2.Cursor仍然显示设置为Screen.CursorcrHourGlass。我研究了TScreen.SetCursor代码,并意识到它为整个表单设置了光标。我的问题:是否可以在整个表格中使用Screen.Cursor,但不影响要设置其他光标的some控件。

TButton也会发生同样的情况。如果在Screen.Cursor设置为crHourGlass时可以某种方式控制光标,则我不介意将SpeedButton放在窗口控件上。

谢谢。

delphi delphi-7 vcl
1个回答
6
投票

[这是documentationTScreen.Cursor中所解释的故意行为:

...当Cursor为crDefault时,各个对象确定光标图像。分配任何其他值都会设置鼠标光标图像属于该应用程序的所有窗口。全局鼠标光标图像保持有效,直到更改屏幕的Cursor属性回到crDefault。 ..

窗口控件在TWinControl.WMSetCursor程序的处理程序中处理其光标,在WM_SETCURSOR消息的处理程序中,如果不是crDefault,则它们显式设置屏幕光标,而忽略它们自己的光标。

因此,要更改行为,您可以处理上述消息。对于TButton插入器,示例如下:

procedure TButton.WMSetCursor(var Message: TWMSetCursor);
begin
  if (Cursor <> crDefault) and (Message.HitTest = HTCLIENT) then begin
    Message.Result := 1;
    Windows.SetCursor(Screen.Cursors[Cursor]);
  end else
    inherited;
end;


图形控件的游标由其父控件TWinControl处理。因此,要更改速度按钮的行为,您仍然需要在其父按钮上处理相同的消息。由于父类可能事先未知,因此这可能是不切实际的。

仍然是一个非常不通用的实现,例如,直接放置在表单上的图形控件,可能看起来如下:

procedure TForm1.WMSetCursor(var Message: TWMSetCursor);
var
  SmPt: TSmallPoint;
  Control: TControl;
begin
  DWORD(SmPt) := GetMessagePos;
  Control := ControlAtPos(ScreenToClient(SmallPointToPoint(SmPt)), True);
  if Assigned(Control) and Boolean(Control.Tag) then begin
    Message.Result := 1;
    Windows.SetCursor(Screen.Cursors[Control.Cursor])
  end else
    inherited;
end;

以上示例将要求图形控件具有非零标记值。例如:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Screen.Cursor := crHourGlass;
  SpeedButton1.Cursor := crHandPoint;
  SpeedButton1.Tag := 1;
end;
© www.soinside.com 2019 - 2024. All rights reserved.