Grafik am Rand im Kontextmenü

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

Lukaso hat geschrieben:Mist, versuche schon seit Tagen in Danilos Code den Orginalen MenuBar (nicht son strich :roll:),
Sorry. Ich hatte die Berechnung der MenuHöhe ganz simple
gemacht, so daß auch die MenuBars die Höhe eines normalen
Eintrags hatten... und dann einfach eine Linie dazu. :D
Lukaso hat geschrieben:Nur vergebnens, entweder es Funtz nicht oder ich bekomme
nen XP-Fehler, bzw. meine Kiste bootet mitm Bluescreen neu :roll: :lol: :cry:
Das hab ich noch nie geschafft - nicht mit GDI-Drawing. :)
Lukaso hat geschrieben:Könnte mir jemand helfen <)
Probier mal folgendes, das sieht (zumindest hier ;)) so ziemlich
wie das Original aus:

Code: Alles auswählen

;
; Owner Drawn PopUp Menu
;
;   by Danilo, 10.11.2004 - german forum
;
;   - updated by Danilo, 15.11.2004:
;     * corrected drawing of MenuBars
;     * added disabled state (DisableMenuItem)
;     * added checked  state (SetMenuItemState)
;
;
#MIIM_FTYPE  = $100
#MIIM_TYPE   = $10
#MIIM_STRING = $40

Global hMenu,hBmp,hBmpWidth,hBmpHeight,tempDC


Procedure GetMenuHeight(hWnd,Menu)
  mem = AllocateMemory(1024)
  If mem
    hDC     = GetDC_(hWnd)
    GetTextExtentPoint32_(hDC,"X",1,size.SIZE);
    ReleaseDC_(hWnd,hDC)

    mii.MENUITEMINFO
    mii\cbSize        = SizeOf(MENUITEMINFO)
    mii\fMask         = #MIIM_STRING;|#MIIM_TYPE
    ;mii\fType         = #MFT_STRING
    mii\dwTypeData    = mem
    mii\cch           = 1023
  
    For i = 0 To GetMenuItemCount_(Menu)-1
      mii\dwTypeData    = mem
      mii\cch           = 1023
      If GetMenuItemInfo_(Menu,i,#TRUE,@mii)
        If mii\dwTypeData
          If PeekS(mii\dwTypeData)
            sizeX + size\cy
          Else
            sizeX + 6
          EndIf
        Else
          sizeX + 6
        EndIf
      EndIf
    Next i
  
    FreeMemory(mem)
  EndIf
  ProcedureReturn sizeX
EndProcedure


Procedure$ GetMenuIDName(itemID)
  mii.MENUITEMINFO
  mii\cbSize        = SizeOf(MENUITEMINFO)
  mii\fMask         = #MIIM_STRING;|#MIIM_TYPE
  ;mii\fType         = #MFT_STRING
  mii\dwTypeData    = AllocateMemory(1024)
  mii\cch           = 1023
  If GetMenuItemInfo_(hMenu,itemID,0,mii)
   ItemName$        = PeekS(mii\dwTypeData)
  EndIf
  FreeMemory(mii\dwTypeData)
  ProcedureReturn ItemName$
EndProcedure


Procedure WndProc(hWnd,Msg,wParam,lParam)
  Select Msg
    Case #WM_MEASUREITEM
      *mis.MEASUREITEMSTRUCT = lParam
      If *mis
        hDC     = GetDC_(hWnd)
        ItemName$ = GetMenuIDName(*mis\itemID)
        If ItemName$ = ""
          *mis\itemWidth  = hBmpWidth
          *mis\itemHeight = 6
        Else
          GetTextExtentPoint32_(hDC,ItemName$,Len(ItemName$),size.SIZE);
          *mis\itemWidth  = size\cx+hBmpWidth
          *mis\itemHeight = size\cy
        EndIf
        ReleaseDC_(hWnd,hDC)
        ProcedureReturn #TRUE
      EndIf
    Case #WM_DRAWITEM
      *dis.DRAWITEMSTRUCT = lParam
      If *dis
        If *dis\itemState & #ODS_SELECTED
          colFill = #COLOR_HIGHLIGHT
          colBack = SetBkColor_(  *dis\hDC,GetSysColor_(#COLOR_HIGHLIGHT))
          colText = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
        Else
          colFill = #COLOR_MENU
          colBack = SetBkColor_(  *dis\hDC,GetSysColor_(#COLOR_MENU))
          colText = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_MENUTEXT))
        EndIf

        SetBkMode_(*dis\hDC, #TRANSPARENT)

        If *dis\itemState & #ODS_GRAYED
          SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_GRAYTEXT))
        EndIf

        *dis\rcItem\left+ hBmpWidth
        x = *dis\rcItem\left + GetSystemMetrics_(#SM_CXMENUCHECK)+2
        y = *dis\rcItem\top

        ItemName$ = GetMenuIDName(*dis\itemID)
        If ItemName$
          brush = GetSysColorBrush_(colFill)
           FillRect_(*dis\hDC,@*dis\rcItem,brush)
          DeleteObject_(brush)
          If *dis\itemState & #ODS_GRAYED
             oldCol = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
             TextOut_(*dis\hDC,x+1,y+2,ItemName$,Len(ItemName$))
             SetTextColor_(*dis\hDC,oldCol)
           EndIf
          TextOut_(*dis\hDC,x,y+1,ItemName$,Len(ItemName$))
        Else
          rect.RECT
          rect\top = *dis\rcItem\top+2
          rect\bottom = *dis\rcItem\top+4
          rect\right  = *dis\rcItem\right
          rect\left   = hBmpWidth
          DrawEdge_(*dis\hDC,@rect,#BDR_SUNKENOUTER,#BF_RECT)
        EndIf
        
        If *dis\itemState & #ODS_CHECKED
          Bmp = LoadBitmap_(0,#OBM_CHECK)
           old = SelectObject_(tempDC,Bmp)
           If *dis\itemState & #ODS_SELECTED
             SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
           EndIf
           BitBlt_(*dis\hDC,*dis\rcItem\left+1,y+2,GetSystemMetrics_(#SM_CXMENUCHECK),GetSystemMetrics_(#SM_CYMENUCHECK),tempDC,0,0,#SRCCOPY)
           SelectObject_(tempDC,old)
          DeleteObject_(Bmp)
        EndIf
        
        BitBlt_(*dis\hDC,0,0,hBmpWidth,hBmpHeight,tempDC,0,0,#SRCCOPY)

        SetTextColor_(*dis\hDC,colText)
        SetBkColor_(  *dis\hDC,colBack)
        ProcedureReturn #TRUE
      EndIf
    Case #WM_INITMENU
      If tempDC=0
        hDC    = GetDC_(hWnd)
        tempDC = CreateCompatibleDC_(hDC)
        SelectObject_(tempDC,hBmp)
        ReleaseDC_(hWnd,hDC)
      EndIf
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure OwnerDrawnMenu(Menu)
  mii.MENUITEMINFO
  mii\cbSize = SizeOf(MENUITEMINFO)
  mii\fMask  = #MIIM_FTYPE
  mii\fType  = #MFT_OWNERDRAW
  For i = 0 To GetMenuItemCount_(Menu)-1
    SetMenuItemInfo_(Menu,i,#TRUE,mii)
  Next i
EndProcedure


;>---------------------------------------


hMenu = CreatePopupMenu(0)
If hMenu
  For i = 1 To 30
    MenuItem(100+i,"Item "+Str(i))
  Next i
  MenuBar()
  OpenSubMenu("Sub")
    MenuItem(1, "SubMenu 1")
    MenuItem(2, "SubMenu 2")
  CloseSubMenu()
  MenuBar()
  MenuItem(3, "Quit")
Else
  End
EndIf

SetMenuItemState(0,101,1)
SetMenuItemState(0,103,1)

SetMenuItemState(0,102,1)
DisableMenuItem(102,1)


If OpenWindow(0,200,200,300,300,#PB_Window_SystemMenu,"OwnerDrawn PopUp Menu")
  SetWindowCallback(@WndProc())

  #barwidth  = 30
  height     = GetMenuHeight(WindowID(),hMenu)
  hBmp       = CreateImage(0,#barwidth,height)
  hBmpWidth  = #barwidth
  hBmpHeight = height

  StartDrawing(ImageOutput())
    stp.f = 255/height
    For y = height To 0 Step -1
      Line(0,y,#barwidth,0,RGB(0,0,b.f))
      b+stp
    Next y
    Locate(3,height-20)
    DrawingMode(1)
    FrontColor($FF,$FF,$00)
    DrawText("Yo!")
  StopDrawing()

  OwnerDrawnMenu(hMenu)



  Repeat
    Select WaitWindowEvent()
      Case #WM_RButtonDown
        DisplayPopupMenu(0,WindowID())
      ;Case #WM_LButtonDown
      ;  DisplayPopupMenu(0,WindowID())
      Case #PB_EventMenu
        menu = EventMenuID()
        If menu = 3
          Break
        EndIf
        MessageRequester("MENU","Menu Event: "+Str(menu),0)
      Case #PB_EventCloseWindow
        Break
    EndSelect
  ForEver
EndIf

If tempDC
  DeleteDC_(tempDC)
EndIf
MenuBars + Disabled + Checked sollte jetzt alles OK sein.

Reicht das, oder brauchst Du noch etwas (z.B. Bitmaps)?
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
Lukaso
Beiträge: 720
Registriert: 08.09.2004 18:51
Wohnort: Oberkirch
Kontaktdaten:

Beitrag von Lukaso »

@Danilo
Super Danke, jetzt läuft alles 1a :allright: :allright:
Reicht das, oder brauchst Du noch etwas (z.B. Bitmaps)?
Ne, ich brauch nix mehr :wink:

Sorry für das Späte melden :roll:

Nochmals DANKE :allright:

MFG Lukaso
Nextgen Guild Wars Fanseite: Guild Wars Tactics (Pseudo-Admin + Developer)
"Das Fluchen ist die einzige Sprache, die jeder Programmierer beherrscht." - Unbekannter Autor
Benutzeravatar
Lukaso
Beiträge: 720
Registriert: 08.09.2004 18:51
Wohnort: Oberkirch
Kontaktdaten:

Beitrag von Lukaso »

Hallo,

ich habe erneut ein Problem mit dem Menü:

Da ich in meinem Menü auch Verschiedene Sprachen anzeige, die teilweise längere bzw. kürzere Menünamen haben, ist mir aufgefallen, dass wenn ein Menüname kurz ist, der Abstand rechts vom Menünamen zum Rand klein ist, aber sobald ein Menüname Lang ist, ist der abstand um einiges größer, je länger die Namen, desto größer der abstand zum Rand ... naja, dass Sieht nen bißchen blöd aus ... /:->

Habe versucht es allein zu behebn, leider ohne erfolg :|

Hier der Source, ein bißchen angepasst:

Code: Alles auswählen

Procedure WndProc(hwnd,Msg,wParam,lParam)
  Select Msg
    Case #WM_MEASUREITEM 
      *mis.MEASUREITEMSTRUCT = lParam 
      If *mis 
        hDC = GetDC_(hwnd) 
        ItemName$ = GetMenuIDName(*mis\itemID) 
        If ItemName$ = "" 
          *mis\itemWidth  = hBmpWidth
          *mis\itemHeight = 9
        Else 
          GetTextExtentPoint32_(hDC,ItemName$,Len(ItemName$),size.SIZE); 
          *mis\itemWidth  = size\cx + hBmpWidth + 8
          *mis\itemHeight = size\cy + 1
        EndIf 
        ReleaseDC_(hwnd,hDC) 
        ProcedureReturn #True 
      EndIf 
    Case #WM_DRAWITEM 
      *dis.DRAWITEMSTRUCT = lParam 
      If *dis
        If *dis\itemState & #ODS_SELECTED
          colFill = #COLOR_HIGHLIGHT
          colBack = SetBkColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHT)) 
          colText = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
          If *dis\itemState & #ODS_GRAYED
            SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_GRAYTEXT))
          EndIf
        Else
          colFill = #COLOR_MENU
          colBack = SetBkColor_(*dis\hDC,GetSysColor_(#COLOR_MENU)) 
          colText = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_MENUTEXT))
          If *dis\itemState & #ODS_GRAYED
            SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_GRAYTEXT))
            SetBkMode_(*dis\hDC, #TRANSPARENT)
          EndIf
        EndIf
        
        *dis\rcItem\left + hBmpWidth
        X = *dis\rcItem\left + GetSystemMetrics_(#SM_CXMENUCHECK) + 8
        y = *dis\rcItem\top
        
        ItemName$ = GetMenuIDName(*dis\itemID) 
        If ItemName$
          brush = GetSysColorBrush_(colFill)
          FillRect_(*dis\hDC,@*dis\rcItem,brush)
          DeleteObject_(brush)
          If *dis\itemState & #ODS_GRAYED
            If *dis\itemState & #ODS_SELECTED
            Else
              oldCol = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
              TextOut_(*dis\hDC,X+1,y+2,ItemName$,Len(ItemName$))
              SetTextColor_(*dis\hDC,oldCol)
            EndIf
          EndIf
          TextOut_(*dis\hDC,X,y+1,ItemName$,Len(ItemName$))
        Else 
          rect.RECT
          rect\top = *dis\rcItem\top + 3
          rect\bottom = *dis\rcItem\top + 5
          rect\right  = *dis\rcItem\right
          rect\left   = hBmpWidth + 2
          DrawEdge_(*dis\hDC,@rect,#BDR_SUNKENOUTER,#BF_RECT) 
        EndIf 
        
        If *dis\itemState & #ODS_CHECKED
          Bmp = LoadBitmap_(0,#OBM_CHECK)
          old = SelectObject_(tempDC,Bmp)
          If *dis\itemState & #ODS_SELECTED
            SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
          EndIf 
          BitBlt_(*dis\hDC,*dis\rcItem\left + 6, y + 2,GetSystemMetrics_(#SM_CXMENUCHECK),GetSystemMetrics_(#SM_CYMENUCHECK),tempDC,0,0,#SRCCOPY) 
          SelectObject_(tempDC,old)
          DeleteObject_(Bmp)
        EndIf 
        
        BitBlt_(*dis\hDC,0,0,hBmpWidth,hBmpHeight,tempDC,0,0,#SRCCOPY) 
        
        SetTextColor_(*dis\hDC,colText)
        SetBkColor_(*dis\hDC,colBack)
        ProcedureReturn #True
      EndIf 
    Case #WM_INITMENU 
      If tempDC = 0 
        hDC    = GetDC_(hwnd) 
        tempDC = CreateCompatibleDC_(hDC) 
        SelectObject_(tempDC,hBmp) 
        ReleaseDC_(hwnd,hDC) 
      EndIf
  EndSelect 
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure 
Desweiteren wäre schön, wenn ich das Problem aus diesem Post noch behoben bekäme ... POST

Danilo, könntest du mir bitte nochmals bißchen unter die Arme greifen :roll: :roll:

1000 DANK :allright: :allright:

MFG Lukaso

EDIT: Hier ein Bild zur verdeutlichung:
Bild
Nextgen Guild Wars Fanseite: Guild Wars Tactics (Pseudo-Admin + Developer)
"Das Fluchen ist die einzige Sprache, die jeder Programmierer beherrscht." - Unbekannter Autor
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

Lukaso hat geschrieben:Danilo, könntest du mir bitte nochmals bißchen unter die Arme greifen :roll: :roll:

1000 DANK :allright: :allright:
Das "Problem" dürfte recht einfach sein. Man muß bei Messen
der Eintragslänge mit GetTextExtentPoint32_() vorher noch
den richtigen Systemfont auswählen (mit SelectObject_()),
so daß dann die exakte Länge herauskommt.

Erinnere mich Montag nochmal daran, falls ich es vergesse.
Hab gerade keine Zeit und fahr gleich weg - ist ja schliesslich
Wochenende.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
MJP
Beiträge: 72
Registriert: 14.10.2004 18:45
Wohnort: Nähe Frankfurt/Hessen
Kontaktdaten:

Beitrag von MJP »

@Lukaso
Wie hast du in die Leiste dein 40-Pix-Player Bild reinbekommen?

Thx MJP
Alle Reschtsreib feler sind beabsichticht unn kosten nichs echtra ;-D
Visit ---|> http://www.Komani.de/
Benutzeravatar
Lukaso
Beiträge: 720
Registriert: 08.09.2004 18:51
Wohnort: Oberkirch
Kontaktdaten:

Beitrag von Lukaso »

MJP hat geschrieben:Wie hast du in die Leiste dein 40-Pix-Player Bild reinbekommen?

Code: Alles auswählen

;
; Owner Drawn PopUp Menu
;
;   by Danilo, 10.11.2004 - german forum
;
;   - updated by Danilo, 15.11.2004:
;     * corrected drawing of MenuBars
;     * added disabled state (DisableMenuItem)
;     * added checked  state (SetMenuItemState)
;
;


#MIIM_FTYPE  = $100
#MIIM_TYPE   = $10
#MIIM_STRING = $40

Global hMenu,hBmp,hBmpWidth,hBmpHeight,tempDC

DataSection
  menu_gfx:         IncludeBinary     "images/menu.bmp"
EndDataSection

menu_gfx        =   CatchImage(0, ?menu_gfx)

Procedure GetMenuHeight(hWnd,Menu)
  mem = AllocateMemory(1024)
  If mem
    hDC     = GetDC_(hWnd)
    GetTextExtentPoint32_(hDC,"X",1,size.SIZE);
    ReleaseDC_(hWnd,hDC)

    mii.MENUITEMINFO
    mii\cbSize        = SizeOf(MENUITEMINFO)
    mii\fMask         = #MIIM_STRING;|#MIIM_TYPE
    ;mii\fType         = #MFT_STRING
    mii\dwTypeData    = mem
    mii\cch           = 1023
 
    For i = 0 To GetMenuItemCount_(Menu)-1
      mii\dwTypeData    = mem
      mii\cch           = 1023
      If GetMenuItemInfo_(Menu,i,#TRUE,@mii)
        If mii\dwTypeData
          If PeekS(mii\dwTypeData)
            sizeX + size\cy
          Else
            sizeX + 6
          EndIf
        Else
          sizeX + 6
        EndIf
      EndIf
    Next i
 
    FreeMemory(mem)
  EndIf
  ProcedureReturn sizeX
EndProcedure


Procedure$ GetMenuIDName(itemID)
  mii.MENUITEMINFO
  mii\cbSize        = SizeOf(MENUITEMINFO)
  mii\fMask         = #MIIM_STRING;|#MIIM_TYPE
  ;mii\fType         = #MFT_STRING
  mii\dwTypeData    = AllocateMemory(1024)
  mii\cch           = 1023
  If GetMenuItemInfo_(hMenu,itemID,0,mii)
   ItemName$        = PeekS(mii\dwTypeData)
  EndIf
  FreeMemory(mii\dwTypeData)
  ProcedureReturn ItemName$
EndProcedure


Procedure WndProc(hwnd,Msg,wParam,lParam)
  Select Msg
    Case #WM_MEASUREITEM
      *mis.MEASUREITEMSTRUCT = lParam
      If *mis
        hDC = GetDC_(hwnd)
        ItemName$ = GetMenuIDName(*mis\itemID)
        If ItemName$ = ""
          *mis\itemWidth  = hBmpWidth
          *mis\itemHeight = 9
        Else
          GetTextExtentPoint32_(hDC,ItemName$,Len(ItemName$),size.SIZE);
          *mis\itemWidth  = size\cx + hBmpWidth + 8
          *mis\itemHeight = size\cy + 1
        EndIf
        ReleaseDC_(hwnd,hDC)
        ProcedureReturn #True
      EndIf
    Case #WM_DRAWITEM
      *dis.DRAWITEMSTRUCT = lParam
      If *dis
        If *dis\itemState & #ODS_SELECTED
          colFill = #COLOR_HIGHLIGHT
          colBack = SetBkColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHT))
          colText = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
          If *dis\itemState & #ODS_GRAYED
            SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_GRAYTEXT))
          EndIf
        Else
          colFill = #COLOR_MENU
          colBack = SetBkColor_(*dis\hDC,GetSysColor_(#COLOR_MENU))
          colText = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_MENUTEXT))
          If *dis\itemState & #ODS_GRAYED
            SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_GRAYTEXT))
            SetBkMode_(*dis\hDC, #TRANSPARENT)
          EndIf
        EndIf
       
        *dis\rcItem\left + hBmpWidth
        X = *dis\rcItem\left + GetSystemMetrics_(#SM_CXMENUCHECK) + 8
        y = *dis\rcItem\top
       
        ItemName$ = GetMenuIDName(*dis\itemID)
        If ItemName$
          brush = GetSysColorBrush_(colFill)
          FillRect_(*dis\hDC,@*dis\rcItem,brush)
          DeleteObject_(brush)
          If *dis\itemState & #ODS_GRAYED
            If *dis\itemState & #ODS_SELECTED
            Else
              oldCol = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
              TextOut_(*dis\hDC,X+1,y+2,ItemName$,Len(ItemName$))
              SetTextColor_(*dis\hDC,oldCol)
            EndIf
          EndIf
          TextOut_(*dis\hDC,X,y+1,ItemName$,Len(ItemName$))
        Else
          rect.RECT
          rect\top = *dis\rcItem\top + 3
          rect\bottom = *dis\rcItem\top + 5
          rect\right  = *dis\rcItem\right
          rect\left   = hBmpWidth + 2
          DrawEdge_(*dis\hDC,@rect,#BDR_SUNKENOUTER,#BF_RECT)
        EndIf
       
        If *dis\itemState & #ODS_CHECKED
          Bmp = LoadBitmap_(0,#OBM_CHECK)
          old = SelectObject_(tempDC,Bmp)
          If *dis\itemState & #ODS_SELECTED
            SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
          EndIf
          BitBlt_(*dis\hDC,*dis\rcItem\left + 6, y + 2,GetSystemMetrics_(#SM_CXMENUCHECK),GetSystemMetrics_(#SM_CYMENUCHECK),tempDC,0,0,#SRCCOPY)
          SelectObject_(tempDC,old)
          DeleteObject_(Bmp)
        EndIf
       
        BitBlt_(*dis\hDC,0,0,hBmpWidth,hBmpHeight,tempDC,0,0,#SRCCOPY)
       
        SetTextColor_(*dis\hDC,colText)
        SetBkColor_(*dis\hDC,colBack)
        ProcedureReturn #True
      EndIf
    Case #WM_INITMENU
      If tempDC = 0
        hDC    = GetDC_(hwnd)
        tempDC = CreateCompatibleDC_(hDC)
        SelectObject_(tempDC,hBmp)
        ReleaseDC_(hwnd,hDC)
      EndIf
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure OwnerDrawnMenu(Menu)
  mii.MENUITEMINFO
  mii\cbSize = SizeOf(MENUITEMINFO)
  mii\fMask  = #MIIM_FTYPE
  mii\fType  = #MFT_OWNERDRAW
  For i = 0 To GetMenuItemCount_(Menu)-1
    SetMenuItemInfo_(Menu,i,#TRUE,mii)
  Next i
EndProcedure


;>---------------------------------------


hMenu = CreatePopupMenu(0)
If hMenu
  For i = 1 To 30
    MenuItem(100+i,"Item "+Str(i))
  Next i
  MenuBar()
  OpenSubMenu("Sub")
    MenuItem(1, "SubMenu 1")
    MenuItem(2, "SubMenu 2")
  CloseSubMenu()
  MenuBar()
  MenuItem(3, "Quit")
Else
  End
EndIf

SetMenuItemState(0,101,1)
SetMenuItemState(0,103,1)

SetMenuItemState(0,102,1)
DisableMenuItem(102,1)


If OpenWindow(0,200,200,300,300,#PB_Window_SystemMenu,"OwnerDrawn PopUp Menu")
  SetWindowCallback(@WndProc())
  
  #barwidth  = 25 
  height     = GetMenuHeight(WindowID(#Player_Window),hMenu)*1.11
  hBmp       = CreateImage(11,#barwidth,height) 
  hBmpWidth  = #barwidth
  hBmpHeight = height 
  
  StartDrawing(ImageOutput())
  
  DrawImage(menu_gfx, 0, height-200)
  StopDrawing()

  OwnerDrawnMenu(hMenu)



  Repeat
    Select WaitWindowEvent()
      Case #WM_RButtonDown
        DisplayPopupMenu(0,WindowID())
      ;Case #WM_LButtonDown
      ;  DisplayPopupMenu(0,WindowID())
      Case #PB_EventMenu
        menu = EventMenuID()
        If menu = 3
          Break
        EndIf
        MessageRequester("MENU","Menu Event: "+Str(menu),0)
      Case #PB_EventCloseWindow
        Break
    EndSelect
  ForEver
EndIf

If tempDC
  DeleteDC_(tempDC)
EndIf
MFG Lukaso
Nextgen Guild Wars Fanseite: Guild Wars Tactics (Pseudo-Admin + Developer)
"Das Fluchen ist die einzige Sprache, die jeder Programmierer beherrscht." - Unbekannter Autor
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

Danilo hat geschrieben:Das "Problem" dürfte recht einfach sein. Man muß bei Messen
der Eintragslänge mit GetTextExtentPoint32_() vorher noch
den richtigen Systemfont auswählen (mit SelectObject_()),
so daß dann die exakte Länge herauskommt.
Dazu kam noch die Länge für den SubMenu-Pfeil und ein
paar Pixel das es schöner aussieht (hab hier 8 genommen).

Siehe Zeile 87 - 100, das ist der veränderte Abschnitt.

Code: Alles auswählen

;
; Owner Drawn PopUp Menu
;
;   by Danilo, 10.11.2004 - german forum
;
;   - updated by Danilo, 15.11.2004:
;     * corrected drawing of MenuBars
;     * added disabled state (DisableMenuItem)
;     * added checked  state (SetMenuItemState)
;
;   - updated by Danilo, 29.11.2004:
;     * changed menu width for submenu arrows
;
#MIIM_SUBMENU = $004
#MIIM_TYPE    = $010
#MIIM_STRING  = $040
#MIIM_FTYPE   = $100

Global hMenu,hBmp,hBmpWidth,hBmpHeight,tempDC


Procedure GetMenuHeight(hWnd,Menu)
  mem = AllocateMemory(1024)
  If mem
    hDC     = GetDC_(hWnd)
    oldFont = SelectObject_(hDC,GetStockObject_(#ANSI_VAR_FONT))
    GetTextExtentPoint32_(hDC,"X",1,size.SIZE)
    size\cy + 2
    SelectObject_(hDC,oldFont)
    ReleaseDC_(hWnd,hDC)

    mii.MENUITEMINFO
    mii\cbSize        = SizeOf(MENUITEMINFO)
    mii\fMask         = #MIIM_STRING;|#MIIM_TYPE
    ;mii\fType         = #MFT_STRING
    mii\dwTypeData    = mem
    mii\cch           = 1023
  
    For i = 0 To GetMenuItemCount_(Menu)-1
      mii\dwTypeData    = mem
      mii\cch           = 1023
      If GetMenuItemInfo_(Menu,i,#TRUE,@mii)
        If mii\dwTypeData
          If PeekS(mii\dwTypeData)
            sizeX + size\cy
          Else
            sizeX + 6
          EndIf
        Else
          sizeX + 6
        EndIf
      EndIf
    Next i
  
    FreeMemory(mem)
  EndIf
  ProcedureReturn sizeX
EndProcedure


Procedure$ GetMenuIDName(itemID)
  mii.MENUITEMINFO
  mii\cbSize        = SizeOf(MENUITEMINFO)
  mii\fMask         = #MIIM_STRING;|#MIIM_TYPE
  ;mii\fType         = #MFT_STRING
  mii\dwTypeData    = AllocateMemory(1024)
  mii\cch           = 1023
  If GetMenuItemInfo_(hMenu,itemID,0,mii)
   ItemName$        = PeekS(mii\dwTypeData)
  EndIf
  FreeMemory(mii\dwTypeData)
  ProcedureReturn ItemName$
EndProcedure


Procedure WndProc(hWnd,Msg,wParam,lParam)
  Select Msg
    Case #WM_MEASUREITEM
      *mis.MEASUREITEMSTRUCT = lParam
      If *mis
        hDC     = GetDC_(hWnd)
        ItemName$ = GetMenuIDName(*mis\itemID)
        If ItemName$ = ""
          *mis\itemWidth  = hBmpWidth
          *mis\itemHeight = 6
        Else
          oldFont = SelectObject_(hDC,GetStockObject_(#ANSI_VAR_FONT))
          GetTextExtentPoint32_(hDC,ItemName$,Len(ItemName$),size.SIZE)
          SelectObject_(hDC,oldFont)
          *mis\itemWidth  = size\cx+hBmpWidth+8
          *mis\itemHeight = size\cy+2

          mii.MENUITEMINFO
          mii\cbSize        = SizeOf(MENUITEMINFO)
          mii\fMask         = #MIIM_SUBMENU
          If GetMenuItemInfo_(hMenu,*mis\itemID,0,mii)
            If mii\hSubMenu
              *mis\itemWidth + 16 ; submenu arrow
            EndIf
          EndIf

        EndIf
        ReleaseDC_(hWnd,hDC)
        ProcedureReturn #TRUE
      EndIf
    Case #WM_DRAWITEM
      *dis.DRAWITEMSTRUCT = lParam
      If *dis
        If *dis\itemState & #ODS_SELECTED
          colFill = #COLOR_HIGHLIGHT
          colBack = SetBkColor_(  *dis\hDC,GetSysColor_(#COLOR_HIGHLIGHT))
          colText = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
        Else
          colFill = #COLOR_MENU
          colBack = SetBkColor_(  *dis\hDC,GetSysColor_(#COLOR_MENU))
          colText = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_MENUTEXT))
        EndIf

        SetBkMode_(*dis\hDC, #TRANSPARENT)

        If *dis\itemState & #ODS_GRAYED
          SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_GRAYTEXT))
        EndIf

        *dis\rcItem\left+ hBmpWidth
        x = *dis\rcItem\left + GetSystemMetrics_(#SM_CXMENUCHECK)+2
        y = *dis\rcItem\top

        ItemName$ = GetMenuIDName(*dis\itemID)
        If ItemName$
          brush = GetSysColorBrush_(colFill)
           FillRect_(*dis\hDC,@*dis\rcItem,brush)
          DeleteObject_(brush)
          If *dis\itemState & #ODS_GRAYED
             oldCol = SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
             TextOut_(*dis\hDC,x+1,y+2,ItemName$,Len(ItemName$))
             SetTextColor_(*dis\hDC,oldCol)
           EndIf
          TextOut_(*dis\hDC,x,y+1,ItemName$,Len(ItemName$))
        Else
          rect.RECT
          rect\top = *dis\rcItem\top+2
          rect\bottom = *dis\rcItem\top+4
          rect\right  = *dis\rcItem\right
          rect\left   = hBmpWidth
          DrawEdge_(*dis\hDC,@rect,#BDR_SUNKENOUTER,#BF_RECT)
        EndIf
        
        If *dis\itemState & #ODS_CHECKED
          Bmp = LoadBitmap_(0,#OBM_CHECK)
           old = SelectObject_(tempDC,Bmp)
           If *dis\itemState & #ODS_SELECTED
             SetTextColor_(*dis\hDC,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
           EndIf
           BitBlt_(*dis\hDC,*dis\rcItem\left+1,y+2,GetSystemMetrics_(#SM_CXMENUCHECK),GetSystemMetrics_(#SM_CYMENUCHECK),tempDC,0,0,#SRCCOPY)
           SelectObject_(tempDC,old)
          DeleteObject_(Bmp)
        EndIf
        
        BitBlt_(*dis\hDC,0,0,hBmpWidth,hBmpHeight,tempDC,0,0,#SRCCOPY)

        SetTextColor_(*dis\hDC,colText)
        SetBkColor_(  *dis\hDC,colBack)
        ProcedureReturn #TRUE
      EndIf
    Case #WM_INITMENU
      If tempDC=0
        hDC    = GetDC_(hWnd)
        tempDC = CreateCompatibleDC_(hDC)
        SelectObject_(tempDC,hBmp)
        ReleaseDC_(hWnd,hDC)
      EndIf
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure OwnerDrawnMenu(Menu)
  mii.MENUITEMINFO
  mii\cbSize = SizeOf(MENUITEMINFO)
  mii\fMask  = #MIIM_FTYPE
  mii\fType  = #MFT_OWNERDRAW
  For i = 0 To GetMenuItemCount_(Menu)-1
    SetMenuItemInfo_(Menu,i,#TRUE,mii)
  Next i
EndProcedure


;>---------------------------------------


hMenu = CreatePopupMenu(0)
If hMenu
  For i = 1 To 30
    MenuItem(100+i,"Item "+Str(i))
  Next i
  MenuBar()
  OpenSubMenu("Sub abcdefghijklmnop")
    MenuItem(1, "SubMenu 1")
    MenuItem(2, "SubMenu 2")
  CloseSubMenu()
  MenuBar()
  MenuItem(3, "Quit")
Else
  End
EndIf

SetMenuItemState(0,101,1)
SetMenuItemState(0,103,1)

SetMenuItemState(0,102,1)
DisableMenuItem(102,1)


If OpenWindow(0,200,200,300,300,#PB_Window_SystemMenu,"OwnerDrawn PopUp Menu")
  SetWindowCallback(@WndProc())

  #barwidth  = 30
  height     = GetMenuHeight(WindowID(),hMenu)
  hBmp       = CreateImage(0,#barwidth,height)
  hBmpWidth  = #barwidth
  hBmpHeight = height

  StartDrawing(ImageOutput())
    stp.f = 255/height
    For y = height To 0 Step -1
      Line(0,y,#barwidth,0,RGB(0,0,b.f))
      b+stp
    Next y
    Locate(3,height-20)
    DrawingMode(1)
    FrontColor($FF,$FF,$00)
    DrawText("Yo!")
  StopDrawing()

  OwnerDrawnMenu(hMenu)



  Repeat
    Select WaitWindowEvent()
      Case #WM_RButtonDown
        DisplayPopupMenu(0,WindowID())
      ;Case #WM_LButtonDown
      ;  DisplayPopupMenu(0,WindowID())
      Case #PB_EventMenu
        menu = EventMenuID()
        If menu = 3
          Break
        EndIf
        MessageRequester("MENU","Menu Event: "+Str(menu),0)
      Case #PB_EventCloseWindow
        Break
    EndSelect
  ForEver
EndIf

If tempDC
  DeleteDC_(tempDC)
EndIf
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
Lukaso
Beiträge: 720
Registriert: 08.09.2004 18:51
Wohnort: Oberkirch
Kontaktdaten:

Beitrag von Lukaso »

Super hast mich nicht vergessen :) , Danke :allright:, ich glaube, dass ich alles habe <)

Danke :allright:

MFG Lukaso
Nextgen Guild Wars Fanseite: Guild Wars Tactics (Pseudo-Admin + Developer)
"Das Fluchen ist die einzige Sprache, die jeder Programmierer beherrscht." - Unbekannter Autor
Benutzeravatar
nicolaus
Moderator
Beiträge: 1175
Registriert: 11.09.2004 13:09
Kontaktdaten:

Beitrag von nicolaus »

@Danilo

nun habe ich auch mal ne frage und zwar wie kann ich es denn schafen das wenn ich über nen menüeintrag mit der maus gehe und dieser blau unterlegt wird das so hellbalu ist wie in Win2000 oder in MS Office?
Hatte das vor längerer zeit schon mal versucht aber nich hin bekommen.
Kannst du mir da vieleicht auch helfen?

THX schon mal.

MfG Nico
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

nicolaus hat geschrieben:nun habe ich auch mal ne frage und zwar wie kann ich es
denn schafen das wenn ich über nen menüeintrag mit der
maus gehe und dieser blau unterlegt wird das so hellbalu ist
wie in Win2000 oder in MS Office?
Ich benutze kein MS Office, von daher weiß ich nicht wie es
dort aussieht.
Du kannst aber bei #WM_DRAWITEM das Menu zeichnen
wie Du es gerne möchtest. Bilder, Text, Farben, ... kannst
Du alles machen wie Du möchtest.

Hier mal der #WM_DRAWITEM-Teil aus dem obigen Code (Zeile 106-165)
mit modifizierten Farben:

Code: Alles auswählen

    Case #WM_DRAWITEM
      *dis.DRAWITEMSTRUCT = lParam
      If *dis
        If *dis\itemState & #ODS_SELECTED
          colFill = $FF8000                           ; #COLOR_HIGHLIGHT
          colBack = SetBkColor_(  *dis\hDC,$FF8000)   ; GetSysColor_(#COLOR_HIGHLIGHT)
          colText = SetTextColor_(*dis\hDC,$FFFFFF)   ; GetSysColor_(#COLOR_HIGHLIGHTTEXT)
        Else
          colFill = $FFFFFF                           ; #COLOR_MENU
          colBack = SetBkColor_(  *dis\hDC,$FFFFFF)   ; GetSysColor_(#COLOR_MENU)
          colText = SetTextColor_(*dis\hDC,$000000)   ; GetSysColor_(#COLOR_MENUTEXT)
        EndIf

        SetBkMode_(*dis\hDC, #TRANSPARENT)

        If *dis\itemState & #ODS_GRAYED
          SetTextColor_(*dis\hDC,$CCCCCC)             ; GetSysColor_(#COLOR_GRAYTEXT)
        EndIf

        *dis\rcItem\left+ hBmpWidth
        x = *dis\rcItem\left + GetSystemMetrics_(#SM_CXMENUCHECK)+2
        y = *dis\rcItem\top

        ItemName$ = GetMenuIDName(*dis\itemID)
        If ItemName$
          brush = CreateSolidBrush_(colFill)          ; GetSysColorBrush_(colFill)
           FillRect_(*dis\hDC,@*dis\rcItem,brush)
          DeleteObject_(brush)
          If *dis\itemState & #ODS_GRAYED
             oldCol = SetTextColor_(*dis\hDC,$AAAAAA) ; GetSysColor_(#COLOR_HIGHLIGHTTEXT)
             TextOut_(*dis\hDC,x+1,y+2,ItemName$,Len(ItemName$))
             SetTextColor_(*dis\hDC,oldCol)
           EndIf
          TextOut_(*dis\hDC,x,y+1,ItemName$,Len(ItemName$))
        Else
          rect.RECT
          rect\top = *dis\rcItem\top      ; +2
          rect\bottom = *dis\rcItem\top+6 ; +4
          rect\right  = *dis\rcItem\right
          rect\left   = hBmpWidth
          ;DrawEdge_(*dis\hDC,@rect,#BDR_SUNKENOUTER,#BF_RECT)

          brush = CreateSolidBrush_($FFFFFF)
           FillRect_(*dis\hDC,@rect,brush)
          DeleteObject_(brush)
          rect\top + 2 : rect\bottom - 2
          brush = CreateSolidBrush_($808080)
           FillRect_(*dis\hDC,@rect,brush)
          DeleteObject_(brush)
          rect\top + 1 : rect\bottom + 1
          brush = CreateSolidBrush_($CCCCCC)
           FillRect_(*dis\hDC,@rect,brush)
          DeleteObject_(brush)
        EndIf
        
        If *dis\itemState & #ODS_CHECKED
          Bmp = LoadBitmap_(0,#OBM_CHECK)
           old = SelectObject_(tempDC,Bmp)
           If *dis\itemState & #ODS_SELECTED
             SetTextColor_(*dis\hDC,$FFFFFF)          ; GetSysColor_(#COLOR_HIGHLIGHTTEXT)
           EndIf
           BitBlt_(*dis\hDC,*dis\rcItem\left+1,y+2,GetSystemMetrics_(#SM_CXMENUCHECK),GetSystemMetrics_(#SM_CYMENUCHECK),tempDC,0,0,#SRCCOPY)
           SelectObject_(tempDC,old)
          DeleteObject_(Bmp)
        EndIf
        
        BitBlt_(*dis\hDC,0,0,hBmpWidth,hBmpHeight,tempDC,0,0,#SRCCOPY)

        SetTextColor_(*dis\hDC,colText)
        SetBkColor_(  *dis\hDC,colBack)
        ProcedureReturn #TRUE
      EndIf
Das zeichnen der MenuBars hab ich hier einfach mal schnell
so gemacht, da ich nicht weiß wie es bei Deinem Office aussieht.
In richtigem Code sollte man das nicht unbedingt so machen. ;)

Das OwnerDraw-Flag ist hier auch nur für das Hauptmenu
eingeschalten, nicht für SubMenus.
Wenn Du Dich mal mit MSDN/PSDK und dem obigen Beispiel
hinsetzt, wirst Du das aber sicherlich alles schnell lernen.
Man sollte diese Sachen schon selbst richtig verstehen, wenn
man eigene Dinge in die Richtung machen möchte.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Antworten