旅途

如果想飞得高,就该把地平线忘掉

子类化窗口如何才能接收到WM_CREATE、WM_NCCREATE等消息

主  题:
子类化窗口如何才能接收到WM_CREATE、WM_NCCREATE等消息
作  者:
mopyman (only you c plus plus)
等  级:
信 誉 值:
98
所属论坛:
VC/MFC 基础类
问题点数:
100
回复次数:
18
发表时间:
2007-3-12 20:57:07








一般子类化窗口的时候是无法接收到WM_CREATE,WM_NCCREATE消息的,因为子类化的时候,已经错过了处理这些消息的时机,有什么方法可以接收到这些消息呢?


回复人:chehw(chehw) ( 两星(中级)) 信誉:110 2007-3-12 21:03:06 得分:0


?

可以使用超类化(supper class)方法。
注册一个新窗口类,新窗口的回调函数默认返回原始窗口的处理过程。

Top


回复人:mopyman(only you c plus plus) ( 三级(初级)) 信誉:98 2007-3-12 21:17:28 得分:0


?

不想超类化也不想全局子类化,有其他方法吗?
Top


回复人:bucherren() ( 一级(初级)) 信誉:99 2007-3-12 21:20:39 得分:0


?

关注,只知道超类化方法
Top


回复人:chehw(chehw) ( 两星(中级)) 信誉:110 2007-3-12 21:38:20 得分:0


?

在PreTranslateMessage或GetMessage消息循环中可以截获,但这是以牺牲性能为代价的。
超类化是最简单易行的方法。
Top


回复人:mopyman(only you c plus plus) ( 三级(初级)) 信誉:98 2007-3-13 8:37:02 得分:0


?

超类化有个缺点,必须要先建立一个窗口才可以超类化,
也就是对应每个窗口类要维护一个额外的窗口,其余的窗口才能从超类化中受益
Top


回复人:chehw(chehw) ( 两星(中级)) 信誉:110 2007-3-13 9:47:57 得分:0


?


如果直接用API, 只要得到窗口回调函数地址的函数指针就可以了,没有必要新建一个窗口。
如果是自定义的窗口类, 那么你已知这个函数的地址, 在超类的回调函数中返回就可以了.
如果是系统内置的窗口控件, 可通过GetClassInfoEx获取函数的地址。

MFC下的方法类似,
Top


回复人:mopyman(only you c plus plus) ( 三级(初级)) 信誉:98 2007-3-13 10:03:29 得分:0


?

记错了,全局子类化需要一个窗口句柄,超类化不需要
Top


回复人:mopyman(only you c plus plus) ( 三级(初级)) 信誉:98 2007-3-13 10:18:52 得分:0


?

超类化也有一个问题,当使用对话框的时候,dialog里的子窗口控制如何超类化掉?
就算在dialog创建之前,把所有用到的子窗口类型都超类化掉,dialog也不会给我们传递
每个子窗口控制的相关信息,也就无法对每个子窗口进行特化。
而如果由我们自己创建子窗口的话,可以在createwindowex中的lparam里传递一些子窗口
控制相关的数据,比如一个窗口对象this指针。
Top


回复人:chehw(chehw) ( 两星(中级)) 信誉:110 2007-3-13 10:29:33 得分:0


?

对于在资源文件中加入的控件, 只能在对话框的WM_INITDIALOG中通过
hChildWnd=GetDlgItem(hDlg, ID_xxx);
SetWindowLong(hChildWnd, GWL_USERDATA, (LONG)pData);
加入额外的数据。

如果是自己手工创建的控件,创建时就可传入必要的数据,通过超类化在WM_CREATE中将数据保存。

Top


回复人:gofqjyie(誓将天下了然于胸) ( 四级(中级)) 信誉:100 2007-3-13 10:32:53 得分:0


?

虚拟继承它,可以吗?
Top


回复人:tszzp(神奇) ( 三级(初级)) 信誉:98 2007-3-13 10:34:06 得分:0


?

你可以使用WH_CBT钩子,这样的话,你就可以收到那些消息了。
Top


回复人:mopyman(only you c plus plus) ( 三级(初级)) 信誉:98 2007-3-13 10:39:36 得分:0


?

WH_CBT钩子有一个问题,我一直不明白,就是当有窗口创建的时候,
你怎么知道就是你想要的窗口呢,也就是如果对应windows窗口句柄和c++窗口对象,
好像所有的窗口创建的时候都会被WH_CBT截获
Top


回复人:mopyman(only you c plus plus) ( 三级(初级)) 信誉:98 2007-3-13 10:45:36 得分:0


?

对于在资源文件中加入的控件, 只能在对话框的WM_INITDIALOG中通过
hChildWnd=GetDlgItem(hDlg, ID_xxx);
SetWindowLong(hChildWnd, GWL_USERDATA, (LONG)pData);
加入额外的数据。

如果是自己手工创建的控件,创建时就可传入必要的数据,通过超类化在WM_CREATE中将数据保存。
=====================================
这样一来,对话框里的子窗口控制将仍然无法获得WM_CREATE消息,
因为我想要的超类的窗口过程是个通用的,通过额外的参数来辨识是哪个窗口对象,
从而把消息先交该窗口对象处理,再调用原系统窗口过程,这样就更
hChildWnd=GetDlgItem(hDlg, ID_xxx);
SetWindowLong(hChildWnd, GWL_USERDATA, (LONG)pData);的时候已经错过了WM_CREATE消息
Top


回复人:chehw(chehw) ( 两星(中级)) 信誉:110 2007-3-13 10:51:11 得分:0


?

你需要知道父窗口的句柄和子窗口的id
LRESULT CALLBACK CBTProc( int nCode, WPARAM wParam, LPARAM lParam );
{
CBT_CREATEWND *pcc=(CBT_CREATEWND *)lParam;
if(pcc->lpcs->hwndParent==hParent && pcc->lpcs->hMenu==(HMENU)id)
{
...
}
return 0L;
}
Top


回复人:chehw(chehw) ( 两星(中级)) 信誉:110 2007-3-13 11:08:09 得分:0


?

有一个方法,但必额外创建一个窗口。如:
HWND hEdit=CreateWindowEx(0, TEXT("EDIT"), ...);
//强行将以后创建的所有edit处理过程均改为超类的窗口过程。
SetClassLong(hEdit, GCL_WNDPROC, (LONG)CMyEdit::MyEditProc);
DestroyWindow(hEdit);


Top


回复人:mopyman(only you c plus plus) ( 三级(初级)) 信誉:98 2007-3-13 12:22:21 得分:0


?

你说的这个就是全局子类化
Top


回复人:Kerrie() ( 五级(中级)) 信誉:100 2007-3-13 12:45:09 得分:0


?

这个问题是有点疙疙瘩瘩的,看你的用途了,如果仅仅是做一些初始化的处理(绘制处理如皮肤等除外),以对话框为例,可以用一些变通的方法:
1。子窗口初始化无法create消息,不过可以触发PreSubClassWnd虚函数。
2。自己创建需要截获消息的子窗口。终究不是所有的子窗口你都需要create消息的:)
3。如楼上各位所说的超类或者钩子处理了,不过个人建议如果不是皮肤等工作,还是避免处理大范围的消息为好

Top


回复人:mynamelj(风动,帆动,仁者心动) ( 两星(中级)) 信誉:105 2007-3-14 8:40:17 得分:0


?

还可以用Hook WndProc来截获
Top





管理 | 关闭窗口




网站简介 - 广告服务 - 网站地图 - 帮助信息 - 联系方式
百联美达美公司 版权所有 京ICP证020026号
Copyright ? CSDN.net, Inc. All rights reserved

posted on 2007-07-18 00:37 旅途 阅读(1423) 评论(0)  编辑 收藏 引用 所属分类: 深入windows


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理