前面看了几天的书,发现那本书太厚了1600多页,是我认真看过的最厚的书,看着就累,我不知道作者和翻译是怎么坚持下来的,这么多的文字就那么写完了;由于有工作要做,并且与计算机的联系不大,自学的时候感到很累,所以学习进度有点慢..........不过这个是我的兴趣,学起来虽然感觉累,但也乐在其中...嘿嘿
上次说到了windows程序显示和更新窗口的WM_PAINT消息的处理机制,这次接着上次没有说完的话题继续瞎扯........
非WM_PAINT消息期间绘制显示区域
在应用程序编制过程中,有时不需要绘制显示区域,而只想获得一些设备内容的信息;或者我们想在非WM_PAINT消息处理期间绘
制显示区域的某个区域,这时我们就需要采用另外一种方法了。我们通过下面的方式进行处理:
1、获取设备内容句柄和释放设备内容句柄:
我们可以通过下面两个API函数来获取设备内容句柄和释放设备内容句柄:
获取设备内容句柄: GetDC
原型:
HDC GetDC(HWND);
释放设备内容句柄: ReleaseDC
原型:
int ReleaseDC(HWMD ,HDC )
2、Tip:
这里和BeginPaint和EndPaint一样, GetDC和ReleaseDC函数必须成对的使用,若在某个消息处理的时使用呼叫GetDC则
必须在同一个消息处理期间呼叫ReleaseDC函数。
不能在处理A消息时呼叫GetDC,而在处理B消息时呼叫ReleaseDC。
3、与BeginPaint的比较
GetDC同样可以获取设备内容句柄,但是与BeginPaint不一样的是:GetDC不会使任何无效区域变为有效;
这个可以理解:
我们知道当产生无效区域的时候,系统会记录无效区域的形态同时发送一个WM_PAINT消息,同时在呼叫
BeginPaint函数时会清除WM_PAINT消息,而GetDC函数不会清除WM_PAINT, 我们知道只要有WM_PAINT消息,
则会存在无效区域。
GetDC返回的设备内容句柄具有一个剪取矩形,它等于整个显示区域,这样就可以在显示区域的某一部分绘制
而不仅仅是在无效矩形上绘制。
4、如何不调用BeginPaint函数而是整个区域有效,可以呼叫:
ValideteRect(hwnd,NULL);
这样就可以清除系统投递到消息队列的WM_PAINT消息。
5、使用GetDC和ReleaseDC
可以呼叫GetDC和ReleaseDC来对键盘消息和鼠标消息作出响应, 这样就可以通过鼠标或者键盘输入来更新显
示区域,而不需要等到窗口出现无效区域在对窗口进行绘制。
6、GetDC与GetWindowDC
GetDC返回一个用于在显示区域进行绘制的设备内容句柄,而GetWindow函数返回一个用于在整个窗口进行绘制的
设备内容句柄。
程序同样应该处理 WM_NCPAINT 非显示区域绘制消息。
窗口绘制的步骤:
1、获取要被绘制窗口的设备内容句柄
2、调用GDI进行窗口绘制
3、释放设备内容句柄。
4.5 TextOut函数
TextOut函数用于显示文字;其语法是:
TextOut(hdc, x, y, psText,iLength);
参数:
hdc: 设备内容句柄,可以是GetDC和BeginPaint函数返回的句柄
设备内容的属性控制被显示的字符串的特征
在设备内容中有一个属性指定文字的颜色,缺省的颜色为黑色,缺省设备内容还定义了白色的字符输出背景,在
用TextOut函数输出文字时,就按照这个缺省的设备内容属性进行文字的输出显示。
改文字背景色与窗口类别定义时设备的背景不相同,窗口类别中的背景是一个画刷,被windows用来擦除显示区域,不是设备
内容的一部分。通常为了使windows擦除的窗口显示区域的背景画刷与缺省文字背景颜色相同,会将wndclass.hbrBackground
画刷设置成白色画刷WHITE_BRUSH.
psText: 待显示的字符串, 字符串中不能包括ASCII控制字符(如换行、回车、制表和退格),windows会将这些显示为实心块。
x,y: x和y是字符显示时的开始坐标位置。x是水平位置,方向向右值增加; y是垂直位置,向下方向值增加。(0,0)是应用程序
显示区域的左上角。这个坐标系成为逻辑坐标系。在Windows内部有多种坐标映像方式,这些坐标映像方式将控制GDI函数指定的逻辑
位置转换为实际图素坐标的显示坐标。在设备内容定义,缺省方式是MM_TEXT, 其单位与实际单位相同,都是图素。
设备内容定义了一个剪裁区域, GetDC获取的设备内容句柄为整个显示区域;而BeginPaint取得的设备内容句柄为无效区域。windows
不会在剪裁区域之外的任何位置绘制字符串。
系统字体:
设备内容定义了TextOut显示文字时windows使用的字体, 缺省字体为系统字体,或用windows表头文件中的标识符SYSTEM_FONT,
系统字体是windows用在标题栏、菜单和对话框中显示字符串的缺省字体。
字符大小
windows显示器的图素最小是640*480。 可以通过呼叫系统函数来获取各种信息。
1、 GetSystemMetrics函数取得使用者接口上各类视觉组件大小的信息,
2、 GetTextMetrics取得字体的大小,GetTextMetrics返回设备内容中当前选择的字体的信息,
因此GetTextMetrics函数需要操作设备内容句柄, 调用这个函数时windows将文字大小不同的值赋值
到TEXTMETRICS结构体中。
TEXTMETRICS结构体共有20个字段,通常我们需要操作的是前面的几个字段
typedef struct tagTEXTMETRIC
{
LONG tmHeght; //tmHeight=tmAscent+tmDescent 表示了在基准线下字符的最大高度
LONG tmAscent;
LONG tmDescent;
LONG tmInternalLeading;
LONG tmExternalLeading;
LONG tmAveCharWidth;
LONG tmMaxCharWidth;
其他字段;
}TEXTMETRIC, *PTEXTMETRIC;
leading:即间距指打印机在两行文字间插入的空间,在TEXTMETRIC结构中,内部间距包括在tmAscent中,并且通常
是重音符号出现的地方。tmInternalLeading字段可以设置成0,这时重音符的字母会稍稍缩短以打印重音符号。
TEXTMETRICS结构包含有描述字符宽度的两个字段:
tmAveCharWidth: 小写字母加权平均宽度
tmMaxCharWidth: 字体中最宽字符的宽度
这里要说明的是: windows使用的是非等宽的字体, 例如 W就比i宽。
大写字母的平均宽度: 大约可以用tmAveCharWidth * 150 % 计算。
上面的字段值的单位取决于选定的设备内容映像方式,在缺省的情况下,映像方式是MM_TEXT,其以图素为单位。
通过下面的方式获取文字的信息:
HDC hdc;
TEXTMETRIC tm;
hdc= GetDC(hwnd)
GetTxtMetrics(hdc, &tm);
ReleaseDC(hwnd,hdc);
这样就可以通过tm结构体变量的各个字段查看当前设备内容中关于字符的信息。
格式化文字:
windows启动后,系统字体的大小就不会发生改变。程序当中可以呼叫一次GetTextMetrics函数,获取系统字体的信息就可以一直使用。
通常建议在处理WM_CREATE消息时进行上述的GetTextMetrics函数呼叫,因为WM_CREATE消息是窗口消息处理程序接收的第一个消息。
可以这样处理:
在消息处理程序中定义:
static int cxChar, //存储系统字符的宽度
cyChar; //存储系统字符的高度
而在消息处理时:
case WM_CREATE:
hdc=GetDC(hwnd);
GetTextMetrics(hdc,&tm);
cxChar=tm.tmAvdCharWidth;
cyChar=tm.tmHeight+tm.tmExternalLeading;
Release(hwnd,hdc);
return 0;
格式化字符串函数: sprintf和wsprintf(windows下可用)。
wspritnf函数原型:
int wsprintf(char *dest,char *source,...);
Exp:
int iLength;
TCHAR szBuffer[40];
iLength=wsprintf(szBuffer,TEXT("the sum of %i and %i is %i"),iA,iB,iA+iB);
TextOut(hdc,x,y,szBuffer,iLength);
wsprintf函数将格式化完的字符串放到一个字符串中,并且这个函数返回放入到字符串中的字符的个数。
这样正好符合TextOut函数的使用的两个参数。
因为函数的调用方式是__stdcall方式,所以可以:
TextOut(hdc,x,y,szBuffer,wsprintf(szBuffer,TEXT("the sum of %i and %i is %i"),iA,iB,iA+iB) )。
获取系统视觉组件大小信息:
GetSyetemMetrics函数
GetSystemMetrics函数返回windows中不同视觉组件的大小信息;如图标、光标、标题栏和滚动条等。这些大小与显示卡
和驱动程序相关。
其函数原型是:
int WINAPI GetSystemMetrics(int index)
今天瞎掰就暂时到这,这里说的有点乱, 不过估计理解应该没有什么问题....................
下一次估计要说滚动条了, 前几天看书,没太看明白, 等看明白后再来瞎掰..........
编制windows的应用程序主要是明白其事件驱动机制以及各个功能的内在机理, 通过那本经典的书可以增强对windows程序的认识, 如果学习有一定的基础的话,同样可以学习那本经典核心编程课程, 也是1000+以上的书,估计看完要一阵子......
计划慢慢的学完这本书,然后在看看罗老师的那本700多页的书, 估计会对windows的运行机理有个大概的认识吧.......
也许以后转行到挨踢行业,也许就不转了.........
谁知道以后的事情呢?