我尝试创建一个弹出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;
答案 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
..