经典的《windows程序设计》第五版第五章“Rectangles, Regions, Clipping”, 有一个演示Clipping的例子程序 clover.c。这个程序运行出现奇怪问题。 下面是我对该例子稍加改动后的程序。很明显, 一条LineTo函数调用出现了两条线段(窗口最大化后最明显)。 关闭win7 “桌面组合”后, 这个问题消失, 打开“桌面组合” 问题出现。 这是不是一个bug?
#include<windows.h>
#include<math.h>
#define
TWO_PI (2.0
* 3.14159)
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
static TCHAR szAppName[]
= TEXT("Clover");
static TCHAR szWndName[]
= TEXT("Draw a clover");
BOOL bRet;
MSG msg;
HWND hwnd;
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
FALSE;
}
hwnd =
CreateWindow(szAppName, szWndName, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
NULL, hInstance,
NULL);
if (!hwnd) {
MessageBox(NULL,
TEXT("Can not create window!"), szAppName, MB_ICONERROR);
return
FALSE;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (bRet
= GetMessage(&msg,
NULL,
0, 0)) {
if (bRet
== -1 ) {
MessageBox(NULL,
TEXT("Can not get message!"), szAppName, MB_ICONERROR);
return
FALSE;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static HRGN hRgnClip;
static
int cxClient, cyClient;
double fAngle, fRadius;
HCURSOR hCursor;
HDC hdc;
HRGN hRgnTemp[6];
int i;
PAINTSTRUCT ps;
HBRUSH hbr;
static TCHAR szBuffer [50];
switch (iMsg) {
case WM_SIZE:
cxClient
= LOWORD(lParam);
cyClient
= HIWORD(lParam);
hCursor
= SetCursor(LoadCursor(NULL,
IDC_WAIT));
ShowCursor(TRUE);
if (hRgnClip)
DeleteObject(hRgnClip);
hRgnTemp[0]
= CreateEllipticRgn(0, cyClient
/ 3, cxClient
/ 2,
2 * cyClient
/ 3);
hRgnTemp[1]
= CreateEllipticRgn(cxClient
/ 2, cyClient
/ 3, cxClient,
2 * cyClient
/ 3);
hRgnTemp[2]
= CreateEllipticRgn(cxClient
/ 3,
0, 2
* cxClient
/ 3, cyClient
/ 2);
hRgnTemp[3]
= CreateEllipticRgn(cxClient
/ 3, cyClient
/ 2,
2 * cxClient
/ 3, cyClient);
hRgnTemp[4]
= CreateRectRgn(0,
0, 1,
1);
hRgnTemp[5]
= CreateRectRgn(0,
0, 1,
1);
hRgnClip
= CreateRectRgn(0,
0, 1,
1);
CombineRgn(hRgnTemp[4], hRgnTemp[0],
hRgnTemp[1], RGN_OR);
CombineRgn(hRgnTemp[5], hRgnTemp[2],
hRgnTemp[3], RGN_OR);
CombineRgn(hRgnClip, hRgnTemp[4], hRgnTemp[5],
RGN_XOR);
for (i
= 0; i
<
6; i++)
DeleteObject(hRgnTemp[i]);
SetCursor(hCursor);
ShowCursor(FALSE);
return
0;
case WM_PAINT:
hdc
= BeginPaint(hwnd,
&ps);
hbr
= GetStockObject(GRAY_BRUSH);
FillRgn(hdc, hRgnClip, hbr);
DeleteObject(hbr);
SetViewportOrgEx(hdc, cxClient
/ 2, cyClient
/ 2,
NULL);
SelectClipRgn(hdc, hRgnClip);
fRadius
= hypot(cxClient
/ 2.0, cyClient
/ 2.0);
fAngle
= 3
* TWO_PI
/ 16;
//for (fAngle = 0.0; fAngle < TWO_PI; fAngle += TWO_PI / 360) {
MoveToEx(hdc,
0, 0,
NULL);
// LineTo(hdc,(int) (fRadius * cos(fAngle) + 0.5) / 3, (int) (-fRadius * sin(fAngle) + 0.5) / 3);
LineTo(hdc, (int)
(fRadius *
cos(fAngle)
+
0.5), (int) (-fRadius
* sin(fAngle)
+
0.5));
// LineTo(hdc, 0, 0);
//TextOut(hdc, 200, 0, szBuffer, wsprintf(szBuffer, TEXT("x = %d, y = %d"),
// (int) (fRadius * cos(fAngle) + 0.5), (int) (-fRadius * sin(fAngle) + 0.5) ));
// }
EndPaint(hwnd,
&ps);
return
0;
case WM_DESTROY:
DeleteObject(hRgnClip);
PostQuitMessage(0);
return
0;
}
return
DefWindowProc(hwnd, iMsg, wParam, lParam);
}