编号为4的区域不会被填充

图片 1

线上箭头表示画线的方向。WINDING模式和ALTERNATE模式都会填充三个封闭的L型区域,号码从1到3。两个更小的内部区域,号码为4和5,在ALTERNATE模式下不被填充。但是在WINDING模式下,号码5的区域会被填充,这是因为区域的内部到达图形的外部必须穿过两条相同方向的线。号码为4的区域不会被填充,因为射线必须穿越两条边框线,但是这两条边框线的绘制方向相反。

图片 2图片 3

  1 /*-------------------------------------------
  2 ALTWIND.C -- Alternate and Winding Fill Modes
  3              (c) Charles Petzold, 1998
  4 -------------------------------------------*/
  5 
  6 #include <Windows.h>
  7 
  8 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  9 
 10 int WINAPI WinMain( __in HINSTANCE hInstance
 11                     , __in_opt HINSTANCE hPrevInstance
 12                     , __in LPSTR lpCmdLine
 13                     , __in int nShowCmd )
 14 {
 15     static TCHAR szAppName[] = TEXT("AltWind");
 16     HWND hwnd;
 17     MSG msg;
 18     WNDCLASS wndclass;
 19 
 20     wndclass.style = CS_HREDRAW | CS_VREDRAW;
 21     wndclass.lpfnWndProc = WndProc;
 22     wndclass.cbClsExtra = 0;
 23     wndclass.cbWndExtra = 0;
 24     wndclass.hInstance = hInstance;
 25     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 26     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
 27     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
 28     wndclass.lpszMenuName = NULL;
 29     wndclass.lpszClassName = szAppName;
 30 
 31     if (!RegisterClass(&wndclass))
 32     {
 33         MessageBox(NULL, TEXT("Program requires Windows NT!")
 34             , szAppName, MB_ICONERROR);
 35         return 0;
 36     }
 37 
 38     hwnd= CreateWindow(szAppName, TEXT("Alternate and Winding Fill Modes")
 39         , WS_OVERLAPPEDWINDOW
 40         , CW_USEDEFAULT, CW_USEDEFAULT
 41         , CW_USEDEFAULT, CW_USEDEFAULT
 42         , NULL, NULL, hInstance, NULL);
 43 
 44     ShowWindow(hwnd, nShowCmd);
 45     UpdateWindow(hwnd);
 46 
 47     while (GetMessage(&msg, NULL, 0, 0))
 48     {
 49         TranslateMessage(&msg);
 50         DispatchMessage(&msg);
 51     }
 52 
 53     return msg.wParam;
 54 }
 55 
 56 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 57 {
 58     static POINT aptFigure[10] = {10, 70
 59                                 , 50, 70
 60                                 , 50, 10
 61                                 , 90, 10
 62                                 , 90, 50
 63                                 , 30, 50
 64                                 , 30, 90
 65                                 , 70, 90
 66                                 , 70, 30
 67                                 , 10, 30};
 68     static int cxClient, cyClient;
 69     HDC hdc;
 70     int i;
 71     PAINTSTRUCT ps;
 72     POINT apt[10];
 73 
 74     switch (message)
 75     {
 76     case WM_SIZE:
 77         cxClient = LOWORD(lParam);
 78         cyClient = HIWORD(lParam);
 79         return 0;
 80 
 81     case WM_PAINT:
 82         hdc = BeginPaint(hwnd, &ps);
 83         SelectObject(hdc, GetStockObject(GRAY_BRUSH));
 84 
 85         for (i = 0; i !=10; ++i)
 86         {
 87             apt[i].x = cxClient * aptFigure[i].x / 200;
 88             apt[i].y = cyClient * aptFigure[i].y / 100;
 89         }
 90         SetPolyFillMode(hdc, ALTERNATE);
 91         Polygon(hdc, apt, 10);
 92 
 93         for (i = 0; i != 10; ++i)
 94         {
 95             apt[i].x += cxClient / 2;
 96         }
 97         SetPolyFillMode(hdc, WINDING);
 98         Polygon(hdc, apt, 10);
 99 
100         EndPaint(hwnd, &ps);
101         return 0;
102 
103     case WM_DESTROY:
104         PostQuitMessage(0);
105         return 0;
106     }
107 
108     return DefWindowProc(hwnd, message, wParam, lParam);
109 }

ALTWIND.C

图形的坐标(按一个100*100单位的区域设定)存储在aptFigure数组中。这些坐标会根据客户去的宽度和高度按比例缩放。程序显示两个图形,一个使用ALTERNATE填充模式,另一个使用WINDING填充模式。结果如图:

图片 4