bump product version to 7.6.3.2-android
[LibreOffice.git] / vcl / win / window / salmenu.cxx
blob91a15284aeb5521c4c550c9f8f6e68c265313e08
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svsys.h>
22 #include <vcl/menu.hxx>
23 #include <vcl/sysdata.hxx>
24 #include <o3tl/char16_t2wchar_t.hxx>
25 #include <o3tl/safeint.hxx>
27 #include <win/wincomp.hxx>
28 #include <win/saldata.hxx>
29 #include <win/salinst.h>
30 #include <win/salframe.h>
31 #include <win/salmenu.h>
33 #include <salgdi.hxx>
35 static DWORD myerr=0;
37 bool SalData::IsKnownMenuHandle( HMENU hMenu )
39 if( mhMenuSet.find( hMenu ) == mhMenuSet.end() )
40 return false;
41 else
42 return true;
45 // WinSalInst factory methods
47 std::unique_ptr<SalMenu> WinSalInstance::CreateMenu( bool bMenuBar, Menu* )
49 WinSalMenu *pSalMenu = new WinSalMenu();
51 pSalMenu->mbMenuBar = bMenuBar;
52 pSalMenu->mhWnd = nullptr;
53 if( bMenuBar )
54 pSalMenu->mhMenu = ::CreateMenu();
55 else
56 pSalMenu->mhMenu = ::CreatePopupMenu();
58 if( pSalMenu->mhMenu )
59 GetSalData()->mhMenuSet.insert( pSalMenu->mhMenu );
61 return std::unique_ptr<SalMenu>(pSalMenu);
64 std::unique_ptr<SalMenuItem> WinSalInstance::CreateMenuItem( const SalItemParams & rItemData )
66 WinSalMenuItem *pSalMenuItem = new WinSalMenuItem();
67 memset( &pSalMenuItem->mInfo, 0, sizeof( MENUITEMINFOW ) );
68 pSalMenuItem->mInfo.cbSize = sizeof( MENUITEMINFOW );
70 if( rItemData.eType == MenuItemType::SEPARATOR )
72 // separator
73 pSalMenuItem->mInfo.fMask = MIIM_TYPE;
74 pSalMenuItem->mInfo.fType = MFT_SEPARATOR;
76 else
78 // item
79 pSalMenuItem->mText = rItemData.aText;
80 pSalMenuItem->mpMenu = rItemData.pMenu;
81 pSalMenuItem->maBitmap= !!rItemData.aImage ? rItemData.aImage.GetBitmapEx().GetBitmap() : Bitmap();
82 pSalMenuItem->mnId = rItemData.nId;
84 // 'translate' mnemonics
85 pSalMenuItem->mText = pSalMenuItem->mText.replaceAll( "~", "&" );
87 pSalMenuItem->mInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
88 pSalMenuItem->mInfo.fType = MFT_STRING;
89 pSalMenuItem->mInfo.dwTypeData = o3tl::toW(const_cast<sal_Unicode *>(pSalMenuItem->mText.getStr()));
90 pSalMenuItem->mInfo.cch = pSalMenuItem->mText.getLength();
92 pSalMenuItem->mInfo.wID = rItemData.nId;
93 pSalMenuItem->mInfo.dwItemData = reinterpret_cast<ULONG_PTR>(pSalMenuItem); // user data
96 return std::unique_ptr<SalMenuItem>(pSalMenuItem);
100 * WinSalMenu
103 WinSalMenu::WinSalMenu()
105 mhMenu = nullptr;
106 mbMenuBar = false;
107 mhWnd = nullptr;
108 mpParentMenu = nullptr;
111 WinSalMenu::~WinSalMenu()
113 // only required if not associated to a window...
114 GetSalData()->mhMenuSet.erase( mhMenu );
115 ::DestroyMenu( mhMenu );
118 bool WinSalMenu::VisibleMenuBar()
120 // The Win32 implementation never shows a native
121 // menubar. Thus, native menus are only visible
122 // when the menu is merged with an OLE container.
123 // The reason are missing tooltips, ownerdraw
124 // issues and accessibility which are better supported
125 // by VCL menus.
126 // Nevertheless, the native menus are always created
127 // and the application will properly react to all native
128 // menu messages.
130 return false;
133 void WinSalMenu::SetFrame( const SalFrame *pFrame )
135 if( pFrame )
136 mhWnd = static_cast<const WinSalFrame*>(pFrame)->mhWnd;
137 else
138 mhWnd = nullptr;
141 void WinSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
143 if( pSalMenuItem )
145 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
146 if( nPos == MENU_APPEND )
148 nPos = ::GetMenuItemCount( mhMenu );
149 if( nPos == static_cast<unsigned>( -1 ) )
150 return;
153 if(!::InsertMenuItemW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
154 myerr = GetLastError();
155 else
156 pWItem->mpSalMenu = this;
160 void WinSalMenu::RemoveItem( unsigned nPos )
162 int num = ::GetMenuItemCount( mhMenu );
163 if( num != -1 && nPos < o3tl::make_unsigned(num) )
165 WinSalMenuItem *pSalMenuItem = nullptr;
167 MENUITEMINFOW mi = {};
168 mi.cbSize = sizeof( mi );
169 mi.fMask = MIIM_DATA;
170 if( !GetMenuItemInfoW( mhMenu, nPos, TRUE, &mi) )
171 myerr = GetLastError();
172 else
173 pSalMenuItem = reinterpret_cast<WinSalMenuItem *>(mi.dwItemData);
175 if( !::RemoveMenu( mhMenu, nPos, MF_BYPOSITION ) )
176 myerr = GetLastError();
177 else
179 if( pSalMenuItem )
180 pSalMenuItem->mpSalMenu = nullptr;
185 static void ImplRemoveItemById( WinSalMenu *pSalMenu, unsigned nItemId )
187 if( !pSalMenu )
188 return;
190 WinSalMenuItem *pSalMenuItem = nullptr;
192 MENUITEMINFOW mi = {};
193 mi.cbSize = sizeof( mi );
194 mi.fMask = MIIM_DATA;
195 if( !GetMenuItemInfoW( pSalMenu->mhMenu, nItemId, FALSE, &mi) )
196 myerr = GetLastError();
197 else
198 pSalMenuItem = reinterpret_cast<WinSalMenuItem *>(mi.dwItemData);
200 if( !::RemoveMenu( pSalMenu->mhMenu, nItemId, MF_BYCOMMAND ) )
201 myerr = GetLastError();
202 else
204 if( pSalMenuItem )
205 pSalMenuItem->mpSalMenu = nullptr;
209 void WinSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos )
211 if( pSalMenuItem )
213 WinSalMenuItem* pWMenuItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
214 WinSalMenu* pWSubMenu = static_cast<WinSalMenu*>(pSubMenu);
215 if( pWMenuItem->mInfo.hSubMenu )
217 GetSalData()->mhMenuSet.erase( pWMenuItem->mInfo.hSubMenu );
218 ::DestroyMenu( pWMenuItem->mInfo.hSubMenu );
221 pWMenuItem->mInfo.fMask |= MIIM_SUBMENU;
222 if( !pSubMenu )
223 pWMenuItem->mInfo.hSubMenu = nullptr;
224 else
226 pWMenuItem->mInfo.hSubMenu = pWSubMenu->mhMenu;
227 pWSubMenu->mpParentMenu = this;
230 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWMenuItem->mInfo ) )
231 myerr = GetLastError();
235 void WinSalMenu::CheckItem( unsigned nPos, bool bCheck )
237 ::CheckMenuItem(mhMenu, nPos, MF_BYPOSITION|(bCheck ? MF_CHECKED : MF_UNCHECKED));
240 void WinSalMenu::EnableItem( unsigned nPos, bool bEnable )
242 ::EnableMenuItem(mhMenu, nPos, MF_BYPOSITION|(bEnable ? MF_ENABLED : (MF_DISABLED|MF_GRAYED)));
245 void WinSalMenu::SetItemImage( unsigned /*nPos*/, SalMenuItem* pSalMenuItem, const Image& rImage )
247 if( pSalMenuItem )
249 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
250 if( !!rImage )
251 pWItem->maBitmap = rImage.GetBitmapEx().GetBitmap();
252 else
253 pWItem->maBitmap = Bitmap();
257 void WinSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const OUString& rText )
259 if( pSalMenuItem )
261 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
262 pWItem->mText = rText;
263 // 'translate' mnemonics
264 pWItem->mText = pWItem->mText.replaceAll( "~", "&" );
265 pWItem->mInfo.fMask = MIIM_TYPE | MIIM_DATA;
266 pWItem->mInfo.fType = MFT_STRING;
268 // combine text and accelerator text
269 OUString aStr( pWItem->mText );
270 if( pWItem->mAccelText.getLength() )
272 aStr += "\t" + pWItem->mAccelText;
274 pWItem->mInfo.dwTypeData = o3tl::toW(const_cast<sal_Unicode *>(aStr.getStr()));
275 pWItem->mInfo.cch = aStr.getLength();
277 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
278 myerr = GetLastError();
282 void WinSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const vcl::KeyCode&, const OUString& rKeyName )
284 if( pSalMenuItem )
286 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
287 pWItem->mAccelText = rKeyName;
288 pWItem->mInfo.fMask = MIIM_TYPE | MIIM_DATA;
289 pWItem->mInfo.fType = MFT_STRING;
291 // combine text and accelerator text
292 OUString aStr( pWItem->mText );
293 if( pWItem->mAccelText.getLength() )
295 aStr += "\t" + pWItem->mAccelText;
297 pWItem->mInfo.dwTypeData = o3tl::toW(const_cast<sal_Unicode *>(aStr.getStr()));
298 pWItem->mInfo.cch = aStr.getLength();
300 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
301 myerr = GetLastError();
305 void WinSalMenu::GetSystemMenuData( SystemMenuData* pData )
307 if( pData )
308 pData->hMenu = mhMenu;
312 * SalMenuItem
315 WinSalMenuItem::WinSalMenuItem()
317 memset( &mInfo, 0, sizeof( MENUITEMINFOW ) );
318 mpMenu = nullptr;
319 mnId = 0xFFFF;
320 mpSalMenu = nullptr;
323 WinSalMenuItem::~WinSalMenuItem()
325 if( mpSalMenu )
326 ImplRemoveItemById( mpSalMenu, mnId );
329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */