Subclassing 笔记

    window class中最重要的是他的lpfnWndProc,他处理由该类别产生的窗口的所有信息。在RegisterClassEx返回之前,系统配置一块内存来记录这个类别的相关信息,包括lpfnWndProc的值.注意是系统完成的!!!

   每当我们的程序用这个类别产生新的窗口,系统又会配置有新的窗口的内存块,用来存放与窗口相关的信息.其中也包括窗口处理函数WndProc的地址,而他是由系统从window class中复制过来的.当任何信息被分配到WndProc时,系统根据  窗口的内存块中的WndProc地址来调用窗口函数,而不是类别中的lpfnWndProc.类别中的那个只是用来做复制用的.

   为了subclassing一个窗口,必须改变窗口的内存块中的窗口函数地址,使他指向一个新的函数地址.但是他不会影响到别的从同一个类别中产生的窗口,因为只是改变了这个类别的其中一个实例的窗口处理地址,而不是改变的是这个类别中的lpfnWndProc.其中用来代替原来的窗口函数的新的函数必须和原来的函数的形式是一样的,也就是标准的窗口函数的样子
LRESULT WINAPI SubClassWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);

    一旦你改变了原来的窗口函数的地址用了新的代替,你可能要做下面的动作:
1.原封不动的调用原来的那个窗口函数。
2.限制只有某些消息可以传入原来的窗口函数.例如,你希望edit控件停止接受数字,你必须处理WM_CHAR,检验(wParam)看看否有0-9之间的数字.如果是,什么也不做就立即返回,如果不是,就将消息传给愿函数。
3.修改某个消息,然后继续传给原来的窗口处理函数。如果你希望combobox只接受大写字母,你应该处理每一个WM_CHAR,将wParam转换为大写(使用CharUpper函数),然后再将它传给原来的窗口处理函数.

    其实要对某个窗口做subclassing,只要取得原来的窗口处理函数代码,并用自己的代替
SubclassWindow宏可以做到,并返回原来的窗口函数地址,这个原来的窗口函数地址,要在新的窗口处理函数中使用,而SubclassWindow在另一个函数中调用,那么两个函数之间的变量是不可见得,除非将这个放原来的窗口函数的变量,声明成文件作用域,不然就使用hwnd的属性,因为,在win32中hwnd基本上都是,在不同函数间传来传去的,那么具体做法:

在调用subclassing的函数中
   SetProp(hwndEdit,"原来的窗口处理函数地址",(HANDLE)(DWORD)pfnWndProcOrg);

在新的窗口处理函数中
  CallWindowProc(
            (WNDPROC)(DWORD)GetProp(hwnd,"原来的窗口处理函数地址"),
            hwnd,uMsg,wParam,lParam);

     注意subclassing 只能在同一进程中使用,如果想在两个进程间使用,那么,看Advance Windows Breaking Through Process Boundary Walls

    其实窗口中有很多方法可以将附加信息放入,如GWL_USERDATA,窗口的属性,和额外元,使用他们都可以在函数与函数间传递变量!!


subclass通常用于由系统注册的window class 产生的窗口,那么由于是系统注册了window class,使得我们无法控制这个类别中的 类别额外字段和窗口额外字段.并且subclassing 的先决条件是必须有窗口存在.所以将一些信息和一个subclassed 窗口关联在一起,象刚才使原来的pfnWndProc和hwnd关联,使用窗口的properties是最好的方法,不过也可以使用GWL_USERDATA来存放一些信息,但是不是好方法,可能那个已经被系统用过了.

下面是Subclassing 的例子

线路:
Subclassing---New window procedure---message handle---Call old window procedure

 

NoDigitsCls.cpp
// 调用WndProc的函数
BOOL WINAPI NoDigitsClass_ConvertEdit(HWND hwndEdit,BOOL fSubclass)
{
 BOOL fOk 
= FALSE;

 
if(fSubclass)
 
{
  fOk 
= SetProp(hwndEdit,g_szNoDigitsClassWndProcOrg,
   (HANDLE)(DWORD)SubclassWindow(hwndEdit,NoDigitsClass_WndProc)); 
 }

 
else{
  WNDPROC wp 
= (WNDPROC)(DWORD)
   RemoveProp(hwndEdit,g_szNoDigitsClassWndProcOrg);
  SubclassWindow(hwndEdit,wp);
  fOk 
= (wp != NULL);
 }

 
return(fOk);
}


// 新的WndProc
LRESULT WINAPI NoDigitsClass_WndProc(HWND hwndEdit,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
//处理一部分信息
 switch(uMsg)
 
{
  HANDLE_MSG(hwndEdit,WM_CHAR,NoDigitsClass_OnChar);
 }

//调用原来消息处理器
 return(NoDigitsClass_CallOrigWndProc(hwndEdit,uMsg,wParam,lParam));
}


// OnChar处理器
void  NoDigitsClass_OnChar(HWND hwndEdit,TCHAR ch, int  cRepeat)
{
 
if(adgINRANGE(__TEXT('0'),ch,__TEXT('9')))
 
{
  MessageBeep(
0);
 }

 
else
 
{       //是字符,调用原来消息处理器
  FORWARD_WM_CHAR(hwndEdit,ch,cRepeat,NoDigitsClass_CallOrigWndProc);
 }

}


// 如果在FORWARD_* 使用 CallWindowProc,那么会错误,因为FORWARD_*的最后一个参数支持的是标准消息处理器,所以定义NoDigitsClass_CallOrigWndProc,在他中调用CallWindowProc

LRESULT NoDigitsClass_CallOrigWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
 
return(CallWindowProc((WNDPROC)(DWORD) GetProp(hwnd,g_szNoDigitsClassWndProcOrg),
  hwnd,uMsg,wParam,lParam));
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值