mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
352 lines
10 KiB
C++
352 lines
10 KiB
C++
|
|
||
|
// ------------------------------------------------------------------
|
||
|
// Windows 2000 Graphics API Black Book
|
||
|
// Chapter 5 - Listing 5.1 (Output Primitives Demo)
|
||
|
//
|
||
|
// Created by Damon Chandler <dmc27@ee.cornell.edu>
|
||
|
// Updates can be downloaded at: <www.coriolis.com>
|
||
|
//
|
||
|
// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu
|
||
|
// if you have any questions about this code.
|
||
|
// ------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
|
#include <windows.h>
|
||
|
#include <cassert>
|
||
|
|
||
|
// 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<HBRUSH>(
|
||
|
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<LONG>(hListBox)
|
||
|
);
|
||
|
|
||
|
SNDMSG(hListBox, LB_ADDSTRING, 0,
|
||
|
reinterpret_cast<LPARAM>(TEXT("Line")));
|
||
|
SNDMSG(hListBox, LB_ADDSTRING, 0,
|
||
|
reinterpret_cast<LPARAM>(TEXT("Bezier Curve")));
|
||
|
SNDMSG(hListBox, LB_ADDSTRING, 0,
|
||
|
reinterpret_cast<LPARAM>(TEXT("Rectangle")));
|
||
|
SNDMSG(hListBox, LB_ADDSTRING, 0,
|
||
|
reinterpret_cast<LPARAM>(TEXT("Rounded Rectangle")));
|
||
|
SNDMSG(hListBox, LB_ADDSTRING, 0,
|
||
|
reinterpret_cast<LPARAM>(TEXT("Ellipse")));
|
||
|
SNDMSG(hListBox, LB_ADDSTRING, 0,
|
||
|
reinterpret_cast<LPARAM>(TEXT("Arc")));
|
||
|
SNDMSG(hListBox, LB_ADDSTRING, 0,
|
||
|
reinterpret_cast<LPARAM>(TEXT("Pie Slice")));
|
||
|
SNDMSG(hListBox, LB_ADDSTRING, 0,
|
||
|
reinterpret_cast<LPARAM>(TEXT("Chord")));
|
||
|
SNDMSG(hListBox, LB_ADDSTRING, 0,
|
||
|
reinterpret_cast<LPARAM>(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<LPMEASUREITEMSTRUCT>(lParam);
|
||
|
assert(lpmis != NULL);
|
||
|
|
||
|
if (lpmis->CtlID == reinterpret_cast<UINT>(hListBox))
|
||
|
{
|
||
|
lpmis->itemHeight = 150;
|
||
|
return TRUE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case WM_DRAWITEM:
|
||
|
{
|
||
|
LPDRAWITEMSTRUCT lpdis =
|
||
|
reinterpret_cast<LPDRAWITEMSTRUCT>(lParam);
|
||
|
assert(lpdis != NULL);
|
||
|
|
||
|
if (lpdis->CtlID == reinterpret_cast<UINT>(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<int>(
|
||
|
0.6 * lpdis->rcItem.right + 0.5
|
||
|
);
|
||
|
FillRect(
|
||
|
lpdis->hDC, &RPrimitive,
|
||
|
reinterpret_cast<HBRUSH>(COLOR_BTNFACE + 1)
|
||
|
);
|
||
|
DrawPrimitive(
|
||
|
lpdis->hDC, RPrimitive,
|
||
|
static_cast<OutPrimitive>(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<LPARAM>(&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);
|
||
|
}
|
||
|
//-------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
|