即窗体作为一个子控件融入TPanel之类的,就像D2007的设计窗口一样,融入的窗口包含边框,标题,图标,只是标题上的关闭等按钮不起作用.截图如下: 

解决方案 »

  1.   

    是这样吗?uses
      unit2;
    procedure TForm1.Button1Click(Sender: TObject);
    var
      frm:Tform2;
    begin
      frm:=Tform2.Create(self);
      frm.Parent:=panel1;
      frm.Show;
      frm.Left:=0;
      frm.Top:=0;
      frm.Width:=panel1.ClientWidth;
      frm.Height:=panel1.ClientHeight;
    end;
    unit Unit2;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;type
      TForm2 = class(TForm)
      private
        { Private declarations }
      public
        { Public declarations }
          procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
      end;var
      Form2: TForm2;implementation{$R *.dfm}{ TForm2 }
    procedure TForm2.WMSysCommand(var Message: TWMSysCommand);
    beginend;
    end.
      

  2.   

    为便于各位调试,我把简单的demo示例写好放上来了,各位只要下载并在里面写代码验证就可以了. 
    http://bbs.2ccc.com/attachments/2008/dejoy_20081013144732.rar
      

  3.   

    你的代码不错,从外观上来看达到效果了,不过有点问题就是不能修改form2中的任何代码,原来是啥样就是啥样,不管啥样,只管融入.
    在不修改form2的基础上,莫非要用hook的方法来hook form2的WM_SYSCOMMAND消息?
      

  4.   

    yuqianyi1974 ,你的方法就是我要的,只是不能在Form2中拦截消息,所以你看在form2不做任何修改的情况下如何达到同样的效果?
      

  5.   

    用RTTI是可以修改FORM2里的代码的
      

  6.   

    这样绕一下行不? Tform3=class(Tform2)
        public
          procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
      end;
      TForm1 = class(TForm)
        Button1: TButton;
        Panel1: TPanel;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}
    procedure TForm1.Button1Click(Sender: TObject);var
      frm:Tform3;
    begin
     frm:=Tform3.Create(self);
      frm.Parent:=panel1;
      frm.Show;
      frm.Left:=0;
      frm.Top:=0;
      frm.Width:=panel1.ClientWidth;
      frm.Height:=panel1.ClientHeight;end;{ Tform3 }procedure Tform3.WMSysCommand(var Message: TWMSysCommand);
    beginend;
      

  7.   

    嗯,这个方法从理论上来说是可行的,不过如果有100 个Form,我岂不要要定义100个form的hack class?
    能否用hook Form2的消息的方法来实现,应该如何呢?
      

  8.   

    而且就如我前面所说form是不固定的,也没法用Tform3=class(Tform2)的方法来重定义一个.只能在一个TForm2的实例Form2上想办法,不能在定义上想法办法啦
    请yuqianyi1974 再研究研究
      

  9.   


    定义一个Form模板,其他的继承自它
      

  10.   

    楼主可以这样想
    Form是存在设计期和运行期两种状态的,我如果来实现这种效果的话,我有几种想法:
    1、不用Form,直接用设计器特定的窗体模仿Form,但不利于所见及所得,以及相关属性的设置
    2、使用Form,在VCL的源代码中分设计状态和运行状态,设计状态会屏蔽某些Command的消息
    3、使用Form,不屏蔽Command消息,Form上包含一个透明的窗体,用于设计器的组件控制(如拖放等)
    4、Hook消息,爱怎么处理怎么处理
      

  11.   

    研究了一下,只能屏蔽最大最小按钮,希望高手出招!var
      HookHandle: HHOOK;
      FRM:Tform2;function TestHookProc(Code: Integer; WParam: Longint;Msg:Longint): Longint;stdcall;
    begin
      result:=1;
      if wparam=frm.Handle then
          if (Code =HCBT_MINMAX) then
              exit;
      Result := CallNextHookEx(HookHandle, Code, WParam, Longint(@Msg));
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      frm:=Tform2.Create(self);
      frm.Parent:=panel1;
      frm.Show;
      HookHandle:=SetWindowsHookEx(WH_CBT ,TestHookProc,0,GetCurrentThreadId);
    end;procedure TForm1.FormDestroy(Sender: TObject);
    begin
       UnHookWindowsHookEx(HookHandle);
    end;
      

  12.   

    这样
    var
      Form1: TForm1;
      HHook: Cardinal;implementation{$R *.dfm}function HookProc(Code: Integer; WParam, LParam:Longint): Integer; stdcall;
    begin
      Result := -1;
      if (PMouseHookStruct(LParam).hwnd = Form1.Handle)
        and (PMouseHookStruct(LParam).wHitTestCode in [HTCLOSE, HTHELP, HTMENU,
          HTMAXBUTTON, HTMINBUTTON, HTSYSMENU]) then
        Exit;
      Result := CallNextHookEx(HHook, Code, WParam, LParam);
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      HHook := SetWindowsHookEx(WH_MOUSE, HookProc, 0, GetCurrentThreadId);
    end;
      

  13.   


    你说的没错,我之所以这么做,就是在设计一个类Delphi IDE的Form Designer,在D7风格及以下好办,直接设计窗体就好了,窗体本身就是设计容器;但用D2005以上风格就不好办了,因为设计时它把被设计的Form也当做一个控件来设计了,使用了另外的设计容器.你提供的Hook方式我尝试一下看可不可以.
      

  14.   

    用frame吧 
    窗体时独立显示的阿
      

  15.   

    楼上的,我对Frame了解不多,不大会用啊
      

  16.   


    function HookProc(Code: Integer; WParam, LParam:Longint): Integer; stdcall;
    begin
      Result := -1;
      if Assigned(Form2) then
      if (PMouseHookStruct(LParam).hwnd = Form2.Handle)
        and (PMouseHookStruct(LParam).wHitTestCode in [HTCLOSE, HTHELP, HTMENU,
          HTMAXBUTTON, HTMINBUTTON, HTSYSMENU]) then
        Exit;
      Result := CallNextHookEx(HHook, Code, WParam, LParam);
    end;
    可以,不过还是能移动,调整大小,而且融入的Form2上的控件鼠标操作都失效了,无法获得焦点
      

  17.   

    Form设置了Parent就行了啊,要不允许移动加上HTCAPTION,要不能改变大小加上HTBOTTOM、HTBOTTOMLEFT等
    设计时窗体要获得焦点干嘛,一般会截获窗体的鼠标动作,在窗体上绘制一个透明窗体,也就是窗体外围那个调整框,来控制窗体或者其他组件
      

  18.   

    谢 lake提供思路,的确,设计时是不需要获得焦点的,这个不用管了.
    我现在的模式是使用实现IDesignerHook接口,赋值给Form.designer.
    对你提议的"在窗体上绘制一个透明窗体,也就是窗体外围那个调整框,来控制窗体或者其他组件"这个方式,我不太了解,能详解下么
      

  19.   

    类似的,在Delphi7设计器中那些控件调整位置的大小的把手实际上是TGrabHandle类型的窗体,它其他部分都是透明的,只绘制了几个调整用的小黑框而已。
    譬如说操作控件就是:
    1、Hook住所有的鼠标事件,在鼠标单击时判断位置,查找该位置的控件。
    2、创建TGrabHandle窗体,设置该窗体的大小为比控件大小大点的面积,并将其移动至控件的上层。
    3、读取控件的所有公开属性及事件,并显示在属性栏。
    4、用户可以在TGrabHandle窗体上拖拽调整TGrabHandle和控件的位置,可以在TGrabHandle的边缘调整TGrabHandle和控件的大小。
    控件可以是Form,也可以是其他东西,不知道你要的是不是这样的效果?
      

  20.   

    一个办法是用一个无边框的透明窗口,遮盖住下面的设计窗口,透明窗口resize时,使被遮盖住的设计窗口跟着一起resize,
    往透明窗口拖放控件时,创建另一个无边框透明子窗口,同时在设计窗口相同位置创建控件
    不过这种办法会导致内存里同时有两份窗体,属于偷懒的做法另一个办法是,设计窗口不用TForm,要研究一下底层“画”窗口的方法,在设计界面中,把窗口画出来,而不给画出来窗口指定消息处理
      

  21.   

    调整大小的手柄大小的TGrabHandle我已经做好了,现在是卡在了把一个窗体作为子控件设计时上(普通的已经完成),想模拟BDS风格及Borland风格,Borland风格已经完成,卡在BDS风格上了.
    Borland风格:
    BDS风格:
      

  22.   

    对Form操作有区别么?我试了下没什么区别啊。
    不过我因为没有Hook,只是用的OnMessage,所以点标题栏没法选中窗体。
      

  23.   

    .net风格时,窗体作为嵌入已解决,但作为独立设计窗体时还没法做到像D2007 Form designer一样
    另设计非窗体的控件如panel时,无法显示背景网格.
    希望各位给些建议和思路.
    示例EXE 
    http://www.rayfile.com/files/fd142297-9d22-11dd-946b-0014221b798a/
      

  24.   

    作为独立设计窗体时:
    为什么不可以在Designer模式下忽略这个属性?让它都是嵌入的,等到运行时才成为独立的。是不是你都是用的Framework的设计器提供的站点接口,而它不是这样做的?非窗体的控件如panel时,无法显示背景网格:
    1、计算容器的位置和大小,直接在屏幕DC上绘制,试试可行不?
    2、钩挂WM_ERASEBKGND或者WM_PAINT,根据其Hanlde得到WindowRect和HDC,然后给它绘网格。
      

  25.   

    作为独立设计窗体时: 
    为什么不可以在Designer模式下忽略这个属性?让它都是嵌入的,等到运行时才成为独立的。是不是你都是用的Framework的设计器提供的站点接口,而它不是这样做的? 
    >>的确,Delphi本身的IDesignerHook都是只支持窗体作为独立设计,是不支持像D2007那样嵌入式设计的,D7以下的版本就是独立式设计的,但D2005以上却又是嵌入式设计,不知Borland自己是怎么实现的,这有点让我迷惑.非窗体的控件如panel时,无法显示背景网格: 
    1、计算容器的位置和大小,直接在屏幕DC上绘制,试试可行不? 
    >>直接在Screen DC上绘制,这个方法我尝试过了,结果把容器上面的控件也覆盖了.
    2、钩挂WM_ERASEBKGND或者WM_PAINT,根据其Hanlde得到WindowRect和HDC,然后给它绘网格。
    >>这个方法我想也应该是唯一可行的了,我再尝试此方法....谢lake提供的思路