vc拓展编程实例.pdf
《vc拓展编程实例.pdf》由会员分享,可在线阅读,更多相关《vc拓展编程实例.pdf(14页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、下载下载第 8 章控 件 窗 口控件窗口是允许用户与应用程序进行交互的按钮、列表框和滚动条。当创建对话框时,使用对话框编辑器定义的控件窗口也随之创建。然而,有时某个控件的外观和位置并不尽如人意,这时便可以对控件进行处理,本章的实例包括:实例28 自己绘制的控件,将看到在使用与控件相关的其他额外开销时如何绘制自己的控件。实例29 在窗口标题中添加按钮,将为一个窗口的标题添加一个按扭。实例30 添加热键控件,将为用户的应用程序添加热键。8.1 实例28:自己绘制的控件1.目标自己绘制一个控件窗口。在这个实例中,将绘制一个列表框,选择的列表项目将产生缩进,如图8-1所示。2.策略首先使用属主绘制风格
2、(o w n e r-d r a w ns t y l e)创建用户自己的控件,然后从 M F C控件类中派生自己的控件类,接下来重载D r a w I t e m()成员函数,在此可以用 M F C的CDC 类和它的成员函数来绘制控件,本实例中将绘制一个列表控件窗口。3.步骤1)创建一个新的列表框类用C l a s s Wi z a r d从C L i s t B o x中派生出一个新的类。2)绘制列表框控件用 C l a s s Wizard 重载C L i s t B o x类的D r a w I t e m()函数。首先在D r a w I t e m()函数中封装(w r a p)从
3、C D C类对象的D R AW I T E M S T R U C T结构中所获得的设备环境的句柄:void CWzdListBox:DrawItem(LPDRAWITEMSTRUCT lpDIS)/get our device context and rectangle to draw toCDC dc;dc.Attach(lpDIS-hDC);CRect rect(lpDIS-rcItem);下一步如何处理取决于怎样绘制这个控件。这可以有很多种情况。对于这个实例,只是简单地采用C D C:D r a w I t e m()来绘制列表框上的项目。但如果某个列表项被鼠标选取,那么将用系统的高亮
4、颜色来绘制该项目,同时它还将缩进 1 0个像素。根据是否被选择来确定并设置列表项的前景色和背景颜色:图8-1 自己绘制的列表框该自绘制列表框将使被选择的列表项所在行缩进第 8 章第控 件 窗 口第第201下载/if our item is selected,then set colors accordingly/and fill in backgroundCOLORREF bk=dc.GetBkColor();COLORREF fg=dc.GetTe x t C o l o r();if(lpDIS-itemState&ODS_SELECTED)bk=:GetSysColor(COLOR_HI
5、GHLIGHT);fg=:GetSysColor(COLOR_HIGHLIGHTTEXT);d c.S e t TextColor(fg);这一步为这个列表项绘制背景颜色:CBrush brush(bk);dc.FillRect(&rect,&brush);接下来用C D C:D r a w Te x t()函数来绘制这个列表项的文本,如果选择这行,那么缩进文本的开始1 0个像素:if(lpDIS-itemState&ODS_SELECTED)rect.left+=10;int nBkMode=dc.SetBkMode(TRANSPARENT);CString str;G e t Text(l
6、pDIS-itemID,str);d c.D r a w Text(str,&rect,DT_LEFT|DT_VCENTER);注意是从列表框控件本身获取要绘制的文本,一般来说,列表框并不能为一个属主绘制控件维持该列表。但可以将这个控件设置为 Has String属性,它将在内部继续维护该列表,这将允许继续使用这个控件类中的A d d S t r i n g()函数。最后需要在D r a w I t e m()函数中进行清除工作:d c.S e t TextColor(fg);dc.SetBkMode(nBkMode);d c.D e t a c h();此列表框控件类的完整程序代码可参考本实
7、例结尾的程序清单列表框类。3)使用新的列表框类为使用这个新的控件类,首先用对话框编辑器为对话框模板添加列表框,确保设置O w n e r-Drawn Fixed和Has Strings属性。如果还没有这样做,则使用C l a s s Wi z a r d为该模板创建一个对话框。使用C l a s s Wi z a r d为对话框类添加控件成员变量,然后使用用户的新类名替代 Class Wi z a r d自动添加的C l i s t B o x类名,同时将该定义设置在 括号之外,使得Class Wi z a r d不会被它弄糊涂,这个列表框将在下次调用U p d a t e D a t a(F
8、A L S E)时被用户的列表框类子类化。4.注意除Wi n d o w s列表框控件之外,其他可以属主绘制的控件包括:组合框、扩展的组合框、列表控件、按钮、标签控件。列表控件和组合框控件都允许用户设置其中每一个项目的尺寸,这可以通过Dialog Editor设置O w n e r-Drawn Va r i a b l e风格来实现。当使用O w n e r-Drawn Va r i a b l e风格时,必须重载用户新控件类的 M e a s u r e I t e m()成员函数并返回每一个项目所希望的尺寸。重载 M e a s u r e I t e m()成员函数的例子可参考实例7。如
9、果使用Dialog Editor还将该控件设置为 S o r t风格,则必须同时在新的控件类中重载S o r t I t e m()成员函数。实际上,在这里“属主绘制”这个词有一点用词不当,从技术上来说,本实例中的控件是自己绘制的控件,“属主绘制”最初的含义是某个控件的属主(o w n e r),例如一个对话框,可以绘制它所拥有的那个控件。然而,在这个实例中,控件发出的用于通知它的属主绘制(W M _ D R AW I T E M)时间已到的消息,将会反射回到该控件的 M F C类并在此进行处理,因此从技术上说,这个正被 M F C类绘制的控件拥有这个控件。然而,由于在 M F C世界中这两种
10、情况被认为是同一个术语,本例中的控件应该被认为是它自己绘制自己或自绘制(s e l f-d r a w n)的。关于消息反射的详细内容,请参阅第 1章。当只是编写一个W M _ PA I N T消息处理函数来绘制控件时,为什么要费心考虑控件的属主绘制风格呢?原因是想使绘制工作和控件的其他功能同步。例如,一个属主绘制组合框将会告诉用户何时绘制它的列表框,而且更重要的是,它将会告诉用户绘制列表框的位置,使得鼠标在屏幕上单击该位置时,将会与该控件上相应的项目相关联。甚至一个属主绘制的按钮控件将通知用户何时绘制一个已按下的或未按下的按钮,使得与当单击它时所创建的命令消息相符。5.使用光盘时注意运行随书
11、附带光盘上的工程时,单击 Te s t按钮,然后再单击W z d菜单命令,打开一个带有列表框的对话框。注意到在单击列表框中的任何一个列表项时都将会导致文本框中的相应一行缩进。6.程序清单列表框类#if!defined(AFX_WZDLISTBOX_H_41500055_E450_11D1_9B7D_00AA003D8695_INCLUDED_)#define AFX_WZDLISTBOX_H_41500055_E450_11 D 1 _ 9 B 7 D _ 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
12、 once#endif /_MSC_VER=1000/WzdListBox.h:header file/CWzdListBox windowclass CWzdListBox:public CListBox/Constructionp u b l i c:C W z d L i s t B o x();/Attributesp u b l i c:/Operationsp u b l i c:/Overrides/ClassWizard generated virtual function overrides202第第第二部分第用户界面实例下载/AFX_VIRTUAL(CWzdListBox)
13、p u b l i c:virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);/AFX_VIRT U A L/Implementationp u b l i c:virtual CWzdListBox();/Generated message map functionsp r o t e c t e d:/AFX_MSG(CWzdListBox)/AFX_MSGD E C L A R E _ M E S S A G E _ M A P();/AFX_INSERT _ L O C AT I O N /Microsoft Develope
14、r Studio will insert additional declarations immediately/before the previous line.#e n d i f/!defined(AFX_WZDLISTBOX_H_41500055_E450_11D1_9B7D_00AA003D8695_INCLUDED_)/WzdListBox.cpp:implementation file/#include stdafx.h#include wzd.h#include WzdListBox.h#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_
15、FILEstatic char THIS_FILE=_FILE_;#e n d i f/CWzdListBoxC W z d L i s t B o x:C W z d L i s t B o x()C W z d L i s t B o x:C W z d L i s t B o x()BEGIN_MESSAGE_MAP(CWzdListBox,CListBox)/AFX_MSG_MAP(CWzdListBox)/AFX_MSG_MAPE N D _ M E S S A G E _ M A P()第 8 章第控 件 窗 口第第203下载/CWzdListBox message handler
16、svoid CWzdListBox:DrawItem(LPDRAWITEMSTRUCT lpDIS)/get our device context and rectangle to draw toCDC dc;dc.Attach(lpDIS-hDC);CRect rect(lpDIS-rcItem);/if our item is selected,then set colors accordingly/and fill in backgroundCOLORREF bk=dc.GetBkColor();COLORREF fg=dc.GetTe x t C o l o r();if(lpDIS-
17、itemState&ODS_SELECTED)bk=:GetSysColor(COLOR_HIGHLIGHT);fg=:GetSysColor(COLOR_HIGHLIGHTTEXT);d c.S e t TextColor(fg);CBrush brush(bk);dc.FillRect(&rect,&brush);/draw textif(lpDIS-itemState&ODS_SELECTED)rect.left+=10;int nBkMode=dc.SetBkMode(TRANSPARENT);CString str;G e t Text(lpDIS-itemID,str);d c.D
18、 r a w Te x t(s t r,&rect,DT_LEFT|DT_VCENTER);/cleanupd c.S e t TextColor(fg);dc.SetBkMode(nBkMode);d c.D e t a c h();8.2 实例29:在窗口标题中添加按钮1.目标在一个窗口的标题栏中添加一个按钮,如图 8-2所示。2.策略从技术上来说,本例将要创建的按钮不是一个控件窗口。实际上要创建的是一个“假的”按钮,该按钮将由用户自己绘制并且处理鼠标消息。系统通过响应两个消息(W M _N C PA I N T和W M _ A C T I VAT E)来绘制窗口标题,在每个消息使用C D
19、 C类的绘制功能之后,用户将对本例中的按钮进行绘制,同时还将处理另一个消息(W M _ N C L B U T TO N D O W N)204第第第二部分第用户界面实例下载图8-2 标题栏中的一个按钮在对话框的标题中放置一个按钮来确定用户是否按下本例中的“按钮”。3.步骤1)为标题按钮设置位图用位图编辑器(Bitmap Editor)创建两个位图:一个用于按钮弹起时,另一个用于按钮按下时。可以在位图边界使用高亮度和阴影颜色来达到这一效果,背景颜色采用灰色装载位图时代替这种颜色。对于一个用于通常窗口标题中常规尺寸的按钮,可以设置其尺寸为1 61 6像素,对于一个工具栏窗口的小尺寸的按钮,可设置
20、其尺寸为 1 21 2像素。在自己的对话框类中的构造函数中,将这两个位图装载到嵌入的 C B i t m a p成员变量中。利用随书附带光盘上为该实例提供的 C W z d B i t m a p类,可以将当前用于按钮的系统颜色替代为灰色背景色,还可以将按钮的状态初始化为未按下(u n p r e s s e d)。CWzdDialog:CWzdDialog(CWnd*pParent/*=NULL*/):CDialog(CWzdDialog:IDD,pParent)/AFX_DATA_INIT(CWzdDialog)/AFX_DATA _ I N I Tm_bPressed=FA L S E;
21、m_bitmapPressed.LoadBitmapEx(IDB_PRESSED_BITMAP,TRUE);m_bitmapUnpressed.LoadBitmapEx(IDB_UNPRESSED_BITMAP,TRUE);注意这个位图类(C W z d B i t m a p)在本系列丛书中的第一本书Visual C+MFC编程实例中创建。2)绘制标题按钮用C l a s s Wi z a r d为该类添加W M _ N C PA I N T和W M _ A C T I VAT E消息处理函数,从这两个消息处理函数中调用一个D r a w B u t t o n()函数,该函数将用于绘制按钮
22、。接下来将编写 DrawButton()函数的代码:void CWzdDialog:OnNcPaint()/draw caption firstC D i a l o g:O n N c P a i n t();/then draw button on topD r a w B u t t o n();void CWzdDialog:OnActivate(UINT nState,CWnd*pWndOther,BOOL bMinimized)CDialog:OnActivate(nState,pWndOther,bMinimized);D r a w B u t t o n();创建 DrawB
23、utton()函数,这个函数将决定绘制哪个按钮位图并且使用如下所示的S t r e t c h B l t()函数绘制它:void CWzdDialog:DrawButton()第 8 章第控 件 窗 口第第205下载206第第第二部分第用户界面实例下载/if window isnt visible or is minimized,skipif(!IsWi n d o w Visible()|IsIconic()r e t u r n;/get appropriate bitmapCDC memDC;CDC*pDC=GetWi n d o w D C();memDC.CreateCompati
24、bleDC(pDC);memDC.SelectObject(m_bPressed?&m_bitmapPressed:&m_bitmapUnpressed);/get button rect and convert into non-client area coordinatesCRect rect,rectWnd;G e t B u t t o n R e c t(r e c t);G e t Wi n d o w R e c t(r e c t W n d);r e c t.O ffsetRect(-rectWnd.left,-rectWnd.top);/draw itpDC-Stretch
25、Blt(rect.left,rect.top,rect.Wi d t h(),rect.Height(),&memDC,0,0,m_bitmapPressed.m_Wi d t h,m_bitmapPressed.m_Height,SRCCOPY);m e m D C.D e l e t e D C();ReleaseDC(pDC);注意到从G e t Wi n d o w D C()中获得了设备环境,这样设备环境就可以绘制到整个窗口,包括标题所在的非客户区。这里使用 S t r e t c h B l t()是因为用户并不能确定使用何种分辨率来绘制对话框。同时,本例使用了另一个称为 G e
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- vc 拓展 编程 实例
限制150内