Seite 1 von 1

Frage an die OwnerDraw-Experten

Verfasst: 16.06.2011 23:20
von X0r
Hallo,
zurzeit versuche ich, simple Skinning-Funktionalitäten in meine Anwendung zu implementieren. Dabei ist jetzt folgendes Problem aufgetaucht:
Erstelle ich OwnerDraw-Buttons (siehe #BS_OWNERDRAW) in Verbindung mit DrawIconEx, so werden diese eigentlich korrekt dargestellt.
Weise ich dem Fenster, auf dem der Button dargestellt werden soll, nun jedoch ein Hintergrundbild zu (siehe #GCL_HBRBACKGROUND), so wird der OwnerDraw-Button zwar immer noch dargestellt, jedoch nicht mehr transparent.

Wie wäre dieses Problem zu beheben?

Re: Frage an die OwnerDraw-Experten

Verfasst: 17.06.2011 20:30
von Danilo
Hier mal ein Fake-Beispiel. Dabei wird der Hintergrund vom Parent-Fenster
genommen, funktioniert also nicht mit darunterliegenden Gadgets.
Den Window-Background kannst Du in Zeile 55 ersetzen:
CreateHatchBrush_(#HS_DIAGCROSS,RGB($80,$80,$80))

Code: Alles auswählen

Procedure WinCallback(hWnd, Msg, wParam, lParam) 
    If Msg = #WM_DRAWITEM
        *dis.DRAWITEMSTRUCT = lParam
        If *dis
            If *dis\CtlType = #ODT_BUTTON
                hDC = *dis\hDC;GetDC_(*dis\hwndItem)
                width  = GadgetWidth(*dis\CtlID)
                height = GadgetHeight(*dis\CtlID)
                x = GadgetX(*dis\CtlID)
                y = GadgetY(*dis\CtlID)
                
                If GetGadgetData(*dis\CtlID) = 0
                    ; no gadget data = transparent background
                    hDC2=CreateCompatibleDC_(hDC)
                    SelectObject_(hDC2,CreateCompatibleBitmap_(hDC,x+width,y+height))
                    SendMessage_(GetParent_(*dis\hwndItem),#WM_ERASEBKGND,hDC2,0)
                    ;SendMessage_(GetParent_(*dis\hwndItem),#WM_PRINT,hDC2,#PRF_ERASEBKGND|#PRF_CLIENT) ; alternativ
                    BitBlt_(hDC,0,0,width,height,hDC2,x,y,#SRCCOPY)
                    DeleteDC_(hDC2)
                Else
                    ; gadget data = background color
                    backBrush = CreateSolidBrush_(GetGadgetData(*dis\CtlID))
                    SelectObject_(hDC,backBrush)
                    PatBlt_(hDC,0,0,width,height,#PATCOPY)
                EndIf

                ; Draw Button
                If *dis\itemState&#ODS_SELECTED
                    stateOffset = 1
                EndIf
                SetBkMode_(hDC,#TRANSPARENT)
                SelectObject_(hDC,GetStockObject_(#HOLLOW_BRUSH))
                SelectObject_(hDC,GetGadgetFont(*dis\CtlID))
                Rectangle_(hDC,stateOffset,stateOffset,width-stateOffset*2,height-stateOffset*2)
                GetClientRect_(*dis\hwndItem,@r.RECT)
                DrawText_(hDC,GetGadgetText(*dis\CtlID),-1,@r,#DT_CENTER|#DT_VCENTER|#DT_SINGLELINE)
                ;ReleaseDC_(*dis\hwndItem,hDC)
                ProcedureReturn #True
            EndIf
        EndIf
    ElseIf Msg = #WM_ERASEBKGND
        SelectObject_(wParam,GetClassLongPtr_(hWnd,#GCL_HBRBACKGROUND))
        GetClientRect_(hWnd,@r.RECT)
        PatBlt_(wParam,0,0,r\right,r\bottom,#PATCOPY)
        ProcedureReturn #True
    EndIf
    ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 


mainWin = OpenWindow(#PB_Any,0,0,1024,768,"Btn",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

SetWindowCallback(@WinCallback())

SetClassLongPtr_(WindowID(mainWin),#GCL_HBRBACKGROUND,CreateHatchBrush_(#HS_DIAGCROSS,RGB($80,$80,$80)))

ButtonGadget(#PB_Any,10,10,100,25,"Button 0")

Btn1 = ButtonGadget(#PB_Any,10,40,100,25,"Button 1",#BS_OWNERDRAW)
;SetGadgetFont(Btn1,LoadFont(0,"Tahoma",12))

Btn2 = ButtonGadget(#PB_Any,10,70,100,25,"Button 2",#BS_OWNERDRAW)
SetGadgetData(Btn2,RGB($FF,$FF,$00))

Btn3 = ButtonGadget(#PB_Any,10,100,100,25,"Button 3",#BS_OWNERDRAW)
SetGadgetData(Btn3,RGB($80,$80,$FF))

Repeat
    Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
            Break
    EndSelect
ForEver
Vielleicht reicht das schon für Deine simple Skinning-Funktionalität.

Re: Frage an die OwnerDraw-Experten

Verfasst: 17.06.2011 21:12
von X0r
Vielen Dank,
aber hast du das ganze mal mit DrawIconEx für die OwnerDraw-Buttons ausprobiert?

Re: Frage an die OwnerDraw-Experten

Verfasst: 18.06.2011 06:55
von Danilo
X0r hat geschrieben:Vielen Dank,
aber hast du das ganze mal mit DrawIconEx für die OwnerDraw-Buttons ausprobiert?
Auf was willst Du denn hinaus?

Verstehe noch nicht ganz wo Dein Problem liegt, aber ist ohne Beispiel
deinerseits auch nicht ganz leicht. :)

Aber von mir aus auch mit DrawIconEx:

Code: Alles auswählen

;
; by Danilo, 18. Juni 2011
;
Global hIcon

Procedure WinCallback(hWnd, Msg, wParam, lParam) 
    If Msg = #WM_DRAWITEM
        *dis.DRAWITEMSTRUCT = lParam
        If *dis
            If *dis\CtlType = #ODT_BUTTON
                hDC = *dis\hDC;GetDC_(*dis\hwndItem)
                width  = GadgetWidth(*dis\CtlID)
                height = GadgetHeight(*dis\CtlID)
                x = GadgetX(*dis\CtlID)
                y = GadgetY(*dis\CtlID)
                
                If GetGadgetData(*dis\CtlID) = 0
                    ; no gadget data = transparent background
                    hDC2=CreateCompatibleDC_(hDC)
                    hBmp=CreateCompatibleBitmap_(hDC,x+width,y+height)
                    oldBmp=SelectObject_(hDC2,hBmp)
                    SendMessage_(GetParent_(*dis\hwndItem),#WM_ERASEBKGND,hDC2,0)
                    ;SendMessage_(GetParent_(*dis\hwndItem),#WM_PRINT,hDC2,#PRF_ERASEBKGND|#PRF_CLIENT) ; alternativ
                    BitBlt_(hDC,0,0,width,height,hDC2,x,y,#SRCCOPY)
                    DeleteDC_(hDC2)
                    DeleteObject_(hBmp)
                Else
                    ; gadget data = background color
                    backBrush = CreateSolidBrush_(GetGadgetData(*dis\CtlID))
                    SelectObject_(hDC,backBrush)
                    PatBlt_(hDC,0,0,width,height,#PATCOPY)
                EndIf

                ; Draw Button
                If *dis\itemState&#ODS_SELECTED
                    stateOffset = 1
                EndIf
                SetBkMode_(hDC,#TRANSPARENT)
                SelectObject_(hDC,GetStockObject_(#HOLLOW_BRUSH))
                SelectObject_(hDC,GetGadgetFont(*dis\CtlID))
                RoundRect_(hDC,stateOffset,stateOffset,width-stateOffset*2,height-stateOffset*2,6,6)
                GetClientRect_(*dis\hwndItem,@r.RECT)
                DrawText_(hDC,GetGadgetText(*dis\CtlID),-1,@r,#DT_CENTER|#DT_VCENTER|#DT_SINGLELINE)
                DrawIconEx_(hDC,10,3,hIcon,0,0,0,0,#DI_DEFAULTSIZE|#DI_IMAGE|#DI_MASK)
                ;ReleaseDC_(*dis\hwndItem,hDC)
                ProcedureReturn #True
            EndIf
        EndIf
    ElseIf Msg = #WM_ERASEBKGND
        SelectObject_(wParam,GetClassLongPtr_(hWnd,#GCL_HBRBACKGROUND))
        GetClientRect_(hWnd,@r.RECT)
        PatBlt_(wParam,0,0,r\right,r\bottom,#PATCOPY)
        ProcedureReturn #True
    EndIf
    ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

;hIcon = LoadImage_(0,#OIC_HAND,#IMAGE_ICON,16,16,#LR_SHARED)
hIcon = LoadCursor_(0,#IDC_ARROW)

mainWin = OpenWindow(#PB_Any,0,0,1024,768,"Btn",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

SetWindowCallback(@WinCallback())

SetClassLongPtr_(WindowID(mainWin),#GCL_HBRBACKGROUND,CreateHatchBrush_(#HS_DIAGCROSS,RGB($80,$80,$80)))

ButtonGadget(#PB_Any,10,10,100,25,"Button 0")

Btn1 = ButtonGadget(#PB_Any,10,40,100,25,"Button 1",#BS_OWNERDRAW)
;SetGadgetFont(Btn1,LoadFont(0,"Tahoma",12))

Btn2 = ButtonGadget(#PB_Any,10,70,100,25,"Button 2",#BS_OWNERDRAW)
SetGadgetData(Btn2,RGB($FF,$FF,$00))

Btn3 = ButtonGadget(#PB_Any,10,100,100,25,"Button 3",#BS_OWNERDRAW)
SetGadgetData(Btn3,RGB($80,$80,$FF))

Repeat
    Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
            Break
    EndSelect
ForEver
Vielleicht möchtest Du ja was anderes machen, dann zeige bitte mal
ein minimales Beispiel mit Deinem Problem. Ich sehe bisher noch
kein Problem. /:->

Re: Frage an die OwnerDraw-Experten

Verfasst: 20.06.2011 19:03
von X0r
Sorry für meine minimalistisch gehaltenen Beiträge. Ich hab es halt ohne diesen "Umweg" gemacht und mich gefragt, wieso die Win API da solche Probleme bereiten muss. :D