Schatten berechnen für Button mit Imagegadget, wie besser?

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Schatten berechnen für Button mit Imagegadget, wie besser?

Beitrag von hjbremer »

Hallo, ich habe für Buttons mit 3D Aussehen, um eine Fläche einen Rahmen aus Polygonen gezeichnet. Dieser Rahmen soll nun unterschiedliche Farben haben, um einen Schatten zu simulieren. Also 4 verschiedene Farben.

Meine Procedure myButtonShadow tut zwar mehr oder weniger was sie soll, aber das sieht ja sowas von grausam primitiv aus, das muß/geht doch bestimmt einfacher !!! HELP !

Und zum Zweiten, ich habe die Polygone 4 mal gezeichnet. Aber würde es nicht reichen ein Polygon zu zeichnen, es 3mal zu duplizieren/drehen/verkleinern oder wäre das aufwendiger ?

Code: Alles auswählen

;07.03.2008 by hjbremer
;Polygone als Imagebutton

#buttondk=4
#contrast0=-30
#contrast1= 30

Enumeration 
 #winnr
 ;hier beginnen die ON Buttons
 #buttonN
 #button1
 #button2
 #button3
 ;hier beginnen die ON-OFF Buttons
 #buttonEA
 #button4
 #button5
 #button6
 #button7
 #button8
 #button9
 #buttonMax 
 ;es folgen sonstige 
 #txt1
 #xyz
 #zxy
 #etc
EndEnumeration

Dim buttonstate(#buttonmax)

Procedure myButtonShadow(farbe,*c.rect)

r=Red(farbe)
g=Green(farbe)
b=Blue(farbe)

rtop=r+48:If rtop > 255:rtop=255:EndIf
          If rtop < 128:rtop=128:EndIf
gtop=g+48:If gtop > 255:gtop=255:EndIf
          If gtop < 128:gtop=128:EndIf
btop=b+48:If btop > 255:btop=255:EndIf
          If btop < 128:btop=128:EndIf
*c\top  = RGB(rtop,gtop,btop)

rleft=r+32:If rleft > 255:rleft=255:EndIf
           If rleft < 104:rleft=104:EndIf
gleft=g+32:If gleft > 255:gleft=255:EndIf
           If gleft < 104:gleft=104:EndIf
bleft=b+32:If bleft > 255:bleft=255:EndIf
           If bleft < 104:bleft=104:EndIf
*c\left  = RGB(rleft,gleft,bleft)

rright=r-96:If rright > 255:rright=255:EndIf
            If rright < 78: rright=78: EndIf
gright=g-96:If gright > 255:gright=255:EndIf
            If gright < 78: gright=78: EndIf
bright=b-96:If bright > 255:bright=255:EndIf
            If bright < 78: bright=78: EndIf
*c\right  = RGB(rright,gright,bright)

rbottom=r-120:If rbottom > 255:rbottom=255:EndIf
              If rbottom < 56: rbottom=56: EndIf
gbottom=g-120:If gbottom > 255:gbottom=255:EndIf
              If gbottom < 56: gbottom=56: EndIf
bbottom=b-120:If bbottom > 255:bbottom=255:EndIf
              If bbottom < 56: bbottom=56: EndIf
*c\bottom  = RGB(rbottom,gbottom,bbottom)

EndProcedure

Procedure myPolyImage(pbnr,br,hh,txt$,txtfarbe,fontnr,farbe)

;farbe = nur für den Text
;   dk = Dicke der Umrandung
;    f = z.B. $222222 um ButtonFarbe zu ändern

dk = #buttondk  ; dicke der Buttonumrandung

id = CreateImage(pbnr,br,hh) 
dc = StartDrawing(ImageOutput(pbnr)) 
  
        ;aktuellen Pen+Brush sichern
        oldpen=GetCurrentObject_(dc,#OBJ_PEN)
        oldbrush=GetCurrentObject_(dc,#OBJ_BRUSH)
        
        If farbe = 0
            ;Farbe Fläche
            cFlaeche = RGB(212,206,188)         
            ;SchattenFarben 
            coben    = RGB(236,230,220) 
            clinks   = RGB(228,218,204) 
            crechts  = RGB(156,154,140) 
            cunten   = RGB(116,110,100) 
        Else    
            cFlaeche = farbe
            myButtonShadow(farbe,c.rect)
            coben  = c\top
            clinks = c\left   
            crechts= c\right
            cunten = c\bottom              
        EndIf        
        
        ;Pen für Umrandung
        pen1=CreatePen_(#PS_NULL,0,0)
        pen2=CreatePen_(#PS_SOLID,0,#Gray)
        
        ;Brush für Fläche ausfüllen
        brush1=CreateSolidBrush_(coben)
        brush2=CreateSolidBrush_(clinks)
        brush3=CreateSolidBrush_(cunten)
        brush4=CreateSolidBrush_(crechts)
        brush5=CreateSolidBrush_(cFlaeche) 
        
        ;Datenfeld
        nopa=4             ;number of points in array
        Dim p.point(nopa)  ;es wird nur 0-3 gebraucht, und der Wert 4 übergeben
        
        ;oben
        p(0)\x=0
        p(0)\y=0
        p(1)\x=br
        p(1)\y=ze
        
        p(2)\x=br-dk
        p(2)\y=dk
        p(3)\x=dk
        p(3)\y=dk
        
        SelectObject_(dc,pen1) 
        SelectObject_(dc,brush1) 
        Polygon_(dc,p(),nopa)
          
        ;links
        p(0)\x=0
        p(0)\y=0
        p(1)\x=dk
        p(1)\y=dk
        
        p(2)\x=dk
        p(2)\y=hh-dk
        p(3)\x=0
        p(3)\y=hh
        
        SelectObject_(dc,brush2) 
        Polygon_(dc,p(),nopa)
        
        ;unten
        p(0)\x=dk
        p(0)\y=hh-dk
        p(1)\x=br-dk
        p(1)\y=hh-dk
        
        p(2)\x=br
        p(2)\y=hh
        p(3)\x=0
        p(3)\y=hh
        
        SelectObject_(dc,brush3) 
        Polygon_(dc,p(),nopa)
          
        ;rechts
        p(0)\x=br-dk
        p(0)\y=dk
        p(1)\x=br
        p(1)\y=0
        
        p(2)\x=br
        p(2)\y=hh
        p(3)\x=br-dk
        p(3)\y=hh-dk
        
        SelectObject_(dc,brush4) 
        Polygon_(dc,p(),nopa)
          
        ;Fläche
        SelectObject_(dc,pen2) 
        SelectObject_(dc,brush5)
        Rectangle_(dc,dk,dk,br-dk,hh-dk)
        
        ;Textfont 
        SelectObject_(dc,fontnr)        ;oder DrawingFont(FontIDnr) 
        
        ;Textmodus 
        SetBkMode_(dc,#TRANSPARENT)     ;oder DrawingMode() 
        SetTextColor_(dc,txtfarbe)
          
        SetTextAlign_(dc,#TA_TOP)       ;ohne geht es nicht 
        fbr=br-dk-dk-2
        fhh=hh-dk-dk-2
        SetRect_(r.RECT,0,0,fbr,fhh)    ;Größe der Textfläche setzen für rect; left,top,right,bottom 
        
        ;berechne via Api die Größe von r.rect für den Text !!! 
        DrawText_(dc,txt$,-1,r,#DT_CALCRECT|#DT_WORDBREAK)  
        
        ;Text zentrieren
        tsp=1+dk+((fbr-r\right)/2)
        tze=1+dk+((fhh-r\bottom)/2)        
        OffsetRect_(r,tsp,tze)

        ;zeichne Text 
        DrawText_(dc,txt$,-1,r,#DT_CENTER|#DT_WORDBREAK) 
        
        ;===================================================

        ;Helligkeit verändern
        x=dk+2
        y=dk+2
        b=br-dk-dk-2-2
        h=hh-dk-dk-2-2
        
        SetStretchBltMode_(dc,#HALFTONE)
        ca.COLORADJUSTMENT                    
        GetColorAdjustment_(dc,ca.COLORADJUSTMENT)
        ca\caContrast=#contrast0
        SetColorAdjustment_(dc,ca.COLORADJUSTMENT)              
        StretchBlt_(dc, x,y,b,h,dc, x,y,b,h, #SRCCOPY)
         
        ;===================================================
                
        ;Pen+Brush wiederherstellen
        SelectObject_(dc,oldpen) 
        SelectObject_(dc,oldbrush) 
        
        ;löschen
        DeleteObject_(pen1) 
        DeleteObject_(pen2) 
        DeleteObject_(brush1) 
        DeleteObject_(brush2) 
        DeleteObject_(brush3) 
        DeleteObject_(brush4) 
        DeleteObject_(brush5)
        
     StopDrawing() 
     
ProcedureReturn id

EndProcedure

Procedure myImageInvert(pbnr,status)
     
  GetClientRect_(GadgetID(pbnr),r.RECT) 
    
  dc = StartDrawing(ImageOutput(pbnr))
        InflateRect_(r,-#buttondk-2,-#buttondk-2)
        ;InvertRect_(dc,r)
        ;oder wenn InvertRect benutzt wird, dann alle Befehle bis Stopdrawing ausschalten
        
        x=#buttondk+2
        y=#buttondk+2
        b=r\right-#buttondk-2
        h=r\bottom-#buttondk-2
        
        ;Helligkeit verändern
        SetStretchBltMode_(dc,#HALFTONE)
        
        ca.COLORADJUSTMENT                    
        GetColorAdjustment_(dc,ca.COLORADJUSTMENT)
        
        If status
           ca\caContrast=#contrast1
        Else
           ca\caContrast=#contrast0
        EndIf
        
        SetColorAdjustment_(dc,ca.COLORADJUSTMENT)              
        StretchBlt_(dc, x,y,b,h,dc, x,y,b,h, #SRCCOPY)
    
       StopDrawing() 
       
  SetGadgetState(pbnr,ImageID(pbnr))
     
EndProcedure     

Procedure myPolyImageGadget(pbnr,sp,ze,br,hh,txt$,farbe=0,fontnr=0,f=0)

  If fontnr = 0
     fontnr = GetStockObject_(#ANSI_VAR_FONT)
  EndIf
  
  imgnr = myPolyImage(pbnr,br,hh,txt$,farbe,fontnr,f)
  
  ImageGadget(pbnr,sp,ze,0,0,imgnr)
  
  ;myImageInvert(pbnr,0)
    
EndProcedure

;=======================================================================

Procedure myImageButtonSetbuttonstate(buttonnr)

Shared buttonstate()

  If buttonstate(buttonnr)
     buttonstate(buttonnr)=0                        
  Else   
     buttonstate(buttonnr)=1 
  EndIf
   
  myImageInvert(buttonnr,buttonstate(buttonnr))
  
EndProcedure
     
Procedure myImageButtonSetbuttonstateX(buttonnr)

Shared buttonstate()

For j=#buttonEA To #buttonMax
  
  If IsGadget(j)

     If buttonstate(j)
      
        buttonstate(j) = 0
        myImageInvert(j,buttonstate(j))
     
     ElseIf j = buttonnr
     
        buttonstate(j) = 1
        myImageInvert(j,buttonstate(j))
        
     EndIf
     
  EndIf
  
Next

EndProcedure

Procedure myImageButtonGetButtonstate(buttonnr)

Shared buttonstate()

ProcedureReturn buttonstate(buttonnr) 

EndProcedure

;=================================================================

flag = #PB_Window_SystemMenu|1|#PB_Window_Invisible
hwnd = OpenWindow(#winnr,0,0,700,300,"Polygon-Test",flag) 
       SetWindowColor(#winnr, #Gray) 

       CreateGadgetList(hwnd)
       
       EditorGadget(#txt1,570,10,100,250)
       
       myPolyImageGadget(#button1,10, 10,120,60,"jeder Button kann ON sein in dieser Spalte") 
       myPolyImageGadget(#button2,10, 80,120,60,"Test, du bist keine Schweinebacke",#Red) 
       myPolyImageGadget(#button3,10,150,120,60,"Test, du Schweinebacke",#Blue) 

       myPolyImageGadget(#button4,210, 10,130,60,"nur ein Button kann ON sein",0,0,#Magenta) 
       myPolyImageGadget(#button5,210, 80,130,60,"drückt man, dann geht der andere Button dieser Spalte aus",#White,0,#Gray) 
       myPolyImageGadget(#button6,210,150,130,60,"ist ja auch nur ein Beispiel",#Yellow,0,#Blue) 

       myPolyImageGadget(#button7,410, 10,130,60,"ist ja auch nur ein Beispiel",0,0,#Red) 
       myPolyImageGadget(#button8,410, 80,130,60,"ist ja auch nur ein Beispiel",0,0,#Green) 
       myPolyImageGadget(#button9,410,150,130,60,"ist ja auch nur ein Beispiel",0,0,#Yellow) 
      
       HideWindow(#winnr,0)
       
Repeat: event = WaitWindowEvent() 

  If Event = #PB_Event_Gadget Or Event = #PB_Event_Menu 
          
      welcherButton=EventGadget()            
                  
      Select welcherButton
      
          Case irgendeinbutton
          
          Case eineListe
          
          Case endebutton
          
          Case #buttonN To #buttonEA
          
              ;jeder Button kann ON sein
              myImageButtonSetbuttonstate(welcherButton)
          
              Select welcherButton              
            
                  Case #button1: 
                  Case #button2: 
                  Case #button3: 
                  
              EndSelect             

          Case #buttonEA To #buttonMax
          
              ;nur ein Button kann ON sein
              myImageButtonSetbuttonstateX(welcherButton)
          
              Select welcherButton              
            
                  Case #button4: 
                  Case #button5: 
                  Case #button6:
                  ;usw 
                  
              EndSelect             

      EndSelect
      
      ;Status anzeigen
      If EventType()=#PB_EventType_LeftClick
          txt$=""
          For j = #button1 To #button9
              txt$+"Status "+Str(buttonstate(j))+#LF$
              SetGadgetText(#txt1,txt$)
          Next
      EndIf
            
  EndIf
 
Until event = #PB_Event_CloseWindow 

End
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Sorry aber ich kapier gar nichts. Alleine dieser Satz:
Hallo, ich habe für Buttons mit 3D Aussehen, um eine Fläche einen Rahmen aus Polygonen gezeichnet.
Was willst du uns sagen? Bild

Und warum Polygone? Warum nicht Box() oder Line()? Warum so aufwendig? Außerdem was ist mit "4 verschiedene Farben" gemeint? Meinst du die einzelnen Seiten links/rechts/oben/unten oder wie ein Verlauf? Also eine Schattenseite (z. B. oben) die 4px hoch ist mit 4 verschiedenen Farbabstufungen.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

der satz ist doch korrekt. :?

> Hallo,
> ich habe für Buttons (mit 3D-Aussehen),
> um eine Fläche [herum]
> einen Rahmen aus Polygonen gezeichnet.

und logischer weise wie ein verlauf, 4x in unterschiedlichen farben.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag von hjbremer »

Kaeru Gaman, du verstehst mich, wenigstens einer und wenn du mir nun noch sagen könntest, wie man diese vier Farben besser und intelligenter berechnen könnte, wäre ich rundum glücklich ! :D :D :D
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

also,

* die notwendigkeit für polygone seh ich hier auch nicht unbedingt gegeben.
du könntest das auch mit überlagerten boxes hinbekommen.
dann müßtest du natürlich von außen nach innen zeichnen, damit du korrekt übermalst.
oder mit line.
sollte eh weniger relevant sein, wenn du prerenderst und nicht on-the-fly zeichnest.

* der rahmen sieht vielleicht etwas besser aus, wenn du die vier äußeren linien
nicht gleichfarbig machst, sondern leicht nach innen heller werdend.

* einen zusätzlichen schatten kannst du erreichen, indem du eine graue
ausgefüllte box zuerst auf ButX+3, ButY+3, ButWidth, ButHeight darstellst.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten