第五章 绘图基础(ALTWIND)
线上箭头表示画线的方向。WINDING模式和ALTERNATE模式都会填充三个封闭的L型区域,号码从1到3。两个更小的内部区域,号码为4和5,在ALTERNATE模式下不被填充。但是在WINDING模式下,号码5的区域会被填充,这是因为区域的内部到达图形的外部必须穿过两条相同方向的线。号码为4的区域不会被填充,因为射线必须穿越两条边框线,但是这两条边框线的绘制方向相反。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
图形的坐标(按一个100*100单位的区域设定)存储在aptFigure数组中。这些坐标会根据客户去的宽度和高度按比例缩放。程序显示两个图形,一个使用ALTERNATE填充模式,另一个使用WINDING填充模式。结果如图: