您的位置:首页 > 大数据 > 人工智能

处理WM_PAINT和WM_DRAWITEM

2012-07-17 23:55 211 查看
通常,当处理一个W M _ PA I N T或W M _ D R AW I T E M窗口消息时,应当在窗口中绘制。当

绘制窗口客户区的时候,由系统发送W M _ PA I N T窗口消息;当需绘制控件的某部分时,

W M _ D R AW I T E M消息被发送到用户绘制控件的物主窗口。

也可以在其他时间画,但必须注意,下一次处理W M _ PA I N T消息时,无论画什么都将被

绘图过程所覆盖。要想再在窗口绘图,只能作为鼠标命令的结果移动对象或线条,例如,在

视图中,用鼠标绘制一个套索框框选取一组目标。

注意 可以用C W n d : : L o c k WindowUpdate( )停止绘图过程绘制窗口。然而,这时该窗口

就不能被移动了。

处理WM_PAINT

void CMyWnd::OnPaint()
{
CPaintDC dc(this); //creates a device context

//draw to dc

}


这里看到的C P a i n t D C类是C D C类的派生类。它不仅创建一个设备环境,而且在OnPaint( )

返回和C P a i n t D C析构自己时销毁该设备环境。

只绘制被无效化的区域

为了防止过度的屏幕闪烁并加快刷新速度,从C P a i n t D C获得的设备环境不总是允许绘制

一个窗口的整个客户区,而只允许重画窗口中发生变化的部分(如一个文本文档的最后一行)。

C P a i n t D C通知设备环境剪切掉在无效区域以外的任何绘图,这可以通过把被无效化的区域添

加到设备环境的R e g i o n对象中实现;如果再调用,则R e g i o n对象定义一个剪切区域,在该区

域以外不能进行绘制。

通常,当一个窗口是新建的或者另一个画在它上面的窗口被关闭时,一个区域变得无

效;当应用程序进入空闲循环时,发送一个W M _ PA I N T消息到每一个具有无效区域的窗口。

通过无效化一个区域或强迫W M _ PA I N T消息被立即发送到一个窗口,可以加快这一过程。

InvalidateRect(rect);

Invalidate(); //invalidates entire client area
UpdateWindow(); //sends WM_PAINT message immediately


注意当编写表面上看起来好像什么也没画的绘图例程时,可能会碰到的一个更加棘手

的问题,任何东西看起来都像它应该的那样,但是没有任何东西在屏幕上出现。剪切

动作通常是问题所在,但只要通过忽略从C P a i n t D C得到的设备环境和使用C C l i e n t D C创

建自己的设备环境,就可以避免这一问题。

OnDraw()

当对一个视图(用C Vi e w类或它的派生类创建的窗口)进行绘制时,应当在C Vi e w的

OnDraw( )函数中处理W M _ PA I N T消息,而不是在它的OnPaint( )中。通过一个打印机设备环

境调用OnDraw( ),C Vi e w可以把视图打印到打印机上。当用户使用F i l e菜单中的标准P r i n t命

令时,就是这样实现的。

但是,许多应用程序不执行 OnDraw( ),因为它们不直接使用C Vi e w;一些使用

C F o r m Vi e w类创建的视图由通用控件组成,而通用控件不用OnDraw( )画它们自己,但还是可

以打印这种类型的视图,不过此时可进行屏幕捕捉而不能绘图。

处理WM_DRAWITEM

一些通用控件窗口允许绘制控件。你可能想要保持控件的功能(如按钮),但需要该控件具

有不同的外观,如文件夹上的标志。为了绘制自己的通用控件,则用属于自己画图的风格来

创建那个控件。对于一个按钮控件,那是B S _ O W N E R D R AW风格。每当需要绘制控件的某一

部分时,该控件的父窗口就会接收到一个 W M _ D R AW I T E M消息。下面的结构包括

W M _ D R AW I T E M窗口消息:

typedef struct tagDRAWITEMSTRUCT
{
UINT CtlType;
UINT CtlID;
UINT itemID;
UINT itemAction;
UINT itemState;
HWND hwndItem;
HDC hDC;
RECT reltem;
DWORD itemData;
}DRAWITEMSTRUCT;
结构中的h D C值是绘制控件的设备环境。要为它封装一个C D C类,可以用:

CDC *pDC=FromHandle(hDC);


注意为了真实封装,应该在从通用控件派生的类中处理WM_DRAWITEM消息。例如,

你可能喜欢创建一个从C B u t t o n派生的称为C M y B u t t o n的类,并由它用消息映射处理

WM_DRAWITEM消息。

你可能在鼠标命令之后绘图,例如,当用鼠标来绘制一条直线时。对于

在这些情况和其他在没有W M _ PA I N T和W M _ D R AW I T E M消息的情况下绘图时,还可以使用

另外两个C D C类的派生类,它们可以使工作轻松。

CClientDC( )类像CPaintDC( )一样创建一个设备环境,但它不试图剪裁任何东西。当

过程开始时,C C l i e n t D C类创建设备环境;而当过程结束时,释放它。

注意在使用设备环境带来方便的同时,也可能会带来隐患。其中之一就是必须记住在

使用之后必须释放它们,否则将承受应用程序慢慢使用完内存的痛苦。不用 C D C

*pDC=GetDC( ),而养成使用C C l i e n t D C的习惯,可能会得到更好的服务,因为不必考

虑释放设备环境。

C WindowDC( )类与CClientDC( )的目的相同,但是,它创建的设备环境允许对整个窗

口进行绘制,其中包括非客户区。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: