📄 menubar.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "MenuBar.hpp"
#include "MenuButton.hpp"
#include "Common.hpp"
#include "Layout.hpp"
#include "PaintHelper.hpp"
#include "PopupMenu.hpp"
#include "PopupMenuItem.hpp"
#include "Debug.hpp"
#include "Resource.h"
#include <windowsx.h>
#include "Input.hpp"
/*------------------------------------------------------------------------------
MenuBarImpl_t::MenuBarImpl_t
Constructor
------------------------------------------------------------------------------*/
MenuBarImpl_t::MenuBarImpl_t(
)
{
TRACE(ZONE_COMMON_CTOR);
m_Menu = NULL;
}
/*------------------------------------------------------------------------------
MenuBarImpl_t::~MenuBarImpl_t
Destructor
------------------------------------------------------------------------------*/
MenuBarImpl_t::~MenuBarImpl_t(
)
{
TRACE(ZONE_COMMON_CTOR);
if (m_Menu)
{
DestroyMenu(m_Menu);
}
}
/*------------------------------------------------------------------------------
MenuBarImpl_t::ControlWindowProc
WndProc for this control
------------------------------------------------------------------------------*/
LRESULT
MenuBarImpl_t::ControlWindowProc(
UINT Message,
WPARAM wParam,
LPARAM lParam,
bool& Handled
)
{
//by default assume we handled the message
Handled = true;
switch (Message)
{
case WM_CREATE:
return OnCreate();
case WM_MENUBAR_GETMENUBUTTONCOUNT:
return OnGetMenuButtonCount();
case WM_MENUBAR_GETMENUHANDLE:
return OnGetMenuHandle();
case WM_MENUBAR_REFRESHINPUTMENUBUTTON:
return OnRefreshInputButton();
case WM_MENUBAR_RESETPOSITIONS:
return OnResetPositions();
case WM_MENUBAR_SETMENU:
return OnSetMenu(
reinterpret_cast<HINSTANCE>(lParam),
wParam
);
case WM_MENUBAR_SETMENUHANDLE:
return OnSetMenuHandle(reinterpret_cast<HMENU>(wParam));
case WM_MENUBAR_SETMENUBUTTONINFO:
return OnSetMenuButtonInfo(
wParam,
reinterpret_cast<const MENUITEMINFO*>(lParam)
);
case WM_MENUBAR_SETMENUITEMINFO:
return OnSetMenuItemInfo(
wParam,
reinterpret_cast<const MENUITEMINFO*>(lParam)
);
case WM_MENUBAR_SHOWMENUBUTTON:
return OnShowMenuButton(wParam, lParam);
default:
Handled = false;
return 0;
}
}
/*------------------------------------------------------------------------------
MenuBarImpl_t::OnCreate
Enumerate the button objects from our parent control
------------------------------------------------------------------------------*/
LRESULT
MenuBarImpl_t::OnCreate(
void
)
{
ASSERT(m_ButtonArray.empty());
HWND Parent = GetParent(m_hwnd);
int ControlIdToGet = IDC_BUTTON1;
while (true)
{
ButtonInfo_t Info;
Info.m_Button = GetDlgItem(Parent, ControlIdToGet);
if ((HWND)Info.m_Button == NULL)
{
break;
}
GetWindowRect(Info.m_Button, &Info.m_WindowRect);
MapWindowRect(NULL, GetParent(m_hwnd), &Info.m_WindowRect);
m_ButtonArray.push_back(Info);
ControlIdToGet++;
}
ASSERT(! m_ButtonArray.empty());
return 0;
}
/*------------------------------------------------------------------------------
MenuBarImpl_t::OnGetMenuButtonCount
Returns (int): the number of menu buttons in the menubar
------------------------------------------------------------------------------*/
LRESULT
MenuBarImpl_t::OnGetMenuButtonCount(
void
) const
{
return m_ButtonArray.size();
}
/*------------------------------------------------------------------------------
MenuBarImpl_t::OnGetMenuHandle
Returns (HMENU): last menu handle
------------------------------------------------------------------------------*/
LRESULT
MenuBarImpl_t::OnGetMenuHandle(
void
) const
{
return reinterpret_cast<LRESULT>(m_Menu);
}
/*------------------------------------------------------------------------------
MenuBarImpl_t::OnRefreshInputButton
Updates the Input menu button if present
Return value is ignored
------------------------------------------------------------------------------*/
LRESULT
MenuBarImpl_t::OnRefreshInputButton(
)
{
int ButtonIndex;
for (ButtonIndex = 0; ButtonIndex < m_ButtonArray.size(); ButtonIndex++)
{
MenuButton_t::ButtonData_t Data;
m_ButtonArray[ButtonIndex].m_Button.GetData(&Data);
if (Data.IsInputButton)
{
InvalidateRect(m_ButtonArray[ButtonIndex].m_Button, NULL, FALSE);
UpdateWindow(m_ButtonArray[ButtonIndex].m_Button);
}
}
return 0;
}
/*------------------------------------------------------------------------------
MenuBarImpl_t::OnSetMenu
Load the specified menu from the resources and turn it into
a new set of buttons and popup menus
Parameters:
Instance: HINSTANCE of the binary containing the menu
ResourceId: resource id of the menu in the binary
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
LRESULT
MenuBarImpl_t::OnSetMenu(
HINSTANCE Instance,
UINT ResourceId
)
{
HMENU MenuHandle;
//Try to load the menu from the binary
MenuHandle = LoadMenu(Instance, MAKEINTRESOURCE(ResourceId));
if (! MenuHandle)
{
return CommonUtilities_t::GetErrorFromWin32();
}
return OnSetMenuHandle(MenuHandle);
}
/*------------------------------------------------------------------------------
MenuBarImpl_t::OnSetMenuHandle
Sets the specified menu and turns it into a new set of buttons and popup menus
Parameters:
MenuHandle: HMENU of the menu
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
LRESULT
MenuBarImpl_t::OnSetMenuHandle(
HMENU MenuHandle
)
{
//If menu bar is being replaced, then we can destroy the menu
if (m_Menu)
{
DestroyMenu(m_Menu);
}
m_Menu = MenuHandle;
//We have an HMENU - now extract the info out of it
MENUITEMINFO Info;
int ButtonIndex = 0;
HRESULT hr = S_OK;
//get each menu item from the HMENU
for (ButtonIndex = 0; ButtonIndex < m_ButtonArray.size(); ButtonIndex++)
{
WCHAR ItemText[100] = L"";
ZeroMemory(&Info, sizeof(Info));
Info.cbSize = sizeof(Info);
Info.fMask = MIIM_ID | MIIM_SUBMENU | MIIM_TYPE;
Info.dwTypeData = ItemText;
Info.cch = _countof(ItemText);
if (!GetMenuItemInfo(
m_Menu,
ButtonIndex,
TRUE, //by position
&Info
))
{
//we're out of items...
hr = S_OK;
break;
}
//otherwise, we only accept strings...
if (Info.fType != MFT_STRING)
{
hr = E_INVALIDARG;
break;
}
MenuButton_t::ButtonData_t Data = {0};
int ShowCommand;
Data.IsInputButton = (Info.dwTypeData &&
(0 == wcscmp(Info.dwTypeData, MenuButtonImpl_t::INPUT_BUTTON)));
//"empty" designation - hide the window
if ((Info.wID == 0) && !Data.IsInputButton)
{
ShowCommand = SW_HIDE;
goto update_button;
}
ShowCommand = SW_SHOW;
//set the text of the button
if (!SetWindowText((HWND)m_ButtonArray[ButtonIndex].m_Button, Info.dwTypeData))
{
hr = CommonUtilities_t::GetErrorFromWin32();
break;
}
if (Info.hSubMenu == NULL)
{
if (!Data.IsInputButton || !Input_IsIMEEnabled())
{
Data.IsMenu = false;
Data.Value.ControlId = Info.wID;
}
else
{
PopupMenu_t Menu;
hr = CreateInputMenu(m_hwnd, Menu);
if (FAILED(hr))
{
break;
}
Data.IsMenu = true;
Data.Value.PopupMenu = Menu;
}
}
else
{
//if there is a submenu, we need to enumerate its items
//and create a new popup menu structure
PopupMenu_t Menu;
hr = CreatePopupMenu(Info.hSubMenu, m_hwnd, Menu);
if (FAILED(hr))
{
break;
}
//set the button to have a popup menu
Data.IsMenu = true;
Data.Value.PopupMenu = Menu;
}
update_button:
//update the button
m_ButtonArray[ButtonIndex].m_Button.SetData(&Data);
if (ShowWindow((HWND)m_ButtonArray[ButtonIndex].m_Button, ShowCommand) &&
(ShowCommand == SW_SHOW))
{
InvalidateRect((HWND)m_ButtonArray[ButtonIndex].m_Button, NULL, TRUE);
}
}
ResizeMenuButtons();
return hr;
}
/*------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -