《windows程序设计》“blokout1.c”的疑问

这个程序点击拖动鼠标可以画出一个矩形轮廓,我的问题有两个,都和一个函数有关。

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);为什么仅调用其中任何一个都会导致不同的绘画效果?(具体效果请自行实验)

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,其效果是将其擦除


(手机码字,有点乱)

以上是 《windows程序设计》“blokout1.c”的疑问 的全部内容, 来源链接: utcz.com/p/195569.html

回到顶部