// Dieses Beispielprogramm erzeugt:
// - 1 Fenster
// - 2 Owner-Draw Buttons
// - 1 Editbox
// - 1 Label (alias Static)
//
// Bei den relevanten Teilen sind hoffentlich genug Kommentare ;-)
#include "stdafx.h"
#include "resource.h"
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
bool DrawButton(DRAWITEMSTRUCT *dis);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
// Initialize global strings
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW|CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = 0;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wcex.lpszMenuName = 0;
wcex.lpszClassName = "window_class";
wcex.hIconSm = 0;
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hWnd=CreateWindow("window_class", "titel", WS_VISIBLE|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX, 20, 20, 300, 150, NULL, NULL, hInstance, NULL);
// 2 Buttons erzeugen:
CreateWindow("BUTTON","Ein Button",BS_OWNERDRAW|WS_CHILD|WS_VISIBLE,5,5,100,20,hWnd,NULL,hInstance,NULL);
CreateWindow("BUTTON","Noch ein Button",BS_OWNERDRAW|WS_CHILD|WS_VISIBLE,110,5,100,20,hWnd,NULL,hInstance,NULL);
// Editbox und Static erzeugen:
CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","Eine Editbox",WS_CHILD|WS_VISIBLE,5,30,100,20,hWnd,NULL,hInstance,NULL);
CreateWindow("STATIC","Ein Label",WS_CHILD|WS_VISIBLE,110,30,100,20,hWnd,NULL,hInstance,NULL);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
// Das Übliche:
case WM_DESTROY:
PostQuitMessage(0);
break;
// Diese Nachricht wird für das Label gesendet, für die Editbox
// nur, wenn die Editbox disabled ist.
case WM_CTLCOLORSTATIC:
// Texthintergrund auf transparent setzen:
SetBkMode((HDC)wParam,TRANSPARENT);
// Textfarbe auf rot setzen
SetTextColor((HDC)wParam,RGB(255,0,0));
// Hintergrundfarbe auf blau setzen:
// Achtung: Den Handle, den CreateSolidBrush() zurückliefert
// kann nicht mehr gelöscht werden, wenn man es so aufruft:
return (long)CreateSolidBrush(RGB(0,0,255));
break;
// Diese Nachricht wird für die EditBox gesendet:
case WM_CTLCOLOREDIT:
SetBkMode((HDC)wParam,TRANSPARENT); // Texthintergrund auf transparent setzen
SetTextColor((HDC)wParam,RGB(255,255,255)); // Textfarbe auf Weiss setzen
return (long)CreateSolidBrush(RGB(0,0,0)); // Hintergrundfarbe auf schwarz setzen
break;
// Diese Nachricht wird für beide Buttons gesendet:
case WM_DRAWITEM:
// Hier rufe ich zwecks Übersichtlichkeit eine eigene
// Funktion zum Button zeichnen auf:
return DrawButton((LPDRAWITEMSTRUCT)lParam);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
bool DrawButton(DRAWITEMSTRUCT *dis)
{
HGDIOBJ OldObj;
char text[500];
HBRUSH aBrush;
RECT rt;
// Damit man später nicht immer "dis->rcItem" schreiben muss:
rt.left=dis->rcItem.left;
rt.top=dis->rcItem.top;
rt.right=dis->rcItem.right;
rt.bottom=dis->rcItem.bottom;
// Bei itemAction ist das Style ODA_DRAWENTIRE enthalten, also
// muss alles gezeichnet werden:
if (dis->itemAction & ODA_DRAWENTIRE)
{
// Hintergrund zeichnen:
aBrush=GetSysColorBrush(COLOR_BTNFACE);
OldObj=SelectObject(dis->hDC,aBrush);
PatBlt(dis->hDC,1,1,(rt.right-2),(rt.bottom-2),PATCOPY);
DeleteObject(SelectObject(dis->hDC,OldObj));
// Text holen:
GetWindowText(dis->hwndItem,text,500);
// Text zeichnen:
// Standard-Schriftart holen:
OldObj=SelectObject(dis->hDC,GetStockObject(DEFAULT_GUI_FONT));
// Hintergrund des Textes auf Transparent schalten:
SetBkMode(dis->hDC,TRANSPARENT);
// Textfarbe setzen:
SetTextColor(dis->hDC,RGB(0,0,0));
// Und nun endlich zeichnen:
rt.top=rt.top+2; // Nur, damits besser passt:
DrawText(dis->hDC,text,strlen(text),&rt,DT_CENTER); // Caption zeichnen
rt.top=rt.top-2; // Damits wieder stimmt!
// Schriftart wieder freigeben und altes Objekt wieder selektieren:
DeleteObject(SelectObject(dis->hDC,OldObj));
}
// Bei itemAction ist ODA_SELECT oder ODA_DRAWENTIRE enthalten,
// es muss der Rand (Border) also gezeichnet werden:
if (dis->itemAction & (ODA_SELECT|ODA_DRAWENTIRE))
{
if (dis->itemState & ODS_SELECTED)
{
// Der Button ist gedrückt, also zeichnen wir
// am rechten Rand und am unteren Rand des Buttons
// eine weisse Linie:
aBrush=GetSysColorBrush(COLOR_BTNHILIGHT);
OldObj=SelectObject(dis->hDC,aBrush);
PatBlt(dis->hDC,(rt.right-1),0,(rt.right-1),(rt.bottom-1),PATCOPY);
PatBlt(dis->hDC,0,(rt.bottom-1),rt.right,1,PATCOPY);
DeleteObject(SelectObject(dis->hDC,OldObj));
// und als oberen und linken Rand einen grauen Rand:
aBrush=GetSysColorBrush(COLOR_BTNSHADOW);
OldObj=SelectObject(dis->hDC,aBrush);
PatBlt(dis->hDC,0,0,(rt.right-1),1,PATCOPY);
PatBlt(dis->hDC,0,0,1,rt.bottom,PATCOPY);
DeleteObject(SelectObject(dis->hDC,OldObj));
}
else
{
// Der Button ist nicht gedrückt, also zeichnen wir
// alles mit umgekehrten Farben, der untere und rechte
// Rand wird jetzt statt weiss grau:
aBrush=GetSysColorBrush(COLOR_BTNSHADOW);
OldObj=SelectObject(dis->hDC,aBrush);
PatBlt(dis->hDC,(rt.right-1),0,(rt.right-1),(rt.bottom-1),PATCOPY);
PatBlt(dis->hDC,0,(rt.bottom-1),rt.right,1,PATCOPY);
DeleteObject(SelectObject(dis->hDC,OldObj));
// ...und der obere und linke Rand wird weiss:
aBrush=GetSysColorBrush(COLOR_BTNHILIGHT);
OldObj=SelectObject(dis->hDC,aBrush);
PatBlt(dis->hDC,0,0,(rt.right-1),1,PATCOPY);
PatBlt(dis->hDC,0,0,1,rt.bottom,PATCOPY);
DeleteObject(SelectObject(dis->hDC,OldObj));
}
}
// itemAction enthält das Style ODA_FOCUS, es soll also eine
// gestrichelte Fokus-Linie gezeichnet werden, wozu ich jetzt
// keine Lust mehr hatte:
if (dis->itemAction & ODA_FOCUS)
{
// Hier könnte man noch den einen gestrichelten Rahmen
// zeichnen, da der Button den Keyboard-Fokus hat
}
else
{
// Der Button hat keinen Keyboard-Fokus (mehr)
}
return true;
}