Icons in menu on XP

Just starting out? Need help? Post your questions and find answers here.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Icons in menu on XP

Post by Joakim Christiansen »

Okay, so I created some beautiful icons and inserted them in my menu using:

Code: Select all

SetMenuItemBitmaps_()
They had a alpha channel too and it worked fine in Windows Vista, but then I tried in Windows XP and of course something had to mess up... :roll:
The icons transparent background turned black and the icons was cut of at 12x12 when they was originally 16x16. I see that the PB editor has 16x16 icons in it's menu and I wonder about how they made this possible? I also wonder about if it's possible to make Windows XP support the transparent background at all or any alpha channel information in the menu icons?
Thanks for any answer! :)
I like logic, hence I dislike humans but love computers.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Those menus are owner-drawn.

Include file:

Code: Select all



Procedure MenuItemEx(MenuItemID, Text.s, Icon.l)
  MenuItem(MenuItemID, Text)
  If Icon
    Icon = Icon ;CatchImage(#PB_Any, Icon)
  EndIf
  ModifyMenu_(MenuID(0), MenuItemID, #MF_OWNERDRAW, MenuItemID, Icon)
EndProcedure

Procedure MenuItemFix(MenuItemID)
  ModifyMenu_(MenuID(0), MenuItemID, #MF_OWNERDRAW, MenuItemID, 0)
EndProcedure

Procedure MeasureMenuItem(WindowID, Message, wParam, lParam)
  Protected ItemHeight.l = 20
  Protected *MeasureItem.MEASUREITEMSTRUCT = lParam
  Protected Text.s
  Protected Img.l
  Protected hDC.l
  Protected Rect.RECT
  Protected TextWidth.l
  Protected Metrics.NONCLIENTMETRICS
  Protected MenuFont.l
  If *MeasureItem\CtlType = #ODT_MENU
    Text = Space(8192)
    GetMenuString_(MenuID(0), *MeasureItem\itemID, @Text, 8192, 0)
    
    Img = CreateImage(-1, 1, 1)
    hDC = StartDrawing(ImageOutput(Img))
      Metrics\cbSize = SizeOf(NONCLIENTMETRICS)
      SystemParametersInfo_(#SPI_GETNONCLIENTMETRICS, SizeOf(NONCLIENTMETRICS), @Metrics, 0)
      MenuFont = CreateFontIndirect_(@Metrics\lfMenuFont)
      SelectObject_(hDC, MenuFont)
      SetTextAlign_(hDC,#TA_LEFT|#TA_TOP|#TA_NOUPDATECP) 
      Rect.RECT\Right = 0
      Rect\Bottom = 0
      DrawText_(hDC, Text, Len(Text), @Rect, #DT_CALCRECT | #DT_EXPANDTABS | #DT_NOCLIP	| #DT_SINGLELINE)
      *MeasureItem\itemWidth = ItemHeight + Rect\Right ;TextWidth(ReplaceString(Text, #TAB$, Space(8)))
    StopDrawing()
    
    With *MeasureItem
      If \itemWidth < 100
        \itemWidth = 100
      EndIf
    EndWith
    
    FreeImage(Img)
    DeleteObject_(MenuFont)
    *MeasureItem\itemHeight = ItemHeight
  EndIf
EndProcedure

Procedure DrawMenuItem(WindowID, Message, wParam, lParam)
  Protected ItemHeight.l = 20
  Protected ItemWidth.l = 24
  Protected *DrawItem.DRAWITEMSTRUCT = lParam
  Protected Item.MENUITEMINFO
  Protected Glyph.l = *DrawItem\itemData
  Protected Text.s = Space(8192)
  Protected hDC
  Protected Left, Top, Right, Bottom
  Protected Brush1, Pen1
  Protected DrawFlag
  GetMenuString_(MenuID(0), *DrawItem\itemID, @Text.s, 8192, 0)
  If *DrawItem\CtlType = #ODT_MENU
    hDC = *DrawItem\hDC
    Left   = *DrawItem\rcItem\left
    Top    = *DrawItem\rcItem\top
    Right  = *DrawItem\rcItem\right
    Bottom = *DrawItem\rcItem\bottom
    If (#ODS_SELECTED & *DrawItem\itemState)
      If (#ODS_GRAYED & *DrawItem\itemState)
        Brush1 = CreateSolidBrush_(GetSysColor_(#COLOR_MENU))
        SetTextColor_(hDC, GetSysColor_(#COLOR_GRAYTEXT))
        Pen1   = CreateSolidBrush_(GetSysColor_(#COLOR_MENU))
      Else
        Brush1 = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
        SetTextColor_(hDC, GetSysColor_(#COLOR_HIGHLIGHTTEXT))
        Pen1   = CreatePen_(#PS_SOLID, 1, GetSysColor_(#COLOR_HIGHLIGHT))
      EndIf
    ElseIf (#ODS_GRAYED & *DrawItem\itemState)
      Brush1 = CreateSolidBrush_(GetSysColor_(#COLOR_MENU))
      SetTextColor_(hDC, GetSysColor_(#COLOR_GRAYTEXT))
      Pen1   = CreatePen_(#PS_SOLID, 1, GetSysColor_(#COLOR_MENU))
    Else
      Brush1 = CreateSolidBrush_(GetSysColor_(#COLOR_MENU))
      SetTextColor_(hDC, GetSysColor_(#COLOR_MENUTEXT))
      Pen1   = CreatePen_(#PS_SOLID, 1, GetSysColor_(#COLOR_MENU))
    EndIf
    SelectObject_(hDC, Brush1)
    SelectObject_(hDC, Pen1)
    Rectangle_(hDC, Left, Top, Right, Bottom)
    SetBkMode_(hDC, #TRANSPARENT)
    *DrawItem\rcItem\left + ItemWidth + 3
    SystemParametersInfo_(#SPI_GETKEYBOARDCUES, 0, @DrawFlag, 0)
    If (Not DrawFlag) And ((*DrawItem\itemState | #ODS_NOACCEL) = *DrawItem\itemState)
      DrawFlag = #DT_HIDEPREFIX
    Else
      DrawFlag = 0
    EndIf
    DrawFlag = DrawFlag | #DT_SINGLELINE | #DT_VCENTER | #DT_EXPANDTABS
    DrawText_(hDC, Text, Len(Text), *DrawItem\rcItem, DrawFlag)
    *DrawItem\rcItem\left - ItemHeight
    If Glyph
      ;hDCGlyph = StartDrawing(ImageOutput(Glyph))
      ;BitBlt_(hDC, (ItemHeight-ImageHeight(Glyph))/2, (ItemHeight-ImageHeight(Glyph))/2 + Top, ImageWidth(Glyph), ImageHeight(Glyph), hDCGlyph, 0, 0, #SRCCOPY)
      ;StopDrawing()
      DrawIconEx_(hDC, (ItemWidth-ImageWidth(Glyph))/2, (ItemHeight-ImageHeight(Glyph))/2 + Top, ImageID(Glyph), ImageWidth(Glyph), ImageHeight(Glyph), 0, 0, #DI_NORMAL | #DI_COMPAT)
    EndIf
    DeleteObject_(Pen1)
    DeleteObject_(Brush1)
  EndIf
EndProcedure

Example:

Code: Select all


XIncludeFile "super_menu_system.pbi"

Procedure MainWindowCallback(WindowID, Message, wParam, lParam)
  Protected Result = #PB_ProcessPureBasicEvents
    Select Message
      Case #WM_MEASUREITEM
        MeasureMenuItem(WindowID, Message, wParam, lParam)
      Case #WM_DRAWITEM
        DrawMenuItem(WindowID, Message, wParam, lParam)
    EndSelect
  ProcedureReturn Result
EndProcedure

OpenWindow(0, 0, 0, 512, 384, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CreateGadgetList(WindowID(0))
SetWindowCallback(@MainWindowCallback(), 0)
  CreateMenu(0, WindowID(MainWindow))
    MenuTitle("&File")
      MenuItemEx(00, "&Open", LoadImage(-1, "folder-open_16.ico"))
  

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
  EndSelect
ForEver



User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Thanks, works fine for icons. But what should I modify to be able to use bitmaps? (sorry, I'm a noob at this)
I like logic, hence I dislike humans but love computers.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Use BitBlt_() instead of DrawIconEx_(). Or just convert your bitmaps to icons.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Trond wrote:Use BitBlt_() instead of DrawIconEx_().
Didn't work.
Trond wrote:Or just convert your bitmaps to icons.
Looks like I have to do that.
I like logic, hence I dislike humans but love computers.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Joakim Christiansen wrote:
Trond wrote:Use BitBlt_() instead of DrawIconEx_().
Didn't work.
BitBlt_() will work if used correctly, but the included code is probably wrong.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Trond wrote:BitBlt_() will work if used correctly, but the included code is probably wrong.
Okay, I got it to work.
But that code you shared is kinda gay, since it doesn't work with multiple menues (I want to use it for popup menues too). But it always uses MenuID(0)...
Is there any easy way to fix this? :?
I like logic, hence I dislike humans but love computers.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

I don't get a #WM_DRAWITEM for popup menus, so the drawing procedure is never triggered. But apart from that, just change menuid(0) into *DrawItem\hwndItem.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Looks like I'm getting it to work quite ok now, so thanks for the help!
But in the MeasureMenuItem procedure I can't use *DrawItem\hwndItem so it ain't measured right.
I like logic, hence I dislike humans but love computers.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Trond wrote:I don't get a #WM_DRAWITEM for popup menus, so the drawing procedure is never triggered. But apart from that, just change menuid(0) into *DrawItem\hwndItem.
Works fine with my popup menues :?

But in the MeasureMenuItem() procedure at:

Code: Select all

GetMenuString_(MenuID(0), *MeasureItem\itemID, @Text, 8192, 0)
I can't seem to find a way for it to find the right MenuID for the menu, if it's possible it would be nice to know the sollution? This is actually halting one of my projects...
I like logic, hence I dislike humans but love computers.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

It should be possible to replace it with *DrawItem\hwndItem. What happens when you do that?
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Trond wrote:It should be possible to replace it with *DrawItem\hwndItem. What happens when you do that?
The MeasureMenuItem() procedure doesn't have an *DrawItem pointer but I have tried creating one and do what you suggested and it didn't work.
I like logic, hence I dislike humans but love computers.
Post Reply