研究了一下,只能屏蔽最大最小按钮,希望高手出招!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;
这样 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;
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上的控件鼠标操作都失效了,无法获得焦点
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.
http://bbs.2ccc.com/attachments/2008/dejoy_20081013144732.rar
在不修改form2的基础上,莫非要用hook的方法来hook form2的WM_SYSCOMMAND消息?
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;
能否用hook Form2的消息的方法来实现,应该如何呢?
请yuqianyi1974 再研究研究
定义一个Form模板,其他的继承自它
Form是存在设计期和运行期两种状态的,我如果来实现这种效果的话,我有几种想法:
1、不用Form,直接用设计器特定的窗体模仿Form,但不利于所见及所得,以及相关属性的设置
2、使用Form,在VCL的源代码中分设计状态和运行状态,设计状态会屏蔽某些Command的消息
3、使用Form,不屏蔽Command消息,Form上包含一个透明的窗体,用于设计器的组件控制(如拖放等)
4、Hook消息,爱怎么处理怎么处理
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;
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;
你说的没错,我之所以这么做,就是在设计一个类Delphi IDE的Form Designer,在D7风格及以下好办,直接设计窗体就好了,窗体本身就是设计容器;但用D2005以上风格就不好办了,因为设计时它把被设计的Form也当做一个控件来设计了,使用了另外的设计容器.你提供的Hook方式我尝试一下看可不可以.
窗体时独立显示的阿
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上的控件鼠标操作都失效了,无法获得焦点
设计时窗体要获得焦点干嘛,一般会截获窗体的鼠标动作,在窗体上绘制一个透明窗体,也就是窗体外围那个调整框,来控制窗体或者其他组件
我现在的模式是使用实现IDesignerHook接口,赋值给Form.designer.
对你提议的"在窗体上绘制一个透明窗体,也就是窗体外围那个调整框,来控制窗体或者其他组件"这个方式,我不太了解,能详解下么
譬如说操作控件就是:
1、Hook住所有的鼠标事件,在鼠标单击时判断位置,查找该位置的控件。
2、创建TGrabHandle窗体,设置该窗体的大小为比控件大小大点的面积,并将其移动至控件的上层。
3、读取控件的所有公开属性及事件,并显示在属性栏。
4、用户可以在TGrabHandle窗体上拖拽调整TGrabHandle和控件的位置,可以在TGrabHandle的边缘调整TGrabHandle和控件的大小。
控件可以是Form,也可以是其他东西,不知道你要的是不是这样的效果?
往透明窗口拖放控件时,创建另一个无边框透明子窗口,同时在设计窗口相同位置创建控件
不过这种办法会导致内存里同时有两份窗体,属于偷懒的做法另一个办法是,设计窗口不用TForm,要研究一下底层“画”窗口的方法,在设计界面中,把窗口画出来,而不给画出来窗口指定消息处理
Borland风格:
BDS风格:
不过我因为没有Hook,只是用的OnMessage,所以点标题栏没法选中窗体。
另设计非窗体的控件如panel时,无法显示背景网格.
希望各位给些建议和思路.
示例EXE
http://www.rayfile.com/files/fd142297-9d22-11dd-946b-0014221b798a/
为什么不可以在Designer模式下忽略这个属性?让它都是嵌入的,等到运行时才成为独立的。是不是你都是用的Framework的设计器提供的站点接口,而它不是这样做的?非窗体的控件如panel时,无法显示背景网格:
1、计算容器的位置和大小,直接在屏幕DC上绘制,试试可行不?
2、钩挂WM_ERASEBKGND或者WM_PAINT,根据其Hanlde得到WindowRect和HDC,然后给它绘网格。
为什么不可以在Designer模式下忽略这个属性?让它都是嵌入的,等到运行时才成为独立的。是不是你都是用的Framework的设计器提供的站点接口,而它不是这样做的?
>>的确,Delphi本身的IDesignerHook都是只支持窗体作为独立设计,是不支持像D2007那样嵌入式设计的,D7以下的版本就是独立式设计的,但D2005以上却又是嵌入式设计,不知Borland自己是怎么实现的,这有点让我迷惑.非窗体的控件如panel时,无法显示背景网格:
1、计算容器的位置和大小,直接在屏幕DC上绘制,试试可行不?
>>直接在Screen DC上绘制,这个方法我尝试过了,结果把容器上面的控件也覆盖了.
2、钩挂WM_ERASEBKGND或者WM_PAINT,根据其Hanlde得到WindowRect和HDC,然后给它绘网格。
>>这个方法我想也应该是唯一可行的了,我再尝试此方法....谢lake提供的思路