您的位置:首页 > 编程语言 > PHP开发

windows程序设计第4章-Text Output练习(83-1121)

2010-05-10 00:17 204 查看
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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: