以下代码只能对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;

解决方案 »

  1.   

    var
      p : TStatusPanel;
    begin
      p := StatusBar1.Panels.Add;
      p.Text := 'asdf';
    end;
      

  2.   

    xhzok (逍遥士) 由于Image这些控件不是继承自TWinControl的,所以上面的代码当然不行,但我觉得你后面写的方法(就是把其放入panel中)是可行,解决移动问题你可以试着当点击image时候直接发送点击和拖动消息到panel来模拟,你可以试一下
      

  3.   

    hkbarton:您好!
    根据您提的思路,我采用以下方法即简单地实现了对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;
      

  4.   

    TRichEdit你直接,它是继承自TWinControl的procedure TForm1.RichEdit1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    begin
    ManipulateControl(RichEdit1, Shift, X, Y, 10);
    end;
    就可以了
      

  5.   

    hkbarton(宁静至远||淡泊明志):您好!
    此法行不通,我就是在为此伤神。现我又觅得一法,但遗憾的是会交替产生一个右上角带关闭小叉的外窗体。
    但愿是山重水复疑无路。(代码如下)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;
      

  6.   

    注: 过程 procedure ManipulateControl(WinControl: TWinControl; Shift: TShiftState; X, Y, Precision: integer); 
    中的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的位置。  
    但我不会,请高手们务必要拉小弟我一把。
      

  7.   

    不会吧,还要那么复杂,还要修改VCL的source??我昨天是在我的机子上试了才贴出来的,richedit是可以直接使用那个方法的,把你写的代码发给我算了
      

  8.   

    hkbarton:您好!
    能告诉我您成功运行的详细情况吗?我的程序是在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。
      

  9.   

    >>xhzok(逍遥士) 
    我试过了,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下编译的,一点问题都没有^^
      

  10.   

    http://www.kaer.cn/default.aspx->软件基地
      

  11.   

    各位专家:您们好!确实可以移动和改变RichEdit的大小,但比起Panel、Button等控件,你们难道不觉得费尽得多吗?
      

  12.   

    非常感谢大家。
    我现在终于彻悟了。
    马上结帖。hkbarton:80;  zzh54zzh:15;  delphizd:5