如能仔细看一下我的问题,给些建议,小弟不胜感激背景是:现在要做一个图形控件Tshapex,继承自TgraphicControl,要处理在运行期控制这个控件的对象,比如拖动,改变大小等操作,所以动态创建一个panel,希望可以在panel的paint函数中把控件画到panel上,这样利用panel的一些move,resize函数,拖动panel的时候,实现拖动控件的效果。
问题是:如何把这个tshapex的对象画到panel的canvas上去。
注:1.继承自Twincontrol的控件,有个Twincontrl(Fcontrol).paintto(canvas.handle,x,y),就可以把控件画到panel.canvas上去了。Tgraphiccontrol没有paintto方法。
    2.有个canvas.draw(x,y,Graphic)方法,在canvas上画Graphic对象,如果用这个方法的话,我的控件继承TGraphic行不行?能做成可视化的控件么?
   3.canvas有个copyrect的方法,可以把指定区域的图形copy到panel的canvas上,这样的话需要先在窗体上画出一个图形,供copy,这样的话,为了实现对控件的操作,需要先在窗体上画一个控件。用这样的方法可以让这个参考的控件不显示出来了么?

解决方案 »

  1.   

    还有一种可能,自定义的图形控件可以继承Twincontrol么?
      

  2.   

    graphicControl控件也可以拖动,改变大小,为什么要放到tpanel上?
      

  3.   

    panel一些继承自Twincontrol的消息函数,可以做一些选中,修改的操作
      

  4.   

    还是不太明白你的意思,不过graphicControl有canvas属性,不过是protected,你可以继承后public
      

  5.   

    做一个类似于cad的程序,运行的时候可以拖动控件(比如直线)
    我觉得他们是把一些对象(直线)画在一个panel上,拖动的这个panel。
      

  6.   

    肯定不是这样的,要是有10000条线,就的创建10000个Tpanel多浪费资源!
      

  7.   

    用TgraphicControl还可以,用Twintronl太浪费内存了
      

  8.   

    你是不是想实现一个可以在运行期可以拖动,改变大小的控件啊.
    可以从 TgraphicControl继承,通过判断鼠标位置来确定是拖动还是改变大小不.
    在拖支的时候 是先按下然后鼠标移动,在弹起. 在这个过程中通过控件 left top 来实现移动在控件的周围绘制8个小方块,通过鼠标位置来确定是否是改变大小.但如果你是想做一个绘图程序,不建议你将绘制的每个元素都控件化.
      

  9.   

    Tshapex中Paint事件中完成自己画自己。
    作画时的宽高就是TshapexTPanel中放入Tshapex对象,Tshapex.align属性为alcient,调整大小时需要使Tshapex重画。
      

  10.   

    我这里有一个运行期拖拉Delphi VCL组件的类使用方法,在使用前用OnEnter绑定就行了你的组件.OnEnter := TDdhSizerControlEx.SizerControlEnter;
    unit DdhSizerExU;interfaceuses
      Classes,SysUtils, Windows, Messages, Controls, StdCtrls,typinfo,Dialogs;const
      sc_DragMove: Longint = $F012;type
      TDdhSizerControlEx = class (TCustomControl)
      private
        FOnChange: TNotifyEvent;
        FOnSelected: TNotifyEvent;
        FControl: TControl;
        FOldControl: TControl;
        FRectList: array [1..8] of TRect;
        FPosList: array [1..8] of Integer;
        procedure KeyUp(var Key: Word; Shift: TShiftState); override;
        procedure SetControl(const Value: TControl);
        procedure SetOnChange(const Value: TNotifyEvent);
        procedure DoEventChange;
        procedure SetOnSelected(const Value: TNotifyEvent);
      protected
        procedure CreateParams (var Params: TCreateParams); override;
        procedure CreateHandle; override;
        procedure WmNcHitTest (var Msg: TWmNcHitTest); message WM_NcHitTest;
        procedure WmSize (var Msg: TWmSize); message WM_Size;
        procedure WmLButtonDown (var Msg: TWmLButtonDown); message WM_LButtonDown;
        procedure WmMove (var Msg: TWmMove); message WM_Move;
        procedure Paint; override;
        procedure SizerControlExit(Sender: TObject);
      public
        constructor Create(AOwner: TComponent);
        destructor Destroy; override;
        procedure DeleteControl;
        procedure SetValue(sName: String;Value: Integer);overload;
        procedure SetValue(sName: String;Value: String); overload;
        property Control: TControl read FControl write SetControl;
        property OnChange: TNotifyEvent read FOnChange write SetOnChange;
        property OnSelected: TNotifyEvent read FOnSelected write SetOnSelected;    class procedure SizerControlEnter(Sender: TObject);
      end;  function DdhSizerControlEx: TDdhSizerControlEx;
      procedure FreeDdhSizerControlEx;implementationuses
      Graphics;
    var
      ADdh: TDdhSizerControlEx = nil;
      // TDdhSizerControl methods  function DdhSizerControlEx: TDdhSizerControlEx;
      begin
        if not Assigned(ADdh) then
        ADdh := TDdhSizerControlEx.Create(nil);
        Result := ADdh;
      end;
      procedure FreeDdhSizerControlEx;
      begin
        if Assigned(ADdh) then
        ADdh.Free;
        ADdh := nil;
      end;
    constructor TDdhSizerControlEx.Create (AOwner: TComponent);
    begin
      inherited Create (AOwner);
    end;procedure TDdhSizerControlEx.CreateHandle;
    begin
      inherited CreateHandle;
    end;procedure TDdhSizerControlEx.CreateParams (var Params: TCreateParams);
    begin
      inherited CreateParams(Params);
      Params.ExStyle := Params.ExStyle +  WS_EX_TRANSPARENT;
    end;procedure TDdhSizerControlEx.Paint;
    var
      I: Integer;
    begin
        if Focused then
        begin
          Canvas.Brush.Color := clBlack;
          for I := 1 to  8 do
          Canvas.Rectangle (FRectList [I].Left, FRectList [I].Top,
          FRectList [I].Right, FRectList [I].Bottom);
        end
    end;procedure TDdhSizerControlEx.WmNcHitTest(var Msg: TWmNcHitTest);
    var
      Pt: TPoint;
      I: Integer;
    begin
      Pt := Point (Msg.XPos, Msg.YPos);
      Pt := ScreenToClient (Pt);
      Msg.Result := 0;
      for I := 1 to  8 do
        if PtInRect (FRectList [I], Pt) then
          Msg.Result := FPosList [I];
      // if the return value was not set
      if Msg.Result = 0 then
        inherited;
      if FOldControl <> FControl then
      begin
        FOldControl := FControl;
        //ShowMessage(FControl.Name);
        if Assigned(FOnSelected) then
        FOnSelected(FControl);
      end;
    end;procedure TDdhSizerControlEx.WmSize (var Msg: TWmSize);
    var
      R: TRect;
    begin
      R := BoundsRect;
      InflateRect (R, -2, -2);
      FControl.BoundsRect := R;
      // setup data structures
      FRectList [1] := Rect (0, 0, 5, 5);
      FRectList [2] := Rect (Width div 2 - 3, 0, Width div 2 + 2, 5);
      FRectList [3] := Rect (Width - 5, 0, Width, 5);
      FRectList [4] := Rect (Width - 5, Height div 2 - 3, Width, Height div 2 + 2);
      FRectList [5] := Rect (Width - 5, Height - 5,Width, Height);
      FRectList [6] := Rect (Width div 2 - 3, Height - 5,Width div 2 + 2, Height);
      FRectList [7] := Rect (0, Height - 5, 5, Height);
      FRectList [8] := Rect (0, Height div 2 - 3, 5, Height div 2 + 2);
      DoEventChange;
    end;procedure TDdhSizerControlEx.SizerControlExit (Sender: TObject);
    begin
        Hide;
    end;procedure TDdhSizerControlEx.WmLButtonDown (var Msg: TWmLButtonDown);
    begin
      Perform(wm_SysCommand, sc_DragMove, 0);
    end;procedure TDdhSizerControlEx.WmMove (var Msg: TWmMove);
    var
      R: TRect;
    begin
      R := BoundsRect;
      InflateRect (R, -2, -2);
      FControl.Invalidate; // repaint entire surface
      FControl.BoundsRect := R;
      DoEventChange;
    end;
    class procedure TDdhSizerControlEx.SizerControlEnter(Sender: TObject);
    begin
        if (Sender as TControl).Parent.Tag = 832 then
        DdhSizerControlEx.Control := Sender as TControl;
    end;procedure TDdhSizerControlEx.KeyUp(var Key: Word; Shift: TShiftState);
    begin
      if (Key = VK_DELETE) then
      begin
        DeleteControl;
      end;
    end;destructor TDdhSizerControlEx.Destroy;
    begin
      FControl := nil;
      inherited;
    end;procedure TDdhSizerControlEx.SetControl(const Value: TControl);
    var
      R: TRect;
    begin
        if Assigned(Value) then
        begin
            FControl := Value;
            // install the new handler
            // set the size and position
            R := FControl.BoundsRect;
            InflateRect (R, 2, 2);
            BoundsRect := R;
            // set the parent
            Parent := FControl.Parent;
            // create the list of positions
            FPosList [1] := htTopLeft;
            FPosList [2] := htTop;
            FPosList [3] := htTopRight;
            FPosList [4] := htRight;
            FPosList [5] := htBottomRight;
            FPosList [6] := htBottom;
            FPosList [7] := htBottomLeft;
            FPosList [8] := htLeft;         Visible := True;
             BringWindowToTop((FControl as TWinControl).Handle);
             BringWindowToTop(Self.Handle);
             if GetAsyncKeyState(VK_LButton) <> 0  then
            begin
               Perform(wm_SysCommand, sc_DragMove, 0);
            end
            else
            begin
            end;
            SetFocus;
            Paint;
        end;
    end;procedure TDdhSizerControlEx.SetOnChange(const Value: TNotifyEvent);
    begin
       FOnChange := Value;
    end;procedure TDdhSizerControlEx.DoEventChange;
    begin
      if Assigned(FOnChange) then
      try
        FOnChange(Self);
      except
      end;
    end;procedure TDdhSizerControlEx.DeleteControl;
    begin
            Hide;
            if Assigned(FControl) then
            begin
                (FControl as TWinControl).Visible := False;
                (FControl as TWinControl).Destroy;
                FControl := nil;
                DoEventChange;
            end;
    end;procedure TDdhSizerControlEx.SetValue(sName: String; Value: Integer);
    begin
        if Assigned(FControl) then
        begin
            if GetPropInfo(FControl,sName) <> nil then
            SetOrdProp(FControl,sName,Value);        SetControl(FControl);
        end;
    end;procedure TDdhSizerControlEx.SetValue(sName, Value: String);
    var
      pinfo: PPropInfo;
      iValue: Integer;
    begin
        if Assigned(FControl) then
        begin
            pinfo := GetPropInfo(FControl,sName);
            if pinfo <> nil then
            if pinfo^.PropType^^.Kind in [tkInteger] then
            begin
                Value := '0' + Value;
                try
                    iValue := StrToInt(Value);
                    SetOrdProp(FControl,sName,iValue);
                finally
                end;
            end
            else
            SetStrProp(FControl,sName,Value);        SetControl(FControl);
        end;
    end;procedure TDdhSizerControlEx.SetOnSelected(const Value: TNotifyEvent);
    begin
      FOnSelected := Value;
    end;end.
      

  11.   

    to lake_cx
     我用了你的控件,非常好用。有一个小问题在粘帖一个控件的时候,弹出错误 “class TWincontrol not found”,不知道什么原因?
      

  12.   

    你需要操作的控件,在用程序初始化的时候用RegisterClass都注册一遍