在Windows应用程序中,设备环境(DC,绘图模式)与图形对象协同进行绘图显示工作。就像画家绘图一样,设备环境(绘图模式)好比是画家的画布,图形对象好比是画家的画具,画家可以使用不同的画布、不同的画笔、画刷、颜料等,画出不同载体、不同色彩、不同线条的画。
MFC绘图类包括绘图环境类和绘图对象类。
1 绘图环境类(绘图模式)绘图环境类是MFC对GDI三类绘图模式函数封装成CDC及三种派生类。

CDC派生类封装的GDI函数及功能说明:
a) CPaintDC类,封装了BeginPaint和EndPaint函数。
用于标准客户区绘图,窗口刷新时不消失,在WM_PAINT消息下使用。
b) CWindowDC类,封装了GetWindowDC和ReleaseDC函数。
用于非客户区绘图,在WM_NCPAINT消息下使用,窗口刷新时不消失。
c) CClientDC类,封装了GetDC和ReleaseDC函数。
用于临时客户区绘图,窗口刷新时消失,任何时候都可以使用。
d) CMemDC类,封装CreateCompatibleDC和DeleteDC等函数。
VC6.0暂未封装该类,VS 2010有封闭。在内存中绘图,常用于双缓冲防止画面闪烁。
CMetaFileDC类-父类是CDC类,作用保存绘制命令。
实例:
void CXdcDlg::OnPaint() {CPaintDC dc(this); // device context for paintingdc.Rectangle(0,0,40,40);dc.Rectangle(80,80,120,120);dc.MoveTo(20,20);dc.LineTo(100,100);}void CXdcDlg::OnNcPaint() {#if 0CWindowDC dc(this);CRect rect;GetWindowRect(rect);dc.Rectangle(0,0,rect.Width(),rect.Height());char str[222];sprintf(str,\"非客户空间(%d,%d,%d,%d)\",rect.left,rect.top,rect.right,rect.bottom);dc.SetTextColor(RGB(255,0,0));dc.TextOut(5,5,str,strlen(str));#endif}void CXdcDlg::OnLButtonDown(UINT nFlags, CPoint point) {CClientDC dc(this);dc.Ellipse(point.x-10,point.y-10,point.x+10,point.y+10);CDialog::OnLButtonDown(nFlags, point);}
2 绘图对象类
使用GDI对象可以改变线条的颜色、大小,可以使用填充颜色,改变字体,显示一张位图等。不过,GDI对象是要通过DC才能发生作用的。要使用这些GDI对象,必须使用SelectObject函数将其选入DC中。
主要有六种,全部由CGdiObject类派生:
CPen-画笔,用于修饰线条 的颜色、宽度和线型(实线、虚线或点划线等);
CBrush-画刷,用于修饰一个闭合图形内部的填充内容(填充颜色、填充线条以及平铺位图;
CFont-字体,用于修饰输出文字的样式、高度、粗细以及字间距等;
CBitmap-位图,用于显示和处理点阵图像;
CRgn-区域,用于修饰输出图像的不规则边界,如椭圆或多边形等;
CPalette-调色板,用于修饰输出图像的色调,如16色或256色等;
颜色变量和处理函数:
typedef DWORD COLORREF;
COLORREF c1 = RGB(255,255,255);
一般按如下步骤使用GDI对象:
a、创建或得到一个GDI对象;
b、使用dc.SelectObject函数把GDI对象选入DC;
c、使用DC进行绘图或文字输出;
d、恢复DC原来的GDI对象并删除刚新创建的GDI对象;
综合DC和GDI对象的使用步骤,则绘图的完整步骤为:
I 获取或者创建一个DC,也就是创建一个绘图模式或环境;
II 获取或者创建一个GDI对象(Pen, Brush等);
III 使用dc.SelectObject函数把GDI对象选入DC;
IV 使用DC进行绘图或文字输出;
V 恢复DC原来的GDI对象并删除刚新创建的GDI对象,如pen.DeleteObject();
VI 释放或删除设备描述表DC;
其中,I和VI,II和IV是对应的。
2.1 CPen类(画笔)画笔决定了线条的颜色、宽度和线型(实线、点线或点划线等)。Windows使用当前在设备描述表中已选择的画笔来画线。程序中可以选择Windows的预定义画笔,也可以选择自定义的画笔。
预定义画笔有三种:BLACK_PEN(黑色笔) 、WHITE_PEN(白色笔)和NULL_PEN(空笔),这些都在windows.h中已经定义好了,程序员可使用GetStockObject函数来选择其中的一种,系统缺省的画笔为黑色笔。Windows.h包含了HPEN的数据类型定义,使用该类型可以定义画笔句柄的变量。
仅靠系统提供的预定义画笔远远不能满足需求,应用程序可根据实际需要创建一种自定义的逻辑画笔。其步骤一般为:首先用CreatePen或CreatePenIndirect函数建立一支画笔,再调用SelectObject函数将其选入设备描述表,此后就可使用该画笔在选定的设备描述表中进行绘图操作。任何时候某一设备描述表只能有一支画笔被选入作为当前画笔,当一支画笔被选入时,原先已选入的画笔便不再有效。完成绘图操作后,可以通过调用DeleteObject来释放已建立的画笔。
函数CreatePen()
HPEN CreatePen(int fnPenStyle,int nWidth,COLORREF clrref);
该函数创建一个逻辑画笔。其中fnPenStyle参数指定画笔的线型,该参数可取由windows.h定义的七个标识符之一,其含义为:
PS_SOLID 实线
PS_DASH 虚线
PS_DOT 点线
PS_DASHDOT 夹一点虚线
PS_DASHDOTDOT 夹二点虚线
PS_NULL 无
PS_INSIDEFRAME 线画在所有构件框架内
nWidth参数是用逻辑单位表示的画笔的宽度;
clrref参数是一个COLORREF类型的颜色值,指定画笔的颜色,可用宏指令RGB构造这个值,如:clrref=RGB(byRed,byGreen,byBlue);
实例
void CPenDlg::OnPaint() {CPaintDC dc(this); // 绘图模式之一(标准客户区绘图),另外还有CWindowDC(非客户区)、CClientDC(临时客户区)dc.TextOut(20,20,\"默认画笔:黑色,宽度为1\");dc.MoveTo(20,60);dc.LineTo(120,60);dc.TextOut(20,80,\"通过构造函数创建画笔:CPen pn1(PS_SOLID,4,RGB(255,0,0));\");CPen pn1(PS_SOLID,4,RGB(255,0,0));CPen pOldPen = dc.SelectObject(&pn1); //选择的是新建画笔,返回的是之前的旧画笔dc.MoveTo(20,120);dc.LineTo(120,120);dc.TextOut(20,140,\"通过CreatePen函数创建画笔:pn2.CreatePen(PS_DASHDOT,1,RGB(0,0,255));\");CPen pn2;pn2.CreatePen(PS_DASHDOT,1,RGB(0,0,255));dc.SelectObject(&pn2);dc.MoveTo(20,180);dc.LineTo(120,180);dc.TextOut(20,200,\"画一个矩形dc.Rectangle(20,240,140,300); 右上、右下角坐标 \");dc.SelectObject(pOldPen); // 选择默认画笔dc.Rectangle(20,240,140,300);dc.TextOut(20,320,\"画一个无边框的矩形:CPen pn3(PS_NULL,1,RGB(0,0,0));\");CPen pn3(PS_NULL,1,RGB(0,0,0));dc.SelectObject(&pn3);dc.Rectangle(20,360,140,420);dc.TextOut(20,440,\"等价的无边框矩形的画法:dc.FillSolidRect(20,440,120,60,RGB(255,255,255));右上角坐标,长,宽\");dc.FillSolidRect(20,480,120,60,RGB(255,255,255)); //右上角坐标,长,宽dc.SelectObject(pOldPen); // 恢复默认画笔}
运行效果:
2.2 CBrush(刷子)
当我们在绘制一些区域图形时,其内部往往需要以某种图案进行填充,这就需要选定\"刷子\"作为绘图工具。Windows系统不仅为用户提供了预定义刷子,而且还允许应用程序自定义刷子。
Windows系统中预定义的刷子有如下七种:
BLACK_BRUSH 黑色刷子
DKGRAY_BRUSH 深灰色刷子
GRAY_BRUSH 灰色刷子
HOLLOW_BRUSH 中空刷子,画边界而不填充
LTGRAY_BRUSH 浅灰色刷子
NULL_BRUSH 空刷子
WHITE_BRUSH 白色刷子
应用程序可以调用GetStockObject函数选用其中一个,系统缺省的刷子是白色刷子。Window.h包含了HBRUSH数据类型的定义,使用该类型就可定义刷子句柄的变量。
仅靠这七种刷子往往不能满足要求,应用程序通过调用如下几种函数创建逻辑刷子,这些函数返回值均为刷子句柄。
CreateHatchBrush()
HBRUSH CreateHatchBrush(int fnStyle, COLORREF clrref);
该创建一个带阴影的逻辑刷子。
FnStyle指定的阴影格式如下:
HS_BDLAGONAL 45度向上斜线组成的阴影图案(自左到右)
HS_CROSS 水平和垂直交叉组成的阴影图案
HS_DIAGCROSS 45度斜线交叉组成的阴影图案
HS_FDIAGONAL 45度向下斜线组成的阴影图案(自左到右)
HS_HORZONA 水平线组成的阴影图案
HS_VERTICAL 垂直线组成的阴影图案
Clrref是具有COLORREF类型定义的刷子颜色值,可用宏指令RGB构造这个值。
函数CreateSolidBrush()
HBRUSH CreateSolidBrush(COLORREF clrre);
该函数创建的是一种实心颜色的逻辑刷子。clrre含义同上。
同样,使用创建刷子的函数时,要检查其返回,确保它是一个有效的句柄。
一旦创建了绘图工具之后,可以SelectObject函数把它选择到显示缓冲区里。
在使用显示缓冲区之前,并不一定非要创建和选择绘图工具,Windows为每个显示缓冲区提供默认的绘图工具。例如:黑色笔,白色刷子和系统字体。
DeleteObject函数用来删除不再需要的绘图工具,但不能删除一个已选进显示缓冲区的绘图工具,而是应该使用SelectObject函数恢复原有的绘图工具,然后再删除需要删除的工具。
实例:
void CBrushDlg::OnPaint(){CPaintDC dc(this); // device context for paintingdc.Rectangle(20,20,120,100);CBrush br1(RGB(0,0,255));CBrush pOldBrush = dc.SelectObject(&br1);dc.Ellipse(140,20,240,100);CBrush br2(HS_FDIAGONAL,RGB(255,0,0));dc.SelectObject(&br2);CPen pen(PS_SOLID,3,RGB(255,0,0));CPen pOldPen = dc.SelectObject(&pen);dc.RoundRect(260,20,300,100,25,25);CBitmap bmp;bmp.LoadBitmap(IDB_BITMAP1);CBrush br3(&bmp);dc.SelectObject(&br3);CPen pen2(PS_SOLID,3,RGB(240,240,240));dc.SelectObject(&pen2);POINT pt[] = {{40,120},{160,120},{240,240},{20,240}};dc.Polygon(pt,4);CBrush br4;LOGBRUSH lb = {BS_NULL};br4.CreateBrushIndirect(&lb);dc.SelectObject(pOldPen);dc.SelectObject(&br4);dc.Chord(CRect(140,120,350,240),CPoint(260,240),CPoint(140,100));dc.SelectObject(pOldBrush);dc.SelectObject(pOldPen);}
运行效果:
2.3 CFont(字体)
Windows是使用定义好的与设备无关的字符集,Windows的\"文本\"字符也是图形,所以屏幕上所显示的用打印机或绘图仪等输出品的文本完全一样,做到\"所见即所得\"。
文本绘制函数有:
TextOut 以当前的字体写一字符串
DrawText 在一个特定矩形区中绘制某一格式的文本
ExtTextOut 在一个特定矩形区中,以当前字体写一字符串
GrayString 用灰色文本写一字符串
TabbedTextOut 写一带扩展字符的字符串
要输出文本就离不开字体。获取字体的相关信息可以使用函数:
BOOL GetTextMetrics( LPTEXTMETRIC lpMetrics )
结构TEXTMETRIC的定义如下所示:
typedef struct tagTEXTMETRIC { // tmLONG tmHeight; //字符高度LONG tmAscent; //字符上部高度(基线以上)LONG tmDescent; //字符下部高度(基线以下)LONG tmInternalLeading; //由tmHeight定义的字符高度的顶部空间数目LONG tmExternalLeading; //加在两行之间的空间数目LONG tmAveCharWidth; //平均字符宽度LONG tmMaxCharWidth; //最宽字符的宽度LONG tmWeight; //字体的粗细轻重程度LONG tmOverhang; //加入某些拼接字体上的附加高度LONG tmDigitizedAspectX; //字体设计所针对的设备水平方向LONG tmDigitizedAspectY; //字体设计所针对的设备垂直方向BCHAR tmFirstChar; //为字体定义的第一个字符BCHAR tmLastChar; //为字体定义的最后一个字符BCHAR tmDefaultChar; //字体中所没有字符的替代字符BCHAR tmBreakChar; //用于拆字的字符BYTE tmItalic; //字体为斜体时非零BYTE tmUnderlined; //字体为下划线时非零BYTE tmStruckOut; //字体被删去时非零BYTE tmPitchAndFamily; //字体间距(低4位)和族(高4位)BYTE tmCharSet; //字体的字符集} TEXTMETRIC;
GDI字体族和字样表如下表所示:
字体族 字体族常量 字样说明
Dontcare FF_DONTCARE System 当不能提供字体信息或字体并不
重要时使用
Decorative FF_DECORATIVE Symbol 新奇字体
Modern FF_MODERN Courer,ModernIerminal 笔画大小固定的字体,但衬线可有可无
Roman FF_ROMAN Roman,TimeRoman 有衬线的、笔画大小可变的罗马字体
Script FF_SCRIPT Script 仿手写体
Swiss FF_SWISS Helvetical,System 无衬线的、笔画大小可变的字体
CreateFontIndirect函数
HFONT CreateFontIndirect(
CONST LOGFONT lplf // pointer to logical font structure
);
参数lplf是LOGFONT结构的指针。结构中含有逻辑字体的特征信息。该函数用lplf所指的LOGFONT结构中的信息创建一种逻辑字体。LOGFONT结构的定义如下:
typedef struct tagLOGFONT { // lfLONG lfHeight; //字高度LONG lfWidth; //字符平均宽度LONG lfEscapement; //行与水平页角度LONG lfOrientation; //基线与水平角度LONG lfWeight; //笔划的粗细BYTE lfItalic; //非零为斜体BYTE lfUnderline; //非零为下划线BYTE lfStrikeOut; //非零为中划线BYTE lfCharSet; //指定字符集BYTE lfOutPrecision; //输出精度BYTE lfClipPrecision; //裁剪精度BYTE lfQuality; //输出质量BYTE lfPitchAndFamily; //字体的字距和族TCHAR lfFaceName[LF_FACESIZE]; //含字体名的字符串} LOGFONT;
函数SetTextAlign
大多数文本函数传递的参数表都要求有一个点坐标参数以定义写文本的参考点。当前文本对齐属性规定了字符串如何相对于所传递的坐标进行写。SetTextAlign函数用以设置当前文本对齐属性。
UINT SetTextAlign( HDC hdc, // handle to device context UINT fMode // text-alignment flag );
该函数设置文本对齐方式。Hdc是参数描述表,fuAlign是文本对齐方式
实例:
void CFontDlg::OnPaint() {CPaintDC dc(this); // device context for paintingdc.TextOut(10,10,\"使用默认字体输出文字!
\");CFont pFont = GetFont();CreateFont(&dc);CreateColor(&dc);Others(&dc, pFont);Width(&dc, pFont);Weight(&dc, pFont);Escape(&dc, pFont);Height(&dc, pFont);Normal(&dc, pFont);}void CFontDlg::Normal(CDC pDC, CFont pFont){pFont = pDC->SelectObject(pFont);pDC->TextOut(10,30,\"使用对话框字体输出!
\");pDC->SelectObject(pFont);}void CFontDlg::Height(CDC pDC, CFont pFont){LOGFONT lf;pFont->GetLogFont(&lf);lf.lfHeight=2;CFont font;font.CreateFontIndirect(&lf);pFont = pDC->SelectObject(&font);pDC->TextOut(10,50,\"测试字符的高度加倍!
\");pDC->SelectObject(pFont);}void CFontDlg::Weight(CDC pDC, CFont pFont){LOGFONT lf;pFont->GetLogFont(&lf);lf.lfWeight=700;CFont font;font.CreateFontIndirect(&lf);pFont = pDC->SelectObject(&font);pDC->TextOut(10,80,\"测试粗体字!
\");pDC->SelectObject(pFont);}void CFontDlg::Width(CDC pDC, CFont pFont){LOGFONT lf;pFont->GetLogFont(&lf);lf.lfWeight=lf.lfHeight;CFont font;font.CreateFontIndirect(&lf);pFont = pDC->SelectObject(&font);pDC->TextOut(10,100,\"测试字体的宽度!
\");pDC->SelectObject(pFont);}void CFontDlg::Others(CDC pDC, CFont pFont){LOGFONT lf;pFont->GetLogFont(&lf);lf.lfItalic = TRUE;lf.lfUnderline = TRUE;lf.lfStrikeOut = TRUE;CFont font;font.CreateFontIndirect(&lf);pFont = pDC->SelectObject(&font);pDC->TextOut(10,120,\"测试斜体、下划线和删除线!
\");pDC->SelectObject(pFont);}void CFontDlg::Escape(CDC pDC, CFont pFont){LOGFONT lf;pFont->GetLogFont(&lf);lf.lfEscapement = 200;CFont font;font.CreateFontIndirect(&lf);pFont = pDC->SelectObject(&font);pDC->TextOut(10,180,\"测试字符串的倾斜度!
\");pDC->SelectObject(pFont);}void CFontDlg::CreateColor(CDC pDC){COLORREF oldText = pDC->SetTextColor(RGB(255,0,0));pDC->TextOut(10,200,\"字体颜色\");COLORREF oldBack = pDC->SetBkColor(RGB(0,0,255));pDC->TextOut(80,200,\"背景颜色\");int nOldMode=pDC->SetBkMode(TRANSPARENT);pDC->TextOut(150,200,\"背景透明\");pDC->SetTextColor(oldText);pDC->SetBkColor(oldBack);pDC->SetBkMode(nOldMode);}void CFontDlg::CreateFont(CDC pDC){CFont ft1;ft1.CreatePointFont(100,\"幼圆\");CFont pOldFont = pDC->SelectObject(&ft1);pDC->TextOut(10,220,\"简单创建字体的方法\");pDC->SelectObject(pOldFont);LOGFONT lf={20};lf.lfCharSet=GB2312_CHARSET;lf.lfWeight=400;strcpy(lf.lfFaceName,\"隶书\");CFont ft2;ft2.CreateFontIndirect(&lf);pDC->SelectObject(&ft2);pDC->TextOut(10,240,\"完整创建字体的方法\");}
运行效果:
2.4 CBitmap类(位图)
void CBitmapDlg::OnPaint() {CPaintDC dc(this); // device context for paintingCBitmap bmp;bmp.LoadBitmap(IDB_BITMAP1);BITMAP bm;bmp.GetBitmap(&bm);CDC mdc;mdc.CreateCompatibleDC(&dc);mdc.SelectObject(&bmp);dc.BitBlt(0,0,bm.bmWidth,bm.bmHeight,&mdc,0,0,SRCCOPY);//从1/3的位置开始输出右下角2/3大小的图片dc.BitBlt(bm.bmHeight+10,10,bm.bmWidth2/3,bm.bmHeight2/3,&mdc,bm.bmWidth/3,bm.bmHeight/3,SRCCOPY);//使用默认算法将图像压缩一半dc.StretchBlt(10,bm.bmWidth+10,bm.bmWidth/2,bm.bmHeight/2,&mdc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);//更换压缩算法提高压缩后的图像品质dc.SetStretchBltMode(COLORONCOLOR);dc.StretchBlt(bm.bmWidth/2+20,bm.bmHeight+10,bm.bmWidth/2,bm.bmHeight/2,&mdc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);//左右对称压缩dc.StretchBlt(bm.bmWidth+30,bm.bmHeight+10,bm.bmWidth/2,bm.bmHeight/2,&mdc,bm.bmWidth,0,-bm.bmWidth,bm.bmHeight,SRCCOPY);}运行效果:
2.5 CRgn类(区域)void CRgnDlg::OnPaint() {CPaintDC dc(this);CBitmap bmp;bmp.LoadBitmap(IDB_BITMAP1);BITMAP bm;bmp.GetBitmap(&bm);int cx = bm.bmWidth;int cy = bm.bmHeight;CDC mdc;mdc.CreateCompatibleDC(&dc);mdc.SelectObject(&bmp);POINT pts[] = {{20,16},{110,56},{114,16},{166,52},{250,20},{240,100},{250,180},{150,160},{32,180},{52,100}};CRgn rg1;rg1.CreatePolygonRgn(pts,sizeof(pts)/sizeof(POINT),WINDING);dc.SelectObject(&rg1);dc.BitBlt(0,0,cx,cy,&mdc,0,0,SRCCOPY);CRgn rg2;int nLeft = cx-50;int nTop = cy - 50;rg2.CreateRoundRectRgn(nLeft,nTop,nLeft+cx,nTop+cy,32,32);dc.SelectObject(&rg2);dc.BitBlt(nLeft,nTop,cx,cy,&mdc,0,0,SRCCOPY);}
运行效果:
附:通过HDC句柄调用GDI函数的三种绘图模式
// DC32.cpp : Defines the entry point for the application.#include \"stdafx.h\"#include \"resource.h\"#include <stdio.h>// GDI函数通过HDC句柄来调用#if 1//消息回调函数 窗口客户区绘图 BeginPaint(hwndDlg,&ps);窗口刷新时不消失,在WM_PAINT消息下使用,封装成CPaintDC类BOOL CALLBACK dlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){switch(uMsg){case WM_COMMAND:switch(wParam){case IDCANCEL:EndDialog(hwndDlg,IDCANCEL);break;}case WM_PAINT://窗口客户区绘图{PAINTSTRUCT ps;//获取与容器客户区关联的绘图句柄HDC hdc=BeginPaint(hwndDlg,&ps);//画两个矩形Rectangle(hdc,0,0,40,40);Rectangle(hdc,80,80,120,120);//画一条线MoveToEx(hdc,20,20,NULL);LineTo(hdc,100,100);EndPaint(hwndDlg,&ps);}break;}return FALSE;}#endif#if 0//消息回调函数 非窗口客户区绘图 ;窗口刷新时不消失,在WM_NCPAINT消息下使用,封装成CWindowDC类BOOL CALLBACK dlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){switch(uMsg){case WM_COMMAND:switch(wParam){case IDCANCEL:EndDialog(hwndDlg,IDCANCEL);break;}case WM_NCPAINT:{HDC hdc = GetWindowDC(hwndDlg);RECT rect;GetWindowRect(hwndDlg,&rect);//获取整个窗口的空间区域//画两个矩形Rectangle(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top);char str[222];sprintf(str,\"非客户空间(%d,%d,%d,%d)\",rect.left,rect.top,rect.right,rect.bottom);SetTextColor(hdc,RGB(255,0,0));TextOut(hdc,5,5,str,strlen(str));ReleaseDC(hwndDlg,hdc);return TRUE;}case WM_MOVE:SendMessage(hwndDlg,WM_NCPAINT,0,0);InvalidateRect(hwndDlg,NULL,TRUE);return TRUE;}return FALSE;}#endif#if 0//消息回调函数 临时客户区绘图 ;窗口刷新时消失,任何时候都可以使用,封装成GetDC类BOOL CALLBACK dlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){switch(uMsg){case WM_COMMAND:switch(wParam){case IDCANCEL:EndDialog(hwndDlg,IDCANCEL);break;}case WM_LBUTTONDOWN:HDC hdc = GetDC(hwndDlg);int x = LOWORD(lParam);int y = HIWORD(lParam);// 画一个圆形Ellipse(hdc,x-10,y-10,x+10,y+10);ReleaseDC(hwndDlg,hdc);return TRUE;}return FALSE;}#endif//测试坐标系转换void ScreenToClient(HWND hwndParent, RECT &rect){POINT lt = {rect.left,rect.top};POINT rb = {rect.right,rect.bottom};ScreenToClient(hwndParent,<);ScreenToClient(hwndParent,&rb);rect.left = lt.x;rect.top = rb.x;rect.bottom = rb.y;}#if 0//消息回调函数 测试坐标系转换BOOL CALLBACK dlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){switch(uMsg){case WM_COMMAND:switch(wParam){case IDCANCEL:EndDialog(hwndDlg,IDCANCEL);break;}case WM_SETCURSOR: //当鼠标靠近或者切换到不同的控件时回调{HWND hwnd = (HWND)wParam;if(hwnd != GetDlgItem(hwndDlg,IDOK))return TRUE;RECT rect;GetWindowRect(hwnd,&rect); //获取按钮的屏幕坐标ScreenToClient(hwndDlg,rect);rect.left -=100;rect.right -= 100;MoveWindow(hwnd,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,TRUE);return TRUE;}break;}return FALSE;}#endifint APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ //MessageBox(NULL,\"first program\",\"note\",0);DialogBox(hInstance,(LPCTSTR)ws,NULL,dlgFunc);return 0;}
运行效果:
-End-