update dev300-m58
[ooovba.git] / vcl / win / source / window / salmenu.cxx
blob702ed8d045a7f2fa1a3a0087bea9cc278ee8150c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salmenu.cxx,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <tools/svwin.h>
34 #include <wincomp.hxx>
35 #include <saldata.hxx>
36 #include <salinst.h>
37 #include <vcl/salgdi.hxx>
38 #include <salmenu.h>
39 #include <vcl/menu.hxx>
40 #include <vcl/sysdata.hxx>
41 #include <salframe.h>
42 #include <vcl/impbmp.hxx>
44 // uncomment the following line to have ownerdrawn menues, ie, with bitmaps
45 // however, this is incompatible with OLE inplace editing
46 // so it is not activated by default
47 //#define OWNERDRAW
49 static DWORD myerr=0;
51 // =======================================================================
53 BOOL SalData::IsKnownMenuHandle( HMENU hMenu )
55 if( mhMenuSet.find( hMenu ) == mhMenuSet.end() )
56 return FALSE;
57 else
58 return TRUE;
61 // =======================================================================
63 // WinSalInst factory methods
65 SalMenu* WinSalInstance::CreateMenu( BOOL bMenuBar )
67 WinSalMenu *pSalMenu = new WinSalMenu();
69 pSalMenu->mbMenuBar = bMenuBar;
70 pSalMenu->mhWnd = NULL;
71 if( bMenuBar )
72 pSalMenu->mhMenu = ::CreateMenu();
73 else
74 pSalMenu->mhMenu = ::CreatePopupMenu();
76 if( pSalMenu->mhMenu )
77 GetSalData()->mhMenuSet.insert( pSalMenu->mhMenu );
79 return pSalMenu;
82 void WinSalInstance::DestroyMenu( SalMenu* pSalMenu )
84 delete pSalMenu;
88 SalMenuItem* WinSalInstance::CreateMenuItem( const SalItemParams* pItemData )
90 if( !pItemData )
91 return NULL;
93 WinSalMenuItem *pSalMenuItem = new WinSalMenuItem();
94 memset( &pSalMenuItem->mInfo, 0, sizeof( MENUITEMINFOW ) );
95 pSalMenuItem->mInfo.cbSize = sizeof( MENUITEMINFOW );
97 if( pItemData->eType == MENUITEM_SEPARATOR )
99 // separator
100 pSalMenuItem->mInfo.fMask = MIIM_TYPE;
101 pSalMenuItem->mInfo.fType = MFT_SEPARATOR;
103 else
105 // item
106 pSalMenuItem->mText = pItemData->aText;
107 pSalMenuItem->mpMenu = pItemData->pMenu;
108 pSalMenuItem->maBitmap= !!pItemData->aImage ? pItemData->aImage.GetBitmapEx().GetBitmap() : Bitmap();
109 pSalMenuItem->mnId = pItemData->nId;
111 // 'translate' mnemonics
112 pSalMenuItem->mText.SearchAndReplace( '~', '&' );
114 pSalMenuItem->mInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
115 pSalMenuItem->mInfo.fType = MFT_STRING;
116 #ifdef OWNERDRAW
117 if( pItemData->pMenu && !pItemData->pMenu->IsMenuBar() )
118 pSalMenuItem->mInfo.fType |= MFT_OWNERDRAW;
119 pSalMenuItem->mInfo.fState = MFS_ENABLED;
120 #endif
121 pSalMenuItem->mInfo.dwTypeData = (LPWSTR) pSalMenuItem->mText.GetBuffer();
122 pSalMenuItem->mInfo.cch = pSalMenuItem->mText.Len();
124 pSalMenuItem->mInfo.wID = pItemData->nId;
125 pSalMenuItem->mInfo.dwItemData = (ULONG_PTR) pSalMenuItem; // user data
128 return pSalMenuItem;
131 void WinSalInstance::DestroyMenuItem( SalMenuItem* pSalMenuItem )
133 delete pSalMenuItem;
137 // =======================================================================
139 static void ImplDrawMenuBar( SalMenu *pMenu )
141 if( pMenu->VisibleMenuBar() )
143 // redrawing the menubar all the time actually seems to be unnecessary (it just flickers)
145 WinSalMenu *pMenuBar = ImplFindMenuBar( pMenu );
146 if( pMenuBar && pMenuBar->mhWnd )
147 ::DrawMenuBar( pMenuBar->mhWnd );
152 // =======================================================================
156 * WinSalMenu
159 WinSalMenu::WinSalMenu()
161 mhMenu = NULL;
162 mbMenuBar = FALSE;
163 mhWnd = NULL;
164 mpParentMenu = NULL;
167 WinSalMenu::~WinSalMenu()
169 // only required if not associated to a window...
170 GetSalData()->mhMenuSet.erase( mhMenu );
171 ::DestroyMenu( mhMenu );
174 BOOL WinSalMenu::VisibleMenuBar()
176 // The Win32 implementation never shows a native
177 // menubar. Thus, native menues are only visible
178 // when the menu is merged with an OLE container.
179 // The reason are missing tooltips, ownerdraw
180 // issues and accessibility which are better supported
181 // by VCL menues.
182 // Nevertheless, the native menues are always created
183 // and the application will properly react to all native
184 // menu messages.
186 return FALSE;
189 void WinSalMenu::SetFrame( const SalFrame *pFrame )
191 if( pFrame )
192 mhWnd = static_cast<const WinSalFrame*>(pFrame)->mhWnd;
193 else
194 mhWnd = NULL;
197 void WinSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
199 if( pSalMenuItem )
201 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
202 if( nPos == MENU_APPEND )
204 nPos = ::GetMenuItemCount( mhMenu );
205 if( nPos == -1 )
206 return;
209 if(!::InsertMenuItemW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
210 myerr = GetLastError();
211 else
213 pWItem->mpSalMenu = this;
214 ImplDrawMenuBar( this );
219 void WinSalMenu::RemoveItem( unsigned nPos )
221 int num = ::GetMenuItemCount( mhMenu );
222 if( num != -1 && nPos < (unsigned)num )
224 WinSalMenuItem *pSalMenuItem = NULL;
226 MENUITEMINFOW mi;
227 memset( &mi, 0, sizeof(mi) );
228 mi.cbSize = sizeof( mi );
229 mi.fMask = MIIM_DATA;
230 if( !GetMenuItemInfoW( mhMenu, nPos, TRUE, &mi) )
231 myerr = GetLastError();
232 else
233 pSalMenuItem = (WinSalMenuItem *) mi.dwItemData;
235 if( !::RemoveMenu( mhMenu, nPos, MF_BYPOSITION ) )
236 myerr = GetLastError();
237 else
239 if( pSalMenuItem )
240 pSalMenuItem->mpSalMenu = NULL;
241 ImplDrawMenuBar( this );
246 void ImplRemoveItemById( WinSalMenu *pSalMenu, unsigned nItemId )
248 if( !pSalMenu )
249 return;
251 WinSalMenuItem *pSalMenuItem = NULL;
253 MENUITEMINFOW mi;
254 memset( &mi, 0, sizeof(mi) );
255 mi.cbSize = sizeof( mi );
256 mi.fMask = MIIM_DATA;
257 if( !GetMenuItemInfoW( pSalMenu->mhMenu, nItemId, FALSE, &mi) )
258 myerr = GetLastError();
259 else
260 pSalMenuItem = (WinSalMenuItem *) mi.dwItemData;
262 if( !::RemoveMenu( pSalMenu->mhMenu, nItemId, MF_BYCOMMAND ) )
263 myerr = GetLastError();
264 else
266 if( pSalMenuItem )
267 pSalMenuItem->mpSalMenu = NULL;
268 ImplDrawMenuBar( pSalMenu );
272 void WinSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos )
274 if( pSalMenuItem )
276 WinSalMenuItem* pWMenuItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
277 WinSalMenu* pWSubMenu = static_cast<WinSalMenu*>(pSubMenu);
278 if( pWMenuItem->mInfo.hSubMenu )
280 GetSalData()->mhMenuSet.erase( pWMenuItem->mInfo.hSubMenu );
281 ::DestroyMenu( pWMenuItem->mInfo.hSubMenu );
284 pWMenuItem->mInfo.fMask |= MIIM_SUBMENU;
285 if( !pSubMenu )
286 pWMenuItem->mInfo.hSubMenu = NULL;
287 else
289 pWMenuItem->mInfo.hSubMenu = pWSubMenu->mhMenu;
290 pWSubMenu->mpParentMenu = this;
293 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWMenuItem->mInfo ) )
294 myerr = GetLastError();
295 else
296 ImplDrawMenuBar( this );
300 void WinSalMenu::CheckItem( unsigned nPos, BOOL bCheck )
302 if( -1 != ::CheckMenuItem( mhMenu, nPos, MF_BYPOSITION|(bCheck ? MF_CHECKED : MF_UNCHECKED) ) )
303 ImplDrawMenuBar( this );
306 void WinSalMenu::EnableItem( unsigned nPos, BOOL bEnable )
308 if( -1 != ::EnableMenuItem( mhMenu, nPos, MF_BYPOSITION|(bEnable ? MF_ENABLED : (MF_DISABLED|MF_GRAYED) ) ) )
309 ImplDrawMenuBar( this );
312 void WinSalMenu::SetItemImage( unsigned /*nPos*/, SalMenuItem* pSalMenuItem, const Image& rImage )
314 if( pSalMenuItem )
316 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
317 if( !!rImage )
318 pWItem->maBitmap = rImage.GetBitmapEx().GetBitmap();
319 else
320 pWItem->maBitmap = Bitmap();
324 void WinSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const XubString& rText )
326 if( pSalMenuItem )
328 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
329 pWItem->mText = rText;
330 // 'translate' mnemonics
331 pWItem->mText.SearchAndReplace( '~', '&' );
332 pWItem->mInfo.fMask = MIIM_TYPE | MIIM_DATA;
333 pWItem->mInfo.fType = MFT_STRING;
334 #ifdef OWNERDRAW
335 if( pWItem->mpMenu && !((Menu*) pWItem->mpMenu)->IsMenuBar() )
336 pWItem->mInfo.fType |= MFT_OWNERDRAW;
337 #endif
339 // combine text and accelerator text
340 XubString aStr( pWItem->mText );
341 if( pWItem->mAccelText.Len() )
343 aStr.AppendAscii("\t");
344 aStr.Append( pWItem->mAccelText );
346 pWItem->mInfo.dwTypeData = (LPWSTR) aStr.GetBuffer();
347 pWItem->mInfo.cch = aStr.Len();
349 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
350 myerr = GetLastError();
351 else
352 ImplDrawMenuBar( this );
356 void WinSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode&, const XubString& rKeyName )
358 if( pSalMenuItem )
360 WinSalMenuItem* pWItem = static_cast<WinSalMenuItem*>(pSalMenuItem);
361 pWItem->mAccelText = rKeyName;
362 pWItem->mInfo.fMask = MIIM_TYPE | MIIM_DATA;
363 pWItem->mInfo.fType = MFT_STRING;
364 #ifdef OWNERDRAW
365 if( pWItem->mpMenu && !((Menu*)pWItem->mpMenu)->IsMenuBar() )
366 pWItem->mInfo.fType |= MFT_OWNERDRAW;
367 #endif
368 // combine text and accelerator text
369 XubString aStr( pWItem->mText );
370 if( pWItem->mAccelText.Len() )
372 aStr.AppendAscii("\t");
373 aStr.Append( pWItem->mAccelText );
375 pWItem->mInfo.dwTypeData = (LPWSTR) aStr.GetBuffer();
376 pWItem->mInfo.cch = aStr.Len();
378 if(!::SetMenuItemInfoW( mhMenu, nPos, TRUE, &pWItem->mInfo ))
379 myerr = GetLastError();
380 else
381 ImplDrawMenuBar( this );
385 void WinSalMenu::GetSystemMenuData( SystemMenuData* pData )
387 if( pData )
388 pData->hMenu = mhMenu;
391 // =======================================================================
394 * SalMenuItem
398 WinSalMenuItem::WinSalMenuItem()
400 memset( &mInfo, 0, sizeof( MENUITEMINFOW ) );
401 mpMenu = NULL;
402 mnId = 0xFFFF;
403 mpSalMenu = NULL;
406 WinSalMenuItem::~WinSalMenuItem()
408 if( mpSalMenu )
409 ImplRemoveItemById( mpSalMenu, mnId );
412 // -------------------------------------------------------------------