子类化思想 简单例示.doc_第1页
子类化思想 简单例示.doc_第2页
子类化思想 简单例示.doc_第3页
子类化思想 简单例示.doc_第4页
子类化思想 简单例示.doc_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

子类化思想 简单例示子类化的思想和子类继承父类的思想一样,子类化一个控件或其他东西可以加入自己想要的功能。子类化实际上并没有像C+一样重载哪个函数,而是靠拦截Windows系统中的某些消息来自己进行处理罢了比如:也许你需要一个特殊的Edit控件,只能输入数字,但是现有的Edit却并不能完成这项工作,我们可以采用子类化技术使它完成这个功能。举例来说,请大家看以下这段简单的窗口回调过程:LRESULT CALLBACK ProcMain(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) switch (Msg) case WM_CLOSE: EndDialog(hDlg, 0); break; case WM_DESTROY: PostQuitMessage(0); break; return 0;在这个回调之中,我手动处理了两个消息:在单击了“关闭”按钮(WM_CLOSE)的时候,我将对话框关闭(EndDialog);在对话框销毁(WM_DESTROY)的时候,我向系统消息队列中发送了退出的消息来完成结束工作(PostQuitMessage)。如果把WM_CLOSE的响应代码改成: case WM_CLOSE: ShowWindow(hDlg, SW_MINIMIZE); break;这样一来,这个对话框就会和好多其他软件一样,在单击了“关闭”之后,就会完成最小化的工作了。那么,对于窗口过程已定义好的系统控件,将如何手动响应它的消息呢?我们可以用函数指针的办法,将我们感兴趣的消息拦截下来,处理完之后再让预定义的窗口过程处理。这个过程大致如下:WNDPROC OldProc;OldProc = (WNDPROC)SetWindowsLong(hWnd, GWL_WNDPROC, (LONG)NewProc);当然,这里的新窗口过程NewProc是预先由你实现好的。上述代码执行以后,系统在处理hWnd的窗口消息时,就会先进入你实现的NewProc回调过程,然后在处理过你感兴趣的消息之后,通过CallWindowProc函数和你预先保存的OldProc再次回到原来的回调过程中完成剩余的工作。以上就是窗口子类化的原理分析,下面我通过一个实例来实际解说如何对窗口进行子类化。这个例子的界面如下: 界面上方的编辑框是用来限制浮点输入的,下面则是一个普通的超级链接。好了,下面我开始按步骤完成对这两个窗口的子类化:第一步,在主窗口对话框初始化的时候,保存原有的窗口过程,并设置新的窗口过程。代码如下: case WM_INITDIALOG: EditProc = (WNDPROC)SetWindowLong(GetDlgItem(hDlg, IDC_EDIT), GWL_WNDPROC, (LONG)ProcFloat); StaticProc = (WNDPROC)SetWindowLong(GetDlgItem(hDlg, IDC_ST_HOMEPAGE), GWL_WNDPROC, (LONG)ProcLink); break;第二步,实现浮点编辑框的窗口过程:LRESULT CALLBACK ProcFloat(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) if (Msg = WM_CHAR & wParam != . & (wParam = 9) & wParam != VK_BACK) MessageBeep(MB_OK); return 0; else return CallWindowProc(EditProc, hWnd, Msg, wParam, lParam);这里需要解释的是,由于控件本身的需求,所以只需要拦截一个消息,就是接收字符的WM_CHAR。当用户输入的字符不是小数点、09以及退格键(注意不要少了退格键,否则你将会发现你的编辑框无法删除输入错误的数字)的时候,就发出一声声音以提示输入错误。至于其它的消息,则调用原有的回调函数进行处理。第三步,实现超级链接的窗口过程:LRESULT CALLBACK ProcLink(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) switch (Msg) case WM_SETCURSOR: SetCursor(LoadCursor(NULL, IDC_HAND); break; case WM_LBUTTONDOWN: ShellExecute(NULL, open, /titilima, NULL, NULL, SW_SHOWNORMAL); break; default: return CallWindowProc(StaticProc, hWnd, Msg, wParam, lParam); return 0;这段代码很容易明白:它完成了两件事,其一是设置光标指针为手形(注意:对于较早的Windows系统,是没有预定义的IDC_HAND指针的,这个时候你需要在EXE的资源中自己画一个手形指针,比如Delphi之中的手形指针就是自己画的),其二是当单击了鼠标左键的时候打开你想打开的网页链接。其实对于超级链接,它更主要的东西是在子类化之外实现的就是它的字体颜色(注意这段代码是在主窗口对话框的回调过程中实现的): case WM_CTLCOLORSTATIC: if (GetDlgItem(hDlg, IDC_ST_HOMEPAGE) = (HWND)lParam) SetTextColor(HDC)wParam, 0xff0000); SetBkMode(HDC)wParam, TRANSPARENT); return (LRESULT)CreateSolidBrush(GetSysColor(COLOR_BTNFACE); break;还有几点要说明的是:1、你的这个Static超链接必须拥有一个唯一的资源ID,比如我的这个就是IDC_ST_HOMEPAGE,这样才能用GetDlgItem获得它的句柄来完成子类化;2、你必须为它设置SS_NOTIFY样式,以保证在单击它的时候它能够通知父窗口对话框;3、单击它打开网页的处理也可以放在子类化之外,处理主窗口对话框的WM_COMMAND消息也可以实现这一功能。一前言 在Widows编程中,如果我们想在窗口程序执行时改变它所包含的控件(对话框中的按钮、下拉菜单等等)的某些行为,采用窗口子类化技术是一个不错的选择。可以使用对己有控件派生子类的方式定义一个子类,而控件的消息处理则在新定义的子类里定义。适当使用子类化技术创建出容易使用的新窗口类,往往可以使你的程序界面更具人性化。 二什么是窗口子类化技术 Windows的窗口类是一个窗口模板,包含一个窗口所具有的的部分窗口属性。编写一个Windows程序时首先要做的工作就是注册一个窗口类,然后基于此注册的窗口类创建一个新的窗口。在Win32平台中,注册窗口类的API函数是RegisterClass和RegisterClassEX,其中RegisterClassEX是推荐使用的函数,使用这个函数注册窗口类时,需要先填写一个WNDCLASSEX结构。这个结构实际上反映了一个窗口类的特征,一个窗口类有本类所以窗口公用的类属性、窗口函数、类图标和小图标、类鼠标、窗口背景、类菜单,当然还有类名。除此之外,每个类还有一定大小的类存储区,可以用来存储该类的公共数据。 每一个创建的窗口都有一个窗口函数,其地址由WNDCLASSEX结构的lpfnWndProc参数设定,该窗口函数处理对应于该窗口类的所有实例消息。当创建一个窗口时,windows将分配一个内存块,用来存放,用来存放与该窗口相关的信息,并将参数lpfnWndProc从窗口类存块拷贝到该内存块中。当消息被分发到窗口时,Windows检查该窗口中内存块中的lpfnWndProc值,并调用该内存块地址上的窗口函数。 一个窗口的行为主要取决于它的窗口函数,如果能够改变一个窗口的窗口函数,使它指向自己写的某个函数,那就意味着发给这个窗口的各种消息将由我们自己写的这个函数来处理。 子类化一个窗口,实际上就是改变窗口内存块中的窗口函数的地址,使其指向用户自定义的新的窗口函数人口,以实现用户希望的窗口特性。 三窗口子类化的作用 窗口子类化技术最大的特点局势能够截取Windows的消息。一旦用户自定义的窗口函数截取了传向原窗口函数的消息,就可以对被截取的消息进行如下处理: (1)将其传给原来的窗口函数。这是对大多数消息应该采取的措施,因为子类通常只对原来的窗口特性作少量的修改。 (2)截取该消息,阻止其向原窗口函数发送。 (3)修改该消息,修改完毕以后再向原窗口函数发送。 Windows SDK提供了一下设计好多窗口类,如EDIT 、LISTBOX、TREEVIEW等。通过截取这些通用窗口类的消息,用户程序可以为他们添加新的特性,改善其外观,扩充其功能。 子类化的优点只要体现在以下两个方面:首先,它不需要创建新的窗口类,不需要了解一个窗口的创建过程。这在原来的窗口函数是由别人编写,而且在创建过程不可见的情况下非常有用;其次,子类化比较容易实现,因为所有要做的工作仅仅就是写一个窗口函数。 四窗口子类化的实现 上面介绍的子类化是从Windows本身的窗口函数概念来讲的,实际上属于SDK(Software De-velopment Kit)编程的范畴,在MFC中情况有所不同。下面将分别描述在这两种情况下窗口子类化的实现方法。 1.Visual C+中基于SDK编程的窗口子类话 Visual C+中基于SDK编程的窗口子类化的基本步骤如下: (1)正常创建原始窗口,得到窗口的句柄。 (2)调用GetWindowLong得到原来的窗口函数OldWndProc. (3)调用SetWindowLong设置新的窗口函数NewWndProc。 新的窗口函数的代码如下所示: 双击代码全选123456789LRESULT NewWndProc(HWND hWnd, UINT message , WPARAM wParam, LPARAM lParam) if message = WM_LCARELT /截取自己感兴趣的消息,作一些处理,达到改变特性的目的 /必要时可以调用原来的窗口函数,使被子类化的窗口仍具有原来的很多特性 return CallWindowProc(OldWndProc , hWnd , wParam, lParam); 值得注意的是,在调用旧的窗口函数时,不能直接调用OldWndProc(),而必须用函数Call-WndProc进行调用,否则会出现堆栈错误。 2. MFC编程中的窗口子类化 MFC窗口实际上已经是被子类化的窗口。所有的MFC窗口共享一个窗口函数,由这个窗口函数根据窗口句柄,查找这个窗口对应的CWnd派生类实例,再通过消息映射这个窗口类的消息处理函数。鉴于以上原因,在MFC中要子类化一个窗口就比较容易了,因为你的任务只是编写一个新的MFC窗口类而不需要写一个窗口函数。 假如我们现在有一个对话框,里面有一个编辑控件,如果我们只希望在该控件中接受非数字字符输入,就可以拦截WM_CHAR消息,在它的处理函数中忽略任何数字的输入。 五窗口子类化举例 MFC为广大编程者提过了汗多功能丰富的窗口类,如果在这些通用类的基础上进行子类化的话,将会给编程者带来很多便利。下面举一个例子来说明 MFC编程中的子类化是多么的简单易行。该例完成上面提到的在编辑控件只接受非数字字符输入的功能。实现这个子类化的基本步骤和相关代码如下: (1)利用AppWziard创建一个基于对话框的程序SubClass。 (2)对MFC提供的标准对话框中的控件进行修改,删除MFC提供的静态文本控件,添加自己的一个编辑控件,设置新控件的ID为IDC_EDIT。合理布置对话框上个控件的位置,使程序界面布局合理、美观。 (3)用ClassWizard从CEdit类派生一个新的窗口类,新窗口的窗口类叫CNoNumEdit。截取CNoNumEdit类的WM_CHAR消息,在OnChar函数中完成忽略任何数字的输入的处理。实现代码如下: 双击代码全选12345678910void CNoNumEdit:OnChar(UINT nChar , UINT nRepCnt , UINT nFlags) TCHAR ch = nChar; if(ch=_T(0) & chm_hWnd);(5)在对话框窗口类CSubClassDlg的OnDestroy中调用m_edit.UnSubClassWindow()执行窗口类的反子类

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论