Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / vcl / win / source / window / salmenu.cxx
blobd292708fc1ab69946befa2e596f3317e70549c49
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 .
21 #include <svsys.h>
23 #include <vcl/menu.hxx>
24 #include <vcl/sysdata.hxx>
26 #include <win/wincomp.hxx>
27 #include <win/saldata.hxx>
28 #include <win/salinst.h>
29 #include <win/salframe.h>
30 #include <win/salmenu.h>
32 #include <impbmp.hxx>
33 #include <salgdi.hxx>
35 // uncomment the following line to have ownerdrawn menus, ie, with bitmaps
36 // however, this is incompatible with OLE inplace editing
37 // so it is not activated by default
38 //#define OWNERDRAW
40 static DWORD myerr=0;
42 // =======================================================================
44 sal_Bool SalData::IsKnownMenuHandle( HMENU hMenu )
46 if( mhMenuSet.find( hMenu ) == mhMenuSet.end() )
47 return FALSE;
48 else
49 return TRUE;
52 // =======================================================================
54 // WinSalInst factory methods
56 SalMenu* WinSalInstance::CreateMenu( sal_Bool bMenuBar, Menu* )
58 WinSalMenu *pSalMenu = new WinSalMenu();
60 pSalMenu->mbMenuBar = bMenuBar;
61 pSalMenu->mhWnd = NULL;
62 if( bMenuBar )
63 pSalMenu->mhMenu = ::CreateMenu();
64 else
65 pSalMenu->mhMenu = ::CreatePopupMenu();
67 if( pSalMenu->mhMenu )
68 GetSalData()->mhMenuSet.insert( pSalMenu->mhMenu );
70 return pSalMenu;
73 void WinSalInstance::DestroyMenu( SalMenu* pSalMenu )
75 delete pSalMenu;
79 SalMenuItem* WinSalInstance::CreateMenuItem( const SalItemParams* pItemData )
81 if( !pItemData )
82 return NULL;
84 WinSalMenuItem *pSalMenuItem = new WinSalMenuItem();
85 memset( &pSalMenuItem->mInfo, 0, sizeof( MENUITEMINFOW ) );
86 pSalMenuItem->mInfo.cbSize = sizeof( MENUITEMINFOW );
88 if( pItemData->eType == MENUITEM_SEPARATOR )
90 // separator
91 pSalMenuItem->mInfo.fMask = MIIM_TYPE;
92 pSalMenuItem->mInfo.fType = MFT_SEPARATOR;
94 else
96 // item
97 pSalMenuItem->mText = pItemData->aText;
98 pSalMenuItem->mpMenu = pItemData->pMenu;
99 pSalMenuItem->maBitmap= !!pItemData->aImage ? pItemData->aImage.GetBitmapEx().GetBitmap() : Bitmap();
100 pSalMenuItem->mnId = pItemData->nId;
102 // 'translate' mnemonics
103 pSalMenuItem->mText.SearchAndReplace( '~', '&' );
105 pSalMenuItem->mInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
106 pSalMenuItem->mInfo.fType = MFT_STRING;
107 #ifdef OWNERDRAW
108 if( pItemData->pMenu && !pItemData->pMenu->IsMenuBar() )
109 pSalMenuItem->mInfo.fType |= MFT_OWNERDRAW;
110 pSalMenuItem->mInfo.fState = MFS_ENABLED;
111 #endif
112 pSalMenuItem->mInfo.dwTypeData = (LPWSTR) pSalMenuItem->mText.GetBuffer();
113 pSalMenuItem->mInfo.cch = pSalMenuItem->mText.Len();
115 pSalMenuItem->mInfo.wID = pItemData->nId;
116 pSalMenuItem->mInfo.dwItemData = (ULONG_PTR) pSalMenuItem; // user data
119 return pSalMenuItem;
122 void WinSalInstance::DestroyMenuItem( SalMenuItem* pSalMenuItem )
124 delete pSalMenuItem;
128 // =======================================================================
130 static void ImplDrawMenuBar( SalMenu *pMenu )
132 if( pMenu->VisibleMenuBar() )
134 // redrawing the menubar all the time actually seems to be unnecessary (it just flickers)
136 WinSalMenu *pMenuBar = ImplFindMenuBar( pMenu );
137 if( pMenuBar && pMenuBar->mhWnd )
138 ::DrawMenuBar( pMenuBar->mhWnd );
143 // =======================================================================
147 * WinSalMenu
150 WinSalMenu::WinSalMenu()
152 mhMenu = NULL;
153 mbMenuBar = FALSE;
154 mhWnd = NULL;
155 mpParentMenu = NULL;
158 WinSalMenu::~WinSalMenu()
160 // only required if not associated to a window...
161 GetSalData()->mhMenuSet.erase( mhMenu );
162 ::DestroyMenu( mhMenu );
165 sal_Bool WinSalMenu::VisibleMenuBar()
167 // The Win32 implementation never shows a native
168 // menubar. Thus, native menus are only visible
169 // when the menu is merged with an OLE container.
170 // The reason are missing tooltips, ownerdraw
171 // issues and accessibility which are better supported
172 // by VCL menus.
173 // Nevertheless, the native menus are always created
174 // and the application will properly react to all native
175 // menu messages.
177 return FALSE;
180 void WinSalMenu::SetFrame( const SalFrame *pFrame )
182 if( pFrame )
183 mhWnd = static_cast<const WinSalFrame*>(pFrame)->mhWnd;
184 else
185 mhWnd = NULL;
188 void WinSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
190 if( pSalMenuItem )
192 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
193 if( nPos == MENU_APPEND )
195 nPos = ::GetMenuItemCount( mhMenu );
196 if( nPos == static_cast<unsigned>( -1 ) )
197 return;
200 if(!::InsertMenuItemW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
201 myerr = GetLastError();
202 else
204 pWItem->mpSalMenu = this;
205 ImplDrawMenuBar( this );
210 void WinSalMenu::RemoveItem( unsigned nPos )
212 int num = ::GetMenuItemCount( mhMenu );
213 if( num != -1 && nPos < (unsigned)num )
215 WinSalMenuItem *pSalMenuItem = NULL;
217 MENUITEMINFOW mi;
218 memset( &mi, 0, sizeof(mi) );
219 mi.cbSize = sizeof( mi );
220 mi.fMask = MIIM_DATA;
221 if( !GetMenuItemInfoW( mhMenu, nPos, TRUE, &mi) )
222 myerr = GetLastError();
223 else
224 pSalMenuItem = (WinSalMenuItem *) mi.dwItemData;
226 if( !::RemoveMenu( mhMenu, nPos, MF_BYPOSITION ) )
227 myerr = GetLastError();
228 else
230 if( pSalMenuItem )
231 pSalMenuItem->mpSalMenu = NULL;
232 ImplDrawMenuBar( this );
237 void ImplRemoveItemById( WinSalMenu *pSalMenu, unsigned nItemId )
239 if( !pSalMenu )
240 return;
242 WinSalMenuItem *pSalMenuItem = NULL;
244 MENUITEMINFOW mi;
245 memset( &mi, 0, sizeof(mi) );
246 mi.cbSize = sizeof( mi );
247 mi.fMask = MIIM_DATA;
248 if( !GetMenuItemInfoW( pSalMenu->mhMenu, nItemId, FALSE, &mi) )
249 myerr = GetLastError();
250 else
251 pSalMenuItem = (WinSalMenuItem *) mi.dwItemData;
253 if( !::RemoveMenu( pSalMenu->mhMenu, nItemId, MF_BYCOMMAND ) )
254 myerr = GetLastError();
255 else
257 if( pSalMenuItem )
258 pSalMenuItem->mpSalMenu = NULL;
259 ImplDrawMenuBar( pSalMenu );
263 void WinSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos )
265 if( pSalMenuItem )
267 WinSalMenuItem* pWMenuItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
268 WinSalMenu* pWSubMenu = static_cast<WinSalMenu*>(pSubMenu);
269 if( pWMenuItem->mInfo.hSubMenu )
271 GetSalData()->mhMenuSet.erase( pWMenuItem->mInfo.hSubMenu );
272 ::DestroyMenu( pWMenuItem->mInfo.hSubMenu );
275 pWMenuItem->mInfo.fMask |= MIIM_SUBMENU;
276 if( !pSubMenu )
277 pWMenuItem->mInfo.hSubMenu = NULL;
278 else
280 pWMenuItem->mInfo.hSubMenu = pWSubMenu->mhMenu;
281 pWSubMenu->mpParentMenu = this;
284 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWMenuItem->mInfo ) )
285 myerr = GetLastError();
286 else
287 ImplDrawMenuBar( this );
291 void WinSalMenu::CheckItem( unsigned nPos, sal_Bool bCheck )
293 if( static_cast<unsigned>( -1 ) != ::CheckMenuItem( mhMenu, nPos, MF_BYPOSITION|(bCheck ? MF_CHECKED : MF_UNCHECKED) ) )
294 ImplDrawMenuBar( this );
297 void WinSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable )
299 if( -1 != ::EnableMenuItem( mhMenu, nPos, MF_BYPOSITION|(bEnable ? MF_ENABLED : (MF_DISABLED|MF_GRAYED) ) ) )
300 ImplDrawMenuBar( this );
303 void WinSalMenu::SetItemImage( unsigned /*nPos*/, SalMenuItem* pSalMenuItem, const Image& rImage )
305 if( pSalMenuItem )
307 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
308 if( !!rImage )
309 pWItem->maBitmap = rImage.GetBitmapEx().GetBitmap();
310 else
311 pWItem->maBitmap = Bitmap();
315 void WinSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& rText )
317 if( pSalMenuItem )
319 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
320 pWItem->mText = rText;
321 // 'translate' mnemonics
322 pWItem->mText.SearchAndReplace( '~', '&' );
323 pWItem->mInfo.fMask = MIIM_TYPE | MIIM_DATA;
324 pWItem->mInfo.fType = MFT_STRING;
325 #ifdef OWNERDRAW
326 if( pWItem->mpMenu && !((Menu*) pWItem->mpMenu)->IsMenuBar() )
327 pWItem->mInfo.fType |= MFT_OWNERDRAW;
328 #endif
330 // combine text and accelerator text
331 XubString aStr( pWItem->mText );
332 if( pWItem->mAccelText.Len() )
334 aStr.AppendAscii("\t");
335 aStr.Append( pWItem->mAccelText );
337 pWItem->mInfo.dwTypeData = (LPWSTR) aStr.GetBuffer();
338 pWItem->mInfo.cch = aStr.Len();
340 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
341 myerr = GetLastError();
342 else
343 ImplDrawMenuBar( this );
347 void WinSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode&, const rtl::OUString& rKeyName )
349 if( pSalMenuItem )
351 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
352 pWItem->mAccelText = rKeyName;
353 pWItem->mInfo.fMask = MIIM_TYPE | MIIM_DATA;
354 pWItem->mInfo.fType = MFT_STRING;
355 #ifdef OWNERDRAW
356 if( pWItem->mpMenu && !((Menu*)pWItem->mpMenu)->IsMenuBar() )
357 pWItem->mInfo.fType |= MFT_OWNERDRAW;
358 #endif
359 // combine text and accelerator text
360 XubString aStr( pWItem->mText );
361 if( pWItem->mAccelText.Len() )
363 aStr.AppendAscii("\t");
364 aStr.Append( pWItem->mAccelText );
366 pWItem->mInfo.dwTypeData = (LPWSTR) aStr.GetBuffer();
367 pWItem->mInfo.cch = aStr.Len();
369 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
370 myerr = GetLastError();
371 else
372 ImplDrawMenuBar( this );
376 void WinSalMenu::GetSystemMenuData( SystemMenuData* pData )
378 if( pData )
379 pData->hMenu = mhMenu;
382 // =======================================================================
385 * SalMenuItem
389 WinSalMenuItem::WinSalMenuItem()
391 memset( &mInfo, 0, sizeof( MENUITEMINFOW ) );
392 mpMenu = NULL;
393 mnId = 0xFFFF;
394 mpSalMenu = NULL;
397 WinSalMenuItem::~WinSalMenuItem()
399 if( mpSalMenu )
400 ImplRemoveItemById( mpSalMenu, mnId );
403 // -------------------------------------------------------------------
405 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */