Windows Vista和后台Windows版本提供作为可视化架构一部分的菜单。 这些菜单使用可视化样式渲染,可以添加到现有应用程序中。 为现有代码添加新功能的代码必须仔细进行,以避免破坏现有的应用程序行为。 某些情况可能导致在应用程序中禁用视觉样式。 这些情况包括:
- 使用所有者绘制菜单项(MFT_OWNERDRAW)自定义菜单
- 使用菜单中断(MFT_MENUBREAK或MFT_MENUBARBREAK)
- 使用HBMMENU_CALLBACK来延迟位图渲染
- 使用销毁的菜单句柄
这些情况会阻止呈现视觉样式菜单。 所有者绘制菜单可以在Windows Vista和后台Windows版本中使用,但菜单不会被视觉设计。 Windows Vista和后Windows版本提供Alpha混合位图,可以显示菜单项,而不使用所有者绘制菜单项。
要求:
- 位图是一个32bpp DIB部分。
- DIB部分具有BI_RGB压缩。
- 该位图包含预乘法α像素。
- 位图存储在hbmpChecked,hbmpUnchecked或hbmpItem字段中。
注意:MFT_BITMAP项目不支持PARGB32位图。
AfxMenu.inc中包含的AfxAddIconToMenuItem函数允许在视觉样式菜单中使用字符图标。
DIM hSubMenu AS HMENU = GetSubMenu(hMenu, 1)
DIM hIcon AS HICON
hIcon = LoadImageW(NULL, "MyIcon.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE)
IF hIcon THEN AfxAddIconToMenuItem(hSubMenu, 0, TRUE, hIcon)
可以使用PNG图标将其首先转换为带有AfxGdipImageFromFile的图标:
hIcon = AfxGdipImageFromFileEx("MyIcon.png")
IF hIcon THEN AfxAddIconToMenuItem(hSubMenu, 0, TRUE, hIcon)
但是,一般来说,我们更感兴趣的是从嵌入在应用程序中的资源文件加载图标。 我们可以使用AfxGdipIconFromRes函数来实现它。
DIM hSubMenu AS HMENU = GetSubMenu(hMenu, 0)
AfxAddIconToMenuItem(hSubMenu, 0, TRUE, AfxGdipIconFromRes(hInst, "IDI_ARROW_LEFT_48"))
以下代码使用与“在工具栏示例中使用PNG图标”相同的资源文件来演示我们只能为工具栏和菜单使用一组图标。
' ########################################################################################
' Microsoft Windows
' Contents: CWindow with a menu
' Compiler: FreeBasic 32 & 64 bit
' Copyright (c) 2016 José Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#define _WIN32_WINNT &h0602
#INCLUDE ONCE "windows.bi"
#INCLUDE ONCE "win/uxtheme.bi"
#INCLUDE ONCE "Afx/CWindow.inc"
#INCLUDE ONCE "Afx/AfxGdiplus.inc"
#INCLUDE ONCE "Afx/AfxMenu.inc"
using Afx
' // Menu identifiers
#define IDM_UNDO 1001 ' Undo
#define IDM_REDO 1002 ' Redo
#define IDM_HOME 1003 ' Home
#define IDM_SAVE 1004 ' Save file
#define IDM_EXIT 1005 ' Exit
DECLARE FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
BYVAL hPrevInstance AS HINSTANCE, _
BYVAL szCmdLine AS ZSTRING PTR, _
BYVAL nCmdShow AS LONG) AS LONG
END WinMain(GetModuleHandleW(NULL), NULL, COMMAND(), SW_NORMAL)
' ========================================================================================
' Build the menu
' ========================================================================================
FUNCTION BuildMenu () AS HMENU
DIM hMenu AS HMENU
DIM hPopUpMenu AS HMENU
hMenu = CreateMenu
hPopUpMenu = CreatePopUpMenu
AppendMenuW hMenu, MF_POPUP OR MF_ENABLED, CAST(UINT_PTR, hPopUpMenu), "&File"
AppendMenuW hPopUpMenu, MF_ENABLED, IDM_UNDO, "&Undo" & CHR(9) & "Ctrl+U"
AppendMenuW hPopUpMenu, MF_ENABLED, IDM_REDO, "&Redo" & CHR(9) & "Ctrl+R"
AppendMenuW hPopUpMenu, MF_ENABLED, IDM_HOME, "&Home" & CHR(9) & "Ctrl+H"
AppendMenuW hPopUpMenu, MF_ENABLED, IDM_SAVE, "&Save" & CHR(9) & "Ctrl+S"
AppendMenuW hPopUpMenu, MF_ENABLED, IDM_EXIT, "E&xit" & CHR(9) & "Alt+F4"
FUNCTION = hMenu
END FUNCTION
' ========================================================================================
' ========================================================================================
' 窗口处理程序
' ========================================================================================
FUNCTION WndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT
SELECT CASE uMsg
CASE WM_CREATE
EXIT FUNCTION
CASE WM_COMMAND
SELECT CASE LOWORD(wParam)
CASE IDCANCEL
' // If ESC key pressed, close the application sending an WM_CLOSE message
IF HIWORD(wParam) = BN_CLICKED THEN
SendMessageW hwnd, WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
CASE IDM_UNDO
MessageBox hwnd, "Undo option clicked", "Menu", MB_OK
EXIT FUNCTION
CASE IDM_REDO
MessageBox hwnd, "Redo option clicked", "Menu", MB_OK
EXIT FUNCTION
CASE IDM_HOME
MessageBox hwnd, "Home option clicked", "Menu", MB_OK
EXIT FUNCTION
CASE IDM_SAVE
MessageBox hwnd, "Save option clicked", "Menu", MB_OK
EXIT FUNCTION
END SELECT
CASE WM_DESTROY
PostQuitMessage(0)
EXIT FUNCTION
END SELECT
FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
BYVAL hPrevInstance AS HINSTANCE, _
BYVAL szCmdLine AS ZSTRING PTR, _
BYVAL nCmdShow AS LONG) AS LONG
' // 设置处理DPI感知
AfxSetProcessDPIAware
DIM pWindow AS CWindow
pWindow.Create(NULL, "CWindow with a menu", @WndProc)
pWindow.SetClientSize(400, 250)
pWindow.Center
' // Add a button
pWindow.AddControl("Button", pWindow.hWindow, IDCANCEL, "&Close", 280, 180, 75, 23)
' // Module instance handle
DIM hInst AS HINSTANCE = GetModuleHandle(NULL)
' // Create the menu
DIM hMenu AS HMENU = BuildMenu
SetMenu pWindow.hWindow, hMenu
' // Add icons to the items of the File menu
DIM hSubMenu AS HMENU = GetSubMenu(hMenu, 0)
AfxAddIconToMenuItem(hSubMenu, 0, TRUE, AfxGdipIconFromRes(hInst, "IDI_ARROW_LEFT_48"))
AfxAddIconToMenuItem(hSubMenu, 1, TRUE, AfxGdipIconFromRes(hInst, "IDI_ARROW_RIGHT_48"))
AfxAddIconToMenuItem(hSubMenu, 2, TRUE, AfxGdipIconFromRes(hInst, "IDI_HOME_48"))
AfxAddIconToMenuItem(hSubMenu, 3, TRUE, AfxGdipIconFromRes(hInst, "IDI_SAVE_48"))
' // Process Windows messages
FUNCTION = pWindow.DoEvents(nCmdShow)
END FUNCTION
' ========================================================================================