小雅以前刚学VC时感觉号称强大的VC一点儿也不方便,想要一行中有不同字体和颜色也不行。其实,所谓“不行”是自己还不会,会了之后就觉得VC实在很强大。
在前面章节中说过,设备文本句柄的方法也可用GetDC()函数,网上和有的书上说BeginPaint()函数只能用于WM_PAINT,其它地方一般不用,而GetDC()函数不能用在WM_PAINT下,其它地方可以用。关于这一点,小雅将通过一个例子来说明,这个例子是在指定位置显示一行文字,用DrawText()可以实现,但这儿用TextOut()函数来实现更方便。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { TCHAR szHello[64]="Wecome you to Http://www.quanxue.cn/!"; HDC hdc;switch
(message) {case
WM_PAINT: hdc = GetDC(hWnd); SetTextColor(hdc, 0x0000FF); SetBkColor(hdc, 0xCDFAFF); TextOut(hdc,30,20,szHello,(int
)strlen(szHello)); //下面三行程序如果没有,窗口不正常地闪动 RECT rt; GetClientRect(hWnd, &rt); ValidateRect(hWnd, &rt); //让窗口有效区变得有效 ReleaseDC(hWnd, hdc);break
;case
WM_DESTROY: PostQuitMessage(0);break
;default
:return
DefWindowProc(hWnd, message, wParam, lParam); }return
0; }
在BeginPaint()函数的帮助上清楚地写着,这个函数将自动更新有效区。原来窗口只要发生任何改变,操作系统都会发送一个WM_PAINT消息来通知窗口刷新,在WM_PAINT中使用BeginPaint()函数,这个函数自动告诉操作系统窗口已经是最新的了。而GetDC()没有这个功能,因此GetDC()一般不用于WM_PAINT消息中,如果一定要在WM_PAINT中使用,那就要用ValidateRect()函数来手动刷新窗口。
在一行中显示不下时,可以改变字体的大小来使一行能够显示。字体和后面章节中讲到的画笔、画刷的使用方法是一样的,都是调用SelectObject()函数来把字体句柄与设备文本句柄进行绑定,同时得到绑定前的字体句柄,用完之后,不能忘记把原来的字体句柄绑定回去,这样,后面如果还有程序的话,可以不受任何影响。
创建字体是用CreateFont()函数来实现的,这儿说的“创建字体”并不是自创一个欧体还是柳体,而是创建一个字体对象,其中包括文字的宽度、高度、角度等许多信息。创建的字体用完之后也一定要手动删除,删除字体用DeleteObject()函数。
下面的例子只改变宽度、高度和字体,当窗口改变大小时,用窗口的宽度除以字符串长度,得到单个字符的宽度,用窗口高度当作字符高度,当然上下左右都要空一点位置,这样比较美观。例子中rc.right-20和rc.bottom-20就是要上下左右都空10象素。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; HFONT hFont, hFontOld;char
*str="劝学网";int
width, height;switch
(message) {case
WM_PAINT: RECT rc; hdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &rc); SetBkMode(hdc, TRANSPARENT); width = (rc.right - 20) / (int
)strlen(str); height = rc.bottom - 20; hFont = CreateFont( height, //字体的逻辑高度 width, //逻辑平均字符宽度 0, //与水平线的角度 0, //基线方位角度 FW_REGULAR, //字形:常规 FALSE, //字形:斜体 FALSE, //字形:下划线 FALSE, //字形:粗体 GB2312_CHARSET, //字符集 OUT_DEFAULT_PRECIS, //输出精度 CLIP_DEFAULT_PRECIS, //剪截精度 PROOF_QUALITY, //输出品质 FIXED_PITCH | FF_MODERN, //倾斜度 "隶书" //字体 ); hFontOld = (HFONT)SelectObject(hdc, hFont); //选择字体 SetTextColor(hdc, 0xC0C0C0); TextOut(hdc, 10, 10, str, (int
)strlen(str)); SelectObject(hdc, hFontOld); //选择旧字体 DeleteObject(hFont); //删除新字体 EndPaint(hWnd, &ps);break
;case
WM_DESTROY: PostQuitMessage(0);break
;default
:return
DefWindowProc(hWnd, message, wParam, lParam); }return
0; }
在上面的例子中,创建字体时变换了文字的方向。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; HFONT hFont, hFontOld;char
*str1="小 雅";char
*str2="劝学网SDK教程";char
*str3="www.quanxue.cn";int
width, height;switch
(message) {case
WM_PAINT: RECT rc; hdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &rc); SetBkMode(hdc, TRANSPARENT); width = (rc.right - 20) / (int
)strlen(str1); height = rc.bottom - 20; hFont = SetMyFont(hdc, (LPCTSTR)"黑体", width, height, 0); //创建字体 hFontOld = (HFONT)SelectObject(hdc, hFont); //选择新字体 SetTextColor(hdc, 0xC0C0C0); TextOut(hdc, 10, 10, str1, (int
)strlen(str1)); DeleteObject(hFont); //删除新字体 hFont = SetMyFont(hdc, (LPCTSTR)"楷体", 0, 32, 450); //创建字体 SelectObject(hdc, hFont); //选择新字体 SetTextColor(hdc, RGB(0, 0, 255)); TextOut(hdc, -3, rc.bottom-16, str2, (int
)strlen(str2)); DeleteObject(hFont); //删除新字体 hFont = SetMyFont(hdc, (LPCTSTR)"宋体", 0, 32, -450);//创建字体 SelectObject(hdc, hFont); //选择字体 SetTextColor(hdc, RGB(255, 0, 0)); TextOut(hdc, 16, 0, str3, (int
)strlen(str3)); SelectObject(hdc, hFontOld); //选择旧字体 DeleteObject(hFont); //删除新字体 EndPaint(hWnd, &ps);break
;case
WM_DESTROY: PostQuitMessage(0);break
;default
:return
DefWindowProc(hWnd, message, wParam, lParam); }return
0; } HFONT SetMyFont(HDC hdc, LPCTSTR face,int
width,int
height,int
angle) { HFONT hFont; hFont = CreateFont( height, //字体的逻辑高度 width, //逻辑平均字符宽度 angle, //与水平线的角度 0, //基线方位角度 FW_REGULAR, //字形:常规 FALSE, //字形:斜体 FALSE, //字形:下划线 FALSE, //字形:粗体 GB2312_CHARSET, //字符集 OUT_DEFAULT_PRECIS, //输出精度 CLIP_DEFAULT_PRECIS, //剪截精度 PROOF_QUALITY, //输出品质 FIXED_PITCH | FF_MODERN, //倾斜度 face //字体 );return
hFont; }