MFC 定制控件(Customize Control) 及 MFC CWnd和WIN32 HWND关联方法

简介: MFC 定制控件(Customize Control) 及 MFC CWnd和WIN32 HWND关联方法  文档将概述MFC中定制自定义控件的3种方法: 拥有者绘制控件(Owner Drawing Control and Menu)   自绘制控件(self drawing contro...

MFC 定制控件(Customize Control) 及 MFC CWnd和WIN32 HWND关联方法 

<参考资料 MSDN MFC TNO 15> 

文档将概述MFC中定制自定义控件的3种方法: 
拥有者绘制控件(Owner Drawing Control and Menu)   自绘制控件(self drawing control and menu)  和子集化(subclass) 



1  使用MFC方法定制控件必备的几个基本概念: 

控制定制风格的控件的几个标准Windows消息: 
WM_MEASUREITEM 
WM_COMPAREITEM 
WM_DELETEITEM 
WM_DRAWITEM 
消息的详细说明: 



1.1 WM_MEASUREITEM 

当自绘制风格(owner draw)的控件(owner-drawn button, combo box, list box, list view control, or menu item)创建时控件的父窗体将受到这个消息用于定制控件的大小
 
WM_MEASUREITE
MidCtl = (UINT) wParam;//控件的标识
lpmis  = (LPMEASUREITEMSTRUCT) lParam;//控件的大小信息

消息处理的返回值: 
当函数处理了这个消息必须返回TRUE 


1.2 WM_COMPAREITEM 
系统发送此消息用于设定一个需要排序的控件(如具有CBS_SORT风格的COMBOBOX,有LBS_SORT风格的LISTBOX)新插入项的位置信息

WM_COMPAREITEM 
idCtl = wParam; // 控件标识 
lpcis = (LPCOMPAREITEMSTRUCT) lParam; // 2个进行比较的子项信息

消息处理的返回值:
-1   子项1在子项2之前的位置
  0  子项1,2 具有相等的排序位置
  1   子项1在子项2之后的位置 


1.3 WM_DELETEITEM 

当ListBox或是combo box被销毁时或它们的某一子项将被除去的时候(如消息 LB_DELETESTRING TCONTENT, CB_DELETESTRING  CB_RESETCONTENT)系统会对应每一个被删除的控件子项发送消息给控件的父窗体

WM_DELETEITEM 
idCtl = wParam; //控件标识 
lpdis = (LPDELETEITEMSTRUCT) lParam; //删除子项信息
 
消息返回值 
当函数处理了这个消息必须返回TRUE 



1.4 WM_DRAWITEM 

当自绘制风格的button, combo box, list box, or menu 的视觉方式需要改变时将发送WM_DRAWITEM消息给所有者窗体

WM_DRAWITEM 
idCtl = (UINT) wParam; // 控件标识
lpdis = (LPDRAWITEMSTRUCT) lParam; // 绘制控件的信息

函数返回值
当函数处理了这个消息必须返回TRUE 

2  以下内容为定制自定义控件的3种常见方法: 

2.1 拥有者绘制控件或菜单(owner draw controls/menu) 

windows支持拥有WS_OWNERDRAW风格的控件发送指定消息给控件的父窗体(控件或是菜单的拥有者)使得父窗体可以定制这些控件的视觉风格或行为 
MFC在其消息路由中直接支持4种消息消息的处理: 
CWnd::OnDrawItem 
CWnd::OnMeasureItem 
CWnd::OnCompareItem 
CWnd::OnDeleteItem 
可以在CWnd的派生类(通常是CMainFrame或是CDialog)中实现这些方法来定制控件 

注意: 
这种方法实现的又很大的弊端,代码重用率低,这样定制的控件如在另一个地方重用时只能把代码从一个地方拷贝到另一个地方 



2.2 自绘制的控件或是菜单 

MFC默认的实现owner draw标准消息的方法,将这些本来由父窗体实现的绘制的工作消息解码发送到指定控件,由这些控件来处理这些消息,这种优雅的处理方式使得很容易实现重用率很高的自定义风格的控件
在这些封装控件的MFC类(CMenu, CButton, CListBox, CListCtrl etc)中 ,只需要派生一个新类并重写对应的虚函数就可以轻松定制自定义风格的控件 
如CMenu的DrawItem(), MesureItem()函数

2.3  动态子集化(dynamic subclassing) 
2.3.1 subclass的概念: 
子集化在windows编程中指用一个新的窗口过程(subclass winproc)取代旧的窗口过程,而是用旧的窗体过程(superclass winproc)作为默认的窗口处理,来使得窗体呈现新的特性; 
superclass 和 subclass在windows编程中的概念可以用C++中的基类和派生类的关系来理解
在WIN32这个过程可以用API: SetWindowLong来实现 

3.4.2 MFC CWnd和WIN32 HWND关联的3种方法 
方法一 创建一个CWnd时 CWnd对象创建一个HWND 此时的HWND的风格是可以更改的,如使用Create()
方法二 创建一个CWnd与一个已经存在的HWND关联 此时HWND的风格是不可以被更改的 如使用Attach() 
方法三 创建一个CWnd与一个已存在的HWND关联,此时HWND的风格是可以更改的 这就是所谓的动态子集化(dynamic subclassing) 这样就可以实现运行时态的改变一个窗体的行为


对于动态子集化MFC提供了两个函数: 
CWnd::SubclassWindow 
CWnd::SubclassDlgItem. 
使用动态子集化是控制界面风格最优雅的风格和方法,代码重用率高和运行时态动态变化
一般一些比较优良的MFC第三方界面库都是基于这种技术实现的

目录
相关文章
[MFC][bug记录]MFC移植对话框属性
[MFC][bug记录]MFC移植对话框属性
|
6月前
|
C++
MFC创建带窗口的DLL
MFC创建带窗口的DLL
131 0
|
API C# Windows
C#实现操作Windows窗口句柄:常用窗口句柄相关API、Winform中句柄属性和Process的MainWindowHandle问题【窗口句柄总结之三】
本篇主要介绍一些与窗口句柄相关的一些API,比如设置窗口状态、当前激活的窗口、窗口客户区的大小、鼠标位置、禁用控件等,以及介绍Winform中的句柄属性,便于直接获取控件或窗体句柄,以及不推荐...
3097 0
C#实现操作Windows窗口句柄:常用窗口句柄相关API、Winform中句柄属性和Process的MainWindowHandle问题【窗口句柄总结之三】
MFC设置窗体大小SetWindowPos
SetWindowPos(NULL,0,0,200,300,SWP_NOMOVE);     表示不考虑(0,0),仅仅将大小改为200x300,位置不变    SetWindowPos(NULL,0,0,200,300,SWP_NOMOVE);    表示不考虑200X300,只是把位置挪到(0,0).
4122 0
|
索引
VC MFC工具栏(CToolBar)控件
一、工具栏 工具栏控件在控件面板里没有对应的选项(图标),但有一个工具栏控件类CToolBar,所以我们如果要创建一个工具栏控件并显示在窗口里的话,只能用代码来完成,事实上任何一种控件,都可以用代码创建,如CButton按钮类,现举一个用代码创建按钮控件并显示在窗口里的例子。
2496 0
VC轻松实现CTreeCtrl控件双击响应
这个陌生的指针类型常使初用树控件的编程者陷入迷茫之中。实际上我们完全不理会它,也可以实现树控件的双击响应,即在OnDblClkTree( )函数中调用树控件的成员函数CTreeCtrl::GetSelectedItem( )以获取树控件的子项句柄HTREEITEM,得到此句柄后,我们便可用下列成员函...
1382 0