这个程序点击拖动鼠标可以画出一个矩形轮廓,我的问题有两个,都和一个函数有关。
1.在
case WM_MOUSEMOVE:
if (fBlocking)
{
SetCursor(LoadCursor(NULL, IDC_CROSS));
DrawBoxOutline(hwnd, ptBeg, ptEnd);
ptEnd.x = GET_X_LPARAM(lParam);
ptEnd.y = GET_Y_LPARAM(lParam);
DrawBoxOutline(hwnd, ptBeg, ptEnd);
}
return 0;
中,为什么需要调用两次DrawBoxOutline(hwnd, ptBeg, ptEnd);为什么仅调用其中任何一个都会导致不同的绘画效果?(具体效果请自行实验)
1.在
case WM_CHAR:
if (fBlocking & (wParam == '\x1B')) // i.e., Escape
{
DrawBoxOutline(hwnd, ptBeg, ptEnd);
SetCursor(LoadCursor(NULL, IDC_ARROW));
DrawBoxOutline(hwnd, ptBeg, ptEnd);
fBlocking = FALSE;
}
return 0;
中,为什么拖动鼠标的过程中按ESC之后矩形反而消失了?函数中不是调用了DrawBoxOutline(hwnd, ptBeg, ptEnd);这个函数吗?
完整程序如下:
/*-----------------------------------------
BLOKOUT1.C -- Mouse Button Demo Program
(c) Charles Petzold, 1998
-----------------------------------------*/
#include <windows.h>
#include <windowsx.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("BlokOut1");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("Program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Mouse Button Demo"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
void DrawBoxOutline(HWND hwnd, POINT ptBeg, POINT ptEnd)
{
HDC hdc;
hdc = GetDC(hwnd);
SetROP2(hdc, R2_NOT);
SelectObject(hdc, GetStockObject(NULL_BRUSH));
Rectangle(hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y);
ReleaseDC(hwnd, hdc);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL fBlocking, fValidBox;
static POINT ptBeg, ptEnd, ptBoxBeg, ptBoxEnd;
HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_LBUTTONDOWN:
ptBeg.x = ptEnd.x = GET_X_LPARAM(lParam);
ptBeg.y = ptEnd.y = GET_Y_LPARAM(lParam);
DrawBoxOutline(hwnd, ptBeg, ptEnd);
SetCursor(LoadCursor(NULL, IDC_CROSS));
fBlocking = TRUE;
return 0;
case WM_MOUSEMOVE:
if (fBlocking)
{
SetCursor(LoadCursor(NULL, IDC_CROSS));
DrawBoxOutline(hwnd, ptBeg, ptEnd);
ptEnd.x = GET_X_LPARAM(lParam);
ptEnd.y = GET_Y_LPARAM(lParam);
DrawBoxOutline(hwnd, ptBeg, ptEnd);
}
return 0;
case WM_LBUTTONUP:
if (fBlocking)
{
ptBoxBeg = ptBeg;
ptBoxEnd.x = GET_X_LPARAM(lParam);
ptBoxEnd.y = GET_Y_LPARAM(lParam);
SetCursor(LoadCursor(NULL, IDC_ARROW));
fBlocking = FALSE;
fValidBox = TRUE;
InvalidateRect(hwnd, NULL, TRUE);
}
return 0;
case WM_CHAR:
if (fBlocking & (wParam == '\x1B')) // i.e., Escape
{
DrawBoxOutline(hwnd, ptBeg, ptEnd);
SetCursor(LoadCursor(NULL, IDC_ARROW));
fBlocking = FALSE;
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
更新
我的问题是拖动鼠标过程中,调用一次与两次DrawBoxOutline()为什么会产生如下两幅图的差别。两张图都是鼠标从左上角拖动到右下角。
这张图拖动过程中会显示很多的矩形轨迹
你的提问与你的完整代码不符: 提问中 WM_CHAR 的处理程序里 DrawBoxOutline 被调用了两次,个人认为后者正确。
居然还看到有人玩 WIN32 编程,好怀念啊
所有的奥秘都在 DrawBoxOutline 中,请看这句:
SetROP2(hdc, R2_NOT);
这句话说明对绘图区域执行的是 非 操作,即 调用一次就绘上去,调用两次则擦除。
嗯可以回答了:
1.在绘制新矩形前,要将旧矩形擦除,故调用两次
2.对上一次的矩形区域调用 DrawBoxOutline,其效果是将其擦除
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。