Ownerdraw-Technik und Hintergrund/Text-farbe von Statics/Editboxen...



  • // 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;
    }
    

Anmelden zum Antworten