OWNERDRAW (Button)



  • Hi!
    Ich habe schon in der FAQ gelesen und die Suchfunktion benutzt, falls ich das jetzt denkt. 😃

    Folgendes. Ich würde meine Buttons jetzt gerne komplett selber zeichnen, also OWNERDRAW verwenden. So weit bin ich gekommen:

    case WM_CREATE:
            {
                hButton = CreateWindowEx(NULL, "button", "BUTTON1", WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, 100, 100, 300, 50, hWnd, (HMENU)IDC_BUTTON, hInst, NULL);
                return true;
            }
            case WM_DRAWITEM:
            {
                LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
                HBRUSH hBrush = NULL;
                switch(dis->CtlID)
                {
                    case IDC_BUTTON:
                    {
                        SetTextColor(dis->hDC, RGB(0, 0, 255));
                        TextOut(dis->hDC, 20, 20, "Mein Ownerdraw Button", strlen("Mein Ownerdraw Button"));
                        break;
                    }
                    break;
                }
                DeleteObject(hBrush);
                break;
            }
    

    Der Button sieht noch unmöglich aus, es ist eine einfache graue Fläche mit einem blauen Text darin. Wenn man darauf klickt, kann ich zwar einfach den Klick abfragen, aber der Button "vertieft" sich nicht solange man mit der Maus darauf klickt...

    Mein Fragen:
    Wie bekommt man es hin, dass es ein PUSHBUTTON wird?
    Wenn man noch darüber hinausgeht, wie schafft man solche Buttons, die erst garkein Rand haben, und wenn man mit der Maus darüberfährt kommt ein Rand darum heraus?
    Achja noch GANZ wichtig, darum geht es mir: wie bekomme ich ein Bild auf den Button per OWNERDRAW? Kann ich in den DC beliebig zeichen, ein Bild links hinsetzen, und rechts Text hinschreiben? Ist möglich oder?

    Tja ein paar Fragen. 🙄
    Aber ich denke es geht in Ordnung und Ihr wisst Antwort?
    Würde mich freuen...
    Jetzt aber Schluss...
    bye



  • Du musst noch den Zustand des Buttons bestimmen bevor du es malst.
    Dann nimmst du einfach zwei Grafiken normal und eingedrückt.

    case WM_CREATE:
            {
                hButton = CreateWindowEx(NULL, "button", "BUTTON1", WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, 100, 100, 300, 50, hWnd, (HMENU)IDC_BUTTON, hInst, NULL);
                return true;
            }
            case WM_DRAWITEM:
            {
                LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
                HBRUSH hBrush = NULL;
                switch(dis->CtlID)
                {
                    case IDC_BUTTON:
                    {
                        switch(LPDRAWITEMSTRUCT->itemState)
                        {
                           case ODS_DEFAULT:
                        SetTextColor(dis->hDC, RGB(0, 0, 255));
                        TextOut(dis->hDC, 20, 20, "Mein Ownerdraw Button", strlen("Mein Ownerdraw Button"));
                           break;
                           case ODS_SELECTED
                           //
                           break;
                        }
                        break;
                    }
                    break;
                }
                DeleteObject(hBrush);
                break;
            }
    


  • Also irgendwie funzt das dann garnix mehr.



  • Naja, anstatt:

    switch(LPDRAWITEMSTRUCT->itemState)
    

    muss es natürlich heißen:

    switch(dis->itemState)
    

    Unter ODS_DEFAULT malst du dann den Button wie er "normal" aussehen soll und unter ODS_SELECTED wie er "gedrückt" aussehen soll.



  • Also irgendwie funzt das dann garnix mehr.

    Aha. Jetzt weiß ich genau bescheid. Prima Problembeschreibung. Hut ab.

    Nochmal: In der DRAWITEMSTRUCT gibt es Member namens 'itemState'. Daran siehst Du, ob der Button nun gedrückt ist oder nicht. Und erzähle bitte nicht, daß der Artikel in den FAQs das nicht berücksichtigt.

    Allerdings hat geeky die Buttons komplett selbst gezeichnet. Einfacher wird es, wenn man die Funktion DrawFrameControl() für sich entdeckt hat.

    BTW: Wenn Ihr das unter XP laufen lassen und auch die Controls der Version 6 verwenden wollt, ist alles wieder ganz anders ...



  • -King-, du bist der King! Jetzt hab ich das auch mal gecheckt! 😃

    thx thx thx!



  • Also irgendwie funzt das dann garnix mehr.

    Aha. Jetzt weiß ich genau bescheid. Prima Problembeschreibung. Hut ab.

    MUAHAHAHAHAHAHAHAHAHAHAHAHHAHA!! Das musste mal sein. Sorry.
    Ne also es lag nicht daran dass ich mein Problem nicht beschreiben konnte sondern weil 'stealth' das falsch erklärt hat. Man darf die States nicht mit case abfragen.

    if(dis->itemState & ODS_FOCUS)
                        {
                            SetTextColor(dis->hDC, RGB(0, 0, 255));
                            TextOut(dis->hDC, 20, 20, "Mein Ownerdraw Button", strlen("Mein Ownerdraw Button"));
                        }
                        if(dis->itemState & ODS_SELECTED)
                        {
                            SetTextColor(dis->hDC, RGB(0, 0, 255));
                            TextOut(dis->hDC, 21, 21, "Mein Ownerdraw Button", strlen("Mein Ownerdraw Button"));
                        }
    

    Geht bei mir wunderbar. Das ganze was ich bis jetzt getan hab ist den Button (den Rand) ganz selbst zu zeichnen:

    LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch(message)
        {
            case WM_CREATE:
            {
                hButton = CreateWindowEx(NULL, "button", "BUTTON1", WS_VISIBLE | WS_CHILD | BS_NOTIFY | BS_OWNERDRAW, 100, 100, 300, 50, hWnd, (HMENU)IDC_BUTTON, hInst, NULL);
                return true;
            }
            case WM_DRAWITEM:
            {
                LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
                HPEN hPen1 = NULL;
                HPEN hPen2 = NULL;
                HPEN hPen3 = NULL;
                HPEN hPen4 = NULL;
                switch(dis->CtlID)
                {
                    case IDC_BUTTON:
                    {
                        //Rectangle(dis->hDC, dis->rcItem.left, dis->rcItem.top, dis->rcItem.right, dis->rcItem.bottom);
    
                        SetTextColor(dis->hDC, RGB(0, 0, 255));
                        TextOut(dis->hDC, 20, 20, "Mein Ownerdraw Button", strlen("Mein Ownerdraw Button"));
                        hPen1 = CreatePen(PS_SOLID, 0, RGB(255, 255, 255));
                        hPen2 = CreatePen(PS_SOLID, 0, RGB(230, 230, 230));
                        hPen3 = CreatePen(PS_SOLID, 0, RGB(170, 170, 170));
                        hPen4 = CreatePen(PS_SOLID, 0, RGB(110, 110, 110));
    
                        SelectObject(dis->hDC, (HPEN)hPen1);
                        MoveToEx(dis->hDC, dis->rcItem.left,  dis->rcItem.top, (LPPOINT)NULL);
                        LineTo  (dis->hDC, dis->rcItem.right - 1, dis->rcItem.top);
                        MoveToEx(dis->hDC, dis->rcItem.left,  dis->rcItem.top, (LPPOINT)NULL);
                        LineTo  (dis->hDC, dis->rcItem.left,  dis->rcItem.bottom - 1);
    
                        SelectObject(dis->hDC, (HPEN)hPen2);
                        MoveToEx(dis->hDC, dis->rcItem.left + 1,  dis->rcItem.top + 1, (LPPOINT)NULL);
                        LineTo  (dis->hDC, dis->rcItem.right - 2, dis->rcItem.top + 1);
                        MoveToEx(dis->hDC, dis->rcItem.left + 1,  dis->rcItem.top + 1, (LPPOINT)NULL);
                        LineTo  (dis->hDC, dis->rcItem.left + 1,  dis->rcItem.bottom - 2);
    
                        SelectObject(dis->hDC, (HPEN)hPen3);
                        MoveToEx(dis->hDC, dis->rcItem.left + 1,  dis->rcItem.bottom - 2, (LPPOINT)NULL);
                        LineTo  (dis->hDC, dis->rcItem.right - 1, dis->rcItem.bottom - 2);
                        MoveToEx(dis->hDC, dis->rcItem.right - 2,  dis->rcItem.bottom - 2, (LPPOINT)NULL);
                        LineTo  (dis->hDC, dis->rcItem.right - 2,  dis->rcItem.top);
    
                        SelectObject(dis->hDC, (HPEN)hPen4);
                        MoveToEx(dis->hDC, dis->rcItem.left - 1,  dis->rcItem.bottom - 1, (LPPOINT)NULL);
                        LineTo  (dis->hDC, dis->rcItem.right - 1, dis->rcItem.bottom - 1);
                        MoveToEx(dis->hDC, dis->rcItem.right - 1,  dis->rcItem.bottom - 1, (LPPOINT)NULL);
                        LineTo  (dis->hDC, dis->rcItem.right - 1,  dis->rcItem.top - 1);
    
                        if(dis->itemState & ODS_CHECKED)
                        {
                            SetTextColor(dis->hDC, RGB(0, 0, 255));
                            TextOut(dis->hDC, 20, 20, "ODS_CHECKED", strlen("ODS_CHECKED"));
                        }
                        if(dis->itemState & ODS_COMBOBOXEDIT)
                            MessageBox(hWnd, "ODS_COMBOBOXEDIT", "Notification", 0);
                        if(dis->itemState & ODS_DEFAULT)
                            MessageBox(hWnd, "ODS_DEFAULT", "Notification", 0);
                        if(dis->itemState & ODS_DEFAULT)
                            MessageBox(hWnd, "ODS_DISABLED", "Notification", 0);
                        if(dis->itemState & ODS_DISABLED)
                            MessageBox(hWnd, "ODS_FOCUS", "Notification", 0);
                        if(dis->itemState & ODS_FOCUS)
                        {
                            SetTextColor(dis->hDC, RGB(0, 0, 255));
                            TextOut(dis->hDC, 20, 20, "Mein Ownerdraw Button", strlen("Mein Ownerdraw Button"));
                        }
                        if(dis->itemState & ODS_GRAYED)
                        {
                            SetTextColor(dis->hDC, RGB(0, 0, 255));
                            TextOut(dis->hDC, 20, 20, "ODS_GRAYED", strlen("ODS_GRAYED"));
                        }
                        if(dis->itemState & ODS_INACTIVE)
                            MessageBox(hWnd, "ODS_INACTIVE", "Notification", 0);
                        if(dis->itemState & ODS_SELECTED)
                        {
                            SetTextColor(dis->hDC, RGB(0, 0, 255));
                            TextOut(dis->hDC, 21, 21, "Mein Ownerdraw Button", strlen("Mein Ownerdraw Button"));
                        }
                        break;
                    }
                    break;
                }
                DeleteObject(hPen1);
                DeleteObject(hPen2);
                DeleteObject(hPen3);
                DeleteObject(hPen4);
                break;
            }
            case WM_DESTROY:
            {
                PostQuitMessage(0);
                break;
            }
            break;
        }
        return DefWindowProc (hWnd, message, wParam, lParam);
    }
    

    Greez Chris|K



  • Diese States sind ja alle ganz schön, aber es gibt keinen über den ich erfahre, dass die Maus über meinem Button ist.

    Wie kann man das anders machen?

    Ich hab schon versucht über WM_MOUSEMOVE des Parent-Fensters die Maus-Koordinaten mit den Feld-Koordinaten meiner Buttons abzugleichen, aber wie ich feststellen musste, erhält mein Parent-Fenster die Nachricht WM_MOUSEMOVE nicht mehr sobald ich auf einen meiner Buttons fahre. Dann ist halt ein anderes Fenster aktiv.

    Ich quäle mich jetzt schon seit gestern Vormittag damit und wäre hocherfreut, wenn mir mal jemand die Augen öffnen könnte.

    lg Max



  • TrackMouseEvent



  • Danke!

    lg Max


Log in to reply