如何在运行时动态调整弹出窗口的大小?

时间:2012-05-05 18:18:02

标签: delphi

我尝试创建一个弹出Treeview的自定义Combobox控件。 一切都很好看。 但是当我尝试向该控件添加运行时调整大小功能时,弹出窗口(Treeview)只是移动而不会改变其大小。

任何建议都将不胜感激。

弹出窗口的片段:

创建

ControlStyle := ControlStyle + [csNoDesignVisible, csReplicatable, csDoubleClicks];

创建参数

begin
  inherited CreateParams(Params);
  with Params do
  begin
    Style := Style or WS_POPUP or WS_VSCROLL or WS_BORDER;
    ExStyle := WS_EX_TOOLWINDOW;
    AddBiDiModeExStyle(ExStyle);
    //WindowClass.Style := CS_SAVEBITS; {this would prevent ondoubleclick event}
  end;

鼠标移动:

var
  ARect, RR: TRect;
  DragStyle: TDragStyle;
  Procedure SetDragStyle(ds:TDragStyle; c:TCursor);
  begin
    FDragStyle:=ds;
    Cursor:=c;
  end;
begin
  inherited;
  FMouseMoveSelected := GetNodeAt(x, y);
  if FDragged then begin
    case FDragStyle of
       dsSizeLeft :begin
                      SetWindowPos(Handle, HWND_TOP, Left+(x-FDragPos.X), Top, Width, Height,
                        SWP_NOACTIVATE or SWP_SHOWWINDOW);
                      //Left:=Left+(x-FDragPos.X); {alternate code that doesn't work either}
                   end;
    end;
    FDragPos:=Point(x,y);
  end else begin
    SetDragStyle(dsMove,crDefault);
    ARect := GetClientRect;
    RR:=ARect;
    InflateRect(RR,-2,-2);
    if (x>=0) and (x<=Width) and (y>=0) and (y<=Height) and (not PtInRect(RR,Point(x,y))) then begin
      if (x<=RR.Left) then begin
        //if (y<=RR.Top) then SetDragStyle(dsSizeTopLeft,crSizeNWSE)else
        if (y>=RR.Bottom) then SetDragStyle(dsSizeBottomLeft,crSizeNESW)
        else SetDragStyle(dsSizeLeft,crSizeWE); 
      end else if (x>=RR.Right) then begin
        //if (y<=RR.Top) then SetDragStyle(dsSizeTopRight,crSizeNESW) else
        if (y>=RR.Bottom) then SetDragStyle(dsSizeBottomRight,crSizeNWSE)
        else SetDragStyle(dsSizeRight,crSizeWE);
      end else begin
        //if (y<=RR.Top) then SetDragStyle(dsSizeTop,crSizeNS) else
        if (y>=RR.Bottom) then SetDragStyle(dsSizeBottom,crSizeNS)
        else SetDragStyle(dsMove,crDefault);
      end;
    end;
  end;
end;
end;

关闭鼠标

begin
  inherited;
  if FDragStyle<>dsMove then begin
    FDragPos:=point(x,y);
    FDragged:=true;
  end;
end;

启用鼠标

begin
  inherited;
  FDragged:=false;
end;

1 个答案:

答案 0 :(得分:4)

您将客户坐标与SetWindowPos来电中的屏幕坐标混合在一起。那是因为你漂浮了一个不应该浮动的窗口而且VCL不知道它。当您引用其Left时,VCL会返回相对于其父级的坐标,可能是表单。在拖动过程中开始拖动时(也就是FDragPos),也不要更改保存的点:

procedure TPanel.MouseMove(Shift: TShiftState; X, Y: Integer);
var
  ARect, RR: TRect;
  DragStyle: TDragStyle;

  Procedure SetDragStyle(ds:TDragStyle; c:TCursor);
  begin
    FDragStyle:=ds;
    Cursor:=c;
  end;

  var
    DragOffset: Integer;
begin
  inherited;
  FMouseMoveSelected := GetNodeAt(x, y);
  if FDragged then begin
    case FDragStyle of
       dsSizeLeft:
         begin
            DragOffset := X - FDragPos.X;
            winapi.windows.GetWindowRect(Handle, ARect);
            SetWindowPos(Handle, HWND_TOP,
                                  ARect.Left + DragOffset,
                                  ARect.Top,
                                  ARect.Right - ARect.Left - DragOffset,
                                  ARect.Bottom - ARect.Top,
                                  SWP_NOACTIVATE or SWP_SHOWWINDOW);
            //Left:=Left+(x-FDragPos.X); {alternate code that doesn't work either}
         end;
    end;
//    FDragPos:=Point(x,y);  // do not change drag origin while you're dragging
  end else begin
    ..