【问题标题】:Dynamically resize controls based on drag area根据拖动区域动态调整控件大小
【发布时间】:2017-02-21 13:47:00
【问题描述】:

我有一个表单,左边是 TTreeview,右边是 TGroupbox。当通过拖动右边缘来调整表单大小时,我希望 Groupbox 相应地增长或缩小。当表单被拖到左边时,我希望 Treeview 调整大小。我尝试了下面的代码并且正确调整大小工作正常。但是左调整大小会导致树视图增长得比它应该的长。实现此目的的正确方法是什么?

procedure TForm1.FormResize(Sender: TObject);
var
  p: TPoint;
begin
  P:= ScreenToClient(Mouse.CursorPos);
  if(P.X<0) then begin
    Treeview1.Anchors:= [akLeft,akTop,akRight,akBottom];
    Groupbox1.Anchors:= [akTop,akBottom];
  end
  else begin
    Treeview1.Anchors:= [akLeft,akTop,akBottom];
    Groupbox1.Anchors:= [akLeft,akTop,akRight,akBottom];
  end;
end;

【问题讨论】:

    标签: delphi resize anchor


    【解决方案1】:

    您可以改为拦截WM_SIZING 消息,而不是处理OnResize 事件

    发送到用户正在调整大小的窗口。 通过处理此消息,应用程序可以监控拖动矩形的大小和位置,并在需要时更改其大小或位置。

    它的wParam 值准确地告诉您正在调整窗口的哪些边缘。您可以使用它来相应地调整Anchors,例如:

    type
      TForm1 = class(TForm)
        TreeView1: TTreeView;
        GroupBox1: TGroupBox;
      private
        { Private declarations }
        procedure WMSizing(var Message: TMessage); message WM_SIZING;
      public
        { Public declarations }
      end;
    
    ...
    
    procedure TForm1.WMSizing(var Message: TMessage);
    var
      TreeViewAnchors: TAnchors;
      GroupBoxAnchors: TAnchors;
    begin
      inherited;
    
      TreeViewAnchors := [akTop, akBottom];
      GroupBoxAnchors := [akTop, akBottom];
    
      case Message.WParam of
        WMSZ_LEFT, WMSZ_BOTTOMLEFT, WMSZ_TOPLEFT: begin
          TreeViewAnchors := TreeViewAnchors + [akLeft, akRight];
          GroupBoxAnchors := GroupBoxAnchors + [akRight];
        end;
        WMSZ_RIGHT, WMSZ_BOTTOMRIGHT, WMSZ_TOPRIGHT: begin
          TreeViewAnchors := TreeViewAnchors + [akLeft];
          GroupBoxAnchors := GroupBoxAnchors + [akLeft, akRight];
        end;
      end;
    
      TreeView1.Anchors := TreeViewAnchors;
      GroupBox1.Anchors := GroupBoxAnchors;
    end;
    

    【讨论】:

      【解决方案2】:

      我认为您在调整左侧窗口大小时忘记将 Groupbox 锚定在右侧。

      procedure TForm1.FormResize(Sender: TObject);
      var
        p: TPoint;
      begin
        if GetAsyncKeyState(VK_LBUTTON) and $8000 <> 0 then exit;
        P:= ScreenToClient(Mouse.CursorPos);
        if(P.X<0) then begin
          Treeview1.Anchors:= [akLeft, akTop, akRight, akBottom];
          Groupbox1.Anchors:= [akTop, akRight, akBottom];
        end
        else begin
          Treeview1.Anchors:= [akLeft, akTop, akBottom];
          Groupbox1.Anchors:= [akLeft, akTop, akRight, akBottom];
        end;
      end;
      

      我试过了,它似乎做你想做的事

      编辑:

      您也可以使用 Align 属性(注意顺序,最后带有 'alClient' 值的组件):

      procedure TForm1.FormResize(Sender: TObject);
      var
        p: TPoint;
      begin
        if GetAsyncKeyState(VK_LBUTTON) and $8000 <> 0 then exit;
        P:= ScreenToClient(Mouse.CursorPos);
        if(P.X<0) then begin        
          Groupbox1.Align:= alRight;
          Treeview1.Align:= alClient;
        end
        else begin
          Treeview1.Align:= alLeft;
          Groupbox1.Align:= alClient;
        end;
      end;
      

      编辑2:检查鼠标左键状态

      您可以使用 Winapi 的 GetAsyncKeyState(vKey) 函数检查按钮或按键的状态。 它返回 SmallInt 中按钮的状态,位为 15 0/1,如果按钮已被按下。

      GetAsyncKeyState

      【讨论】:

      • 不,当您在左侧向左和向右拖动数次时,Groupbox 最终会消失。这里发生了一些奇怪的事情。
      • @fullerm 将akRight 添加到GroupBox1.Anchors 似乎在Delphi 10.1 Berlin 中运行良好。如果它对您不起作用,那么您的测试用例中肯定还有一些您没有告诉我们的东西。
      • 我正在使用 XE 并在一个空白项目中测试了这段代码。在左侧多次来回拖动后,Treeview 重叠到 Groupbox 上。 XE 中可能存在错误。
      • 我看到了问题:当您调整左侧窗口的大小并将光标拖到窗口右侧时,Treeview 会重叠到 Groupbox 上,因为我认为 OnResize 事件已处理再次使用 P.X > 0。我们必须找到其他解决方案...
      • 我找到了解决办法:可以查看鼠标左键的状态。如果单击它,则退出该过程,否则执行此操作。检查按钮或键的状态:GetAsyncKeyState(vKey) --> Winapi.Windows
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-19
      • 1970-01-01
      • 2015-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多