windowsAPI文本输出

来源:互联网 发布:jqueryrotate.js官网 编辑:程序博客网 时间:2024/06/06 03:06
1、WM_PAINT消息
(1)当以下任何一个事件发生时,窗口过程会收到一条WM_PAINT消息
用户移动一个窗口,导致原来被遮盖的部分窗口暴露出来
用户调整窗口的大小(当窗口类型设定为CS_HREDRAW,CS_VREDRAW值时,每个WM_SIZE消息后都跟一个WM_PAINT消息)
程序调用ScrollWindow或ScrollDC函数滚动客户区
程序调用InvalidRect或InvalidRectRgn函数显式生成WM_PAINT消息
(2)系统每次都只保存一个WM_PAINT消息,当在处理一条等候的消息时,客户区的另一部分也失效了,那么windows将计算出一个覆盖这两个部分的新区域。
2、利用BeginPaint来获取设备环境句柄
处理代码如下:
PAINTSTRUCT ps;
HDC hdc;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
{使用GDI函数}
EndPaint(hwnd,&ps);
return 0;
由于部分客户区是无效的,windows才会在消息队列中放置一条WM_PAINT消息。除非调用BeginPaint和EndPaint函数对(或ValidateRcet),否则windows不会将那个区域有效化。因此windows将会不停地发送WM_PAINT消息,直到永远。
typedef struct tagPAINTSTRUCT{
HDC hdc;
BOOL fErase;//表示是否擦除背景
RECT rcPaint;//无效矩形的边界
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
}PAINTSTRUCT;

InvalidateRect函数可以发送WM_PAINT消息,并将此消息插入到消息队列中

3、利用GetDC获取环境句柄
hdc=GetDC(hwnd);
{使用GDI函数}
ReleaseDC(hwnd,hdc);
此函数可以再飞WM_PAINT区绘制,并且区域是整个客户区。但与BeginPaint不同,GetDC不会将无效区域有效化。如果要将整个客户区有效化,可以像下面这样调用函数ValidateRect。另一个与GetDC类似的函数是GetWindowDC,后者返回的是整个窗口的设备句柄。

4、字体输出
(1)首先获取字体信息
在WM_CREATE消息中处理,因为这些在应用程序运行期间不会改变
typedef struct tagTEXTMETRIC{
LONG tmHeight;//字符高度
LONG tmAscent;//字符基线上高度
LONG tmDescent;//字符基线下高度
LONG tmInternalLeading;//内部间距,包含在字符高度中,通常用来显示重音符号
LONG tmExternalLeading;//外部间距,表示两行文字间留出的空间的大小
LONG tmAveCharWidth;//小写字符的加权平均宽度
LONG tmMaxCharWidth;//字体中最宽的字符的宽度,在等宽字体中,这两个值是一样的
}TEXTMETRIC,*PTEXTMETRIC;

static int cxChar,cxCaps,cyChar;
HDC hdc;
TEXTMETRIC tm;
case WM_CREATE:
hdc=GetDC(hwnd);
GetTextMetrics(hdc,&tm);
cxChar=tm.tmAveCharWidth;//小写字符宽度
cxCaps=(tm.tmPitchAndFamily&1?3:2)*cxChar/2;//大写字符宽度,若不是等宽字符,则为1.5倍
cyChar=tm.tmHeight+tm.tmExternalLeading;//长度为高度加上外部间距
ReleaseDC(hwnd,hdc);
return 0;

在WM_PAINT消息中输出字体
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
SetTextAlign(hdc,TA_RIGHT|TA_TOP);//字符从右上方对齐
TextOut(hdc,xbegin,ybegin,szBuffer,wsprintf(szBuffer,TEXT("%5d"),4)));
SetTextAlign(hdc,TA_LEFT|TA_TOP);//字符从左上方对齐
EndPaint(hwnd,&ps);
return 0;
5、获取客户区大小
当窗口的大小发生变化时,windows会向窗口过程发送一条WM_SIZE消息。相应的lParam变量的低位字是客户区的宽度,而高位字是高度。
static int cxClient,cyClient;
case WM_SIZE:
cxClient=LOWORD(lParam);
,cyClient=HIWORD(lParam);
return 0;
则cyClient/cyChar表示可以显示的行数
则cxClient/cxChar表示可以显示的列数

6、滚动条
(1)首先在CreateWindow函数调用中在第三个参数中设定了WS_VSCROLL风格,从而在窗口中包括了垂直滚动条。
(2)在WM_CREATE消息的代码中设定垂直滚动条的范围和初始位置
SetScrollRange(hwnd,SB_VERT,0,NUMLINES-1,FALSE);//滚动范围为0-NUMLINES-1
SetScrollPos(hwnd,SB_VERT,iVscrollPos,TRUE);//初始位置为,iVscrollPos,在范围之内
(3)实例代码
case WM_VSCROLL:
switch(LOWORD(wParam))//wParam的低字节表示鼠标在滚动条上的动作
{
case SB_LINEUP://上则减1,按下向上箭头
iVscrollPos-=1;
break;
case SB_LINEDOWN:
iVscrollPos+=1;
break;
case SB_PAGEUP://按下滑块与上箭头之间的部分
iVscrollPos-=cyClient/cyChar;
break;
case SB_PAGEDOWN:
iVscrollPos+=cyClient/cyChar;
break;
case SB_THUMBPOSITION://表示按下鼠标移动滑块 SB_THUMBTRACK按下鼠标移动滑块后松开鼠标
iVscrollPos=HIWORD(wParam);//在这种情况下,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);//只是将WM_PAINT消息插入到队列中,而UpdateWindow则立即响应该消息
}
return 0;
则cyChar*(i-iVscrollPos)表示y坐标,当i小于iVscrollPos时,这个值是负的。不会显示
7、新的滚动条函数
在新函数下滚动范围为max(0,NUMLINES-cyClient/cyChar)即为(si.nMax-si.nPage+1)即这个是滑块的移动范围。在这个范围可以看到所有的si.nMin到si.nMax的内容。
case WM_SIZE:
cxClient=LOWORD(lParam);
cxClient=HIWORD(lParam);

SCROLLINFO si;
si.cbSize=sizeof(si);//结构大小
si.fMask=SIF_RANGE|SIF_PAGE;//获取或设置信息的掩码
si.nMax=NUMLINES-1;//最大
si.nMin=0;//最小
si.nPage=cyClient/cyChar;//滚动页大小
SetScrollInfo(hwnd,SB_VERT,&si,TRUE);//设置
return 0;
case WM_VSCROLL:
si.cbSize=sizeof(si);
si.fMask=SIF_ALL;//获取全部信息
GetScrollInfo(hwnd,SB_VERT,&si);
iVscrollPos=si.nPos;
switch(LOWORD(wParam))//wParam的低字节表示鼠标在滚动条上的动作
{
case SB_TOP://用户的上下和程序员的上下正好相反
si.nPos=si.nMin;
break;
case SB_BOTTOM:
si.nPos=si.nMax;
break;
case SB_LINEUP://上则减1,按下向上箭头
si.nPos-=1;
break;
case SB_LINEDOWN:
si.nPos+=1;
break;
case SB_PAGEUP://按下滑块与上箭头之间的部分
si.nPos-=si.nPage;
break;
case SB_PAGEDOWN:
si.nPos+=si.nPage;
break;
case SB_THUMBPOSITION://表示按下鼠标移动滑块 SB_THUMBTRACK按下鼠标移动滑块后松开鼠标
si.nPos=si.nTrackPos;//前者为当前位置,后者为移动后位置
break;
default:break; 
}
si.fMask=SIF_POS;
SetScrollInfo(hwnd,SB_VERT,&si,TRUE);
GetScrollInfo(hwnd,SB_VERT,&si);
if(si.nPos!=iVscrollPos)
{
ScrollWindow(hwnd,0,cyChar*(iVscrollPos-si.nPos),NULL,NULL);//指定垂直滚动的距离,以设备单位计。
//如果窗口类风格为CS_OWNDC或CS_CLASSDC,则此参数则使用逻辑单位而非设备单位。当向上滚动窗体内容时,参                         //数值必须为负。
UpdateWindow(hwnd);
}
return 0;
原创粉丝点击