📄 menu.cxx
字号:
/*
* menu.cxx
*
* Menu handling classes.
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: menu.cxx,v $
* Revision 1.26 1999/08/17 03:46:42 robertj
* Fixed usage of inlines in optimised version.
*
* Revision 1.25 1999/08/07 06:51:49 robertj
* Fixed problem with menu item stopping working on calling SetString().
*
* Revision 1.24 1998/12/16 13:00:35 robertj
* Moved function from common code.
*
* Revision 1.23 1998/11/30 05:38:54 robertj
* Added missing implementation of RedrawMenu().
*
* Revision 1.22 1998/10/16 02:08:07 robertj
* Fixed problem with changing first tier menus when have maximised MDI child.
*
* Revision 1.21 1998/09/24 03:42:50 robertj
* Added open software license.
*
* Revision 1.20 1997/04/27 05:50:33 robertj
* DLL support.
*
* Revision 1.19 1996/08/08 10:10:59 robertj
* Directory structure changes for common files.
*
* Revision 1.18 1995/01/27 11:29:27 robertj
* Fixed numerous bugs.
* Fixed bug in nested messages.
* Underscored library variables.
*
* Revision 1.17 1994/11/19 00:06:08 robertj
* Removed variable argument list binding for menus and controls.
*
// Revision 1.16 1994/10/30 11:47:39 robertj
// Changed mechanism for doing notification callback functions.
//
// Revision 1.15 1994/10/23 06:04:12 robertj
// Shortened OS error assert.
// Fixed problem when changing menus - help menu being splattered.
//
// Revision 1.14 1994/07/27 05:58:07 robertj
// Synchronisation.
//
// Revision 1.13 1994/07/17 10:46:06 robertj
// Enhancements, bug fixes etc.
//
// Revision 1.12 1994/06/25 11:55:15 robertj
// Unix version synchronisation.
//
// Revision 1.11 1994/04/20 12:17:44 robertj
// assert changes
//
*/
#include <pwlib.h>
#if !P_USE_INLINES
#include <pwlib/interact.inl>
#endif
//////////////////////////////////////////////////////////////////////////////
// PMenuEntry
PMenuEntry::~PMenuEntry()
{
if (itsMenu != NULL) {
PINDEX pos = GetPosition();
if (pos != P_MAX_INDEX) {
if (itsMenu->hMenu != NULL)
PAssertOS(RemoveMenu(itsMenu->GetHMENU(), pos, MF_BYPOSITION));
itsMenu->entries.DisallowDeleteObjects();
itsMenu->entries.Remove(this);
itsMenu->entries.AllowDeleteObjects();
}
}
}
PINDEX PMenuEntry::GetPosition() const
{
if (itsMenu == NULL)
return -1;
PINDEX pos = itsMenu->entries.GetObjectsIndex(this);
if (pos == P_MAX_INDEX)
return pos;
if (!itsMenu->IsDescendant(PRootMenu::Class()))
return pos;
// Jump through hoops to allow for a maximised MDI child window.
PSubMenu & firstEntry = (PSubMenu &)(*itsMenu)[0];
PAssert(firstEntry.IsDescendant(PSubMenu::Class()), PLogicError);
if (firstEntry.GetHMENU() != GetSubMenu(itsMenu->GetHMENU(), 0))
pos++;
return pos;
}
//////////////////////////////////////////////////////////////////////////////
// PMenuItem
PMenuItem::PMenuItem(PRESOURCE_ID newID, PSubMenu & menu, const PString & str)
: PMenuEntry(menu, NULL),
name(str)
{
menuID = newID;
Construct(TRUE);
}
void PMenuItem::Construct(BOOL setID)
{
PRootMenu * root = GetRootMenu();
if (root != NULL) {
if (setID) {
menuID = 1;
while (root->GetItemFromKey(menuID) != NULL)
menuID++;
}
root->keyedItems.SetAt(menuID, this);
}
if (setID)
PAssertOS(InsertMenu(itsMenu->GetHMENU(),
GetPosition(), MF_BYPOSITION|MF_STRING, menuID, name));
}
void PMenuItem::SetString(const PString & str)
{
PAssert(!str.IsEmpty(), PInvalidParameter);
name = str;
ModifyMenu(itsMenu->GetHMENU(), menuID, MF_STRING, menuID, str);
}
void PMenuItem::SetAccelerator(const PKeyCode & accel)
{
accelerator = accel;
}
//////////////////////////////////////////////////////////////////////////////
PMenuSeparator::PMenuSeparator(PSubMenu & menu, PMenuEntry * before)
: PMenuEntry(menu, before)
{
PAssertOS(InsertMenu(itsMenu->GetHMENU(),
GetPosition(), MF_BYPOSITION|MF_SEPARATOR, 0, NULL));
}
//////////////////////////////////////////////////////////////////////////////
// PSubMenu
PSubMenu::PSubMenu(PSubMenu & menu,
const PString & menuTitle, PMenuEntry * before)
: PMenuEntry(menu, before)
{
hMenu = CreatePopupMenu();
PAssertNULL(hMenu);
title = menuTitle;
PAssertOS(InsertMenu(itsMenu->GetHMENU(),
GetPosition(), MF_BYPOSITION|MF_POPUP|MF_STRING, (UINT)hMenu,title));
}
PSubMenu::PSubMenu(HMENU hSubMenu, PSubMenu & menu, const char * menuTitle)
: PMenuEntry(menu, NULL)
{
title = menuTitle;
hMenu = hSubMenu;
LoadSubMenu();
}
PSubMenu::~PSubMenu()
{
entries.RemoveAll();
DestroyMenu(hMenu);
}
void PSubMenu::SetString(const PString & str)
{
PAssert(!str.IsEmpty(), PInvalidParameter);
title = str;
ModifyMenu(itsMenu->GetHMENU(),
GetPosition(), MF_BYPOSITION|MF_STRING, (UINT)hMenu, str);
}
void PSubMenu::LoadSubMenu()
{
for (int i = 0; i < GetMenuItemCount(hMenu); i++) {
PRESOURCE_ID id = (PRESOURCE_ID)GetMenuItemID(hMenu, i);
char mTitle[100];
switch (id) {
case -1 :
GetMenuString(hMenu, i, mTitle, sizeof(mTitle), MF_BYPOSITION);
new PSubMenu(GetSubMenu(hMenu, i), *this, mTitle);
break;
case 0 :
new PMenuSeparator(id, *this);
break;
default:
GetMenuString(hMenu, i, mTitle, sizeof(mTitle), MF_BYPOSITION);
new PMenuItem(id, *this, mTitle, PKeyCode());
}
}
}
//////////////////////////////////////////////////////////////////////////////
// PRootMenu
POrphanSubMenu::POrphanSubMenu(const PString & menuTitle)
{
hMenu = CreatePopupMenu();
PAssertNULL(hMenu);
title = menuTitle;
}
//////////////////////////////////////////////////////////////////////////////
// PRootMenu
PRootMenu::PRootMenu()
{
keyedItems.DisallowDeleteObjects();
hMenu = CreateMenu();
PAssertNULL(hMenu);
accelerators = NULL;
}
PRootMenu::PRootMenu(PRESOURCE_ID resID)
{
keyedItems.DisallowDeleteObjects();
hMenu = LoadMenu(PApplication::Current().GetInstance(), MAKEINTRESOURCE(resID));
PAssertNULL(hMenu);
LoadSubMenu();
accelerators = LoadAccelerators(PApplication::Current().GetInstance(),
MAKEINTRESOURCE(resID));
}
//////////////////////////////////////////////////////////////////////////////
void PTopLevelWindow::SetMenu(PRootMenu * newMenu, BOOL autoDelete)
{
PAssertOS(::SetMenu(GetHWND(), NULL));
owner->hAccelerator = NULL;
if (menu == NULL)
GetSystemMenu(GetHWND(), TRUE);
else {
HMENU hMenu = menu->GetHMENU();
PAssertOS(RemoveMenu(hMenu, GetMenuItemCount(hMenu)-1, MF_BYPOSITION));
if (deleteMenu)
delete menu;
}
menu = newMenu;
deleteMenu = autoDelete;
if (menu != NULL) {
HMENU hMenu = menu->GetHMENU();
PAssertOS(AppendMenu(hMenu,
MF_POPUP, (UINT)helpMenu.GetHMENU(), helpMenu.GetString()));
PAssertOS(::SetMenu(GetHWND(), hMenu));
owner->hAccelerator = menu->GetHACCEL();
}
else {
HMENU hMenu = GetSystemMenu(_hWnd, FALSE);
PAssertOS(AppendMenu(hMenu, MF_SEPARATOR, 0, NULL));
PAssertOS(AppendMenu(hMenu,
MF_STRING, PSTD_ID_MENU_ABOUT, owner->GetAboutMenuItemString()));
}
DrawMenuBar(GetHWND());
}
void PTopLevelWindow::RedrawMenu()
{
DrawMenuBar(GetHWND());
}
void PMDIFrameWindow::SetMenu(PRootMenu * newMenu, BOOL autoDelete)
{
if (menu != NULL) {
HMENU hMenu = menu->GetHMENU();
PAssertOS(RemoveMenu(hMenu, GetMenuItemCount(hMenu)-2, MF_BYPOSITION));
}
if (newMenu != NULL)
PAssertOS(AppendMenu(newMenu->GetHMENU(),
MF_POPUP, (UINT)windowMenu.GetHMENU(), windowMenu.GetString()));
PTopLevelWindow::SetMenu(newMenu, autoDelete);
}
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -