首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在不影响其他游标设置代码的情况下,在某些组件上更改鼠标光标。

在不影响其他游标设置代码的情况下,在某些组件上更改鼠标光标。
EN

Stack Overflow用户
提问于 2017-06-05 10:42:35
回答 2查看 2.2K关注 0票数 3

我正在使用Delphi DevExpress QuantumGrid (MasterView)的一个古老的前身,并希望某些单元格有效地充当超链接(当鼠标游标从crDefault更改为crHandPoint时,当鼠标移动到超链接时,并触发单击操作)。

网格组件的配置使单个单元格不是它们自己的组件,我需要从鼠标光标坐标中找到单元格并从那里设置游标。

我认为我需要在网格对象上设置几个事件来实现这一点,但我对这些事件如何与代码交互感到有些不舒服,这些代码在执行长期运行的操作时将光标设置为沙漏(当前使用IDisposible处理,以便在完成后将光标设置为原始),并希望在开始之前反复检查是否有更好的方法来完成这些操作,然后找到一吨使鼠标处于错误状态的边缘情况。

我想我需要推翻:

  • omMouseMove -获取XY坐标并将光标设置为手/箭头。
  • onMouseDown -得到XY协调和‘激活’超链接,如果有(可能恢复为箭头?超链接通常会打开一个新窗口,被调用的代码可能会将光标更改为沙漏)
  • onMouseLeave -将光标重置为箭头(此事件实际上未公开,因此认为我需要手动处理消息)

这种功能在TButton上是默认的,但我无法在VCL中看到它是如何实现的,而且可能是底层Windows控件的一个特性。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-06-05 13:16:15

实际上,我在四处浏览时找到了解决方案。

我忘记了组件通常有自己的游标属性,这就是当指针在组件上时如何设置正确的鼠标光标类型(即按钮行为)。

如果游标位于超链接单元格上,则重写MouseMove以将其更改为crHandPoint,并将旧的游标属性存储到如果不是超链接的话,则会很好地工作(并且独立于在长时间运行的代码中设置的screen.cursor )。我需要完成代码以确认它是否正确工作,所以我将暂时不回答这个问题,直到我能够确认一切都如我所期望的那样。

编辑:添加一些代码。我决定使用一个拦截器类,而不是子类化网格和注册控件--我将只在一个应用程序中的一两个位置使用它,这样就不必设置其他人的机器了。

代码语言:javascript
运行
复制
TdxMasterView = class(dxMasterView.TdxMasterView)
private
  FDefaultCursor: TCursor;
  procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
public
  constructor Create(AOwner: TComponent); override;
end;

constructor TdxMasterView.Create(AOwner: TComponent);
begin
  inherited create(AOwner);
  FDefaultCursor := self.Cursor;
end;

procedure TdxMasterView.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  lvHitTestCode: TdxMasterViewHitTestCode;
  lvNode : TdxMasterViewNode;
  lvColumn: TdxMasterViewColumn;
  lvRowIndex, lvColIndex: integer;
begin
  inherited;
  lvHitTestCode   := self.GetHitTestInfo( Point(X,Y),
                                          lvNode,
                                          lvColumn,
                                          lvRowIndex,
                                          lvColIndex );
  if (lvHitTestCode = htContent) and (lvColumn is TMasterViewClickableColumn) then
  begin
    TMasterViewClickableColumn(lvColumn).onClickContentCell(lvNode);
  end;
end;

procedure TdxMasterView.MouseMove(Shift: TShiftState; X, Y: Integer);
var
  lvHitTestCode: TdxMasterViewHitTestCode;
  lvNode : TdxMasterViewNode;
  lvColumn: TdxMasterViewColumn;
  lvRowIndex, lvColIndex: integer;
begin
  inherited;
  lvHitTestCode   := self.GetHitTestInfo( Point(X,Y), 
                                          lvNode,
                                          lvColumn,
                                          lvRowIndex,
                                          lvColIndex );
  if (lvHitTestCode = htContent) and (lvColumn is TMasterViewClickableColumn) then
  begin
    self.cursor := TMasterViewClickableColumn(lvColumn).cursorOnMouseOver;
  end
  else
  begin
    self.cursor := self.FDefaultCursor;
  end;
end;
票数 0
EN

Stack Overflow用户

发布于 2017-06-05 21:42:51

这是我更喜欢的情景。游标是从WM消息处理程序和后端工作设置的标志。然后从MouseDown方法重写处理链接单击。请注意,光标仅为此控件更改(当鼠标光标悬停该控件时)。伪码:

代码语言:javascript
运行
复制
type
  THitCode =
  (
    hcHeader,
    hcGridCell,
    hcHyperLink { ← this is the extension }
  );

  THitInfo = record
    HitRow: Integer;
    HitCol: Integer;
    HitCode: THitCode;
  end;

  TMadeUpGrid = class(TGridAncestor)
  private
    FWorking: Boolean;
    procedure DoStartWork;
    procedure DoFinishWork;
    procedure UpdateCursor;
    procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
  protected
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  public
    function GetHitTest(X, Y: Integer): THitInfo; override; 
  end;

implementation

procedure TMadeUpGrid.DoStartWork;
begin
  FWorking := True;
  UpdateCursor;
end;

procedure TMadeUpGrid.DoFinishWork;
begin
  FWorking := False;
  UpdateCursor;
end;

procedure TMadeUpGrid.UpdateCursor;
begin
  Perform(CM_CURSORCHANGED, 0, 0); { ← triggers WM_SETCURSOR handler if needed }
end;

procedure TMadeUpGrid.WMSetCursor(var Msg: TWMSetCursor);
var
  P: TPoint;
  HitInfo: THitInfo;
begin
  { the mouse is inside the control client rect, inherited call here should
    "default" to the Cursor property cursor type }
  if Msg.HitTest = HTCLIENT then
  begin
    GetCursorPos(P);
    P := ScreenToClient(P);
    HitInfo := GetHitTest(P.X, P.Y);
    { if the mouse is hovering a hyperlink or the grid backend is working }
    if FWorking or (HitInfo.HitCode = hcHyperLink) then
    begin
      { here you can setup the "temporary" cursor for the hyperlink, or
        for the working grid backend }
      if not FWorking then
        SetCursor(Screen.Cursors[crHandPoint])
      else
        SetCursor(Screen.Cursors[crHourGlass]);
      { tell the messaging system that this message has been handled }
      Msg.Result := 1;
    end
    else
      inherited;
  end
  else
    inherited;
end;

procedure TMadeUpGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  HitInfo: THitInfo;
begin
  if Button = mbLeft then
  begin
    HitInfo := GetHitTest(X, Y);
    { the left mouse button was pressed when hovering the hyperlink, so set
      the working flag, trigger the WM_SETCURSOR handler "manually" and do the
      navigation; when you finish the work, call DoFinishWork (from the main
      thread context) }
    if HitInfo.HitCode = hcHyperLink then
    begin
      DoStartWork;
      DoSomeNavigation(HitInfo.HitRow, HitInfo.HitCol);
    end;
  end;
end;

function TMadeUpGrid.GetHitTest(X, Y: Integer): THitInfo;
begin
  { fill the Result structure properly }
end;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44367166

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档