- 浏览: 11738126 次
文章分类
最新评论
-
wahahachuang8:
我觉得这种东西自己开发太麻烦了,就别自己捣鼓了,找个第三方,方 ...
WebSocket和node.js -
xhpscdx:
写的这么详细,全面,对架构师的工作职责,个人能力都进行了梳理。 ...
架构师之路---王泽宾谈架构师的职责 -
xgbzsc:
是http://www.haoservice.com 吗?
android WIFI定位 -
lehehe:
http://www.haoservice.com/docs/ ...
android WIFI定位 -
lehehe:
http://www.haoservice.com/docs/ ...
android WIFI定位
WTL for MFC Programmers, Part V - Advanced Dialog UI Classes
WTL for MFC Programmers, Part V - Advanced Dialog UI Classes
原作 :Michael Dunn [英文原文]
翻译 :Orbit(星轨 oRbIt) [http://www.winmsg.com/cn/orbit.htm]
本章内容
第五章介绍
在上一篇文章我们介绍了一些与对话框和控件有关的WTL的特性,它们和MFC的相应的类作用相同。本文将介绍一些新类实现高级界面特性新类:控件自画和自定外观控件,新的WTL控件,UI updating和对话框数据验证(DDV)。
特别的自画和外观定制类
由于自画和定制外观控件在图形用户界面中是很常用的手段,所以WTL提供了几个嵌入类来完成这些令人厌烦的工作。我接着就会介绍它们,事实上我们在上一个例子工程ControlMania2的结尾部分已经这么做了。如果你正随着我的讲解用应用程序生成向导创建新工程,请不要忘了使用无模式对话框,为了使正常工作必须使用无模式对话框,我会在对话框中控件的UI Updating部分详细解释为什么这样作。
COwnerDraw
控件的自画需要响应四个消息:WM_MEASUREITEM, WM_DRAWITEM, WM_COMPAREITEM, 和WM_DELETEITEM,在atlframe.h头文件中定义的COwnerDraw类可以简化这些工作,使用这个类就不需要处理这四个消息,你只需将消息链入COwnerDraw,它会调用你的类中的重载函数。
如何将消息链入COwnerDraw取决与你是否将消息反射给控件,两种方法有些不同。下面是COwnerDraw类的消息映射链,它使得两种方法的差别更加明显:
template <class T> class COwnerDraw
{
public:
BEGIN_MSG_MAP(COwnerDraw<T>)
MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
MESSAGE_HANDLER(WM_COMPAREITEM, OnCompareItem)
MESSAGE_HANDLER(WM_DELETEITEM, OnDeleteItem)
ALT_MSG_MAP(1)
MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem)
MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem)
MESSAGE_HANDLER(OCM_COMPAREITEM, OnCompareItem)
MESSAGE_HANDLER(OCM_DELETEITEM, OnDeleteItem)
END_MSG_MAP()
};
注意,消息映射链的主要部分处理WM_*消息,而ATL部分处理反射的消息,OCM_*。自画的通知消息就像WM_NOTIFY消息一样,你可以在父窗口处理它们,也可以将它们反射会控件,如果你使用前一种方法,消息被直接链入COwnerDraw:
class CSomeDlg : public COwnerDraw<CSomeDlg>, ...
{
BEGIN_MSG_MAP(CSomeDlg)
//... CHAIN_MSG_MAP(COwnerDraw<CSomeDlg>) END_MSG_MAP() void DrawItem ( LPDRAWITEMSTRUCT lpdis );
};
当然,如果你想要控件自己处理这些消息,你需要使用CHAIN_MSG_MAP_ALT宏将消息链入ALT_MSG_MAP(1)部分:
class CSomeButtonImpl : public COwnerDraw<CSomeButtonImpl>, ...
{
BEGIN_MSG_MAP(CSomeButtonImpl)
//... CHAIN_MSG_MAP_ALT(COwnerDraw<CSomeButtonImpl>, 1)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
void DrawItem ( LPDRAWITEMSTRUCT lpdis );
};
COwnerDraw类将对消息传递的参数展开,然后调用你的类中的实现函数。上面的例子中,我们自己的类实现DrawItem()函数,当有WM_DRAWITEM或OCM_DRAWITEM消息被链入COwnerDraw时,这个函数就会被调用。你可以重载的方法有:
void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
int CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct);
void DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct);
如果你不想处理某个消息,你可以调用SetMsgHandled(false),消息会被传递给消息映射链中的其他响应者。SetMsgHandled()事实上是COwnerDraw类的成员函数,但是它的作用和在BEGIN_MSG_MAP_EX()中使用SetMsgHandled()一样。
对于ControlMania2,它从ControlMania1中的树控件开始,添加了自画按钮处理反射的WM_DRAWITEM消息,下面是资源编辑器中的新按钮:
现在我们需要一个新类实现自画按钮:
class CODButtonImpl : public CWindowImpl<CODButtonImpl, CButton>,
public COwnerDraw<CODButtonImpl>
{
public:
BEGIN_MSG_MAP_EX(CODButtonImpl)
CHAIN_MSG_MAP_ALT(COwnerDraw<CODButtonImpl>, 1)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
void DrawItem ( LPDRAWITEMSTRUCT lpdis );
};
DrawItem()使用了像BitBlt()这样的GDI函数向按钮的表面画位图,代码应该很容易理解,因为WTL使用的类名和函数名都和MFC类似。
void CODButtonImpl::DrawItem ( LPDRAWITEMSTRUCT lpdis )
{
// NOTE: m_bmp is a CBitmap init'ed in the constructor. CDCHandle dc = lpdis->hDC; CDC dcMem; dcMem.CreateCompatibleDC ( dc ); dc.SaveDC(); dcMem.SaveDC(); // Draw the button's background, red if it has the focus, blue if not. if ( lpdis->itemState & ODS_FOCUS )
dc.FillSolidRect ( &lpdis->rcItem, RGB(255,0,0) );
else dc.FillSolidRect ( &lpdis->rcItem, RGB(0,0,255) );
// Draw the bitmap in the top-left, or offset by 1 pixel if the button // is clicked. dcMem.SelectBitmap ( m_bmp ); if ( lpdis->itemState & ODS_SELECTED )
dc.BitBlt ( 1, 1, 80, 80, dcMem, 0, 0, SRCCOPY );
else dc.BitBlt ( 0, 0, 80, 80, dcMem, 0, 0, SRCCOPY );
dcMem.RestoreDC(-1);
dc.RestoreDC(-1);
}
我们的按钮看起来是这个样子:
CCustomDraw
CCustomDraw类使用和COwnerDraw类相同的方法处理NM_CUSTOMDRAW消息,对于自定绘制的每个阶段都有相应的重载函数:
DWORD OnPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnPostErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPostEraset(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnSubItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
这些函数默认都是返回CDRF_DODEFAULT,如果想自画控件或返回一个不同的值,就需要重载这些函数:
你可能注意到上面的屏幕截图将“道恩”(Dawn:女名)显示成绿色,这是因为CBuffyTreeCtrl将消息链入CCustomDraw并重载了OnPrePaint()和OnItemPrePaint()方法。向树控件中添加节点时,节点的item data字段被设置成1,OnItemPrePaint()检查这个值,然后改变文字的颜色。
DWORD CBuffyTreeCtrl::OnPrePaint(int idCtrl,
LPNMCUSTOMDRAW lpNMCD)
{
return CDRF_NOTIFYITEMDRAW;
}
DWORD CBuffyTreeCtrl::OnItemPrePaint(int idCtrl,
LPNMCUSTOMDRAW lpNMCD)
{
if ( 1 == lpNMCD->lItemlParam )
pnmtv->clrText = RGB(0,128,0);
return CDRF_DODEFAULT;
}
CCustomDraw类也有SetMsgHandled()函数,你可以像在COwnerDraw类那样使用这个函数。
WTL的新控件
WTL有几个新控件,它们要么是其他封装类的扩展(像 CTreeViewCtrlEx),要么是提供windows标准控件没有的新功能(像 CHyperLink)。
CBitmapButton
WTL的CBitmapButton类声明在atlctrlx.h中,它比MFC的同名类使用起来要简单的多。WTL的CBitmapButton类使用image list而不是单个的位图资源,你可以将多个按钮的图像放到一个位图文件中,减少GDI资源的占用。这对于使用很多图片并需要在Windows 9X系统上运行的程序很有好处,因为使用太多的单个位图将会很快耗尽GDI资源并导致系统崩溃。
CBitmapButton是一个CWindowImpl派生类,它又很多特色:自动调整控件的大小,自动生成3D边框,支持hot-tracking,每个按钮可以使用多个图像分别表示按钮的不同状态。
在ControlMania2中,我们对前面的例子创建的自画按钮使用CBitmapButton类。现在CMainDlg对话框类中添加CBitmapButton类型的变量m_wndBmpBtn,调用SubclassWindow()函数或使用DDX将其和控件联系起来,将位图装载到image list并告诉按钮使用这个image list,还要告诉按钮每个图像分别对应按钮的什么状态。下面是OnInitDialog()函数中建立和使用这个按钮的代码段:
// Set up the bitmap button CImageList iml; iml.CreateFromImage ( IDB_ALYSON_IMGLIST, 81, 1, CLR_NONE,
IMAGE_BITMAP, LR_CREATEDIBSECTION );
m_wndBmpBtn.SubclassWindow ( GetDlgItem(IDC_ALYSON_BMPBTN) );
m_wndBmpBtn.SetToolTipText ( _T("Alyson") );
m_wndBmpBtn.SetImageList ( iml );
m_wndBmpBtn.SetImages ( 0, 1, 2, 3 );
默认情况下,按钮只是引用image list,所以OnInitDialog()不能delete它所创建的image list。下面显示的是新按钮的一般状态,注意控件是如何根据图像的大小来调整自己的大小。
因为CBitmapButton是一个非常有用的类,我想介绍一下它的公有方法。
CBitmapButton methods
CBitmapButtonImpl类包含了实现一个按钮的所有代码,除非你想重载某个方法或消息处理,你可以对控件直接使用CBitmapButton类。
CBitmapButtonImpl constructor
CBitmapButtonImpl(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE,HIMAGELIST hImageList = NULL)
构造函数可以指定按钮的扩展样式(这与窗口的样式不冲突)和图像列表,通常使用默认参数就足够了,因为可以使用其他的方法设定这些属性。
SubclassWindow()
BOOL SubclassWindow(HWND hWnd)
SubclassWindow()是个重载函数,主要完成控件的子类化和初始化控件类保有的内部数据。
Bitmap button extended styles
DWORD GetBitmapButtonExtendedStyle()
DWORD SetBitmapButtonExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
CBitmapButton支持一些扩展样式,这些扩展样式会对按钮的外观和操作方式产生影响:
调用SetBitmapButtonExtendedStyle()时,dwMask参数控制着那个样式将被改变,默认值是0,意味着用新样式完全替换旧的样式。
Image list management
HIMAGELIST GetImageList()
HIMAGELIST SetImageList(HIMAGELIST hImageList)
调用SetImageList()设置按钮使用的image list。
Tooltip management
int GetToolTipTextLength()
bool GetToolTipText(LPTSTR lpstrText, int nLength)
bool SetToolTipText(LPCTSTR lpstrText)
CBitmapButton支持显示工具提示(tooltip),调用SetToolTipText()指定显示的文字。
Setting the images to use
void SetImages(int nNormal, int nPushed = -1,int nFocusOrHover = -1, int nDisabled = -1)
调用SetImages()函数告诉按钮分别使用image list的拿一个图像表示那个状态。nNormal是必须的,其它是可选的,使用-1表示对应的状态没有图像。
CCheckListViewCtrl
CCheckListViewCtrl类在atlctrlx.h中定义,它是一个CWindowImpl派生类,实现了一个带检查框的list view控件。它和MFC的CCheckListBox不同,CCheckListBox只是一个list box,不是list view。CCheckListViewCtrl类非常简单,只添加了很少的函数,当然,它使用了一个新的辅助类CCheckListViewCtrlImplTraits,它和CWinTraits类的作用类似,只是第三个参数是list view控件的扩展样式属性,如果你没有定义自己的CCheckListViewCtrlImplTraits,它将使用没默认的样式:LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT。
下面是一个定义list view扩展样式属性的例子,加入了一个使用这个样式的新类。(注意,扩展属性必须包含LVS_EX_CHECKBOXES,否则会因起断言错误消息。)
typedef CCheckListViewCtrlImplTraits<
WS_CHILD | WS_VISIBLE | LVS_REPORT,
WS_EX_CLIENTEDGE,
LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES | LVS_EX_UNDERLINEHOT |
LVS_EX_ONECLICKACTIVATE> CMyCheckListTraits;
class CMyCheckListCtrl :
public CCheckListViewCtrlImpl<CMyCheckListCtrl, CListViewCtrl,
CMyCheckListTraits>
{
private:
typedef CCheckListViewCtrlImpl<CMyCheckListCtrl, CListViewCtrl,
CMyCheckListTraits> baseClass;
public:
BEGIN_MSG_MAP(CMyCheckListCtrl)
CHAIN_MSG_MAP(baseClass)
END_MSG_MAP()
};
CCheckListViewCtrl methods
SubclassWindow()
当子类化一个已经存在的list view控件时,SubclassWindow()查看CCheckListViewCtrlImplTraits的扩展样式属性并将之应用到控件上。未用到前两个参数(窗口样式和扩展窗口样式)。
SetCheckState() and GetCheckState()
这些方法实际上是在CListViewCtrl中,SetCheckState()使用行的索引和一个布尔类型参数,该布尔参数的值表示是否check这一行。GetCheckState()以行索引未参数,返回改行的checked状态。
CheckSelectedItems()
这个方法使用item的索引作为参数,它翻转这个item的check状态,这个item必须是被选定的,同时还将其他所有被选择的item设置成相应状态(译者加:多选状态下)。你大概不会用到这个方法,因为CCheckListViewCtrl会在check box被单击或用户按下了空格键时设置相应的item的状态。
下面是ControlMania2中的CCheckListViewCtrl的样子:
CTreeViewCtrlEx and CTreeItem
有两个类使得树控件的使用简化了很多:CTreeItem类封装了HTREEITEM,一个CTreeItem对象含有一个HTREEITEM和一个指向包含这个HTREEITEM的树控件的指针,使你不必每次调用都引用树控件;CTreeViewCtrlEx和CTreeViewCtrl一样,只是它的方法操作CTreeItem而不是HTREEITEM。例如,InsertItem()函数返回一个CTreeItem而不是HTREEITEM,你可以使用CTreeItem操作新添加的item。下面是一个例子:
// Using plain HTREEITEMs: HTREEITEM hti, hti2; hti = m_wndTree.InsertItem ( "foo", TVI_ROOT, TVI_LAST );
hti2 = m_wndTree.InsertItem ( "bar", hti, TVI_LAST );
m_wndTree.SetItemData ( hti2, 100 );
// Using CTreeItems: CTreeItem ti, ti2; ti = m_wndTreeEx.InsertItem ( "foo", TVI_ROOT, TVI_LAST );
ti2 = ti.AddTail ( "bar", 0 );
ti2.SetData ( 100 );
CTreeViewCtrl对HTREEITEM的每一个操作,CTreeItem都有与之对应的方法,正像每一个关于HWND的API都有一个CWindow方法与之对应一样。查看ControlMania2的代码可以看到更多的CTreeViewCtrlEx和CTreeItem类的方法的演示。
CHyperLink
CHyperLink是一个CWindowImpl派生类,它子类化一个static text控件,使之变成可点击的超链接。CHyperLink根据用户的IE使用的颜色画链接对象,还支持键盘导航。CHyperLink类的构造函数没有参数,下面是其它的公有方法。
CHyperLink methods
CHyperLinkImpl类内含实现一个超链接的全部代码,如果不需要重载它的方法或处理消息的话,你可以直接使用CHyperLink类。
SubclassWindow()
BOOL SubclassWindow(HWND hWnd)
重载函数SubclassWindow()完成控件子类化,然后初始化该类保有的内部数据。
Text label management
bool GetLabel(LPTSTR lpstrBuffer, int nLength)
bool SetLabel(LPCTSTR lpstrLabel)
获得或设置控件显示的文字,如果不指定显示文字,控件会显示资源编辑器指定给控件的静态字符串。
Hyperlink management
bool GetHyperLink(LPTSTR lpstrBuffer, int nLength)
bool SetHyperLink(LPCTSTR lpstrLink)
获得或设置控件关联超链接的URL,如果不指定超链接URL,控件会使用显示的文字字符串作为URL。
Navigation
bool Navigate()
导航到当前超链接的URL,该URL或者是由SetHyperLink()函数指定的URL,或者就是控件的窗口文字。
Tooltip management
没有公开的方法设置工具提示,所以需要直接使用CToolTipCtrl成员m_tip。
下图显示的就是ControlMania2对话框中的超链接控件:
在OnInitDialog()函数中设置URL:
m_wndLink.SetHyperLink ( _T("http://www.codeproject.com/") );
对话框中控件的UI Updating
对话框中的的UI updating控制比MFC中简单得多,在MFC中,你需要响应未公开的WM_KICKIDLE消息,处理这个消息并触发控件的updating,在WTL中,没有这个诡计,不过向导存在一个BUG,需要手工添加一行代码解决这个问题。
首先需要记住的是对话框必须是无模式的,因为CUpdateUI需要在程序的消息循环控制下工作。如果对话框是模式的,系统处理消息循环,我们程序的空闲处理函数就不会被调用,由于CUpdateUI是在空闲时间工作的,所以没有空闲处理就没有UI updating。
ControlMania2的对话框是非模式的,类定义的开始部分很像是一个框架窗口类:
class CMainDlg : public CDialogImpl<CMainDlg>, public CUpdateUI<CMainDlg>,
public CMessageFilter, public CIdleHandler
{
public:
enum { IDD = IDD_MAINDLG };
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual BOOL OnIdle();
BEGIN_MSG_MAP_EX(CMainDlg)
MSG_WM_INITDIALOG(OnInitDialog)
COMMAND_ID_HANDLER_EX(IDOK, OnOK)
COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel)
COMMAND_ID_HANDLER_EX(IDC_ALYSON_BTN, OnAlysonODBtn)
END_MSG_MAP()
BEGIN_UPDATE_UI_MAP(CMainDlg)
END_UPDATE_UI_MAP()
//... };
注意CMainDlg类从CUpdateUI派生并含有一个update UI链。OnInitDialog()做了这些工作,这和前面介绍的框架窗口中的代码很相似:
// register object for message filtering and idle updates CMessageLoop* pLoop = _Module.GetMessageLoop(); ATLASSERT(pLoop != NULL); pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);
UIAddChildWindowContainer(m_hWnd);
只是这次我们不是调用UIAddToolbar()或UIAddStatusBar(),而是调用UIAddChildWindowContainer(),它告诉CUpdateUI我们的对话框含有需要updating的字窗口,只要看看OnIdle(),你会怀疑少了写什么:
BOOL CMainDlg::OnIdle()
{
return FALSE;
}
你可能猜想这里应该调用另一个CUpdateUI的方法做一些实在的updating工作,你是对的,应该是这样的,向导在OnIdle()中漏掉了一行代码,现在加上:
BOOL CMainDlg::OnIdle()
{
UIUpdateChildWindows(); return FALSE;
}
为了演示UI updating,我们设定鼠标点击左边的位图按钮,使得右边的按钮变得可用或禁用。先在update UI链中添加一个消息入口,使用UPDUI_CHILDWINDOW标志表示此入口是子窗口类型:
BEGIN_UPDATE_UI_MAP(CMainDlg)
UPDATE_ELEMENT(IDC_ALYSON_BMPBTN, UPDUI_CHILDWINDOW) END_UPDATE_UI_MAP()
在左边的按钮的单击事件处理中,我们调用UIEnable()来翻转另一个按钮的使能状态:
void CMainDlg::OnAlysonODBtn ( UINT uCode, int nID, HWND hwndCtrl )
{
static bool s_bBtnEnabled = true;
s_bBtnEnabled = !s_bBtnEnabled;
UIEnable ( IDC_ALYSON_BMPBTN, s_bBtnEnabled );
}
DDV
WTL的对话框数据验证(DDV)比MFC简单一些,在MFC中你需要分别使用DDX(对话框数据交换)宏和DDV(对话框数据验证)宏,在WTL中只需一个宏就可以了,WTL包含基本的数据验证支持,在DDV链中可以使用三个宏:
DDX_TEXT_LEN
DDX_INT_RANGE
and DDX_UINT_RANGE
DDX_FLOAT_RANGE
ControlMania2有一个ID是IDC_FAV_SEASON的edit box,它和成员变量m_nSeason相关联。
由于有效的值是1到7,所以使用这样的数据验证宏:
BEGIN_DDX_MAP(CMainDlg)
//... DDX_INT_RANGE(IDC_FAV_SEASON, m_nSeason, 1, 7)
END_DDX_MAP()
OnOK()调用DoDataExchange()获得season的数值,并验证是在1到7之间。
处理DDV验证失败
如果控件的数据验证失败,CWinDataExchange会调用重载函数OnDataValidateError(),默认到处理是驱动PC喇叭发出声音,你可能想给出更友好的错误指示。OnDataValidateError()的函数原型是:
void OnDataValidateError ( UINT nCtrlID, BOOL bSave, _XData& data );
_XData是一个WTL的内部数据结构,CWinDataExchange根据输入的数据和允许的数据范围填充这个数据结构。下面是这个数据结构的定义:
struct _XData
{
_XDataType nDataType;
union { _XTextData textData; _XIntData intData; _XFloatData floatData; }; };
nDataType指示联合中的三个成员那个是有意义的,nDataType 的取值可以是:
enum _XDataType
{
ddxDataNull = 0,
ddxDataText = 1,
ddxDataInt = 2,
ddxDataFloat = 3,
ddxDataDouble = 4 };
在我们的例子中,nDataType的值是ddxDataInt,这表示_XData中的_XIntData成员是有效的,_XIntData是个简单的数据结构:
struct _XIntData
{
long nVal;
long nMin;
long nMax;
};
我们重载OnDataValidateError()函数,显示错误信息并告诉用户允许的数值范围:
void CMainDlg::OnDataValidateError ( UINT nCtrlID, BOOL bSave, _XData& data )
{
CString sMsg;
sMsg.Format ( _T("Enter a number between %d and %d"),
data.intData.nMin, data.intData.nMax );
MessageBox ( sMsg, _T("ControlMania2"), MB_ICONEXCLAMATION );
::SetFocus ( GetDlgItem(nCtrlID) );
}
_XData中的另外两个结构_XTextData和_XFloatData的定义在atlddx.h中,感兴趣的话可以打开这个文件查看一下。
改变对话框的大小
WTL引起我的注意的第一件事是对可调整大小对话框的内建的支持。在这之前我曾写过一篇关于这个主题的文章,详情请参考这篇文章。简单的说就是将CDialogResize类添加到对话框的集成列表,在OnInitDialog()中调用DlgResize_Init(),然后将消息链入CDialogResize。
继续
下一章,我将介绍如何在对话框中使用ActiveX控件和如何处理控件触发的事件。
参考
Using WTL's Built-in Dialog Resizing Class - Michael Dunn
Using DDX and DDV with WTL - Less Wright
修改记录
2003年4月28日,本文第一次发表。
相关推荐
WTL for MFC Programmers, Part V - Advanced Dialog UI Classes - WTL WTL for MFC Programmers, Part VI - Hosting ActiveX Controls - WTL WTL for MFC Programmers, Part VII - Splitter Windows - WTL WTL for ...
Part V - Advanced Dialog UI Part VI - Hosting ActiveX Controls Part VII - Splitter Windows Part VIII - Property Sheets and Wizards Part IX - GDI Classes, Common Dialogs, and Utility Classes Part X - ...
《WTL for MFC Programmers》是专为熟悉MFC的开发者设计的一本权威指南,旨在帮助他们过渡到WTL框架,从而利用其优势进行更为灵活和高效的编程。 **WTL与MFC的关联与区别** MFC是微软提供的一个面向对象的C++库,...
**WTL for MFC Programmers 中英文** Windows Template Library (WTL) 是一个轻量级的C++库,由微软开发并提供,主要用于构建Windows应用程序。这个库是为那些已经熟悉Microsoft Foundation Class (MFC) 库的程序员...
WTL 具有两面性,确实是...并在其内包含了WTL的CSplitterWindow,在CSplitterWindow中又使用了MFC的CDialogs -- 我并不是为了炫耀什么,只是修改了MFC的代码使之能够使用WTL的分割窗口,它比MFC的分割窗口好的多)。
WTL for MFC Programmers.PDF
这个资源在网上很多下得到,只不过是html文件包,不方便使用,这个是我做的一个chm文件,希望对大家有用。
【WTL for MFC Programmers】是一本专为熟悉MFC的程序员介绍Windows Template Library (WTL)的著作。WTL是微软开发的一个轻量级的C++库,旨在为Windows应用程序开发提供高效的界面框架解决方案,它扩展了ATL(Active...
**WTL for MFC程序员** 是一套专门为那些已经熟悉MFC(Microsoft Foundation Classes)并希望扩展到Windows Template Library(WTL)的开发者准备的学习资源。WTL是一个轻量级的库,它提供了对Windows API的直接访问...
**Windows Template Library (WTL) for MFC Programmers** Windows Template Library (WTL) 是一个轻量级的库,由Microsoft开发,它扩展了Microsoft Foundation Class (MFC) 库的功能,尤其在创建Windows应用程序时...
《WTL for MFC Programmers》由迈克尔·敦编写,是专门为已经熟悉MFC的开发者设计的一本指南。这本书将帮助读者理解如何将已有的MFC知识应用于WTL开发,从而快速上手并掌握WTL的精髓。教程可能涵盖以下几个方面: 1...
**Windows Template Library (WTL) for MFC程序员指南** Windows Template Library(WTL)是Microsoft为MFC(Microsoft Foundation Classes)程序员提供的一种轻量级、高效且强大的库,用于开发Windows应用程序。...
MFC程序员的WTL指南,中文翻译版本,原文链接https://www.codeproject.com/Articles/3841/WTL-for-MFC-Programmers-Part-I-ATL-GUI-Classes。
### WTL for MFC Programmer:关键技术点解析 #### 一、引言 WTL (Windows Template Library) 是一套由微软开发的轻量级GUI库,主要用于简化基于Windows平台的应用程序开发工作。它提供了大量用于创建窗口类、...
This code accompanied the article: WTL for MFC Programmers, Part X - Implementing a Drag and Drop Source available at this URL: ... June 16, 2006 <br>If you're looking for the license ...
5. **Advanced Dialog UI Classes**:这部分介绍了WTL中一些高级对话框类。 - **自画和外观定制类**:介绍了如何使用这些类来自定义对话框的外观。 - **新控件**:列举了一些WTL特有的控件,如CBitmapButton等。 ...
在本文中,我们将深入探讨`WTL-GUI-Base-Classes.zip_wtl`资源中的关键知识点,包括WTL的基础类以及如何使用它们来构建GUI应用程序。 **1. WTL基础类** WTL的核心在于一系列基类,这些类帮助开发者构建用户界面...