一、绘图基础这一章强调最多的莫过于 资源的取得 及 释放
1、希望在图形输出设备上绘制图形,必须首先获取设备环境(DC)的句柄。在GDI函数中这个句柄作为一个参数,告诉windows在哪个设备上进行绘图。对设备的使用完毕时,必须释放该句柄。
a、如果在处理一条消息时获取了视频显示的设备环境,则应该在退出当前窗口过程之前释放它。释放句柄后,它将不再有效。对打印机设备环境句柄,规则并没这么严格。
处理WM_PAINT消息时使用 BeginPaint 和 EndPaint函数;
非WM_PAINT消息时, GetDC 和 ReleaseDC GetWindowDC 和 ReleaseDC。 (如果使用GetWindowDC,则还应当捕获 WM_NCPAINT 消息,windows使用这个消息在窗口的非客户区绘图)。这三个函数可以获得在视频显示器上与一个特定窗口相关的设备环境。
b、更为通用的用于获取设备环境句柄的函数 CreatDC, 释放用 DeleteDC。
hdc = CreateDC(pszDriver,pszDevice, pszOutput, pData);
DeleteDc(hdc);
特例 hdc = CreateDC( TEXT("Display"), NULL, NULL, NULL); 可以获取当前整个屏幕的设备环境句柄。
2、GDI对象(画笔、画刷等)使用的三条规则
a、最终应当删除你所创建的所有GDI对象;
b、当GDI对象被选入一个有效的设备环境时,不要删除它;
c、不要删除备用对象
关于GDI 对象的泄露,可以在任务管理器 打开 GDI对象 的选项进行观察
二、关于设备坐标系统
屏幕坐标
全窗口坐标
客户区坐标
三、关于PeekMessage。
在Windows中有很多的“空闲时间”,在这期间所有的消息队列都是空的,Windows就在等待键盘或者鼠标的输入。那么能否在空闲期间从某种程度上获取控制来处理事情,而一但有消息加载到程序的消息队列,就释放控制呢?
while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
do some work;
}
}
return msg.wParam ;
PeekMessage函数的返回值表示队列中是否有消息,因此检查 WM_QUIT是必要的。如果要删除消息队列中的消息,把最后一个参数设置为 PM_REMOVE。如果不想删除则把设置为 PM_NOREMOVE.
GetMessage并不把控制权交还给程序,除非它从程序的消息队列中获得了消息。但是PeekMessage函数总是立即返回,不管消息是否出现。 当一个消息在程序的消息队列中时,PeekMessage函数的返回值是TRUE,当没有消息时,返回值是FALSE。
四、关于SendMessage。给窗口过程发送假冒的消息,使系统任务得到了另外的消息,去执行那个消息内的逻辑。
SendMessage(hwnd, message, wParam, lParam)。当调用SendMessage时,Windows调用窗口句柄是hwnd的窗口过程,同时把4个函数变量传递给它。当窗口过程处理完此消息,Windows把控制权交还给紧跟着SendMessage调用的下一条语句。你向它发送消息的窗口过程可以是同一窗口过程,也可以是同一程序中的其他窗口过程,或者甚至是另一个应用程序的窗口过程。
在第六章中,个人认为最受益的是,把相同的处理方式归结到一个消息内,其它消息则产生一个所谓的欺骗消息。程序也是一样的,把逻辑相同的写成一个处理函数。其他地方直接调用函数。需要修改时,只需更改一次。