本节中的示例演示如何跟踪鼠标光标。它包含窗口过程的一部分,使得用户可以通过拖动鼠标在窗口的客户区中绘制线条。
当窗口过程接收到WM_LBUTTONDOWN消息时,它捕获鼠标并使用坐标作为行的起点保存光标的坐标。它还使用ClipCursor函数在行绘制操作期间将光标限制在客户区。
在第一个WM_MOUSEMOVE消息中,窗口过程从起始点到光标的当前位置绘制一条线。在随后的WM_MOUSEMOVE消息中,窗口过程通过用反转的笔颜色绘制来擦除上一行。然后它从起始点到光标的新位置绘制一条新行。
WM_LBUTTONUP消息表示绘图操作的结束。窗口过程释放鼠标捕获,并从客户端区域释放鼠标。
LRESULT APIENTRY MainWndProc(hwndMain,uMsg,wParam,lParam)en
HWND hwndMain;
UINT uMsg;
WPARAM wParam;
LPARAM lParam;
{
HDC hdc; /* handle of device context */
RECT rcClient; /* client area rectangle */
POINT ptClientUL; /* client upper left corner */
POINT ptClientLR; /* client lower right corner */
static POINTS ptsBegin; /* beginning point */
static POINTS ptsEnd; /* new endpoint */
static POINTS ptsPrevEnd; /* previous endpoint */
static BOOL fPrevLine = FALSE; /* previous line flag */
开关(uMsg){
case WM_LBUTTONDOWN:
/ *捕获鼠标输入。*/
SetCapture(hwndMain);
/*
*检索客户区域的屏幕坐标,
*并将其转换为客户端坐标。
/*
GetClientRect(hwndMain, &rcClient);
ptClientUL.x = rcClient.left;
ptClientUL.y = rcClient.top;
/*
*添加一个到右侧和底部,因为
*由GetClientRect检索的坐标不要
*包括最左边和最下面的像素。
*/
ptClientLR.x = rcClient.right + 1;
ptClientLR.y = rcClient.bottom + 1;
ClientToScreen(hwndMain, &ptClientUL);
ClientToScreen(hwndMain, &ptClientLR);
/*
*复制客户端区域的客户端坐标
*到rcClient结构。限制鼠标光标
*通过传递rcClient结构到客户端区域
*到ClipCursor函数。
*/
SetRect对(& RC客户机,ptClientUL.x,ptClientUL.y,
ptClientLR.x, ptClientLR.y);
ClipCursor(&rcClient);
/*
*将光标坐标转换为POINTS
*结构,它定义了起点
*在WM_MOUSEMOVE消息中绘制的行。
*/
ptsBegin = MAKEPOINTS(lParam);
return 0;
case WM_MOUSEMOVE:
/*
*移动鼠标时,用户必须按住
*鼠标左键绘制线条。
*/
if(wParam & MK_LBUTTON){
/*
*检索客户端的设备上下文(DC)
*区域。
*/
hdc = GetDC(hwndMain);
/*
*以下功能确保像素
*以前绘制的线条设置为白色
*新线的设置为黑色。
*/
SetROP2(hdc, R2_NOTXORPEN);
/*
*如果在早些时候画了一条线
* WM_MOUSEMOVE消息,画出它。这擦除
*通过将其像素的颜色设置为该行
*白色。
*/
if(fPrevLine){
MoveToEx(hdc,ptsBegin.x,ptsBegin.y,
(LPPOINT) NULL);
LineTo(hdc, ptsPrevEnd.x, ptsPrevEnd.y);
}
/*
*将当前光标坐标转换为a
* POINTS结构,然后画一条新行。
*/
ptsEnd = MAKEPOINTS(lParam);
MoveToEx(hdc,ptsBegin.x,ptsBegin.y,
(LPPOINT) NULL);
LineTo(hdc, ptsEnd.x, ptsEnd.y);
/*
*设置前一行标志,保存结束
*点新线,然后释放DC。
*/
fPrevLine = TRUE;
ptsPrevEnd = ptsEnd;
ReleaseDC(hwndMain, hdc);
}
break;
case WM_LBUTTONUP:
/*
*用户已经完成绘制线。重置
*上一行标志,释放鼠标光标,和
*释放鼠标捕获。
*/
fPrevLine = FALSE;
ClipCursor(NULL);
ReleaseCapture();
return 0;
case WM_DESTROY:
PostQuitMessage(0);
break;
.
./ *处理其他消息。*/
.