WM_PAINT
2016-05-26 21:03 sylar_liang 阅读(574) 评论(0) 编辑 收藏 举报WM_PAINT:
BeginPaint(hWnd, &ps);
其中: ps 为
typedef struct tagPAINTSTRUCT
{
HDC hdc; //设备环境句柄
BOOL fErase;
RECT rcPaint;
...
}
主要是前3个参数设置。
bErase大多数情况下被设置为FALSE(默认),意味着Windows在先前的BeginPaint函数中已经擦除了无效区域的背景。
如果想在窗口过程中自定义背景擦除方式,必须自己处理WM_ERASEBKGND消息。
InvalidRect函数使一个矩形无效,最后一个参数传FALSE将指定背景是否要被擦除。
FALSE: Windows不会擦除背景。
TRUE: 擦除。
调用BeginPaint函数后,PAINTSTRUCT的bErase值将是TRUE。
处理WM_PAINT消息时,在调用BeginPaint前调用
InvalidateRect(hWnd, NULL, TRUE);
这个调用将整个客户区无效化,并使其后调用的BeginPaint擦除原有的背景。
最后一个参数设为FALSE,BeginPaint函数将不会擦除背景。
GetDC获取的是整个客户区的设备环境句柄,BeginPaint获取的是无效区域的设备环境句柄。
GetDC不会将无效区域有效化,如需有效化整个客户区,ValidateRect(hWnd, NULL);
GetWindowDC获取的是整个窗口的设备环境句柄。如需修改窗口的标题栏输出,程序还需处理WM_NCPAINT(非客户区绘制)消息。
---
TextOut(hdc, x, y, psText, Length ); //x,y 在客户区的起始位置。距离左上角的坐标点。
文本背景色和窗口类中设定的背景色是不一样的。
传给函数的坐标一般称为 "逻辑坐标";
映射方式决定将GDI绘图函数中的逻辑坐标转换成显示器上的物理像素坐标。默认映射方式是MM_TEXT。
MM_TEXT模式下逻辑单位和物理单位都是像素点。
GetSystemMetrics函数来获取用户界面的尺寸。
GetTextMetrics获取字体尺寸。//定义变量 TEXTMETRIC tm;
typedef struct tagTEXTMETRIC
{
LONG tmHeight;
LONG tmAscent;
LONG tmDescent;
LONG tmInternalLeading;
LONG tmExternalLeading;
...
}
主要是这5个参数。
Leading(间距)是2行文字之间的空间。tmInternalLeading内部间距,通常用于显示重音符号。
tmExternalLeading不包含在tmHeight内,该字段指在两行文字之间留出的空间大小。
tmHeight = tmAscent + tmDescent;
系统字体的尺寸取决于Windows运行时的分辨率,有时还取决于用户选定的系统字号。
tmAscent 包括 tmInternalLeading;
Windows运行时,系统字体不会变化,应用程序只需调用一次GetTextMetrics,最好的时机是在窗口处理WM_CREATE。
定义2个变量来保存字符的平均宽度和总高度:
static int cxChar, cyChar; //变量名中的c 代表 count
示例代码:
GetTextMetrics(hdc, &tm);
cxChar = tm.tmAveCharWidth; //tmAveCharWidth是小写字符的加权平均宽度,tmMaxCharWidth是字体中最宽的字符的宽度。
cyChar = tm.tmHeight + tm.tmExternalLeading; //ExteralLeading 一般为0.
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2; //大写字符的平均宽度。等宽字体中,cxCaps等于cxChar;变宽字体cxCaps是cxChar的1.5倍。tmPitchAndFamily字段的低位决定字体是否为等宽,1 变宽, 0 等宽。
通常需要显示的是格式化的数字和字符串。用 sprintf函数。
WM_SIZE 低位lParam客户区的宽度,wParam客户区的高度。
static int cxClient, cyClient;
cxClient = LWORD(lParam); //cxClient / cxChar 整行能显示的字数。
cyClient = HWORD(wParam); //cyClient 高度
滚动条: CreateWindow 第三个参数加上 WS_HSCROLL(水平滚动条) WS_VSCROLL(垂直滚动条)
SetScrollRange(hWnd, iBar, iMin, iMax, bRedraw); //bRedraw = FALSE,不重绘
//iMin~iMax滚动条范围(默认0-100)
//iBar 要么是 SB_VERT, SB_HORZ
如果在调用SetScrollRange函数之后还将调用其他函数来调整滚动条的显示时,最好将bRedraw设为FALSE避免过多的重绘。
SetScrollPos(hWnd, iBar, iPos, bRedraw); //设置滚动条位置。
消息有: SB_LINEDOWN, SB_LINEUP, SB_PAGEUP, SB_PAGEDOWN, SB_THUMBPOSITION
SB_THUMBTRACK消息,wParam的高位字是用户拖动滑块的当前位置。
SB_THUMBPOSITION消息,wParam的高位字是用户松开鼠标键时滑块的最终位置。 //这个比较好处理,直接调用SetScrollPos函数。
//部分示例代码
iVscrollPos = max(0, min(iVscrollPos, Max- 1)); //可以防止 iVscrollPos小于0的情况。
if (iVscrollPos != GetScrollPos(hWnd, SB_VERT))
{
SetScrollPos(hWnd, SB_VERT, iVscrollPos, TRUE); //bRedraw 为TRUE
InvalidateRect(hWnd, NULL, TRUE); //使整个窗口无效。
}
如果想立刻更新无效区域,可以在调用InvalidateRect后调用UpdateWindow函数。-》发送WM_PAINT消息。
//新滚动条函数 SetScrollInfo GetScrollInfo
SetScrollInfo(hWnd, iBar, &si, bRedraw);
GetScrollInfo(hWnd, iBar, &si);
typedef struct tagSCROLLINFO
{
UINT cbSize; //设为sizeof(SCROLLINFO)
UINT fMask; //要设置或获取的值
int nMin;
int nMax;
UINT nPage; //页面大小
int nPos; //当前位置
int nTrackPos; //当前追踪位置
}SCROLLINFO
iBar:
1>SIF_RANGE 返回 nMin nMax范围
2>SIF_POS 当前位置。
3>SIF_ALL