Frage an die OwnerDraw-Experten

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Frage an die OwnerDraw-Experten

Beitrag 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?
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Frage an die OwnerDraw-Experten

Beitrag 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.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Re: Frage an die OwnerDraw-Experten

Beitrag von X0r »

Vielen Dank,
aber hast du das ganze mal mit DrawIconEx für die OwnerDraw-Buttons ausprobiert?
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Frage an die OwnerDraw-Experten

Beitrag 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. /:->
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Re: Frage an die OwnerDraw-Experten

Beitrag 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
Antworten