merged tag ooo/DEV300_m102
[LibreOffice.git] / vcl / win / source / window / salmenu.cxx
blob23295838bfc99ec75a49b22aacf3621eba90b6f0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 #include <tools/svwin.h>
31 #include <wincomp.hxx>
32 #include <saldata.hxx>
33 #include <salinst.h>
34 #include <vcl/salgdi.hxx>
35 #include <salmenu.h>
36 #include <vcl/menu.hxx>
37 #include <vcl/sysdata.hxx>
38 #include <salframe.h>
39 #include <vcl/impbmp.hxx>
41 // uncomment the following line to have ownerdrawn menues, ie, with bitmaps
42 // however, this is incompatible with OLE inplace editing
43 // so it is not activated by default
44 //#define OWNERDRAW
46 static DWORD myerr=0;
48 // =======================================================================
50 sal_Bool SalData::IsKnownMenuHandle( HMENU hMenu )
52 if( mhMenuSet.find( hMenu ) == mhMenuSet.end() )
53 return FALSE;
54 else
55 return TRUE;
58 // =======================================================================
60 // WinSalInst factory methods
62 SalMenu* WinSalInstance::CreateMenu( sal_Bool bMenuBar, Menu* )
64 WinSalMenu *pSalMenu = new WinSalMenu();
66 pSalMenu->mbMenuBar = bMenuBar;
67 pSalMenu->mhWnd = NULL;
68 if( bMenuBar )
69 pSalMenu->mhMenu = ::CreateMenu();
70 else
71 pSalMenu->mhMenu = ::CreatePopupMenu();
73 if( pSalMenu->mhMenu )
74 GetSalData()->mhMenuSet.insert( pSalMenu->mhMenu );
76 return pSalMenu;
79 void WinSalInstance::DestroyMenu( SalMenu* pSalMenu )
81 delete pSalMenu;
85 SalMenuItem* WinSalInstance::CreateMenuItem( const SalItemParams* pItemData )
87 if( !pItemData )
88 return NULL;
90 WinSalMenuItem *pSalMenuItem = new WinSalMenuItem();
91 memset( &pSalMenuItem->mInfo, 0, sizeof( MENUITEMINFOW ) );
92 pSalMenuItem->mInfo.cbSize = sizeof( MENUITEMINFOW );
94 if( pItemData->eType == MENUITEM_SEPARATOR )
96 // separator
97 pSalMenuItem->mInfo.fMask = MIIM_TYPE;
98 pSalMenuItem->mInfo.fType = MFT_SEPARATOR;
100 else
102 // item
103 pSalMenuItem->mText = pItemData->aText;
104 pSalMenuItem->mpMenu = pItemData->pMenu;
105 pSalMenuItem->maBitmap= !!pItemData->aImage ? pItemData->aImage.GetBitmapEx().GetBitmap() : Bitmap();
106 pSalMenuItem->mnId = pItemData->nId;
108 // 'translate' mnemonics
109 pSalMenuItem->mText.SearchAndReplace( '~', '&' );
111 pSalMenuItem->mInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
112 pSalMenuItem->mInfo.fType = MFT_STRING;
113 #ifdef OWNERDRAW
114 if( pItemData->pMenu && !pItemData->pMenu->IsMenuBar() )
115 pSalMenuItem->mInfo.fType |= MFT_OWNERDRAW;
116 pSalMenuItem->mInfo.fState = MFS_ENABLED;
117 #endif
118 pSalMenuItem->mInfo.dwTypeData = (LPWSTR) pSalMenuItem->mText.GetBuffer();
119 pSalMenuItem->mInfo.cch = pSalMenuItem->mText.Len();
121 pSalMenuItem->mInfo.wID = pItemData->nId;
122 pSalMenuItem->mInfo.dwItemData = (ULONG_PTR) pSalMenuItem; // user data
125 return pSalMenuItem;
128 void WinSalInstance::DestroyMenuItem( SalMenuItem* pSalMenuItem )
130 delete pSalMenuItem;
134 // =======================================================================
136 static void ImplDrawMenuBar( SalMenu *pMenu )
138 if( pMenu->VisibleMenuBar() )
140 // redrawing the menubar all the time actually seems to be unnecessary (it just flickers)
142 WinSalMenu *pMenuBar = ImplFindMenuBar( pMenu );
143 if( pMenuBar && pMenuBar->mhWnd )
144 ::DrawMenuBar( pMenuBar->mhWnd );
149 // =======================================================================
153 * WinSalMenu
156 WinSalMenu::WinSalMenu()
158 mhMenu = NULL;
159 mbMenuBar = FALSE;
160 mhWnd = NULL;
161 mpParentMenu = NULL;
164 WinSalMenu::~WinSalMenu()
166 // only required if not associated to a window...
167 GetSalData()->mhMenuSet.erase( mhMenu );
168 ::DestroyMenu( mhMenu );
171 sal_Bool WinSalMenu::VisibleMenuBar()
173 // The Win32 implementation never shows a native
174 // menubar. Thus, native menues are only visible
175 // when the menu is merged with an OLE container.
176 // The reason are missing tooltips, ownerdraw
177 // issues and accessibility which are better supported
178 // by VCL menues.
179 // Nevertheless, the native menues are always created
180 // and the application will properly react to all native
181 // menu messages.
183 return FALSE;
186 void WinSalMenu::SetFrame( const SalFrame *pFrame )
188 if( pFrame )
189 mhWnd = static_cast<const WinSalFrame*>(pFrame)->mhWnd;
190 else
191 mhWnd = NULL;
194 void WinSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
196 if( pSalMenuItem )
198 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
199 if( nPos == MENU_APPEND )
201 nPos = ::GetMenuItemCount( mhMenu );
202 if( nPos == -1 )
203 return;
206 if(!::InsertMenuItemW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
207 myerr = GetLastError();
208 else
210 pWItem->mpSalMenu = this;
211 ImplDrawMenuBar( this );
216 void WinSalMenu::RemoveItem( unsigned nPos )
218 int num = ::GetMenuItemCount( mhMenu );
219 if( num != -1 && nPos < (unsigned)num )
221 WinSalMenuItem *pSalMenuItem = NULL;
223 MENUITEMINFOW mi;
224 memset( &mi, 0, sizeof(mi) );
225 mi.cbSize = sizeof( mi );
226 mi.fMask = MIIM_DATA;
227 if( !GetMenuItemInfoW( mhMenu, nPos, TRUE, &mi) )
228 myerr = GetLastError();
229 else
230 pSalMenuItem = (WinSalMenuItem *) mi.dwItemData;
232 if( !::RemoveMenu( mhMenu, nPos, MF_BYPOSITION ) )
233 myerr = GetLastError();
234 else
236 if( pSalMenuItem )
237 pSalMenuItem->mpSalMenu = NULL;
238 ImplDrawMenuBar( this );
243 void ImplRemoveItemById( WinSalMenu *pSalMenu, unsigned nItemId )
245 if( !pSalMenu )
246 return;
248 WinSalMenuItem *pSalMenuItem = NULL;
250 MENUITEMINFOW mi;
251 memset( &mi, 0, sizeof(mi) );
252 mi.cbSize = sizeof( mi );
253 mi.fMask = MIIM_DATA;
254 if( !GetMenuItemInfoW( pSalMenu->mhMenu, nItemId, FALSE, &mi) )
255 myerr = GetLastError();
256 else
257 pSalMenuItem = (WinSalMenuItem *) mi.dwItemData;
259 if( !::RemoveMenu( pSalMenu->mhMenu, nItemId, MF_BYCOMMAND ) )
260 myerr = GetLastError();
261 else
263 if( pSalMenuItem )
264 pSalMenuItem->mpSalMenu = NULL;
265 ImplDrawMenuBar( pSalMenu );
269 void WinSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos )
271 if( pSalMenuItem )
273 WinSalMenuItem* pWMenuItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
274 WinSalMenu* pWSubMenu = static_cast<WinSalMenu*>(pSubMenu);
275 if( pWMenuItem->mInfo.hSubMenu )
277 GetSalData()->mhMenuSet.erase( pWMenuItem->mInfo.hSubMenu );
278 ::DestroyMenu( pWMenuItem->mInfo.hSubMenu );
281 pWMenuItem->mInfo.fMask |= MIIM_SUBMENU;
282 if( !pSubMenu )
283 pWMenuItem->mInfo.hSubMenu = NULL;
284 else
286 pWMenuItem->mInfo.hSubMenu = pWSubMenu->mhMenu;
287 pWSubMenu->mpParentMenu = this;
290 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWMenuItem->mInfo ) )
291 myerr = GetLastError();
292 else
293 ImplDrawMenuBar( this );
297 void WinSalMenu::CheckItem( unsigned nPos, sal_Bool bCheck )
299 if( -1 != ::CheckMenuItem( mhMenu, nPos, MF_BYPOSITION|(bCheck ? MF_CHECKED : MF_UNCHECKED) ) )
300 ImplDrawMenuBar( this );
303 void WinSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable )
305 if( -1 != ::EnableMenuItem( mhMenu, nPos, MF_BYPOSITION|(bEnable ? MF_ENABLED : (MF_DISABLED|MF_GRAYED) ) ) )
306 ImplDrawMenuBar( this );
309 void WinSalMenu::SetItemImage( unsigned /*nPos*/, SalMenuItem* pSalMenuItem, const Image& rImage )
311 if( pSalMenuItem )
313 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
314 if( !!rImage )
315 pWItem->maBitmap = rImage.GetBitmapEx().GetBitmap();
316 else
317 pWItem->maBitmap = Bitmap();
321 void WinSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const XubString& rText )
323 if( pSalMenuItem )
325 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
326 pWItem->mText = rText;
327 // 'translate' mnemonics
328 pWItem->mText.SearchAndReplace( '~', '&' );
329 pWItem->mInfo.fMask = MIIM_TYPE | MIIM_DATA;
330 pWItem->mInfo.fType = MFT_STRING;
331 #ifdef OWNERDRAW
332 if( pWItem->mpMenu && !((Menu*) pWItem->mpMenu)->IsMenuBar() )
333 pWItem->mInfo.fType |= MFT_OWNERDRAW;
334 #endif
336 // combine text and accelerator text
337 XubString aStr( pWItem->mText );
338 if( pWItem->mAccelText.Len() )
340 aStr.AppendAscii("\t");
341 aStr.Append( pWItem->mAccelText );
343 pWItem->mInfo.dwTypeData = (LPWSTR) aStr.GetBuffer();
344 pWItem->mInfo.cch = aStr.Len();
346 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
347 myerr = GetLastError();
348 else
349 ImplDrawMenuBar( this );
353 void WinSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode&, const XubString& rKeyName )
355 if( pSalMenuItem )
357 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
358 pWItem->mAccelText = rKeyName;
359 pWItem->mInfo.fMask = MIIM_TYPE | MIIM_DATA;
360 pWItem->mInfo.fType = MFT_STRING;
361 #ifdef OWNERDRAW
362 if( pWItem->mpMenu && !((Menu*)pWItem->mpMenu)->IsMenuBar() )
363 pWItem->mInfo.fType |= MFT_OWNERDRAW;
364 #endif
365 // combine text and accelerator text
366 XubString aStr( pWItem->mText );
367 if( pWItem->mAccelText.Len() )
369 aStr.AppendAscii("\t");
370 aStr.Append( pWItem->mAccelText );
372 pWItem->mInfo.dwTypeData = (LPWSTR) aStr.GetBuffer();
373 pWItem->mInfo.cch = aStr.Len();
375 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
376 myerr = GetLastError();
377 else
378 ImplDrawMenuBar( this );
382 void WinSalMenu::GetSystemMenuData( SystemMenuData* pData )
384 if( pData )
385 pData->hMenu = mhMenu;
388 // =======================================================================
391 * SalMenuItem
395 WinSalMenuItem::WinSalMenuItem()
397 memset( &mInfo, 0, sizeof( MENUITEMINFOW ) );
398 mpMenu = NULL;
399 mnId = 0xFFFF;
400 mpSalMenu = NULL;
403 WinSalMenuItem::~WinSalMenuItem()
405 if( mpSalMenu )
406 ImplRemoveItemById( mpSalMenu, mnId );
409 // -------------------------------------------------------------------