
Office-style menus
Nice code
but the systemmenu loses the color

but the systemmenu loses the color
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.

Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.

True, in the window callback, while processing #WM_INITPOPUPMENU I check if the menu is the system menu by doing so:ts-soft wrote:Nice code![]()
but the systemmenu loses the color
Code: Select all
If Not HiWord ( lParam )
OfficeMenuSetItems ( wParam ) ; sets menu items to owner-drawn
EndIf
If you really need to owner-draw the system menu, you can probably work around the annoyances by creating a copy of the system menu (GetSystemMenu_ function) and processing the menu whose handle is returned by the function, or by playing around with the undocumented Windows message 787 ($313), which displays the system menu at coordinates given in lParam (not sure if it receives the system menu handle in wParam or somehow else, but I doubt it).
- electrochrisso
- Addict
- Posts: 989
- Joined: Mon May 14, 2007 2:13 am
- Location: Darling River
Sorry I did not get back quickly I have been away for a few days.
Anyway I tried your latest update on my clunky old laptop on 98se and it seems to look good now, icons and all. The main problem at moment is it freezes after about ten seconds. I will try on XP later and see if I get the same problem. I like the menu style.
Anyway I tried your latest update on my clunky old laptop on 98se and it seems to look good now, icons and all. The main problem at moment is it freezes after about ten seconds. I will try on XP later and see if I get the same problem. I like the menu style.
Hello,
first of all: GREAT!!!
I ve tested it with MDIGadget and it doesnt work properly with popupmenu on MDIWindow. If I would like to initialise it with initoffice(#mdiwindow) it crashes with stack overflow.
So, I can only initoffice() one time. Right ?
Has anybody experienced the same problem ? Maybe solution ?
first of all: GREAT!!!
I ve tested it with MDIGadget and it doesnt work properly with popupmenu on MDIWindow. If I would like to initialise it with initoffice(#mdiwindow) it crashes with stack overflow.
So, I can only initoffice() one time. Right ?
Has anybody experienced the same problem ? Maybe solution ?

Added: Menu titles are ownerdrawn now too. (See first post for updated code.)
@Amnesty, I'll take a look, but it will take a while as I don't have much time these days. Shouldn't be too hard to fix. I'm planning on rewriting the whole thing anyway, as right now it is nothing but silly hacks upon even sillier hacks.
@Amnesty, I'll take a look, but it will take a while as I don't have much time these days. Shouldn't be too hard to fix. I'm planning on rewriting the whole thing anyway, as right now it is nothing but silly hacks upon even sillier hacks.
- NoahPhense
- Addict
- Posts: 1999
- Joined: Thu Oct 16, 2003 8:30 pm
- Location: North Florida
Re: Office-style menus
bad as$ bro .. nice chunk
- np
- np
-
- PureBasic Expert
- Posts: 4229
- Joined: Sat Apr 26, 2003 8:27 am
- Location: Strasbourg / France
- Contact:
I have tested your last version :
- WinNT4 : doesn't work [no menu strings] and crashes at exit
- Win98 : seems to work at first but crashes after a short time
- WinXP : works _but_ after you played around some time with the menus, all menus become white with no text and no selection highlighting. Tested on 2 different PCs with WinXP.
Here is a quick fix for Win9x (the WinXP issue remains, now also seen on Win9x as it no longer crashes) :
- WinNT4 : doesn't work [no menu strings] and crashes at exit
- Win98 : seems to work at first but crashes after a short time
- WinXP : works _but_ after you played around some time with the menus, all menus become white with no text and no selection highlighting. Tested on 2 different PCs with WinXP.
Here is a quick fix for Win9x (the WinXP issue remains, now also seen on Win9x as it no longer crashes) :
Code: Select all
;
; Office Style Menus
;
;****************************************************************
;*
;- Data
;*
;****************************************************************
Enumeration
#Office_Menu_Normal
#Office_Menu_Title
EndEnumeration
Structure OFFICEMENUITEM
MenuID.l
IconID.l
MenuType.b
MenuString.s
EndStructure
;****************************************************************
;*
;- Office Colors
;*
;****************************************************************
Enumeration
#Office_Color_Face_Bright
#Office_Color_Face_Dim
#Office_Color_Disabled
#Office_Color_Outline
#Office_Color_Selected
#Office_Color_Selected_Outline
EndEnumeration
Macro AlphaBlend(LColor, RColor, Alpha)
RGB(((Red(RColor)* Alpha + Red(LColor)*(256 - Alpha)) / 256),(( Green(RColor)* Alpha + Green(LColor)*(256 - Alpha)) / 256),(( Blue(RColor)* Alpha + Blue(LColor)*(256 - Alpha)) / 256))
EndMacro
Procedure Office_Color(Type)
Select Type
Case #Office_Color_Face_Bright
ProcedureReturn GetSysColor_(#COLOR_3DHIGHLIGHT)
Case #Office_Color_Face_Dim
ProcedureReturn AlphaBlend(GetSysColor_(#COLOR_3DFACE), GetSysColor_(#COLOR_3DHILIGHT), 55)
Case #Office_Color_Disabled
ProcedureReturn AlphaBlend(GetSysColor_(#COLOR_GRAYTEXT), GetSysColor_(#COLOR_3DHILIGHT), 77)
Case #Office_Color_Outline
ProcedureReturn AlphaBlend(GetSysColor_(#COLOR_3DDKSHADOW), GetSysColor_(#COLOR_3DFACE), 96)
Case #Office_Color_Selected
ProcedureReturn AlphaBlend(GetSysColor_(#COLOR_ACTIVECAPTION), GetSysColor_(#COLOR_3DHIGHLIGHT), 189)
Case #Office_Color_Selected_Outline
ProcedureReturn AlphaBlend(AlphaBlend(GetSysColor_(#COLOR_ACTIVECAPTION), GetSysColor_(#COLOR_3DFACE), 32), GetSysColor_(#COLOR_3DHIGHLIGHT), 64)
EndSelect
EndProcedure
;****************************************************************
;*
;- Office Dimensions
;*
;****************************************************************
Enumeration
#Office_Dim_Menu_Offset_X = 1
#Office_Dim_Menu_Offset_Y = 2
#Office_Dim_Menu_Bar = 24
EndEnumeration
;****************************************************************
;*
;- Macros
;*
;****************************************************************
Macro HiWord(Value)
(( Value >> 16)& $FFFF)
EndMacro
Macro LoWord(Value)
(Value & $FFFF)
EndMacro
Macro DrawItemsPick(DC, Brush, Pen)
TempBrush = SelectObject_(DC, Brush)
TempPen = SelectObject_(DC, Pen)
EndMacro
Macro DrawItemsDrop(DC)
DeleteObject_(SelectObject_(DC, DC#TempBrush))
DeleteObject_(SelectObject_(DC, DC#TempPen))
EndMacro
Macro DrawItemsSwap(DC, Brush, Pen)
DeleteObject_(SelectObject_(DC, DC#TempBrush))
DeleteObject_(SelectObject_(DC, DC#TempPen))
DC#TempBrush = SelectObject_(DC, Brush)
DC#TempPen = SelectObject_(DC, Pen)
EndMacro
Macro DrawBrushPick(DC, Brush)
DC#TempBrush = SelectObject_(DC, Brush)
EndMacro
Macro DrawBrushDrop(DC)
DeleteObject_(SelectObject_(DC, DC#TempBrush))
EndMacro
Macro DrawBrushSwap(DC, Brush)
DeleteObject_(SelectObject_(DC, DC#TempBrush))
DC#TempBrush = SelectObject_(DC, Brush)
EndMacro
Macro DrawPenPick(DC, Pen)
DC#TempPen = SelectObject_(DC, Pen)
EndMacro
Macro DrawPenDrop(DC)
DeleteObject_(SelectObject_(DC, DC#TempPen))
EndMacro
Macro DrawPenSwap(DC, Pen)
DeleteObject_(SelectObject_(DC, DC#TempPen))
DC#TempPen = SelectObject_(DC, Pen)
EndMacro
Macro DrawFontPick(DC, Font)
DC#TempFont = SelectObject_(DC, Font)
EndMacro
Macro DrawFontDrop(DC)
DeleteObject_(SelectObject_(DC, DC#TempFont))
EndMacro
Macro DrawRectWhole(DC)
Rectangle_(DC, *Item\rcItem\left, *Item\rcItem\top, *Item\rcItem\right, *Item\rcItem\bottom)
EndMacro
Macro DrawRectWholeEx(DC)
Rectangle_(DC, *Item\rcItem\left, *Item\rcItem\top, *Item\rcItem\right + 1, *Item\rcItem\bottom + 1)
EndMacro
Macro DrawRectBar(DC)
Rectangle_(DC, *Item\rcItem\left, *Item\rcItem\top, #Office_Dim_Menu_Bar - 3, *Item\rcItem\bottom + 1)
EndMacro
Macro DrawTextPrep(DC)
*Item\rcItem\top = (*Item\rcItem\top + *Item\rcItem\bottom - *Size\cy)/ 2
*Item\rcItem\left = #Office_Dim_Menu_Bar + 4
DrawText_(DC, @String$, -1, *Item\rcItem, #DT_END_ELLIPSIS | #DT_EXPANDTABS)
EndMacro
Macro DrawBarPrep()
*Item\rcItem\top = (*Item\rcItem\top + *Item\rcItem\bottom)/ 2
*Item\rcItem\left = #Office_Dim_Menu_Bar + 4
*Item\rcItem\right + #Office_Dim_Menu_Bar
*Item\rcItem\bottom = *Item\rcItem\top + 1
EndMacro
Macro APIGetMenuString(String)
If *OfficeMenuItem\MenuType = #Office_Menu_Title
String = *OfficeMenuItem\MenuString
Else
String = Space(255)
GetMenuString_(*OfficeMenuItem\MenuID, *Item\itemID, @String, Len(String), #MF_BYCOMMAND)
EndIf
EndMacro
;****************************************************************
;*
;- Drawing and Measuring
;*
;****************************************************************
Procedure Office_Menu_Get_Font()
Metrics.NONCLIENTMETRICS
Metrics\cbSize = SizeOf(NONCLIENTMETRICS)
SystemParametersInfo_(#SPI_GETNONCLIENTMETRICS, SizeOf(NONCLIENTMETRICS), @Metrics, #Null)
ProcedureReturn CreateFontIndirect_(@Metrics\lfMenuFont)
EndProcedure
Procedure Office_Menu_Measure_Title(*Item.MEASUREITEMSTRUCT, *Size.SIZE)
*Item\itemWidth = *Size\cx + 4
*Item\itemHeight = MenuHeight()
EndProcedure
Procedure Office_Menu_Measure_Entry(String$, *Item.MEASUREITEMSTRUCT, *Size.SIZE)
*Item\itemWidth = #Office_Dim_Menu_Bar + *Size\cx + 16 + 10 * CountString(String$, Chr(9))
*Item\itemHeight = 22
EndProcedure
Procedure Office_Menu_Measure_Bar(*Item.MEASUREITEMSTRUCT)
*Item\itemWidth = #Office_Dim_Menu_Bar
*Item\itemHeight = #Office_Dim_Menu_Offset_Y + 3
EndProcedure
Procedure Office_Menu_Measure_All(Handle, *Item.MEASUREITEMSTRUCT)
*OfficeMenuItem.OFFICEMENUITEM = *Item\itemData
If *Item\CtlType = #ODT_MENU
DC = GetWindowDC_(Handle)
If DC
APIGetMenuString(String$)
If String$
DrawFontPick(DC, Office_Menu_Get_Font())
GetTextExtentPoint32_(DC, String$, Len(String$), @Size.SIZE)
If *OfficeMenuItem\MenuType = #Office_Menu_Title
Office_Menu_Measure_Title(*Item, @Size)
Else
Office_Menu_Measure_Entry(String$, *Item, @Size)
EndIf
DrawFontDrop(DC)
Else
Office_Menu_Measure_Bar(*Item)
EndIf
ReleaseDC_(Handle, DC)
EndIf
EndIf
EndProcedure
Procedure Office_Menu_Draw_Check(DC, *Item.DRAWITEMSTRUCT)
MemoryDC = CreateCompatibleDC_(DC)
If MemoryDC
DrawItemsSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Selected)), CreatePen_(#PS_SOLID, 1, Office_Color(#Office_Color_Selected_Outline)))
TempBitmap = SelectObject_(MemoryDC, CreateBitmap_(GetSystemMetrics_(#SM_CXMENUCHECK), GetSystemMetrics_(#SM_CYMENUCHECK), 1, 1, #Null))
If TempBitmap
Rectangle.RECT
Rectangle\right = Rectangle\left + GetSystemMetrics_(#SM_CXMENUCHECK)
Rectangle\bottom = Rectangle\top + GetSystemMetrics_(#SM_CYMENUCHECK)
DrawFrameControl_(MemoryDC, @Rectangle, #DFC_MENU, #DFCS_MENUCHECK)
If *Item\itemState & #ODS_DISABLED
SetBkColor_(DC, Office_Color(#Office_Color_Face_Dim))
ElseIf *Item\itemState & #ODS_SELECTED
SetBkColor_(DC, Office_Color(#Office_Color_Selected))
Else
SetBkColor_(DC, Office_Color(#Office_Color_Face_Dim))
EndIf
BitBlt_(DC, *Item\rcItem\left + 4, *Item\rcItem\top + GetSystemMetrics_(#SM_CYMENUCHECK)/ 2 - 2, GetSystemMetrics_(#SM_CXMENUCHECK), GetSystemMetrics_(#SM_CYMENUCHECK), MemoryDC, 0, 0, #SRCCOPY)
EndIf
DeleteObject_(SelectObject_(MemoryDC, TempBitmap))
DeleteDC_(MemoryDC)
EndIf
EndProcedure
Procedure Office_Menu_Draw_Icon(DC, *Item.DRAWITEMSTRUCT)
*OfficeMenuItem.OFFICEMENUITEM = *Item\itemData
DrawIconEx_(DC, *Item\rcItem\left + 2, *Item\rcItem\top + 3, *OfficeMenuItem\IconID, 16, 16, #Null, #Null, #DI_NORMAL)
EndProcedure
Procedure Office_Menu_Draw_Title_Normal(DC, *Item.DRAWITEMSTRUCT)
DrawItemsPick(DC, CreateSolidBrush_(GetSysColor_(#COLOR_3DFACE)), GetStockObject_(#NULL_PEN))
Rectangle_(DC, *Item\rcItem\left, *Item\rcItem\top, *Item\rcItem\right + 1, *Item\rcItem\bottom + 1)
EndProcedure
Procedure Office_Menu_Draw_Title_Selected(DC, *Item.DRAWITEMSTRUCT)
DrawItemsPick(DC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)), CreatePen_(#PS_SOLID, 1, Office_Color(#Office_Color_Outline)))
DrawRectWhole(DC)
DrawPenSwap(DC, GetStockObject_(#NULL_PEN))
Rectangle_(DC, *Item\rcItem\left + 1, *Item\rcItem\bottom - 1, *Item\rcItem\right, *Item\rcItem\bottom + 1)
SetProp_(GetActiveWindow_(), "FlagWidth", *Item\rcItem\right - *Item\rcItem\left)
EndProcedure
Procedure Office_Menu_Draw_Title_Hover(DC, *Item.DRAWITEMSTRUCT)
DrawItemsPick(DC, CreateSolidBrush_(Office_Color(#Office_Color_Selected)), CreatePen_(#PS_SOLID, 1, Office_Color(#Office_Color_Selected_Outline)))
DrawRectWhole(DC)
EndProcedure
Procedure Office_Menu_Draw_Title_Text(DC, String$, *Item.DRAWITEMSTRUCT)
GetTextExtentPoint32_(DC, String$, Len(String$), @Size.SIZE)
*Item\rcItem\top = *Item\rcItem\top +(( *Item\rcItem\bottom - *Item\rcItem\top)/ 2 - Size\cy / 2)- 1
DrawTextEx_(DC, @String$, -1, *Item\rcItem, #DT_CENTER | #DT_VCENTER | #DT_END_ELLIPSIS, #Null)
EndProcedure
Procedure Office_Menu_Draw_Entry_Normal(DC, *Item.DRAWITEMSTRUCT)
DrawRectWholeEx(DC)
DrawBrushSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)))
DrawRectBar(DC)
EndProcedure
Procedure Office_Menu_Draw_Entry_Selected(DC, *Item.DRAWITEMSTRUCT)
DrawItemsSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Selected)), CreatePen_(#PS_SOLID, 1, Office_Color(#Office_Color_Selected_Outline)))
DrawRectWhole(DC)
EndProcedure
Procedure Office_Menu_Draw_Entry_Disabled(DC, *Item.DRAWITEMSTRUCT)
SetTextColor_(DC, Office_Color(#Office_Color_Disabled))
DrawRectWholeEx(DC)
DrawBrushSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)))
DrawRectBar(DC)
EndProcedure
Procedure Office_Menu_Draw_Bar(DC, *Item.DRAWITEMSTRUCT)
DrawRectWholeEx(DC)
DrawBrushSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)))
DrawRectBar(DC)
DrawItemsSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Disabled)), CreatePen_(#PS_SOLID , 1, Office_Color(#Office_Color_Disabled)))
DrawBarPrep()
DrawRectWhole(DC)
EndProcedure
Procedure Office_Menu_Draw_Item(DC, String$, *Item.DRAWITEMSTRUCT, *Size.SIZE)
Shared FirstTimeDisplayCounter
*OfficeMenuItem.OFFICEMENUITEM = *Item\itemData
SetTextColor_(DC, #Black)
If *OfficeMenuItem\MenuType = #Office_Menu_Title
FirstTimeDisplayCounter = 0
If *Item\itemState & #ODS_SELECTED
Office_Menu_Draw_Title_Selected(DC, *Item)
ElseIf *Item\itemState & #ODS_HOTLIGHT
Office_Menu_Draw_Title_Hover(DC, *Item)
Else
Office_Menu_Draw_Title_Normal(DC, *Item)
EndIf
Office_Menu_Draw_Title_Text(DC, String$, *Item)
Else
FirstTimeDisplayCounter + 1
Debug FirstTimeDisplayCounter
DrawItemsPick(DC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Bright)), GetStockObject_(#NULL_PEN))
If String$
If *Item\itemState & #ODS_GRAYED
Office_Menu_Draw_Entry_Disabled(DC, *Item)
Else
SetTextColor_(DC, #Black)
If *Item\itemState & #ODS_SELECTED
If FirstTimeDisplayCounter > GetMenuItemCount_(*OfficeMenuItem\MenuID)
Office_Menu_Draw_Entry_Selected(DC, *Item)
EndIf
Else
Office_Menu_Draw_Entry_Normal(DC, *Item)
EndIf
EndIf
If *Item\itemState & #ODS_CHECKED
Office_Menu_Draw_Check(DC, *Item)
EndIf
If *OfficeMenuItem\IconID
Office_Menu_Draw_Icon(DC, *Item)
EndIf
DrawTextPrep(DC)
Else
Office_Menu_Draw_Bar(DC, *Item)
EndIf
EndIf
DrawItemsDrop(DC)
EndProcedure
Procedure Office_Menu_Draw_All(Handle, *Item.DRAWITEMSTRUCT)
*OfficeMenuItem.OFFICEMENUITEM = *Item\itemData
If *Item\CtlType = #ODT_MENU
DC = *Item\hdc
If DC
SetBkMode_(DC, #TRANSPARENT)
APIGetMenuString(String$)
GetTextExtentPoint32_(DC, String$, Len(String$), @Size.SIZE)
Office_Menu_Draw_Item(DC, String$, *Item, @Size)
EndIf
EndIf
EndProcedure
Procedure Office_Menu_Draw_Background(Handle, DC)
If Not DC
DC = GetWindowDC_(Handle)
EndIf
If DC
MemoryDC = CreateCompatibleDC_(DC)
If MemoryDC
GetWindowRect_(Handle, Rectangle.RECT)
TempBitmap = SelectObject_(MemoryDC, CreateCompatibleBitmap_(DC, Rectangle\right - Rectangle\left, Rectangle\bottom - Rectangle\top))
If TempBitmap
DrawItemsPick(MemoryDC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Bright)), CreatePen_(#PS_SOLID, 1, Office_Color(#Office_Color_Outline)))
Rectangle_(MemoryDC, 0, 0, Rectangle\right - Rectangle\left, Rectangle\bottom - Rectangle\top)
DrawItemsSwap(MemoryDC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)), GetStockObject_(#NULL_PEN))
Rectangle_(MemoryDC, 1, 2, #Office_Dim_Menu_Bar, Rectangle\bottom - Rectangle\top - 1)
If GetProp_(GetActiveWindow_(), "FlagOpen")= #True
DrawBrushSwap(MemoryDC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)))
Rectangle_(MemoryDC, 1, 0, GetProp_(GetActiveWindow_(), "FlagWidth"), 2)
EndIf
BitBlt_(DC, 0, 0, Rectangle\right - Rectangle\left, Rectangle\bottom - Rectangle\top, MemoryDC, 0, 0, #SRCCOPY)
EndIf
DeleteObject_(SelectObject_(MemoryDC, TempBitmap))
DeleteDC_(MemoryDC)
EndIf
ReleaseDC_(Handle, DC)
EndIf
EndProcedure
;****************************************************************
;*
;- Callbacks etc.
;*
;****************************************************************
Procedure OfficeMenuSetIcon(MenuID, itemID, IconID)
If IsMenu_(MenuID)
MenuInfo.MENUITEMINFO
MenuInfo\cbSize = SizeOf(MENUITEMINFO)
MenuInfo\fMask = #MIIM_DATA
MenuInfo\dwItemData = IconID
SetMenuItemInfo_(MenuID, itemID, #False, @MenuInfo)
EndIf
EndProcedure
Procedure Office_Menu_Set_Items(MenuID)
Shared FirstTimeDisplayCounter
FirstTimeDisplayCounter = 0
For Counter = 0 To GetMenuItemCount_(MenuID)- 1
MenuInfo.MENUITEMINFO
MenuInfo\cbSize = SizeOf(MENUITEMINFO)
MenuInfo\fMask = #MIIM_DATA
GetMenuItemInfo_(MenuID, Counter, #True, @MenuInfo)
*OfficeMenuItem.OFFICEMENUITEM = AllocateMemory(SizeOf(OFFICEMENUITEM))
*OfficeMenuItem\MenuID = MenuID
*OfficeMenuItem\IconID = MenuInfo\dwItemData
MenuInfo\fMask = #MIIM_TYPE | #MIIM_DATA
MenuInfo\fType = #MFT_OWNERDRAW
MenuInfo\dwItemData = *OfficeMenuItem
SetMenuItemInfo_(MenuID, Counter, #True, @MenuInfo)
Next
EndProcedure
Procedure Office_Menu_Reset_Items(MenuID)
Shared FirstTimeDisplayCounter
FirstTimeDisplayCounter = 0
For Counter = 0 To GetMenuItemCount_(MenuID)- 1
MenuInfo.MENUITEMINFO
MenuInfo\cbSize = SizeOf(MENUITEMINFO)
MenuInfo\fMask = #MIIM_DATA
GetMenuItemInfo_(MenuID, Counter, #True, @MenuInfo)
*OfficeMenuItem.OFFICEMENUITEM = MenuInfo\dwItemData
MenuInfo\fMask = #MIIM_DATA
MenuInfo\dwItemData = *OfficeMenuItem\IconID
FreeMemory(*OfficeMenuItem)
SetMenuItemInfo_(MenuID, Counter, #True, @MenuInfo)
Next
EndProcedure
Procedure Office_Window_Callback(Handle, message, wParam, lParam)
Protected WindowProc.l, ReturnValue.l
Select message
Case #WM_INITMENUPOPUP
If Not HiWord(lParam)
Office_Menu_Set_Items(wParam)
SetProp_(Handle, "FlagOpen", GetProp_(Handle, "FlagOpen")+ 1)
EndIf
Case #WM_UNINITMENUPOPUP
If Not HiWord(lParam)
Office_Menu_Reset_Items(wParam)
SetProp_(Handle, "FlagOpen", GetProp_(Handle, "FlagOpen")- 1)
If Not GetProp_(Handle, "FlagOpen")
SetProp_(Handle, "FlagWidth", #Null)
EndIf
EndIf
Case #WM_MEASUREITEM
Office_Menu_Measure_All(Handle, lParam)
ProcedureReturn #True
Case #WM_DRAWITEM
Office_Menu_Draw_All(Handle, lParam)
ProcedureReturn #True
Case #WM_DESTROY
RemoveProp_(Handle, "WindowProc")
RemoveProp_(Handle, "FlagWidth")
RemoveProp_(Handle, "FlagOpen")
EndSelect
WindowProc = GetProp_(Handle, "WindowProc")
If WindowProc
ReturnValue = CallWindowProc_ (WindowProc, Handle, message, wParam, lParam)
EndIf
ProcedureReturn ReturnValue
EndProcedure
Procedure Office_Menu_Check_Window(Handle)
GetWindowRect_(Handle, MenuRectangle.RECT)
GetWindowRect_(GetActiveWindow_(), ParentRectangle.RECT)
GetCursorPos_(MousePoint.POINT)
GetWindowRect_(FindWindow_("Shell_TrayWnd", ""), @TrayRectangle.RECT)
If PtInRect_(@TrayRectangle, MousePoint\X, MousePoint\Y)
ProcedureReturn #False
EndIf
If MenuRectangle\top - ParentRectangle\top = GetSystemMetrics_(#SM_CYBORDER)* 2 + GetSystemMetrics_(#SM_CYCAPTION)
ProcedureReturn #False
EndIf
If MenuRectangle\bottom => ParentRectangle\top And MenuRectangle\bottom <= ParentRectangle\top + GetSystemMetrics_(#SM_CYCAPTION)+ GetSystemMetrics_(#SM_CYBORDER)
ProcedureReturn #False
EndIf
If MenuRectangle\top => ParentRectangle\top And MenuRectangle\top <= ParentRectangle\top + GetSystemMetrics_(#SM_CYCAPTION)+ GetSystemMetrics_(#SM_CYBORDER)
ProcedureReturn #False
EndIf
If MenuRectangle\top <= ParentRectangle\top And MenuRectangle\bottom <= ParentRectangle\top + GetSystemMetrics_(#SM_CYCAPTION)+ GetSystemMetrics_(#SM_CYBORDER)
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure Office_Menu_Callback(Handle, message, wParam, lParam)
Protected WindowProc.l, ReturnValue.l
If Office_Menu_Check_Window(Handle)
Select message
Case #WM_PAINT
Office_Menu_Draw_Background(Handle, #Null)
InvalidateRect_(Handle, #Null, #Null)
EndSelect
EndIf
WindowProc = GetProp_(Handle, "WindowProc")
If WindowProc
ReturnValue = CallWindowProc_ (WindowProc, Handle, message, wParam, lParam)
EndIf
ProcedureReturn ReturnValue
EndProcedure
Procedure Office_Hook(code, wParam, lParam)
*Temporary.CWPSTRUCT = lParam
Select code
Case #HC_ACTION
Select *Temporary\message
Case #WM_CREATE
*CreateParams.CREATESTRUCT = *Temporary\lParam
If *CreateParams\lpszClass = 32768
SetProp_(*Temporary\hwnd, "FlagMenu", #True)
SetProp_(*Temporary\hwnd, "WindowProc", SetWindowLong_(*Temporary\hwnd, #GWL_WNDPROC, @Office_Menu_Callback()))
SystemParametersInfo_(#SPI_GETMENUFADE, #Null, @MenuFade, #Null)
SystemParametersInfo_(#SPI_GETMENUANIMATION, #Null, @MenuAnim, #Null)
SetProp_(*Temporary\hwnd, "MenuFade", MenuFade)
SetProp_(*Temporary\hwnd, "MenuAnim", MenuAnim)
If MenuFade : SystemParametersInfo_(#SPI_SETMENUFADE, #Null, #False, #Null): EndIf
If MenuAnim : SystemParametersInfo_(#SPI_SETMENUANIMATION, #Null, #False, #Null): EndIf
EndIf
Case #WM_DESTROY
If GetProp_(*Temporary\hwnd, "FlagMenu")
RemoveProp_(*Temporary\hwnd, "FlagMenu")
RemoveProp_(*Temporary\hwnd, "WindowProc")
SystemParametersInfo_(#SPI_SETMENUFADE, #Null, GetProp_(*Temporary\hwnd, "MenuFade"), #Null)
SystemParametersInfo_(#SPI_SETMENUANIMATION, #Null, GetProp_(*Temporary\hwnd, "MenuAnim"), #Null)
RemoveProp_(*Temporary\hwnd, "MenuFade")
RemoveProp_(*Temporary\hwnd, "MenuAnim")
EndIf
EndSelect
EndSelect
ProcedureReturn CallNextHookEx_(@Office_Hook(), code, wParam, lParam)
EndProcedure
Procedure InitOffice(Window)
If Not GetProp_(WindowID(Window), "OfficeMenuHook")
SetProp_(WindowID(Window), "WindowProc", SetWindowLong_(WindowID(Window), #GWL_WNDPROC, @Office_Window_Callback()))
SetProp_(WindowID(Window), "WindowHook", SetWindowsHookEx_(#WH_CALLWNDPROC, @Office_Hook(), #Null, GetWindowThreadProcessId_(WindowID(Window), #Null)))
MenuID = GetMenu_(WindowID(Window))
If MenuID
For Counter = 0 To GetMenuItemCount_(MenuID)- 1
String$ = Space(256)
GetMenuString_(MenuID, Counter, @String$, Len(String$), #MF_BYPOSITION)
*OfficeMenuTitle.OFFICEMENUITEM = AllocateMemory(SizeOf(OFFICEMENUITEM))
*OfficeMenuTitle\MenuID = MenuID
*OfficeMenuTitle\MenuType = #Office_Menu_Title
*OfficeMenuTitle\MenuString = String$
ModifyMenu_(MenuID, Counter, #MF_BYPOSITION | #MF_OWNERDRAW, -1, *OfficeMenuTitle)
Next
DrawMenuBar_(WindowID(Window))
EndIf
ProcedureReturn #True
EndIf
ProcedureReturn #Null
EndProcedure
;****************************************************************
;*
;- Let the testing begin!
;*
;****************************************************************
#Window = 1
#Menu = 2
#Popup = 3
If OpenWindow(#Window, 0, 0, 500, 400, "Menu Test", #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered | #PB_Window_Invisible)
If CreateGadgetList(WindowID(#Window))
EndIf
If CreateMenu(#Menu, WindowID(#Window))
MenuTitle("&File")
MenuItem(0, "New" + Chr(9 )+ Chr(9 )+ "Ctrl+N")
MenuItem(1, "Open..." + Chr(9 )+ Chr(9 )+ "Ctrl+O")
MenuItem(2, "Save" + Chr(9 )+ Chr(9 )+ "Ctrl+S")
MenuItem(3, "Save As...")
MenuItem(4, "Save All")
MenuItem(5, "Close" + Chr(9)+ Chr(9)+ "Ctrl+W")
MenuItem(6, "Close All")
MenuBar()
MenuItem(7, "Sort Sources...")
MenuBar()
MenuItem(8, "Preferences...")
MenuBar()
OpenSubMenu("Recent Files")
MenuItem(9, "config.ini")
MenuItem(10, "autoexec.bat")
MenuItem(11, "kaboom.pb")
MenuBar()
OpenSubMenu("More Files")
MenuItem(200, "alpha.exe")
MenuItem(201, "beta.bat")
MenuItem(202, "gamma.com")
MenuItem(203, "delta.ini")
MenuItem(204, "epsilon.jpg")
MenuItem(205, "theta.bmp")
MenuItem(206, "omicron.mpg")
MenuItem(207, "omega.ogg")
MenuItem(208, "pi.tmp")
MenuItem(209, "tau.bak")
MenuItem(210, "mhy.txt")
CloseSubMenu()
CloseSubMenu()
MenuBar()
MenuItem(12, "Quit")
DisableMenuItem(#Menu, 1, #True)
DisableMenuItem(#Menu, 2, #True)
DisableMenuItem(#Menu, 3, #True)
DisableMenuItem(#Menu, 4, #True)
SetMenuItemState(#Menu, 0, #True)
SetMenuItemState(#Menu, 1, #True)
MenuTitle("&Tools")
MenuItem(20, "Visual Designer" + Chr(9)+ Chr(9)+ "Alt+V")
MenuItem(21, "File Viewer")
MenuItem(22, "Structure Viewer" + Chr(9)+ "Alt+S")
MenuItem(23, "Variable Viewer")
MenuItem(24, "Procedure Browser")
MenuItem(25, "Templates" + Chr(9)+ Chr(9)+ "Alt+X")
MenuItem(26, "Color Picker" + Chr(9)+ Chr(9)+ "Alt+P")
MenuItem(27, "Ascii Table" + Chr(9)+ Chr(9)+ "Alt+A")
MenuItem(28, "Smart Update")
MenuBar()
MenuItem(29, "Configure Tools...")
OfficeMenuSetIcon(MenuID(#Menu), 21, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 46))
OfficeMenuSetIcon(MenuID(#Menu), 22, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 23))
OfficeMenuSetIcon(MenuID(#Menu), 23, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 3))
OfficeMenuSetIcon(MenuID(#Menu), 26, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 12))
DisableMenuItem(#Menu, 22, #True)
MenuTitle("&Help")
MenuItem(30, "Help..." + Chr(9))
MenuBar()
OpenSubMenu("External Help")
MenuItem(31 ,"Call Fred!")
MenuItem(32 ,"Cry Wolf!")
MenuItem(33 ,"Dial 911!")
CloseSubMenu()
MenuBar()
MenuItem(34, "About")
EndIf
If CreatePopupMenu(#Popup)
MenuItem(100, "Simple")
MenuItem(101, "Popup")
MenuItem(102, "Menu")
MenuBar()
OpenSubMenu("--->")
MenuItem(103, "Boo!")
MenuBar()
OpenSubMenu("--->")
MenuItem(104, "Yikes!")
CloseSubMenu()
CloseSubMenu()
OfficeMenuSetIcon(MenuID(#Popup), 100, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 22))
EndIf
EndIf
InitOffice(#Window)
HideWindow(#Window, #False)
Repeat
Event = WaitWindowEvent()
If Event = #WM_RBUTTONDOWN
DisplayPopupMenu(#Popup, WindowID(#Window))
EndIf
Until Event = #PB_Event_CloseWindow
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
That's strange, for some reason I can't reproduce this at all -- which just proves how flaky Windows-menus really are... I'll have a look though.gnozal wrote:- WinXP : works _but_ after you played around some time with the menus, all menus become white with no text and no selection highlighting. Tested on 2 different PCs with WinXP.
- DoubleDutch
- Addict
- Posts: 3220
- Joined: Thu Aug 07, 2003 7:01 pm
- Location: United Kingdom
- Contact:
I've done some slight changes to make it nicer to use with keys...
I haven't encountered the XP bug mentioned here by gnozal, anyone been able to track it down?
Code: Select all
Enumeration
#Office_Menu_Normal
#Office_Menu_Title
EndEnumeration
Structure OFFICEMENUITEM
MenuID.l
IconID.l
MenuType.b
MenuString.s
EndStructure
Enumeration
#Office_Color_Face_Bright
#Office_Color_Face_Dim
#Office_Color_Disabled
#Office_Color_Outline
#Office_Color_Selected
#Office_Color_Selected_Outline
EndEnumeration
Macro AlphaBlend(LColor, RColor, Alpha)
RGB(((Red(RColor)* Alpha + Red(LColor)*(256 - Alpha)) / 256),(( Green(RColor)* Alpha + Green(LColor)*(256 - Alpha)) / 256),(( Blue(RColor)* Alpha + Blue(LColor)*(256 - Alpha)) / 256))
EndMacro
Procedure Office_Color(Type)
Select Type
Case #Office_Color_Face_Bright
ProcedureReturn GetSysColor_(#COLOR_3DHIGHLIGHT)
Case #Office_Color_Face_Dim
ProcedureReturn AlphaBlend(GetSysColor_(#COLOR_3DFACE), GetSysColor_(#COLOR_3DHILIGHT), 55)
Case #Office_Color_Disabled
ProcedureReturn AlphaBlend(GetSysColor_(#COLOR_GRAYTEXT), GetSysColor_(#COLOR_3DHILIGHT), 77)
Case #Office_Color_Outline
ProcedureReturn AlphaBlend(GetSysColor_(#COLOR_3DDKSHADOW), GetSysColor_(#COLOR_3DFACE), 96)
Case #Office_Color_Selected
ProcedureReturn AlphaBlend(GetSysColor_(#COLOR_ACTIVECAPTION), GetSysColor_(#COLOR_3DHIGHLIGHT), 189)
Case #Office_Color_Selected_Outline
ProcedureReturn AlphaBlend(AlphaBlend(GetSysColor_(#COLOR_ACTIVECAPTION), GetSysColor_(#COLOR_3DFACE), 32), GetSysColor_(#COLOR_3DHIGHLIGHT), 64)
EndSelect
EndProcedure
;****************************************************************
;*
;- Office Dimensions
;*
;****************************************************************
Enumeration
#Office_Dim_Menu_Offset_X = 1
#Office_Dim_Menu_Offset_Y = 2
#Office_Dim_Menu_Bar = 24
EndEnumeration
;****************************************************************
;*
;- Macros
;*
;****************************************************************
Macro HiWord(Value)
(( Value >> 16)& $FFFF)
EndMacro
Macro LoWord(Value)
(Value & $FFFF)
EndMacro
Macro DrawItemsPick(DC, Brush, Pen)
TempBrush = SelectObject_(DC, Brush)
TempPen = SelectObject_(DC, Pen)
EndMacro
Macro DrawItemsDrop(DC)
DeleteObject_(SelectObject_(DC, DC#TempBrush))
DeleteObject_(SelectObject_(DC, DC#TempPen))
EndMacro
Macro DrawItemsSwap(DC, Brush, Pen)
DeleteObject_(SelectObject_(DC, DC#TempBrush))
DeleteObject_(SelectObject_(DC, DC#TempPen))
DC#TempBrush = SelectObject_(DC, Brush)
DC#TempPen = SelectObject_(DC, Pen)
EndMacro
Macro DrawBrushPick(DC, Brush)
DC#TempBrush = SelectObject_(DC, Brush)
EndMacro
Macro DrawBrushDrop(DC)
DeleteObject_(SelectObject_(DC, DC#TempBrush))
EndMacro
Macro DrawBrushSwap(DC, Brush)
DeleteObject_(SelectObject_(DC, DC#TempBrush))
DC#TempBrush = SelectObject_(DC, Brush)
EndMacro
Macro DrawPenPick(DC, Pen)
DC#TempPen = SelectObject_(DC, Pen)
EndMacro
Macro DrawPenDrop(DC)
DeleteObject_(SelectObject_(DC, DC#TempPen))
EndMacro
Macro DrawPenSwap(DC, Pen)
DeleteObject_(SelectObject_(DC, DC#TempPen))
DC#TempPen = SelectObject_(DC, Pen)
EndMacro
Macro DrawFontPick(DC, Font)
DC#TempFont = SelectObject_(DC, Font)
EndMacro
Macro DrawFontDrop(DC)
DeleteObject_(SelectObject_(DC, DC#TempFont))
EndMacro
Macro DrawRectWhole(DC)
Rectangle_(DC, *Item\rcItem\left, *Item\rcItem\top, *Item\rcItem\right, *Item\rcItem\bottom)
EndMacro
Macro DrawRectWholeEx(DC)
Rectangle_(DC, *Item\rcItem\left, *Item\rcItem\top, *Item\rcItem\right + 1, *Item\rcItem\bottom + 1)
EndMacro
Macro DrawRectBar(DC)
Rectangle_(DC, *Item\rcItem\left, *Item\rcItem\top, #Office_Dim_Menu_Bar - 3, *Item\rcItem\bottom + 1)
EndMacro
Macro DrawTextPrep(DC)
*Item\rcItem\top = (*Item\rcItem\top + *Item\rcItem\bottom - *Size\cy)/ 2
*Item\rcItem\left = #Office_Dim_Menu_Bar + 4
*Item\rcItem\right - 2
pos=FindString(String$,Chr(9),1)
If pos
llen=pos-1
rlen=Len(String$)-pos
Else
llen=Len(String$)
rlen=0
EndIf
DrawText_(DC, @String$,llen, *Item\rcItem,#DT_END_ELLIPSIS|#ES_LEFT)
If rlen
SetTextColor_(DC,RGB(80,20,128))
DrawText_(DC,@String$+llen+1,rlen,*Item\rcItem,#DT_END_ELLIPSIS|#ES_RIGHT)
EndIf
EndMacro
Macro DrawBarPrep()
*Item\rcItem\top = (*Item\rcItem\top + *Item\rcItem\bottom)/ 2
*Item\rcItem\left = #Office_Dim_Menu_Bar + 4
*Item\rcItem\right + #Office_Dim_Menu_Bar
*Item\rcItem\bottom = *Item\rcItem\top + 1
EndMacro
Macro APIGetMenuString(String)
If *OfficeMenuItem\MenuType = #Office_Menu_Title
String = *OfficeMenuItem\MenuString
Else
String = Space(255)
GetMenuString_(*OfficeMenuItem\MenuID, *Item\itemID, @String, Len(String), #MF_BYCOMMAND)
EndIf
EndMacro
Procedure Office_Menu_Get_Font()
Metrics.NONCLIENTMETRICS
Metrics\cbSize = SizeOf(NONCLIENTMETRICS)
SystemParametersInfo_(#SPI_GETNONCLIENTMETRICS, SizeOf(NONCLIENTMETRICS), @Metrics, #Null)
ProcedureReturn CreateFontIndirect_(@Metrics\lfMenuFont)
EndProcedure
Procedure Office_Menu_Measure_Title(*Item.MEASUREITEMSTRUCT, *Size.SIZE)
*Item\itemWidth = *Size\cx + 4
*Item\itemHeight = MenuHeight()
EndProcedure
Procedure Office_Menu_Measure_Entry(String$, *Item.MEASUREITEMSTRUCT, *Size.SIZE)
*Item\itemWidth = #Office_Dim_Menu_Bar + *Size\cx + 20
*Item\itemHeight = 22
EndProcedure
Procedure Office_Menu_Measure_Bar(*Item.MEASUREITEMSTRUCT)
*Item\itemWidth = #Office_Dim_Menu_Bar
*Item\itemHeight = #Office_Dim_Menu_Offset_Y + 3
EndProcedure
Procedure Office_Menu_Measure_All(Handle, *Item.MEASUREITEMSTRUCT)
*OfficeMenuItem.OFFICEMENUITEM = *Item\itemData
If *Item\CtlType = #ODT_MENU
DC = GetWindowDC_(Handle)
If DC
APIGetMenuString(String$)
If String$
DrawFontPick(DC, Office_Menu_Get_Font())
GetTextExtentPoint32_(DC, String$, Len(String$), @Size.SIZE)
If *OfficeMenuItem\MenuType = #Office_Menu_Title
Office_Menu_Measure_Title(*Item, @Size)
Else
Office_Menu_Measure_Entry(String$, *Item, @Size)
EndIf
DrawFontDrop(DC)
Else
Office_Menu_Measure_Bar(*Item)
EndIf
ReleaseDC_(Handle, DC)
EndIf
EndIf
EndProcedure
Procedure Office_Menu_Draw_Check(DC, *Item.DRAWITEMSTRUCT)
MemoryDC = CreateCompatibleDC_(DC)
If MemoryDC
DrawItemsSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Selected)), CreatePen_(#PS_SOLID, 1, Office_Color(#Office_Color_Selected_Outline)))
TempBitmap = SelectObject_(MemoryDC, CreateBitmap_(GetSystemMetrics_(#SM_CXMENUCHECK), GetSystemMetrics_(#SM_CYMENUCHECK), 1, 1, #Null))
If TempBitmap
Rectangle.RECT
Rectangle\right = Rectangle\left + GetSystemMetrics_(#SM_CXMENUCHECK)
Rectangle\bottom = Rectangle\top + GetSystemMetrics_(#SM_CYMENUCHECK)
DrawFrameControl_(MemoryDC, @Rectangle, #DFC_MENU, #DFCS_MENUCHECK)
If *Item\itemState & #ODS_DISABLED
SetBkColor_(DC, Office_Color(#Office_Color_Face_Dim))
ElseIf *Item\itemState & #ODS_SELECTED
SetBkColor_(DC, Office_Color(#Office_Color_Selected))
Else
SetBkColor_(DC, Office_Color(#Office_Color_Face_Dim))
EndIf
BitBlt_(DC, *Item\rcItem\left + 4, *Item\rcItem\top + GetSystemMetrics_(#SM_CYMENUCHECK)/ 2 - 2, GetSystemMetrics_(#SM_CXMENUCHECK), GetSystemMetrics_(#SM_CYMENUCHECK), MemoryDC, 0, 0, #SRCCOPY)
EndIf
DeleteObject_(SelectObject_(MemoryDC, TempBitmap))
DeleteDC_(MemoryDC)
EndIf
EndProcedure
Procedure Office_Menu_Draw_Icon(DC, *Item.DRAWITEMSTRUCT)
*OfficeMenuItem.OFFICEMENUITEM = *Item\itemData
DrawIconEx_(DC, *Item\rcItem\left + 2, *Item\rcItem\top + 3, *OfficeMenuItem\IconID, 16, 16, #Null, #Null, #DI_NORMAL)
EndProcedure
Procedure Office_Menu_Draw_Title_Normal(DC, *Item.DRAWITEMSTRUCT)
DrawItemsPick(DC, CreateSolidBrush_(GetSysColor_(#COLOR_3DFACE)), GetStockObject_(#NULL_PEN))
Rectangle_(DC, *Item\rcItem\left, *Item\rcItem\top, *Item\rcItem\right + 1, *Item\rcItem\bottom + 1)
EndProcedure
Procedure Office_Menu_Draw_Title_Selected(DC, *Item.DRAWITEMSTRUCT)
DrawItemsPick(DC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)), CreatePen_(#PS_SOLID, 1, Office_Color(#Office_Color_Outline)))
DrawRectWhole(DC)
DrawPenSwap(DC, GetStockObject_(#NULL_PEN))
Rectangle_(DC, *Item\rcItem\left + 1, *Item\rcItem\bottom - 1, *Item\rcItem\right, *Item\rcItem\bottom + 1)
SetProp_(GetActiveWindow_(), "FlagWidth", *Item\rcItem\right - *Item\rcItem\left)
EndProcedure
Procedure Office_Menu_Draw_Title_Hover(DC, *Item.DRAWITEMSTRUCT)
DrawItemsPick(DC, CreateSolidBrush_(Office_Color(#Office_Color_Selected)), CreatePen_(#PS_SOLID, 1, Office_Color(#Office_Color_Selected_Outline)))
DrawRectWhole(DC)
EndProcedure
Procedure Office_Menu_Draw_Title_Text(DC, String$, *Item.DRAWITEMSTRUCT)
GetTextExtentPoint32_(DC, String$, Len(String$), @Size.SIZE)
*Item\rcItem\top = *Item\rcItem\top +(( *Item\rcItem\bottom - *Item\rcItem\top)/ 2 - Size\cy / 2)- 1
DrawTextEx_(DC, @String$, -1, *Item\rcItem, #DT_CENTER | #DT_VCENTER | #DT_END_ELLIPSIS, #Null)
EndProcedure
Procedure Office_Menu_Draw_Entry_Normal(DC, *Item.DRAWITEMSTRUCT)
DrawRectWholeEx(DC)
DrawBrushSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)))
DrawRectBar(DC)
EndProcedure
Procedure Office_Menu_Draw_Entry_Selected(DC, *Item.DRAWITEMSTRUCT)
DrawItemsSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Selected)), CreatePen_(#PS_SOLID, 1, Office_Color(#Office_Color_Selected_Outline)))
DrawRectWhole(DC)
EndProcedure
Procedure Office_Menu_Draw_Entry_Disabled(DC, *Item.DRAWITEMSTRUCT)
SetTextColor_(DC, Office_Color(#Office_Color_Disabled))
DrawRectWholeEx(DC)
DrawBrushSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)))
DrawRectBar(DC)
EndProcedure
Procedure Office_Menu_Draw_Bar(DC, *Item.DRAWITEMSTRUCT)
DrawRectWholeEx(DC)
DrawBrushSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)))
DrawRectBar(DC)
DrawItemsSwap(DC, CreateSolidBrush_(Office_Color(#Office_Color_Disabled)), CreatePen_(#PS_SOLID , 1, Office_Color(#Office_Color_Disabled)))
DrawBarPrep()
DrawRectWhole(DC)
EndProcedure
Procedure Office_Menu_Draw_Item(DC, String$, *Item.DRAWITEMSTRUCT, *Size.SIZE)
Shared FirstTimeDisplayCounter
*OfficeMenuItem.OFFICEMENUITEM = *Item\itemData
SetTextColor_(DC, #Black)
If *OfficeMenuItem\MenuType = #Office_Menu_Title
FirstTimeDisplayCounter = 0
If *Item\itemState & #ODS_SELECTED
Office_Menu_Draw_Title_Selected(DC, *Item)
ElseIf *Item\itemState & #ODS_HOTLIGHT
Office_Menu_Draw_Title_Hover(DC, *Item)
Else
Office_Menu_Draw_Title_Normal(DC, *Item)
EndIf
Office_Menu_Draw_Title_Text(DC, String$, *Item)
Else
FirstTimeDisplayCounter + 1
Debug FirstTimeDisplayCounter
DrawItemsPick(DC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Bright)), GetStockObject_(#NULL_PEN))
If String$
If *Item\itemState & #ODS_GRAYED
Office_Menu_Draw_Entry_Disabled(DC, *Item)
Else
SetTextColor_(DC, #Black)
If *Item\itemState & #ODS_SELECTED
If FirstTimeDisplayCounter > GetMenuItemCount_(*OfficeMenuItem\MenuID)
Office_Menu_Draw_Entry_Selected(DC, *Item)
EndIf
Else
Office_Menu_Draw_Entry_Normal(DC, *Item)
EndIf
EndIf
If *Item\itemState & #ODS_CHECKED
Office_Menu_Draw_Check(DC, *Item)
EndIf
If *OfficeMenuItem\IconID
Office_Menu_Draw_Icon(DC, *Item)
EndIf
DrawTextPrep(DC)
Else
Office_Menu_Draw_Bar(DC, *Item)
EndIf
EndIf
DrawItemsDrop(DC)
EndProcedure
Procedure Office_Menu_Draw_All(Handle, *Item.DRAWITEMSTRUCT)
*OfficeMenuItem.OFFICEMENUITEM = *Item\itemData
If *Item\CtlType = #ODT_MENU
DC = *Item\hdc
If DC
SetBkMode_(DC, #TRANSPARENT)
APIGetMenuString(String$)
GetTextExtentPoint32_(DC, String$, Len(String$), @Size.SIZE)
Office_Menu_Draw_Item(DC, String$, *Item, @Size)
EndIf
EndIf
EndProcedure
Procedure Office_Menu_Draw_Background(Handle, DC)
If Not DC
DC = GetWindowDC_(Handle)
EndIf
If DC
MemoryDC = CreateCompatibleDC_(DC)
If MemoryDC
GetWindowRect_(Handle, Rectangle.RECT)
TempBitmap = SelectObject_(MemoryDC, CreateCompatibleBitmap_(DC, Rectangle\right - Rectangle\left, Rectangle\bottom - Rectangle\top))
If TempBitmap
DrawItemsPick(MemoryDC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Bright)), CreatePen_(#PS_SOLID, 1, Office_Color(#Office_Color_Outline)))
Rectangle_(MemoryDC, 0, 0, Rectangle\right - Rectangle\left, Rectangle\bottom - Rectangle\top)
DrawItemsSwap(MemoryDC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)), GetStockObject_(#NULL_PEN))
Rectangle_(MemoryDC, 1, 2, #Office_Dim_Menu_Bar, Rectangle\bottom - Rectangle\top - 1)
If GetProp_(GetActiveWindow_(), "FlagOpen")= #True
DrawBrushSwap(MemoryDC, CreateSolidBrush_(Office_Color(#Office_Color_Face_Dim)))
Rectangle_(MemoryDC, 1, 0, GetProp_(GetActiveWindow_(), "FlagWidth"), 2)
EndIf
BitBlt_(DC, 0, 0, Rectangle\right - Rectangle\left, Rectangle\bottom - Rectangle\top, MemoryDC, 0, 0, #SRCCOPY)
EndIf
DeleteObject_(SelectObject_(MemoryDC, TempBitmap))
DeleteDC_(MemoryDC)
EndIf
ReleaseDC_(Handle, DC)
EndIf
EndProcedure
;****************************************************************
;*
;- Callbacks etc.
;*
;****************************************************************
Procedure OfficeMenuSetIcon(MenuID, itemID, IconID)
If IsMenu_(MenuID)
MenuInfo.MENUITEMINFO
MenuInfo\cbSize = SizeOf(MENUITEMINFO)
MenuInfo\fMask = #MIIM_DATA
MenuInfo\dwItemData = IconID
SetMenuItemInfo_(MenuID, itemID, #False, @MenuInfo)
EndIf
EndProcedure
Procedure Office_Menu_Set_Items(MenuID)
Shared FirstTimeDisplayCounter
FirstTimeDisplayCounter = 0
For Counter = 0 To GetMenuItemCount_(MenuID)- 1
MenuInfo.MENUITEMINFO
MenuInfo\cbSize = SizeOf(MENUITEMINFO)
MenuInfo\fMask = #MIIM_DATA
GetMenuItemInfo_(MenuID, Counter, #True, @MenuInfo)
*OfficeMenuItem.OFFICEMENUITEM = AllocateMemory(SizeOf(OFFICEMENUITEM))
*OfficeMenuItem\MenuID = MenuID
*OfficeMenuItem\IconID = MenuInfo\dwItemData
MenuInfo\fMask = #MIIM_TYPE | #MIIM_DATA
MenuInfo\fType = #MFT_OWNERDRAW
MenuInfo\dwItemData = *OfficeMenuItem
SetMenuItemInfo_(MenuID, Counter, #True, @MenuInfo)
Next
EndProcedure
Procedure Office_Menu_Reset_Items(MenuID)
Shared FirstTimeDisplayCounter
FirstTimeDisplayCounter = 0
For Counter = 0 To GetMenuItemCount_(MenuID)- 1
MenuInfo.MENUITEMINFO
MenuInfo\cbSize = SizeOf(MENUITEMINFO)
MenuInfo\fMask = #MIIM_DATA
GetMenuItemInfo_(MenuID, Counter, #True, @MenuInfo)
*OfficeMenuItem.OFFICEMENUITEM = MenuInfo\dwItemData
MenuInfo\fMask = #MIIM_DATA
MenuInfo\dwItemData = *OfficeMenuItem\IconID
FreeMemory(*OfficeMenuItem)
SetMenuItemInfo_(MenuID, Counter, #True, @MenuInfo)
Next
EndProcedure
Procedure Office_Window_Callback(Handle, message, wParam, lParam)
Protected WindowProc.l, ReturnValue.l
Select message
Case #WM_INITMENUPOPUP
If Not HiWord(lParam)
Office_Menu_Set_Items(wParam)
SetProp_(Handle, "FlagOpen", GetProp_(Handle, "FlagOpen")+ 1)
EndIf
Case #WM_UNINITMENUPOPUP
If Not HiWord(lParam)
Office_Menu_Reset_Items(wParam)
SetProp_(Handle, "FlagOpen", GetProp_(Handle, "FlagOpen")- 1)
If Not GetProp_(Handle, "FlagOpen")
SetProp_(Handle, "FlagWidth", #Null)
EndIf
EndIf
Case #WM_MEASUREITEM
Office_Menu_Measure_All(Handle, lParam)
ProcedureReturn #True
Case #WM_DRAWITEM
Office_Menu_Draw_All(Handle, lParam)
ProcedureReturn #True
Case #WM_DESTROY
RemoveProp_(Handle, "WindowProc")
RemoveProp_(Handle, "FlagWidth")
RemoveProp_(Handle, "FlagOpen")
EndSelect
WindowProc = GetProp_(Handle, "WindowProc")
If WindowProc
ReturnValue = CallWindowProc_ (WindowProc, Handle, message, wParam, lParam)
EndIf
ProcedureReturn ReturnValue
EndProcedure
Procedure Office_Menu_Check_Window(Handle)
GetWindowRect_(Handle, MenuRectangle.RECT)
GetWindowRect_(GetActiveWindow_(), ParentRectangle.RECT)
GetCursorPos_(MousePoint.POINT)
GetWindowRect_(FindWindow_("Shell_TrayWnd", ""), @TrayRectangle.RECT)
If PtInRect_(@TrayRectangle, MousePoint\X, MousePoint\Y)
ProcedureReturn #False
EndIf
If MenuRectangle\top - ParentRectangle\top = GetSystemMetrics_(#SM_CYBORDER)* 2 + GetSystemMetrics_(#SM_CYCAPTION)
ProcedureReturn #False
EndIf
If MenuRectangle\bottom => ParentRectangle\top And MenuRectangle\bottom <= ParentRectangle\top + GetSystemMetrics_(#SM_CYCAPTION)+ GetSystemMetrics_(#SM_CYBORDER)
ProcedureReturn #False
EndIf
If MenuRectangle\top => ParentRectangle\top And MenuRectangle\top <= ParentRectangle\top + GetSystemMetrics_(#SM_CYCAPTION)+ GetSystemMetrics_(#SM_CYBORDER)
ProcedureReturn #False
EndIf
If MenuRectangle\top <= ParentRectangle\top And MenuRectangle\bottom <= ParentRectangle\top + GetSystemMetrics_(#SM_CYCAPTION)+ GetSystemMetrics_(#SM_CYBORDER)
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure Office_Menu_Callback(Handle, message, wParam, lParam)
Protected WindowProc.l, ReturnValue.l
If Office_Menu_Check_Window(Handle)
Select message
Case #WM_PAINT
Office_Menu_Draw_Background(Handle, #Null)
InvalidateRect_(Handle, #Null, #Null)
EndSelect
EndIf
WindowProc = GetProp_(Handle, "WindowProc")
If WindowProc
ReturnValue = CallWindowProc_ (WindowProc, Handle, message, wParam, lParam)
EndIf
ProcedureReturn ReturnValue
EndProcedure
Procedure Office_Hook(code, wParam, lParam)
*Temporary.CWPSTRUCT = lParam
Select code
Case #HC_ACTION
Select *Temporary\message
Case #WM_CREATE
*CreateParams.CREATESTRUCT = *Temporary\lParam
If *CreateParams\lpszClass = 32768
SetProp_(*Temporary\hwnd, "FlagMenu", #True)
SetProp_(*Temporary\hwnd, "WindowProc", SetWindowLong_(*Temporary\hwnd, #GWL_WNDPROC, @Office_Menu_Callback()))
SystemParametersInfo_(#SPI_GETMENUFADE, #Null, @MenuFade, #Null)
SystemParametersInfo_(#SPI_GETMENUANIMATION, #Null, @MenuAnim, #Null)
SetProp_(*Temporary\hwnd, "MenuFade", MenuFade)
SetProp_(*Temporary\hwnd, "MenuAnim", MenuAnim)
If MenuFade : SystemParametersInfo_(#SPI_SETMENUFADE, #Null, #False, #Null): EndIf
If MenuAnim : SystemParametersInfo_(#SPI_SETMENUANIMATION, #Null, #False, #Null): EndIf
EndIf
Case #WM_DESTROY
If GetProp_(*Temporary\hwnd, "FlagMenu")
RemoveProp_(*Temporary\hwnd, "FlagMenu")
RemoveProp_(*Temporary\hwnd, "WindowProc")
SystemParametersInfo_(#SPI_SETMENUFADE, #Null, GetProp_(*Temporary\hwnd, "MenuFade"), #Null)
SystemParametersInfo_(#SPI_SETMENUANIMATION, #Null, GetProp_(*Temporary\hwnd, "MenuAnim"), #Null)
RemoveProp_(*Temporary\hwnd, "MenuFade")
RemoveProp_(*Temporary\hwnd, "MenuAnim")
EndIf
EndSelect
EndSelect
ProcedureReturn CallNextHookEx_(@Office_Hook(), code, wParam, lParam)
EndProcedure
Procedure InitOffice(Window)
If Not GetProp_(WindowID(Window), "OfficeMenuHook")
SetProp_(WindowID(Window), "WindowProc", SetWindowLong_(WindowID(Window), #GWL_WNDPROC, @Office_Window_Callback()))
SetProp_(WindowID(Window), "WindowHook", SetWindowsHookEx_(#WH_CALLWNDPROC, @Office_Hook(), #Null, GetWindowThreadProcessId_(WindowID(Window), #Null)))
MenuID = GetMenu_(WindowID(Window))
If MenuID
For Counter = 0 To GetMenuItemCount_(MenuID)- 1
String$ = Space(256)
GetMenuString_(MenuID, Counter, @String$, Len(String$), #MF_BYPOSITION)
*OfficeMenuTitle.OFFICEMENUITEM = AllocateMemory(SizeOf(OFFICEMENUITEM))
*OfficeMenuTitle\MenuID = MenuID
*OfficeMenuTitle\MenuType = #Office_Menu_Title
*OfficeMenuTitle\MenuString = String$
ModifyMenu_(MenuID, Counter, #MF_BYPOSITION | #MF_OWNERDRAW, -1, *OfficeMenuTitle)
Next
DrawMenuBar_(WindowID(Window))
EndIf
ProcedureReturn #True
EndIf
ProcedureReturn #Null
EndProcedure
;****************************************************************
;*
;- Let the testing begin!
;*
;****************************************************************
#Window = 1
#Menu = 2
#Popup = 3
If OpenWindow(#Window, 0, 0, 500, 400, "Menu Test", #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered | #PB_Window_Invisible)
If CreateGadgetList(WindowID(#Window))
EndIf
If CreateMenu(#Menu, WindowID(#Window))
MenuTitle("&File")
MenuItem(0, "New" + Chr(9 )+ "Ctrl N")
MenuItem(1, "Open..." + Chr(9 )+ "Ctrl O")
MenuItem(2, "Save" + Chr(9 )+ "Ctrl S")
MenuItem(3, "Save As...")
MenuItem(4, "Save All")
MenuItem(5, "Close" + Chr(9)+ "Ctrl W")
MenuItem(6, "Close All")
MenuBar()
MenuItem(7, "Sort Sources...")
MenuBar()
MenuItem(8, "Preferences...")
MenuBar()
OpenSubMenu("Recent Files")
MenuItem(9, "config.ini")
MenuItem(10, "autoexec.bat")
MenuItem(11, "kaboom.pb")
MenuBar()
OpenSubMenu("More Files")
MenuItem(200, "alpha.exe")
MenuItem(201, "beta.bat")
MenuItem(202, "gamma.com")
MenuItem(203, "delta.ini")
MenuItem(204, "epsilon.jpg")
MenuItem(205, "theta.bmp")
MenuItem(206, "omicron.mpg")
MenuItem(207, "omega.ogg")
MenuItem(208, "pi.tmp")
MenuItem(209, "tau.bak")
MenuItem(210, "mhy.txt")
CloseSubMenu()
CloseSubMenu()
MenuBar()
MenuItem(12, "Quit")
DisableMenuItem(#Menu, 1, #True)
DisableMenuItem(#Menu, 2, #True)
DisableMenuItem(#Menu, 3, #True)
DisableMenuItem(#Menu, 4, #True)
SetMenuItemState(#Menu, 0, #True)
SetMenuItemState(#Menu, 1, #True)
MenuTitle("&Tools")
MenuItem(20, "Visual Designer" + Chr(9)+ "Alt V")
MenuItem(21, "File Viewer")
MenuItem(22, "Structure Viewer" + Chr(9)+ "Alt S")
MenuItem(23, "Variable Viewer")
MenuItem(24, "Procedure Browser")
MenuItem(25, "Templates" + Chr(9)+ "Alt X")
MenuItem(26, "Color Picker" + Chr(9)+ "Alt P")
MenuItem(27, "Ascii Table" + Chr(9)+ "Alt A")
MenuItem(28, "Smart Update")
MenuBar()
MenuItem(29, "Configure Tools...")
OfficeMenuSetIcon(MenuID(#Menu), 21, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 46))
OfficeMenuSetIcon(MenuID(#Menu), 22, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 23))
OfficeMenuSetIcon(MenuID(#Menu), 23, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 3))
OfficeMenuSetIcon(MenuID(#Menu), 26, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 12))
DisableMenuItem(#Menu, 22, #True)
MenuTitle("&Help")
MenuItem(30, "Help...")
MenuBar()
OpenSubMenu("External Help")
MenuItem(31 ,"Call Fred!")
MenuItem(32 ,"Cry Wolf!")
MenuItem(33 ,"Dial 911!")
CloseSubMenu()
MenuBar()
MenuItem(34, "About")
EndIf
If CreatePopupMenu(#Popup)
MenuItem(100, "Simple")
MenuItem(101, "Popup")
MenuItem(102, "Menu")
MenuBar()
OpenSubMenu("--->")
MenuItem(103, "Boo!")
MenuBar()
OpenSubMenu("--->")
MenuItem(104, "Yikes!")
CloseSubMenu()
CloseSubMenu()
OfficeMenuSetIcon(MenuID(#Popup), 100, ExtractIcon_(GetModuleHandle_(#Null), "Shell32.dll", 22))
EndIf
EndIf
InitOffice(#Window)
HideWindow(#Window, #False)
Repeat
Event = WaitWindowEvent()
If Event = #WM_RBUTTONDOWN
DisplayPopupMenu(#Popup, WindowID(#Window))
EndIf
Until Event = #PB_Event_CloseWindow