windows程序设计第4章-Text Output练习(83-1121)
Painting和重绘
通过Post WM_PAINT消息通知WndProc,客户区的无效区域要重绘。
WM_PAINT消息
在以下情况下WndProc收到WM_PAINT
1.被遮挡的区域通过窗口移动又重现
2..resize
3. ScrollWindow或ScrollDC的调用,以scroll客户区
4. 程序调用了InvalidateRect或InvalidateRgn
有时,当客户区的某部分被暂时重写时,Windows也会试图保存之前的display以便restore。但不保证成功,所以有时Windows也会post WM_PAINT消息,有下列几种情况:
1.对话框,消息框在客户区的移动
2.menu拉动
3.tool tip显示
在下列情况,windows可以restore之前保存的display
1.mouse光标移动
2.icon拖曳入客户区
Valid和Invalid矩形区
每次只需更新一个小的区域,即有display更改的矩形区域,以提高绘制效率。当客户区有invalid区时,Windows就会将WM_PAINT消息放置到消息队列。
Wndows内部对每个窗口都维护了一个paint information structure,对于invalid区,包含了一个最小的能encompass invalid区的矩形,即”invalid矩形”。倘若在WndProc处理等待的WM_PAINT消息之前,又有新的invalid区产生,则Windows会计算对应的新的invalid矩形。
WndProc可以通过调用InvalidateRect函数,来使自己的客户区的一个矩形变成invalid矩形,倘若此时队列中有WM_PAINT,则合并生成新的invalid矩形,否则,则放置一个WM_PAINT到队列。
通过GetUpdateRect,我们可得到invalid矩形的坐标。而通过调用ValidateRect函数,可将任一矩形区设为valid,如果该函数将整个客户区都validate了,那么队列中的WM_PAINT将统统被移去。(有invalid矩形,才有重绘的必要)。
GDI介绍
GDI(Graphics Device Interface)。
设备上下文(DC)
DC是GDI内部维护的一个数据结构,它和一个特定的显示设备联系在一起。DC有一些graphics的属性值,诸如文字颜色,字体等等。用完DC后,要记得release。
获取DC句柄:法1
在处理WM_PAINT时用此法,涉及两个函数,BeginPaint和EndPaint。使用前者填充PAINTSTRUCT结构ps,并返回DC句柄,后者负责释放DC。
必须成对出现。另外,有一个很重要的clipping区的概念,windows只能在clipping区绘制,调用BeginPaint,将会把Update区设为clipping区,如果有标志要erase背景,则BeginPaint会将Update区的背景擦掉。BeginPaint还会把invalid区设为有效,不用担心,原来的invalid区信息已保存在DC和ps中。
Paint信息结构
fErase:是否要erase背景,如果之前调用了BeginPaint,则不需要,如果调用InvalidateRect,并将该函数的最后一个参数设为0,则引发的WM_PAINT处理时,fErase为真,需要erase invalid矩形的背景。
rcPaint: 客户区中的invalid 矩形,此为应该绘制之所。
获取DC句柄:法2
在WM_PAINT处理之外,用GetDC得到DC,最后用ReleaseDC释放。此法返回的DC的clipping区是整个客户区,即可以随便画。而且它不会validate任何区域,若想validate整个客户区,需调用
ValidateRect(hwnd,NULL)
TextOut:细说
TextOut(hdc,x,y,psTest,iLength);
系统字体
不同的字符宽度不一。
字符大小
系统字体的height和平均width。有用的函数:GetTextMetrics
Text Metrics:细节
LONG tmHeight ;
LONG tmAscent ;
LONG tmDescent ;
LONG tmInternalLeading ;
LONG tmExternalLeading ;
LONG tmAveCharWidth ;
LONG tmMaxCharWidth ;
格式化文本
sprintf,wsprintf,不好用printf了
putting it all together
例子程序:利用GetSystemMetrics获取各种属性,并打印在客户区。
/*----------------------------------------------- SYSMETS.H -- System metrics display structure -----------------------------------------------*/ #define NUMLINES ((int) (sizeof sysmetrics / sizeof sysmetrics [0])) struct { int iIndex; TCHAR * szLabel; TCHAR * szDesc; } sysmetrics[] = { SM_CXSCREEN, TEXT ("SM_CXSCREEN"), TEXT ("Screen width in pixels"), SM_CYSCREEN, TEXT ("SM_CYSCREEN"), TEXT ("Screen height in pixels"), SM_CXVSCROLL, TEXT ("SM_CXVSCROLL"), TEXT ("Vertical scroll width"), SM_CYHSCROLL, TEXT ("SM_CYHSCROLL"), TEXT ("Horizontal scroll height"), SM_CYCAPTION, TEXT ("SM_CYCAPTION"), TEXT ("Caption bar height"), SM_CXBORDER, TEXT ("SM_CXBORDER"), TEXT ("Window border width"), SM_CYBORDER, TEXT ("SM_CYBORDER"), TEXT ("Window border height"), SM_CXFIXEDFRAME, TEXT ("SM_CXFIXEDFRAME"), TEXT ("Dialog window frame width"), SM_CYFIXEDFRAME, TEXT ("SM_CYFIXEDFRAME"), TEXT ("Dialog window frame height"), SM_CYVTHUMB, TEXT ("SM_CYVTHUMB"), TEXT ("Vertical scroll thumb height"), SM_CXHTHUMB, TEXT ("SM_CXHTHUMB"), TEXT ("Horizontal scroll thumb width"), SM_CXICON, TEXT ("SM_CXICON"), TEXT ("Icon width"), SM_CYICON, TEXT ("SM_CYICON"), TEXT ("Icon height"), SM_CXCURSOR, TEXT ("SM_CXCURSOR"), TEXT ("Cursor width"), SM_CYCURSOR, TEXT ("SM_CYCURSOR"), TEXT ("Cursor height"), SM_CYMENU, TEXT ("SM_CYMENU"), TEXT ("Menu bar height"), SM_CXFULLSCREEN, TEXT ("SM_CXFULLSCREEN"), TEXT ("Full screen client area width"), SM_CYFULLSCREEN, TEXT ("SM_CYFULLSCREEN"), TEXT ("Full screen client area height"), SM_CYKANJIWINDOW, TEXT ("SM_CYKANJIWINDOW"), TEXT ("Kanji window height"), SM_MOUSEPRESENT, TEXT ("SM_MOUSEPRESENT"), TEXT ("Mouse present flag"), SM_CYVSCROLL, TEXT ("SM_CYVSCROLL"), TEXT ("Vertical scroll arrow height"), SM_CXHSCROLL, TEXT ("SM_CXHSCROLL"), TEXT ("Horizontal scroll arrow width"), SM_DEBUG, TEXT ("SM_DEBUG"), TEXT ("Debug version flag"), SM_SWAPBUTTON, TEXT ("SM_SWAPBUTTON"), TEXT ("Mouse buttons swapped flag"), SM_CXMIN, TEXT ("SM_CXMIN"), TEXT ("Minimum window width"), SM_CYMIN, TEXT ("SM_CYMIN"), TEXT ("Minimum window height"), SM_CXSIZE, TEXT ("SM_CXSIZE"), TEXT ("Min/Max/Close button width"), SM_CYSIZE, TEXT ("SM_CYSIZE"), TEXT ("Min/Max/Close button height"), SM_CXSIZEFRAME, TEXT ("SM_CXSIZEFRAME"), TEXT ("Window sizing frame width"), SM_CYSIZEFRAME, TEXT ("SM_CYSIZEFRAME"), TEXT ("Window sizing frame height"), SM_CXMINTRACK, TEXT ("SM_CXMINTRACK"), TEXT ("Minimum window tracking width"), SM_CYMINTRACK, TEXT ("SM_CYMINTRACK"), TEXT ("Minimum window tracking height"), SM_CXDOUBLECLK, TEXT ("SM_CXDOUBLECLK"), TEXT ("Double click x tolerance"), SM_CYDOUBLECLK, TEXT ("SM_CYDOUBLECLK"), TEXT ("Double click y tolerance"), SM_CXICONSPACING, TEXT ("SM_CXICONSPACING"), TEXT ("Horizontal icon spacing"), SM_CYICONSPACING, TEXT ("SM_CYICONSPACING"), TEXT ("Vertical icon spacing"), SM_MENUDROPALIGNMENT, TEXT ("SM_MENUDROPALIGNMENT"),TEXT ("Left or right menu drop"), SM_PENWINDOWS, TEXT ("SM_PENWINDOWS"), TEXT ("Pen extensions installed"), SM_DBCSENABLED, TEXT ("SM_DBCSENABLED"), TEXT ("Double-Byte Char Set enabled"), SM_CMOUSEBUTTONS, TEXT ("SM_CMOUSEBUTTONS"), TEXT ("Number of mouse buttons"), SM_SECURE, TEXT ("SM_SECURE"), TEXT ("Security present flag"), SM_CXEDGE, TEXT ("SM_CXEDGE"), TEXT ("3-D border width"), SM_CYEDGE, TEXT ("SM_CYEDGE"), TEXT ("3-D border height"), SM_CXMINSPACING, TEXT ("SM_CXMINSPACING"), TEXT ("Minimized window spacing width"), SM_CYMINSPACING, TEXT ("SM_CYMINSPACING"), TEXT ("Minimized window spacing height"), SM_CXSMICON, TEXT ("SM_CXSMICON"), TEXT ("Small icon width"), SM_CYSMICON, TEXT ("SM_CYSMICON"), TEXT ("Small icon height"), SM_CYSMCAPTION, TEXT ("SM_CYSMCAPTION"), TEXT ("Small caption height"), SM_CXSMSIZE, TEXT ("SM_CXSMSIZE"), TEXT ("Small caption button width"), SM_CYSMSIZE, TEXT ("SM_CYSMSIZE"), TEXT ("Small caption button height"), SM_CXMENUSIZE, TEXT ("SM_CXMENUSIZE"), TEXT ("Menu bar button width"), SM_CYMENUSIZE, TEXT ("SM_CYMENUSIZE"), TEXT ("Menu bar button height"), SM_ARRANGE, TEXT ("SM_ARRANGE"), TEXT ("How minimized windows arranged"), SM_CXMINIMIZED, TEXT ("SM_CXMINIMIZED"), TEXT ("Minimized window width"), SM_CYMINIMIZED, TEXT ("SM_CYMINIMIZED"), TEXT ("Minimized window height"), SM_CXMAXTRACK, TEXT ("SM_CXMAXTRACK"), TEXT ("Maximum draggable width"), SM_CYMAXTRACK, TEXT ("SM_CYMAXTRACK"), TEXT ("Maximum draggable height"), SM_CXMAXIMIZED, TEXT ("SM_CXMAXIMIZED"), TEXT ("Width of maximized window"), SM_CYMAXIMIZED, TEXT ("SM_CYMAXIMIZED"), TEXT ("Height of maximized window"), SM_NETWORK, TEXT ("SM_NETWORK"), TEXT ("Network present flag"), SM_CLEANBOOT, TEXT ("SM_CLEANBOOT"), TEXT ("How system was booted"), SM_CXDRAG, TEXT ("SM_CXDRAG"), TEXT ("Avoid drag x tolerance"), SM_CYDRAG, TEXT ("SM_CYDRAG"), TEXT ("Avoid drag y tolerance"), SM_SHOWSOUNDS, TEXT ("SM_SHOWSOUNDS"), TEXT ("Present sounds visually"), SM_CXMENUCHECK, TEXT ("SM_CXMENUCHECK"), TEXT ("Menu check-mark width"), SM_CYMENUCHECK, TEXT ("SM_CYMENUCHECK"), TEXT ("Menu check-mark height"), SM_SLOWMACHINE, TEXT ("SM_SLOWMACHINE"), TEXT ("Slow processor flag"), SM_MIDEASTENABLED, TEXT ("SM_MIDEASTENABLED"), TEXT ("Hebrew and Arabic enabled flag"), SM_MOUSEWHEELPRESENT, TEXT ("SM_MOUSEWHEELPRESENT"),TEXT ("Mouse wheel present flag"), SM_XVIRTUALSCREEN, TEXT ("SM_XVIRTUALSCREEN"), TEXT ("Virtual screen x origin"), SM_YVIRTUALSCREEN, TEXT ("SM_YVIRTUALSCREEN"), TEXT ("Virtual screen y origin"), SM_CXVIRTUALSCREEN, TEXT ("SM_CXVIRTUALSCREEN"),TEXT ("Virtual screen width"), SM_CYVIRTUALSCREEN, TEXT ("SM_CYVIRTUALSCREEN"),TEXT ("Virtual screen height"), SM_CMONITORS, TEXT ("SM_CMONITORS"), TEXT ("Number of monitors"), SM_SAMEDISPLAYFORMAT, TEXT ("SM_SAMEDISPLAYFORMAT"),TEXT ("Same color format flag") };
//SYSMETS1.cpp
#include <Windows.h> #include "SYSMETS.h" LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow) { static TCHAR szAppName[] = TEXT("SysMets1"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL,TEXT("fail!"),szAppName,MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("Get System Metrics No. 1"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); ShowWindow(hwnd,iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; // return 0; } //WParam是int,LPARAM是long LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { static int cxChar,cxCaps,cyChar; HDC hdc; PAINTSTRUCT ps; TCHAR szBuffer[10]; TEXTMETRIC tm; switch(message) { case WM_CREATE: hdc = GetDC(hwnd); GetTextMetrics(hdc,&tm); cxChar = tm.tmAveCharWidth; cxCaps = (tm.tmPitchAndFamily & 1 ? 3:2) * cxChar / 2; cyChar = tm.tmHeight + tm.tmExternalLeading; ReleaseDC(hwnd,hdc); return 0; case WM_PAINT: hdc = BeginPaint(hwnd,&ps); for(int i =0;i < NUMLINES;i++) { TextOut(hdc,0,cyChar * i,sysmetrics[i].szLabel,lstrlen(sysmetrics[i].szLabel)); TextOut(hdc,22 * cxCaps,cyChar * i,sysmetrics[i].szDesc,lstrlen(sysmetrics[i].szDesc)); SetTextAlign(hdc,TA_RIGHT | TA_TOP); int len = wsprintf(szBuffer,TEXT("%5d"),GetSystemMetrics(sysmetrics[i].iIndex)); TextOut(hdc, 22 * cxCaps + 40 * cxChar, cyChar * i,szBuffer,len); SetTextAlign(hdc,TA_LEFT | TA_TOP); } EndPaint(hwnd,&ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd,message,wParam,lParam); }
SYSMETS2.cpp
#include <Windows.h> #include "SYSMETS.h" LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow) { static TCHAR szAppName[] = TEXT("SysMets2"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL,TEXT("fail!"),szAppName,MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("Get System Metrics No. 2"), WS_OVERLAPPEDWINDOW | WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); ShowWindow(hwnd,iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; // return 0; } //WParam是int,LPARAM是long LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { static int cxChar,cxCaps,cyChar,cyClient,iVscrollPos; HDC hdc; PAINTSTRUCT ps; TCHAR szBuffer[10]; TEXTMETRIC tm; switch(message) { case WM_CREATE: hdc = GetDC(hwnd); GetTextMetrics(hdc,&tm); cxChar = tm.tmAveCharWidth; cxCaps = (tm.tmPitchAndFamily & 1 ? 3:2) * cxChar / 2; cyChar = tm.tmHeight + tm.tmExternalLeading; ReleaseDC(hwnd,hdc); SetScrollRange(hwnd,SB_VERT,0,NUMLINES - 1,FALSE); SetScrollPos(hwnd,SB_VERT,iVscrollPos,TRUE); return 0; case WM_SIZE: cyClient = HIWORD(lParam); return 0; case WM_VSCROLL: switch(LOWORD(wParam)) { case SB_LINEUP: iVscrollPos --; break; case SB_LINEDOWN: iVscrollPos ++; break; case SB_PAGEUP: iVscrollPos -= cyClient / cyChar; break; case SB_PAGEDOWN: iVscrollPos += cyClient / cyChar; break; case SB_THUMBPOSITION: iVscrollPos = HIWORD(wParam); break; default: break; } iVscrollPos = max(0,min(iVscrollPos,NUMLINES - 1)); if (iVscrollPos != GetScrollPos(hwnd,SB_VERT)) { SetScrollPos(hwnd,SB_VERT,iVscrollPos,TRUE); InvalidateRect(hwnd,NULL,TRUE); UpdateWindow(hwnd);//马上绘制 } case WM_PAINT: hdc = BeginPaint(hwnd,&ps); for(int i =0;i < NUMLINES;i++) { int y = cyChar * (i - iVscrollPos); TextOut(hdc,0,y,sysmetrics[i].szLabel,lstrlen(sysmetrics[i].szLabel)); TextOut(hdc,22 * cxCaps,y,sysmetrics[i].szDesc,lstrlen(sysmetrics[i].szDesc)); SetTextAlign(hdc,TA_RIGHT | TA_TOP); int len = wsprintf(szBuffer,TEXT("%5d"),GetSystemMetrics(sysmetrics[i].iIndex)); TextOut(hdc, 22 * cxCaps + 40 * cxChar, y,szBuffer,len); SetTextAlign(hdc,TA_LEFT | TA_TOP); } EndPaint(hwnd,&ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd,message,wParam,lParam); }
posted on 2010-05-10 00:17 speedmancs 阅读(479) 评论(0) 编辑 收藏 举报