//---------------------------------------------------------------------------- // ObjectWindows // (C) Copyright 1991, 1994 by Borland International, All Rights Reserved // // Implementation of Window Menu encapsulation class //---------------------------------------------------------------------------- #include #include DIAG_DECLARE_GROUP(OwlWin); // General window diagnostic group // // Construct a menu using CreateMenu() // TMenu::TMenu(TAutoDelete autoDelete) : Handle(::CreateMenu()), ShouldDelete(autoDelete) { WARNX(OwlWin, !Handle, 0, "Cannot Create Menu"); CheckValid(); } // // Construct a menu as a deep copy of an exisiting menu // TMenu::TMenu(const TMenu& original, TAutoDelete autoDelete) : Handle(::CreateMenu()), ShouldDelete(autoDelete) { WARNX(OwlWin, !Handle, 0, "Cannot Create Menu for Copy"); CheckValid(); DeepCopy(*this, original); } // // Construct a menu as an alias for an existing handle // TMenu::TMenu(HMENU handle, TAutoDelete autoDelete) : Handle(handle), ShouldDelete(autoDelete) { } // // Construct a menu alias for a given window's menu // TMenu::TMenu(HWND hWnd, TAutoDelete autoDelete) : Handle(::GetMenu(hWnd)), ShouldDelete(autoDelete) { PRECONDITION(hWnd); WARNX(OwlWin, !Handle, 0, "Cannot Get Menu from " << hex << (uint)hWnd); CheckValid(); } // // Construct a menu from a menu template struct // TMenu::TMenu(const void far* menuTemplate) { PRECONDITION(menuTemplate); Handle = ::LoadMenuIndirect(menuTemplate); WARNX(OwlWin, !Handle, 0, "Cannot Load Menu Indirect " << hex << uint32(menuTemplate)); CheckValid(); ShouldDelete = true; } // // Construct a menu by loading it from resource // TMenu::TMenu(HINSTANCE resInstance, TResId resId) { PRECONDITION(resInstance && resId); Handle = ::LoadMenu(resInstance, resId); WARNX(OwlWin, !Handle, 0, "Cannot Load Menu " << hex << (uint)resInstance << " " << resId); CheckValid(); ShouldDelete = true; } // // Copy an existing menu onto this menu, using DeepCopy // TMenu& TMenu::operator =(const TMenu& original) { // Delete all items and submenus // Look at possible alternatives for !ShouldDelete menus? Maybe use Remove // then? // while (GetMenuItemCount()) DeleteMenu(0, MF_BYPOSITION); DeepCopy(*this, original); return *this; } // // Destruct the menu by destroying the handle if appropriate. // TMenu::~TMenu() { if (ShouldDelete && Handle) ::DestroyMenu(Handle); } // // Get the menu ID. If it's a regular menu item just returns its id. // Otherwise if it's a popup menu use id of the first item in the popup menu. // uint TMenu::GetMenuItemID(int pos) const { uint id = ::GetMenuItemID(Handle, pos); if (id != uint(-1)) return id; // Maybe a submenu // TMenu subMenu(GetSubMenu(pos)); if (subMenu.Handle == 0) return 0; return subMenu.GetMenuItemID(0) - 1; } #pragma warn -par // resId param is never used in small model void TMenu::CheckValid(uint resId) { if (!Handle) THROW( TXMenu(resId) ); } #pragma warn .par void TMenu::MeasureItem(MEASUREITEMSTRUCT far&) { } void TMenu::DrawItem(DRAWITEMSTRUCT far&) { } // // Deep copy 'count' popup-menus or items from 'src' _appending_ to 'dst' // menu starting at 'offset' position in this menu // void TMenu::DeepCopy(TMenu& dst, const TMenu& src, int srcOff, int count) { if (count < 0) count = src.GetMenuItemCount() - srcOff; for (int i = 0; i < count; i++) { uint state = src.GetMenuState(srcOff+i, MF_BYPOSITION); if (state == uint(-1)) return; char str[256]; src.GetMenuString(srcOff+i, str, sizeof(str), MF_BYPOSITION); // Currently does NOT support MF_BITMAP or MF_OWNERDRAW // if (state & MF_POPUP) { state &= (MF_STRING | MF_POPUP); // strip off breaks, separators, etc TMenu subMenu(src.GetSubMenu(srcOff+i)); TMenu newSubMenu(NoAutoDelete); DeepCopy(newSubMenu, subMenu); dst.AppendMenu(state, newSubMenu, str); } else { dst.AppendMenu(state, src.GetMenuItemID(srcOff+i), str); } } } // // Deep copy 'count' popup-menus or items from 'src' to 'dst' menu // starting at 'srcOff' position in src and inserting at 'dstOff' in the // destination // void TMenu::DeepCopy(TMenu& dst, int dstOff, const TMenu& src, int srcOff, int count) { if (count < 0) count = src.GetMenuItemCount() - srcOff; for (int i = 0; i < count; i++) { uint state = src.GetMenuState(srcOff+i, MF_BYPOSITION); if (state == uint(-1)) return; char str[256]; src.GetMenuString(srcOff+i, str, sizeof(str), MF_BYPOSITION); // Currently does NOT support MF_BITMAP or MF_OWNERDRAW // if (state & MF_POPUP) { state &= (MF_STRING | MF_POPUP); // strip off breaks, separators, etc TMenu subMenu(src.GetSubMenu(srcOff+i)); TMenu newSubMenu(NoAutoDelete); DeepCopy(newSubMenu, subMenu); if (dstOff >= 0) dst.InsertMenu(dstOff, state|MF_BYPOSITION, newSubMenu, str); else dst.AppendMenu(state, newSubMenu, str); } else { if (dstOff >= 0) dst.InsertMenu(dstOff, state|MF_BYPOSITION, src.GetMenuItemID(srcOff+i), str); else dst.AppendMenu(state, src.GetMenuItemID(srcOff+i), str); } } } TSystemMenu::TSystemMenu(HWND wnd, bool revert) : TMenu(::GetSystemMenu(wnd, revert), NoAutoDelete) { } TPopupMenu::TPopupMenu(TAutoDelete autoDelete) : TMenu(::CreatePopupMenu(), autoDelete) { } TPopupMenu::TPopupMenu(HMENU handle, TAutoDelete autoDelete) : TMenu(handle, autoDelete) { } TMenu::TXMenu::TXMenu(unsigned resId) : TXOwl(resId) { } TXOwl* TMenu::TXMenu::Clone() { return new TXMenu(*this); } void TMenu::TXMenu::Throw() { THROW( *this ); }