以下代码只能对TButton类,TPanel类等控件有效,而对TRichEdit和TImage类控件却无效。请教各位高手,我该如何做?
我也曾考虑将RichEdit/Image装入TPanel,但这只能改变大小,无法移动,因为Panel位于RichEdit/Image背后。////任意摆布一个控件(拖动、放大、缩小)******************************************//==============================================================================procedure ManipulateControl(WinControl: TWinControl; Shift: TShiftState; X, Y, Precision: integer);//Precision:精度,该方法可以在onmousemove中调用var SC_MANIPULATE: Word;begin //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的最左侧********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (X<=Precision) and (Y>Precision) and (Y<WinControl.Height-Precision) then begin SC_MANIPULATE := $F001; WinControl.Cursor := crSizeWE; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的最右侧********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>=WinControl.Width-Precision) and (Y>Precision) and (Y<WinControl.Height-Precision) then begin SC_MANIPULATE := $F002; WinControl.Cursor := crSizeWE; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的最上侧********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>Precision) and (X<WinControl.Width-Precision) and (Y<=Precision) then begin SC_MANIPULATE := $F003; WinControl.Cursor := crSizeNS; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的左上角********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X<=Precision) and (Y<=Precision) then begin SC_MANIPULATE := $F004; WinControl.Cursor := crSizeNWSE; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的右上角********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>=WinControl.Width-Precision) and (Y<=Precision) then begin SC_MANIPULATE := $F005; WinControl.Cursor := crSizeNESW ; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的最下侧********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>Precision) and (X<WinControl.Width-Precision) and (Y>=WinControl.Height-Precision) then begin SC_MANIPULATE := $F006; WinControl.Cursor := crSizeNS; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的左下角********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X<=Precision) and (Y>=WinControl.Height-Precision) then begin SC_MANIPULATE := $F007; WinControl.Cursor := crSizeNESW; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的右下角********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>=WinControl.Width-Precision) and (Y>=WinControl.Height-Precision) then begin SC_MANIPULATE := $F008; WinControl.Cursor := crSizeNWSE; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的客户区(移动整个控件)****************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>5) and (Y>5) and (X<WinControl.Width-5) and (Y<WinControl.Height-5) then begin SC_MANIPULATE := $F009; WinControl.Cursor := crSizeAll; end else begin SC_MANIPULATE := $F000; WinControl.Cursor := crDefault; end; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if Shift=[ssLeft] then begin ReleaseCapture; WinControl.Perform(WM_SYSCOMMAND, SC_MANIPULATE, 0); end; end;
调用例子:
procedure TForm_Main.Button1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);begin Caption := IntToStr(X) + '/' + IntToStr(Y); ManipulateControl((Sender as TWinControl), Shift, X, Y, 10);end;
我也曾考虑将RichEdit/Image装入TPanel,但这只能改变大小,无法移动,因为Panel位于RichEdit/Image背后。////任意摆布一个控件(拖动、放大、缩小)******************************************//==============================================================================procedure ManipulateControl(WinControl: TWinControl; Shift: TShiftState; X, Y, Precision: integer);//Precision:精度,该方法可以在onmousemove中调用var SC_MANIPULATE: Word;begin //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的最左侧********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (X<=Precision) and (Y>Precision) and (Y<WinControl.Height-Precision) then begin SC_MANIPULATE := $F001; WinControl.Cursor := crSizeWE; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的最右侧********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>=WinControl.Width-Precision) and (Y>Precision) and (Y<WinControl.Height-Precision) then begin SC_MANIPULATE := $F002; WinControl.Cursor := crSizeWE; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的最上侧********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>Precision) and (X<WinControl.Width-Precision) and (Y<=Precision) then begin SC_MANIPULATE := $F003; WinControl.Cursor := crSizeNS; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的左上角********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X<=Precision) and (Y<=Precision) then begin SC_MANIPULATE := $F004; WinControl.Cursor := crSizeNWSE; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的右上角********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>=WinControl.Width-Precision) and (Y<=Precision) then begin SC_MANIPULATE := $F005; WinControl.Cursor := crSizeNESW ; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的最下侧********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>Precision) and (X<WinControl.Width-Precision) and (Y>=WinControl.Height-Precision) then begin SC_MANIPULATE := $F006; WinControl.Cursor := crSizeNS; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的左下角********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X<=Precision) and (Y>=WinControl.Height-Precision) then begin SC_MANIPULATE := $F007; WinControl.Cursor := crSizeNESW; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的右下角********************************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>=WinControl.Width-Precision) and (Y>=WinControl.Height-Precision) then begin SC_MANIPULATE := $F008; WinControl.Cursor := crSizeNWSE; end //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //光标在控件的客户区(移动整个控件)****************************************** //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else if (X>5) and (Y>5) and (X<WinControl.Width-5) and (Y<WinControl.Height-5) then begin SC_MANIPULATE := $F009; WinControl.Cursor := crSizeAll; end else begin SC_MANIPULATE := $F000; WinControl.Cursor := crDefault; end; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if Shift=[ssLeft] then begin ReleaseCapture; WinControl.Perform(WM_SYSCOMMAND, SC_MANIPULATE, 0); end; end;
调用例子:
procedure TForm_Main.Button1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);begin Caption := IntToStr(X) + '/' + IntToStr(Y); ManipulateControl((Sender as TWinControl), Shift, X, Y, 10);end;
p : TStatusPanel;
begin
p := StatusBar1.Panels.Add;
p.Text := 'asdf';
end;
根据您提的思路,我采用以下方法即简单地实现了对TImage控件的拖动。procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
ManipulateControl(Panel1, Shift, X, Y, 10);
end;不过,还有一点遗憾,对TRichEdit控件,此法却无效(见下面源码)。如何解决?procedure TForm1.RichEdit1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
ManipulateControl(Panel1, Shift, X, Y, 10);
end;
Y: Integer);
begin
ManipulateControl(RichEdit1, Shift, X, Y, 10);
end;
就可以了
此法行不通,我就是在为此伤神。现我又觅得一法,但遗憾的是会交替产生一个右上角带关闭小叉的外窗体。
但愿是山重水复疑无路。(代码如下)procedure TForm1.FormCreate(Sender: TObject);
begin
RichEdit1.OnMouseMove:=Form1.OnMouseMove;
Form1.docksite:=true;
RichEdit1.DragKind:=dkdock;
RichEdit1.DragMode:=dmautomatic;
end;procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
ManipulateControl((Sender as TWinControl), Shift, X, Y, 10);
end;
中的WinControl:TWinControl也可被Control:TControl所代替。为何会产生带小叉的外窗体?
(以下摘自一位高手对此问题的剖析,他用的是Image控件,实际效果跟用RichEdit一样)问题出在下面的代码: (VCL的Controls单元)
这是拖动结束要泊靠时调用的,用来取鼠标处的泊靠点。
function GetDockSiteAtPos(MousePos: TPoint; Client: TControl): TWinControl;
begin
Result := nil;
if (DockSiteList = nil) or
not (Application.AutoDragDocking xor ((GetKeyState(VK_CONTROL) and not $7FFF) <> 0)) then
Exit;
QualifyingSites.Clear;
for I := 0 to DockSiteList.Count - 1 do
begin
Site := TWinControl(DockSiteList[I]);
if (Site <> Client) and Site.Showing and Site.Enabled and
IsWindowVisible(Site.Handle) and (not IsSiteChildOfClient) and
[u[red]]((Client.HostDockSite <> Site) or (Site.VisibleDockClientCount > 1)) //就在这里 [/red][/u]then
begin
CanDock := True;
Site.GetSiteInfo(Client, R, MousePos, CanDock);
if CanDock and PtInRect(R, MousePos) then
QualifyingSites.AddSite(Site);
end;
end;
if QualifyingSites.Count > 0 then
Result := QualifyingSites.GetTopSite;
if (Result <> nil) and not ValidDockTarget(Result) then
Result := nil;
end;
刚开始时,Image的HostDockSite等于nil,此时此方法将返回Form1。放下后Image.HostDockSite就被设置成Form1了,下次再拖就不能通过上面注释的那句判断,将返回nil,也就是说鼠标下没有泊靠点,于是Image将变成浮动状态。当再创建一个Image之后并拖放一次,Form1的VisibleDockClientCount将变成2,因此就可以通过判断,返回Form1作为鼠标下的泊靠点。这就是原因。他提出了以下建议:
1。可以修改VCl源码,把那句判断注释掉。
2。可以不用泊靠。自己响应Drag,Drop事件,来设置Image的位置。
但我不会,请高手们务必要拉小弟我一把。
能告诉我您成功运行的详细情况吗?我的程序是在Delphi6下编译的。
除了 ManipulateControl过程就是以下这个。procedure TForm1.RichEdit1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
ManipulateControl(RichEdit1, Shift, X, Y, 10);
end;以上方法几乎没有什么实际用途,原因如下:
1.虽然可以改变大小,但条件十分苛刻,即只有当RichEdit1.BorderStyle=bsSingle,并拖动控件左上角或右上角时。
2.几乎不能移动richedit。
我试过了,RichEdit没有问题。我建议你重新建立一个测试工程,在窗体上加入一个RichEdit,然后对它的MouseMove赋予事件:
procedure TForm1.RichEdit1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
ManipulateControl((Sender as TWinControl), Shift, X, Y, 10);
end;
RichEdit的其他属性什么都不用改,你试试^^
我也是在delphi6下编译的,一点问题都没有^^
我现在终于彻悟了。
马上结帖。hkbarton:80; zzh54zzh:15; delphizd:5