ATLWTL第九部分Word下载.docx
- 文档编号:19316602
- 上传时间:2023-01-05
- 格式:DOCX
- 页数:27
- 大小:109.73KB
ATLWTL第九部分Word下载.docx
《ATLWTL第九部分Word下载.docx》由会员分享,可在线阅读,更多相关《ATLWTL第九部分Word下载.docx(27页珍藏版)》请在冰豆网上搜索。
此设计与ATL窗口类的设计是一致的,CWindow
是对
HWND
的一个简单的封装层,而
CWindowImpl
管理了一个窗口的生命期。
GDI封装类定义于
atlgdi.h
中,不过
CMenuT
是个例外,它定义于
atluser.h
中(译者注:
此处作者的说法欠妥,菜单在Windows里原本就是属于USER32的,而不是GDI32)。
你自己不必包含这些头文件,因为
atlapp.h
总会为你包含它们。
每个类还有一个易于记忆的typedef名字:
封装的GDI对象
模板类
管理对象的typedef名
普通封装的typedef名
Pen
CPenT
CPen
CPenHandle
Brush
CBrushT
CBrush
CBrushHandle
Font
CFontT
CFont
CFontHandle
Bitmap
CBitmapT
CBitmap
CBitmapHandle
Palette
CPaletteT
CPalette
CPaletteHandle
Region
CRgnT
CRgn
CRgnHandle
Devicecontext
CDCT
CDC
CDCHandle
Menu
CMenuT
CMenu
CMenuHandle
与MFC传递对象指针相比较,我更喜欢这种方法。
你永远也不必担心收到了一个NULL指针(封装的句柄可能会是NULL,但那是另一回事),也不会有这种特殊的情况,你有一个临时对象,但你却不能把它保存下来然后对它进行不止一次的函数调用。
创建这些类的实例代价也是很低的,因为它们只有一个成员变量,即所封装的句柄。
就像
CWindow
一样,在线程之间传递封装类的对象也不会有问题,因为WTL并没有像MFC那样的线程相关的映射。
另外还有几个设备上下文的封装类,用于特定的绘制场景:
∙CClientDC:
封装了对
GetDC()
ReleaseDC()
的调用,用于在窗口的客户区内绘制
∙CWindowDC:
GetWindowDC()
的调用,用于在窗口内的任意地方绘制
∙CPaintDC:
BeginPaint()
EndPaint()
的调用,用于
WM_PAINT
处理器中
这些类中的任一个都是在构造函数中接受一个
HWND,而行为与其在MFC中的同名类相似。
所有这三个类都派生于
CDC,因此它们都管理着自己的设备上下文。
封装类里的公用函数
GDI封装类都遵循相同的设计。
简明起见,在这儿我只介绍
CBitmapT
里的方法,但其它类工作起来都很相似。
封装的GDI对象句柄
每个类都持有一个公用成员变量,其中保留了此C++对象关联着的GDI对象的句柄。
则具有一个名为
m_hBitmap
的
HBITMAP
成员。
构造函数
构造函数有一个参数,为一个
HBITMAP,其缺省值为NULL。
被初始化为此参数的值。
析构函数
为true,而且
不是NULL,则析构函数会调用
DeleteObject()
以销毁位图。
Attach()
operator
=
这两个方法都接受一个
句柄。
true,而且
不是NULL,这些方法会先调用
以销毁
对象管理着的位图,然后将
设置为作为参数传入的
HBITMAP。
Detach()
Detach()
会将
设置为NULL,然后再返回原来在
中的值。
当
返回后,CBitmapT
对象就不再与任何GDI有关联了。
创建GDI对象的方法
对Win32中创建位图的API也有封装:
LoadBitmap()、LoadMappedBitmap()、CreateBitmap()、CreateBitmapIndirect()、CreateCompatibleBitmap()、CreateDiscardableBitmap()、CreateDIBitmap()以及
CreateDIBSection()。
不是NULL时,这些方法都会产生断言。
如果要为另一个GDI位图重用本
对象,就要先调用DeleteObject()
或者
Detach()。
DeleteObject()
销毁GDI位图对象并将
置为NULL。
这一方法仅当
不为NULL时才应该调用,否则会产生断言。
IsNull()
IsNull()
在
为NULL时返回
true,否则返回
false。
这一方法用来测试
对象当前是否关联着一个GDI位图。
HBITMAP
这个转换器会返回
m_hBitmap,这就使你可以把
对象传递给一个接收
句柄的函数或者Win32API。
这个转换器在以下情况下也会被调用,或者是一个
在布尔值的上下文环境下被求值,或者是对
的逻辑取反求值。
因而,这两个if语句是等效的:
CBitmapHandlebmp=/*someHBITMAPvalue*/;
if(!
bmp.IsNull()){dosomething...}
if(bmp){dosomethingmore...}
GetObject()
的封装
具有一个对于Win32API
GetObject()的类型安全的封装:
GetBitmap()。
有两个重载形态:
一个是接收
LOGBITMAP*
参数而直接调用
GetObject(),另一个则接收
LOGBITMAP&
参数并返回一个表示成功与否的
值。
后者更为易用些。
例如:
CBitmapHandlebmp2=/*someHBITMAPvalue*/;
LOGBITMAPlogbmp={0};
boolbSuccess;
if(bmp2)
bSuccess=bmp2.GetLogBitmap(logbmp);
操作GDI对象的API的封装
对接收
参数的Win32API也进行了封装:
GetBitmapBits()、SetBitmapBits()、GetBitmapDimension()、SetBitmapDimension()、GetDIBits()以及
SetDIBits()。
这些方法在
为NULL时都会产生断言。
其它辅助方法
还有两个作用于
上的有用的方法:
LoadOEMBitmap()
GetSize()。
使用CDCT
CDCT
与其它类有一点不同,因此我要单独介绍其差别。
方法上的差别
销毁一个DC的方法叫做
DeleteDC()
而不是
将对象选入DC
MFC的
CDC
在把对象选入到其中时有一个容易导致错误的地方。
有若干个重载的
SelectObject()
函数,每个都是接收一个指向不同类型的GDI封装类的指针(CPen*,CBitmap*,等等)作为参数。
如果你把一个C++对象而不是指向该对象的指针传递给
SelectObject(),代码最终会调用一个未文档化的,接收一个
HGDIOBJ
句柄为参数的重载,这样就会导致问题。
WTL的
使用了一种更好的方法,它有好几个选择函数,每一个都只作于特定类型的GDI对象:
HPENSelectPen(HPENhPen)
HBRUSHSelectBrush(HBRUSHhBrush)
HFONTSelectFont(HFONThFont)
HBITMAPSelectBitmap(HBITMAPhBitmap)
intSelectRgn(HRGNhRgn)
HPALETTESelectPalette(HPALETTEhPalette,BOOLbForceBackground)
在调试模式的构建中,每个方法都会断言
m_hDC
为非NULL值,而且参数是恰当类型的GDI对象的句柄。
然后再调用
API,并将其返回值转型为合适的类型。
还存在着几个辅助函数,它们先用给定的常量调用
GetStockObject(),然后再把对象选入到DC:
HPENSelectStockPen(intnPen)
HBRUSHSelectStockBrush(intnBrush)
HFONTSelectStockFont(intnFont)
HPALETTESelectStockPalette(intnPalette,BOOLbForceBackground)
与MFC封装类的区别
较少的构造函数:
WTL的封装类缺少可以创建新的GDI对象的构造函数。
比如,MFC的
CBrush
有一个构造函数可以创建一个实心画刷或者模式(patterne)画刷。
而使用WTL的类,你必须使用某个方法来创建该GDI对象。
用更好的方法把对象选入DC:
参看上面使用CDCT
节
没有
m_hAttribDC:
m_hAttribDC
成员
一些方法里有少许的参数差异:
例如,CDC:
:
GetWindowExt()
在MFC里返回一个
CSize
对象,而在WTL里返回一个
bool,而大小通过输出参数来返回。
资源加载函数
WTL里的若干个全局函数是极具帮助的加载不同类型的资源的捷径。
在接触这些函数之前,我们需要了解一个工具类:
_U_STRINGorID。
在Win32中,大多数资源可以用一个字符串(LPCTSTR)或者一个无符号整数(UINT)来标识。
接收资源标识符的API需要接收一个
LPCTSTR
参数,如果要传递一个
UINT
的话,你需要使用
MAKEINTRESOURCE
宏来将之转换为一个
LPCTSTR。
_U_STRINGorID,当作为资源标识符参数类型来使用的时候,会隐藏这一不同,因而调用者就可以直接传递
如果需要的话,函数可以使用一个
来加载字符串:
voidsomefunc(_U_STRINGorIDid)
{
CStringstr(id.m_lpstr);
//usestr...
}
voidfunc2()
//Call1-usingastringliteral
somefunc(_T("
WillowRosenberg"
));
//Call2-usingastringresourceID
somefunc(IDS_BUFFY_SUMMERS);
这能够工作的原因是,CString
接收
的构造函数会检查参数是否是一个字符串ID。
如果是的话,就会从字符串表中加载该字符串并赋予该
CString。
在VC6里,_U_STRINGorID
由WTL在
atlwinx.h
中提供;
在VC7里,_U_STRINGorID
是ATL的一部分。
无论哪种,这个类的定义总会被其他的ATL/WTL头文件包含进来。
此节中的函数都是从保存在
_Module
全局变量(VC6)或者
_AtlBaseModule
(VC7)中的资源实例句柄加载资源。
使用其他模块的资源超出了本文的范围,因此我在这儿不会提及。
只需要记住,缺省情况下,这些函数总是在代码正运行于其中的EXE或者DLL中寻找。
这些函数并没有比调用API多做什么,它们的作用在于由
_U_STRINGorID
所提供的资源标识符的处理简化上。
HACCELAtlLoadAccelerators(_U_STRINGorIDtable)
调用流向
LoadAccelerators()。
HMENUAtlLoadMenu(_U_STRINGorIDmenu)
LoadMenu()。
HBITMAPAtlLoadBitmap(_U_STRINGorIDbitmap)
LoadBitmap()。
HCURSORAtlLoadCursor(_U_STRINGorIDcursor)
LoadCursor()。
HICONAtlLoadIcon(_U_STRINGorIDicon)
LoadIcon()。
注意一下这个函数,和
LoadIcon()
一样,仅可以加载32x32图标。
intAtlLoadString(UINTuID,LPTSTRlpBuffer,intnBufferMax)
boolAtlLoadString(UINTuID,BSTR&
bstrText)
LoadString()。
字符串可以返回至一个
TCHAR
缓冲区,或者是赋与一个
BSTR,取决于你使用哪一个重载。
注意这两个函数仅接收
作为其资源ID,因为字符串表项不能有字符串标识符。
下面这组函数封装了对
LoadImage()
的调用,而且还接受传递给
的附加参数。
HBITMAPAtlLoadBitmapImage(
_U_STRINGorIDbitmap,UINTfuLoad=LR_DEFAULTCOLOR)
使用
IMAGE_BITMAP
类型调用
LoadImage(),并将
fuLoad
标志传入。
HCURSORAtlLoadCursorImage(
_U_STRINGorIDcursor,
UINTfuLoad=LR_DEFAULTCOLOR|LR_DEFAULTSIZE,
intcxDesired=0,intcyDesired=0)
IMAGE_CURSOR
由于一个光标资源可以包含若干个不同尺寸的光标,因而你可以把尺寸传递给cxDesired
cyDesired
参数以加载一个特定大小的光标。
HICONAtlLoadIconImage(
_U_STRINGorIDicon,
IMAGE_ICON
cxDesired
参数的用法同
AtlLoadCursorImage()。
下面这一组函数封装了加载系统定义的资源(例如,标准的手状光标)的调用。
其中的一些资源ID(主要是位图的那些)缺省是不被包含的,需要在你的stdafx.h
文件中
#define
OEMRESOURCE
符号来引用它们。
HBITMAPAtlLoadSysBitmap(LPCTSTRlpBitmapName)
使用NULL资源句柄调用
使用此函数可以加载任何在
LoadBitmap()
的文档中列出的
OBM_*
位图。
HCURSORAtlLoadSysCursor(LPCTSTRlpCursorName)
LoadCursor()
IDC_*
光标。
HICONAtlLoadSysIcon(LPCTSTRlpIconName)
IDI_*
图标。
不过要注意此函数——就像LoadIcon()
——只能加载32x32的图标。
HBITMAPAtlLoadSysBitmapImage(
WORDwBitmapID,UINTfuLoad=LR_DEFAULTCOLOR)
使用NULL资源句柄以及
LoadImage()。
你可以使用此函数来加载与
AtlLoadSysBitmap()
相同的位图。
HCURSORAtlLoadSysCursorImage(
AtlLoadSysCursor()
相同的光标。
HICONAtlLoadSysIconImage(
AtlLoadSysIcon()
相同的图标,不过可以指定一个不同的尺寸,例如16x16。
最后的这组函数是对
GetStockObject()
API的类型安全的封装。
HPENAtlGetStockPen(intnPen)
HBRUSHAtlGetStockBrush(intnBrush)
HFONTAtlGetStockFont(intnFont)
HPALETTEAtlGetStockPalette(intnPalette)
每个函数都会检查你是不是传入了恰当的值(比方说,AtlGetStockPen()
只接受
WHITE_PEN,BLACK_PEN
等值),然后再调用
GetStockObject()。
使用公用对话框
WTL还有些类,可以使Win32的公用对话框使用起来更容易些。
每个类都会处理公用对话框发送的消息以及回调,并依次调用那些可覆盖的函数。
这和用于属性表的设计是一样的,只不过在那儿你是为各个被
CPropertyPageImpl
在必要时调用的属性表通知编写处理器,例如
OnWizardNext(),用来处理
PSN_WIZNEXT。
WTL为每种公用对话框都包含了两个类,例如,选择文件夹对话框由
CFolderDialogImpl
CFolderDialog
封装。
如果需要改变缺省行为,或者是要为某个消息编写处理器,你可以从
派生一个新类并在其中作改动。
的缺省行为已经足够了,则你可以使用
CFolderDialog。
公用对话框及其相应的WTL类有:
公用对话框
相应的Win32API
实现类
不可定制类
文件打开和文件保存
GetOpenFileName(),
GetSaveFileName()
CFileDialogImpl
CFileDialog
选择文件夹
SHBrowseForFolder()
CFolderDialogImpl
CFolderDialog
选择字体
ChooseFont()
CFontDialogImpl,
CRichEditFontDialogImpl
CFontDialog,
CRichEditFontDialog
选择颜色
ChooseColor()
CColorDialogImpl
CColorDialog
打印及打印设置
PrintDlg()
CPrintDialogImpl
CPrintDialog
打印(Windows2000及之后)
PrintDlgEx()
CPrintDialogExImpl
CPrintDialogEx
页面设置
PageSetupDlg()
CPageSetupDialogImpl
CPageSetupDialog
文本查找及替换
FindText(),
ReplaceText()
CFindReplaceDialogImpl
CFindReplaceDialog
把这些类全写出来将会使本文相当的长,因此我只选择了前两个,也正是你在使用中经常用到的两个。
CFileDialog
及其基类
CFileDialogImpl
用于显示文件打开和文件保存对话框。
中最重要的两个数据成员是
m_ofn
m_szFileName。
是一个OPENFILENAME
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ATLWTL 第九 部分