MFC编程案例chapter010.pdf
《MFC编程案例chapter010.pdf》由会员分享,可在线阅读,更多相关《MFC编程案例chapter010.pdf(17页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、下载下载第10章 控 件 窗 口控件窗口是允许用户与应用程序进行交互的按钮、列表框和滚动条。当一个对话框被创建时,用对话框编辑器定义的控件窗口也被创建,然而一些控件窗口可能要求在运行时填充它们,如组合框。此外,一些控件窗口不能在资源模板中被创建。有关可用的控件窗口的讨论,以及使用它们的例子参见附录 A,本章中的例子讨论怎样动态地创建和填充控件窗口。例46 在任意位置创建一个控件窗口讨论怎样在任意位置创建一个控件窗口,这里强调在“任意位置”。例47 用子分类定制一个通用控件窗口讨论通过使用子分类让类控制一个控件窗口的方法,子分类在第三章中已有详细描述。例48 用超分类定制一个通用控件窗口讨论通过
2、使用超分类让类控制一个控件窗口的方法,超分类在第3章中也有详细描述。例49 在按钮上放置位图放弃按钮上常用的文本,而使用位图图像。例50 动态填充一个组合框讨论一种显示最新信息的方法,通过用户打开组合框时填充它来实现。例51 排序一个列表控件讨论用户单击一个列表控件的标题时,怎样通过调整该标题所在列作出反应。例52 分割线控件最后将讨论怎样在一个对话框中创建一条蚀刻线,该线不用自己绘制。10.1 例46 在任意位置创建一个控件窗口目标在任意位置创建一个控件窗口(见图1 0-1)。图10-1 把一个按钮控件放置到一个视图中或任意位置策略每个控件窗口,如一个按钮或一个编辑框,只是一个特殊的子窗口。
3、它可以在用户界面的任意位置被打开,也可以传送到任何其他窗口。通常,打开一个对话框时,M F C处理打开控件窗口的繁琐工作。然而,可以用两个步骤手工打开控件窗口,首先,通过创建一个M F C该按钮在视图中创建,而没有一个对话框,当被单击时,它直接发送命令到视图窗口第10章 控 件 窗 口183下载控件类的实例,如C B u t t o n,封装该控件;第二步,通过调用那个类的 Create()成员函数,真正打开控件窗口。步骤1.创建M F C控件类的一个实例确定要创建的控件类型(如按钮、编辑框等),然后确定封装该控件的M F C类(如C B u t t o n封装一个按钮控件窗口),有关例子参见
4、附录 A。然后把那个类插入到计划用来打开该控件的类中。本例中把C B u t t o n类插入到一个对话类中。p r i v a t e:CButton m_ctrlButton;2.创建控件窗口1)用C l a s s Wi z a r d,为已插入M F C控件类的对话框添加一个 W M _ C R E AT E消息处理函数,或者一个W M _ I N I T D I A L O G消息处理函数。在 OnCreate()消息处理函数中,调用控件类的Create()成员函数,并赋予它风格、扩展风格、标题(如果有的话)、物主窗口、控件I D、大小和位置。创建一个控件需要提供的项可以随控件类的不
5、同而改变,风格也改变,参见附录 A。本例创建按钮控件窗口。CRect rect(20,20,100,50);m _ c t r l B u t t o n.C r e a t e(W z d&1,WS_CHILD|WS_VISIBLE,rect,this,I D C _ W Z D _ C O N T R O L);2)当一个对话框创建一个对话框模板中的控件时,它的任务不仅仅是创建该控件窗口,例如一个对话框还要设置每个控件窗口的字体。这里,为按钮控件设置字体,该按钮控件具有3-D窗口风格。CFont*pFont=CFont:FromHandle(H F O N T):G e t S t o c
6、 k O b j e c t(A N S I _ VA R _ F O N T);m _ c t r l B u t t o n.S e t F o n t(p F o n t);说明前面已讨论创建任何一个控件窗口需要分两步进行:第一,创建 M F C控件类的一个实例;第二,调用它的Create()成员函数以创建真正的窗口。删除一个 M F C类和控件窗口可能比较复杂。如果 M F C类的实例被销毁,它将自动销毁它的控件窗口。然而,如果控件窗口先被销毁,则操作系统不知道是 M F C控件窗口类创建了它,这需要手工销毁该M F C控件类。在这种情况下,问题也不大,因为 M F C类被插入到另一个
7、类中,当对话框被关闭时,该类会自动销毁它。参见第 1章有关该主题的详细内容。有关用C l a s s Wi z a r d添加一个消息处理函数的例子参见例 1 3。CD说明在C D上执行该工程时,可以看到一个按钮控件显示在视图的中央。10.2 例47 用子分类定制一个通用控件窗口目标通过子分类,添加功能到一个已有的通用控件。184第二部分 用户界面实例下载策略像按钮和编辑框一样,控件窗口通常用它们具有的系统提供的窗口过程维护它们,即使用M F C控件类创建一个控件,如C B u t t o n,也由系统提供的功能处理那个控件窗口的所有消息。子分类是一个过程,它通过在窗口对象中,用窗口过程的地址
8、替换原有的窗口对象地址,允许切入控件窗口和它的原始窗口过程间的消息流。如果一个需要用原始窗口过程处理的消息到来,诸如绘制该控件,则把它传递到原始窗口过程地址。否则,可以用新的令人兴奋的方式处理消息,还好,M F C用C W n d:S u b c l a s s Window()减少子分类一个窗口的许多繁琐工作。如果在对话框中为一个控件创建一个控件成员变量,甚至可以不用 S u b c l a s s Window()当对话框进行数据交换时,它可以被自动调用。要子分类控件窗口,首先创建一个M F C控件类的派生类,然后直接或间接地通过DoDataExchange(),用S u b c l a
9、s s Window()把派生类的消息映像插入一个控件窗口和它的原始窗口过程间的消息流中。现在可以在该派生类中方便安全地处理消息,传送它们或者处理其中的一部分并传送其余消息。有关该主题的详细内容参见第 3章。步骤1.创建一个从M F C控件类派生的新控件类1)用C l a s s Wi z a r d创建一个从诸多控件类中派生的新类,本例中,从 C E d i t派生C W z d E d i t,从C C o m b o B o x派生C W z d C o m b o B o x。2)用C l a s s Wi z a r d为想要在控件窗口和它的原始窗口过程间截获的消息添加一个消息处理函
10、数。如果需要子分类的控件在一个对话框中,可以用 C l a s s Wi z a r d添加一个C o n t r o l类型的成员变量到对话框类中,它可以自动地子分类一个控件窗口,这可以在下面看到。2.用C l a s s Wi z a r d子分类一个控件1)打开C l a s s Wi z a r d并选择合适的对话框类,然后选择 Member Va r i a b l e s标签页,找到并选择需要子分类的控件的控件 I D,从可用的成员变量类型列表中选择 C o n t r o l。本例中,添加了编辑和组合框控件成员变量,它使得 C l a s s Wi z a r d添加下面的代码行
11、到那个类的.h文件中。/A F X _ D ATA(C W z d D i a l o g)enum IDD=IDD_WZD_DIALOG;CEdit m_ctrlEdit;CComboBox m_ctrlComboBox;/A F X _ D ATA2)把这些定义放到 括弧下面,以便C l a s s Wi z a r d不能改变它,以及把这些标准M F C类名改变为新的派生的类名。/A F X _ D ATA(C W z d D i a l o g)enum IDD=IDD_WZD_DIALOG;/A F X _ D ATACWzdEdit m_ctrlEdit;CWzdComboBox
12、m_ctrlComboBox;m_hWnd,className,8);/if the class name is Edit,weve found our controlif(!stricmp(Edit,className)/subclass as beforem _ c t r l C o m b o E d i t B o x.S u b c l a s s Wi n d o w(p W n d-m _ h W n d);while(pWnd=pWnd-GetWi n d o w(G W _ H W N D N E X T);在这里可以看到,一旦编辑框控件窗口被找到,可以用前面的方法子分类它
13、。2)如果使用组合窗的下拉风格,只有在列表框被下拉时,才能找到它的列表框窗口部分;一旦被下拉,可以用前面的方法子分类它。说明控件具有绘制自身和接收消息的所有功能,但却不能轻易修改它们。这就是说,除非创建者有远见,正好提供合适的窗口风格,或提供正好要控制的控件通知。否则,子分类一个控件窗口,通过能够真正地监视控件消息并有选择性地处理其中的一些消息,可以提供更多的控制能力。如果不喜欢控件的外观,截住它的W M _ PA I N T消息,并亲自为它绘制一个。如果一个控件没有你需要的或关心的通知消息现在,通过子分类可以访问它的所有消息。第10章 控 件 窗 口185下载CD说明在C D上执行该工程时,
14、单击 Te s t/W z d命令以打开一个对话框,可以看到这些对话控件都有一个阴影背景,并通过按下上下箭头键在这些控件间移动。清单编辑类#if!defined(AFX_WZDEDIT_H_1EC84996_C589_11 D 1 _ 9 B 5 C _ 0 0 A A 0 0 3 D 8 6 9 5 _ _ I N C L U D E D _)#define AFX_WZDEDIT_H_1EC84996_C589_11 D 1 _ 9 B 5 C _ 0 0 A A 0 0 3 D 8 6 9 5 _ _ I N C L U D E D _#if _MSC_VER=1000#pragma o
15、nce#endif/_MSC_VER=1000/WzdEdit.h:header file/CWzdEdit windowclass CWzdEdit:public CEdit/Constructionp u b l i c:C W z d E d i t();/Attributesp u b l i c:/Operationsp u b l i c:/Overrides/ClassWizard generated virtual function overrides/A F X _ V I RT U A L(C W z d E d i t)p u b l i c:virtual BOOL P
16、reTranslateMessage(MSG*pMsg);/A F X _ V I RT U A L/Implementationp u b l i c:virtual CWzdEdit();/Generated message map functionsp r o t e c t e d:/A F X _ M S G(C W z d E d i t)afx_msg HBRUSH CtlColor(CDC*pDC,UINT nCtlColor);/A F X _ M S G186第二部分 用户界面实例下载第10章 控 件 窗 口187下载D E C L A R E _ M E S S A G
17、E _ M A P()p r i v a t e:CBrush m_brush;/A F X _ I N S E RT _ L O C AT I O N /Microsoft Developer Studio will insert additional declarations immediately/before the previous line.#endif/!defined(A F X _ W Z D E D I T _ H _ _ 1 E C 8 4 9 9 6 _ C 5 8 9 _ 11 D 1 _ 9 B 5 C _ 0 0 A A 0 0 3 D 8 6 9 5 _ _ I
18、 N C L U D E D _)/WzdEdit.cpp:implementation file/#include stdafx.h#include wzd.h#include WzdEdit.h#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE=_FILE_;#e n d i f/CWzdEditC W z d E d i t:C W z d E d i t()m_brush.CreateHatchBrush(HS_BDIAGONAL,RGB(0,255,0);C W z d E d i t:C W
19、 z d E d i t()BEGIN_MESSAGE_MAP(CWzdEdit,CEdit)/A F X _ M S G _ M A P(C W z d E d i t)O N _ W M _ C T L C O L O R _ R E F L E C T()/A F X _ M S G _ M A PE N D _ M E S S A G E _ M A P()/CWzdEdit message handlersHBRUSH CWzdEdit:CtlColor(CDC*pDC,UINT nCtlColor)return m_brush;BOOL CWzdEdit:PreTranslateM
20、essage(MSG*pMsg)if(pMsg-message=WM_KEYDOWN&(pMsg-wParam=VK_UP|pMsg-wParam=VK_DOWN|pMsg-wParam=VK_RETURN)int nextprev=GW_HWNDNEXT;int firstlast=GW_HWNDFIRST;if(pMsg-wParam=VK_UP)n e x t p r e v=G W _ H W N D P R E V;f i r s t l a s t=G W _ H W N D L A S T;HWND hWnd=m_hWnd;while(hWnd)HWND hWndx=hWnd;i
21、f(hWnd=:GetWindow(hWnd,nextprev)=NULL)hWnd=:GetWindow(hWndx,firstlast);long style=:GetWi n d o w L o n g(h W n d,G W L _ S T Y L E);if(style&WS_TA B S TOP&!(style&WS_DISABLED)&style&WS_VISIBLE)|hWnd=m_hWnd)b r e a k;:S e t F o c u s(h W n d);return TRUE;return CEdit:PreTr a n s l a t e M e s s a g e
22、(p M s g);10.3 例48 用超分类定制一个通用控件窗口目标从一个控件窗口截取并处理W M _ C R E AT E和W M _ N C C R E AT E消息。不能用子分类做该工作,因为只能子分类一个已有的控件(即一个已被创建的控件,并已处理了 W M _ C R E AT E和W M _ N C C R E AT E消息)。策略要超分类一个控件,只要用系统提供的通用控件窗口类创建一个窗口类,作为模板,然后把窗口过程捆绑到该新窗口类,保存原始窗口类的地址,以便可以发送所有其他消息。因为这一改变将影响每个由该新类创建的控件窗口,因此,在应用程序类中,在应用程序被初188第二部分 用
23、户界面实例下载始化前进行替换。注意一个窗口类不是一个MFC类,更不是一个C+类,它早于并存在于C+之外,是系统创建任何窗口时使用的模板。参见第1章有关该主题的详细内容。步骤1.创建一个新的窗口类1)在应用程序类的 InitInstance()函数中,调用一个辅助函数以做实际工作,使InitInstance()函数看起来不那么乱。本例中,将超分类所有的按钮控件,因此,辅助函数被叫做SuperclassButtons()。BOOL CWzdApp:InitInstance()S u p e r c l a s s B u t t o n s();:2)在SuperclassButtons()中,首
24、先,使用:GetClassInfo(),用需要超分类的窗口类的当前信息填充一个W N D C L A S S结构(本例中是B U T TO N)。void CWzdApp:SuperclassButtons()WNDCLASS wClass;/get existing class information:G e t C l a s s I n f o(A f x G e t I n s t a n c e H a n d l e(),B U T TO N ,&w C l a s s);3)接着,把当前B U T TO N窗口类的窗口过程保存到一个静态变量中,然后用窗口过程的实例和地址填充该类结
25、构。/at the top of your sourceWNDPROC lpfnButtonWndProc;:/save old window process and substitute our ownl p f n B u t t o n W n d P r o c=w C l a s s.l p f n W n d P r o c;w C l a s s.h I n s t a n c e=A f x G e t I n s t a n c e H a n d l e();w C l a s s.l p f n W n d P r o c=B u t t o n W n d P r o
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MFC 编程 案例 chapter010
限制150内