// ------------------------------------------------------------------ // Windows 2000 Graphics API Black Book // Chapter 5 - Listing 5.1 (Output Primitives Demo) // // Created by Damon Chandler // Updates can be downloaded at: // // Please do not hesistate to e-mail me at dmc27@ee.cornell.edu // if you have any questions about this code. // ------------------------------------------------------------------ //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #include #include // for the MakeFont() function... #include "mk_font.h" //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HINSTANCE hInst; const char* WndClassName = "GMainWnd"; LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, LPARAM LParam); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int nCmdShow) { hInst = hInstance; WNDCLASS wc; memset(&wc, 0, sizeof(WNDCLASS)); wc.style = CS_VREDRAW | CS_HREDRAW; wc.lpszClassName = WndClassName; wc.lpfnWndProc = MainWndProc; wc.hInstance = hInst; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = reinterpret_cast( COLOR_BTNFACE + 1 ); if (RegisterClass(&wc)) { HWND hWnd = CreateWindow( WndClassName, TEXT("Output Primitives Demo"), WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_VISIBLE | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInst, NULL ); if (hWnd) { ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } } } return 0; } //------------------------------------------------------------------ enum OutPrimitive { opLine, opBezier, opRectangle, opRoundRect, opEllipse, opArc, opPie, opChord, opCustom }; void DrawPrimitive(IN HDC hDC, IN const RECT& RPrimitive, IN OutPrimitive PrimitiveID) { RECT R = RPrimitive; InflateRect(&R, -10, -10); switch (PrimitiveID) { case opLine: { const POINT PLine[] = {{R.left, R.top}, {R.right, R.bottom}}; Polyline(hDC, PLine, 2); break; } case opBezier: { const POINT PControlPoints[] = { {R.left, R.top}, {(R.right - R.left) / 2, R.top}, {(R.right - R.left) / 2, R.bottom}, {R.right, R.bottom} }; PolyBezier(hDC, PControlPoints, 4); break; } case opRectangle: { Rectangle(hDC, R.left, R.top, R.right, R.bottom); break; } case opRoundRect: { RoundRect(hDC, R.left, R.top, R.right, R.bottom, 20, 20); break; } case opEllipse: { Ellipse(hDC, R.left, R.top, R.right, R.bottom); break; } case opArc: { const POINT PRads[] = { {(R.right - R.left) / 3 + R.left, R.top}, {(R.right - R.left) / 3 + R.left, R.bottom} }; Arc(hDC, R.left, R.top, R.right, R.bottom, PRads[0].x, PRads[0].y, PRads[1].x, PRads[1].y); break; } case opPie: { const POINT PRads[] = { {(R.right - R.left) / 3 + R.left, R.top}, {(R.right - R.left) / 3 + R.left, R.bottom} }; Pie(hDC, R.left, R.top, R.right, R.bottom, PRads[0].x, PRads[0].y, PRads[1].x, PRads[1].y); break; } case opChord: { const POINT PRads[] = { {(R.right - R.left) / 3 + R.left, R.top}, {(R.right - R.left) / 3 + R.left, R.bottom} }; Chord(hDC, R.left, R.top, R.right, R.bottom, PRads[0].x, PRads[0].y, PRads[1].x, PRads[1].y); break; } case opCustom: { const POINT PVertices[] = { {R.left, (R.bottom - R.top) / 2 + R.top}, {(R.right - R.left) / 2 + R.left, R.top}, {R.right, (R.bottom - R.top) / 2 + R.top}, {(R.right - R.left) / 2 + R.left, R.bottom} }; Polygon(hDC, PVertices, 4); break; } } } //------------------------------------------------------------------ HWND hListBox = NULL; // handle to the list box HBRUSH hListBrush = NULL; // handle to the list box brush HPEN hListPen = NULL; // handle to the list box pen HFONT hListFont = NULL; // handle to the list box font LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: { hListBox = CreateWindowEx( WS_EX_CLIENTEDGE, TEXT("LISTBOX"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_OWNERDRAWFIXED, 0, 0, 640, 480, hWnd, NULL, hInst, NULL ); assert(hListBox != NULL); SetWindowLong( hListBox, GWL_ID, reinterpret_cast(hListBox) ); SNDMSG(hListBox, LB_ADDSTRING, 0, reinterpret_cast(TEXT("Line"))); SNDMSG(hListBox, LB_ADDSTRING, 0, reinterpret_cast(TEXT("Bezier Curve"))); SNDMSG(hListBox, LB_ADDSTRING, 0, reinterpret_cast(TEXT("Rectangle"))); SNDMSG(hListBox, LB_ADDSTRING, 0, reinterpret_cast(TEXT("Rounded Rectangle"))); SNDMSG(hListBox, LB_ADDSTRING, 0, reinterpret_cast(TEXT("Ellipse"))); SNDMSG(hListBox, LB_ADDSTRING, 0, reinterpret_cast(TEXT("Arc"))); SNDMSG(hListBox, LB_ADDSTRING, 0, reinterpret_cast(TEXT("Pie Slice"))); SNDMSG(hListBox, LB_ADDSTRING, 0, reinterpret_cast(TEXT("Chord"))); SNDMSG(hListBox, LB_ADDSTRING, 0, reinterpret_cast(TEXT("Custom"))); hListBrush = CreateSolidBrush(PALETTERGB(64, 192, 64)); hListPen = CreatePen(PS_SOLID, 3, PALETTERGB(0, 0, 0)); HDC hScreenDC = GetDC(NULL); #if 0 try #endif { // MakeFont() from Chapter 4 hListFont = font::MakeFont( hScreenDC, "Impact", 20, ANSI_CHARSET, font::FS_BOLD | font::FS_UNDERLINE ); } #if 0 catch (...) #endif { ReleaseDC(NULL, hScreenDC); } ReleaseDC(NULL, hScreenDC); break; } case WM_MEASUREITEM: { LPMEASUREITEMSTRUCT lpmis = reinterpret_cast(lParam); assert(lpmis != NULL); if (lpmis->CtlID == reinterpret_cast(hListBox)) { lpmis->itemHeight = 150; return TRUE; } break; } case WM_DRAWITEM: { LPDRAWITEMSTRUCT lpdis = reinterpret_cast(lParam); assert(lpdis != NULL); if (lpdis->CtlID == reinterpret_cast(hListBox)) { SaveDC(lpdis->hDC); #if 0 try #endif { SelectObject(lpdis->hDC, hListBrush); SelectObject(lpdis->hDC, hListPen); SelectObject(lpdis->hDC, hListFont); bool selected = (lpdis->itemState & ODS_SELECTED); COLORREF clrText = GetSysColor( selected ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT ); HBRUSH hListBrush = GetSysColorBrush( selected ? COLOR_HIGHLIGHT : COLOR_WINDOW ); // fill the background FillRect(lpdis->hDC, &lpdis->rcItem, hListBrush); // render the output primitive RECT RPrimitive = lpdis->rcItem; InflateRect(&RPrimitive, -5, -5); RPrimitive.right = static_cast( 0.6 * lpdis->rcItem.right + 0.5 ); FillRect( lpdis->hDC, &RPrimitive, reinterpret_cast(COLOR_BTNFACE + 1) ); DrawPrimitive( lpdis->hDC, RPrimitive, static_cast(lpdis->itemID) ); if (selected) InvertRect(lpdis->hDC, &RPrimitive); DrawEdge(lpdis->hDC, &RPrimitive, EDGE_SUNKEN, BF_RECT); // render the text TCHAR text[13]; if (SNDMSG(hListBox, LB_GETTEXT, lpdis->itemID, reinterpret_cast(&text)) != LB_ERR) { RECT RText = RPrimitive; RText.left = RPrimitive.right; RText.right = lpdis->rcItem.right; SelectObject(lpdis->hDC, hListFont); SetBkMode(lpdis->hDC, TRANSPARENT); SetTextColor(lpdis->hDC, clrText); DrawText(lpdis->hDC, text, -1, &RText, DT_CENTER | DT_VCENTER | DT_SINGLELINE); } // indicate keyboard focus if (lpdis->itemState & ODS_FOCUS) { RECT RFocus = lpdis->rcItem; InflateRect(&RFocus, -1, -1); DrawFocusRect(lpdis->hDC, &RFocus); } } #if 0 catch (...) #endif { RestoreDC(lpdis->hDC, -1); } RestoreDC(lpdis->hDC, -1); return TRUE; } break; } case WM_SIZE: { MoveWindow( hListBox, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE ); return 0; } case WM_DESTROY: { if (hListBrush) DeleteObject(hListBrush); if (hListPen) DeleteObject(hListPen); if (hListFont) DeleteObject(hListFont); PostQuitMessage(0); return 0; } } return DefWindowProc(hWnd, msg, wParam, lParam); } //-------------------------------------------------------------------------