1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salmenu.cxx,v $
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>
37 #include <vcl/salgdi.hxx>
39 #include <vcl/menu.hxx>
40 #include <vcl/sysdata.hxx>
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
51 // =======================================================================
53 BOOL
SalData::IsKnownMenuHandle( HMENU hMenu
)
55 if( mhMenuSet
.find( hMenu
) == mhMenuSet
.end() )
61 // =======================================================================
63 // WinSalInst factory methods
65 SalMenu
* WinSalInstance::CreateMenu( BOOL bMenuBar
)
67 WinSalMenu
*pSalMenu
= new WinSalMenu();
69 pSalMenu
->mbMenuBar
= bMenuBar
;
70 pSalMenu
->mhWnd
= NULL
;
72 pSalMenu
->mhMenu
= ::CreateMenu();
74 pSalMenu
->mhMenu
= ::CreatePopupMenu();
76 if( pSalMenu
->mhMenu
)
77 GetSalData()->mhMenuSet
.insert( pSalMenu
->mhMenu
);
82 void WinSalInstance::DestroyMenu( SalMenu
* pSalMenu
)
88 SalMenuItem
* WinSalInstance::CreateMenuItem( const SalItemParams
* pItemData
)
93 WinSalMenuItem
*pSalMenuItem
= new WinSalMenuItem();
94 memset( &pSalMenuItem
->mInfo
, 0, sizeof( MENUITEMINFOW
) );
95 pSalMenuItem
->mInfo
.cbSize
= sizeof( MENUITEMINFOW
);
97 if( pItemData
->eType
== MENUITEM_SEPARATOR
)
100 pSalMenuItem
->mInfo
.fMask
= MIIM_TYPE
;
101 pSalMenuItem
->mInfo
.fType
= MFT_SEPARATOR
;
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
;
117 if( pItemData
->pMenu
&& !pItemData
->pMenu
->IsMenuBar() )
118 pSalMenuItem
->mInfo
.fType
|= MFT_OWNERDRAW
;
119 pSalMenuItem
->mInfo
.fState
= MFS_ENABLED
;
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
131 void WinSalInstance::DestroyMenuItem( SalMenuItem
* 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 // =======================================================================
159 WinSalMenu::WinSalMenu()
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
182 // Nevertheless, the native menues are always created
183 // and the application will properly react to all native
189 void WinSalMenu::SetFrame( const SalFrame
*pFrame
)
192 mhWnd
= static_cast<const WinSalFrame
*>(pFrame
)->mhWnd
;
197 void WinSalMenu::InsertItem( SalMenuItem
* pSalMenuItem
, unsigned nPos
)
201 WinSalMenuItem
* pWItem
= static_cast<WinSalMenuItem
*>(pSalMenuItem
);
202 if( nPos
== MENU_APPEND
)
204 nPos
= ::GetMenuItemCount( mhMenu
);
209 if(!::InsertMenuItemW( mhMenu
, nPos
, TRUE
, &pWItem
->mInfo
))
210 myerr
= GetLastError();
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
;
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();
233 pSalMenuItem
= (WinSalMenuItem
*) mi
.dwItemData
;
235 if( !::RemoveMenu( mhMenu
, nPos
, MF_BYPOSITION
) )
236 myerr
= GetLastError();
240 pSalMenuItem
->mpSalMenu
= NULL
;
241 ImplDrawMenuBar( this );
246 void ImplRemoveItemById( WinSalMenu
*pSalMenu
, unsigned nItemId
)
251 WinSalMenuItem
*pSalMenuItem
= NULL
;
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();
260 pSalMenuItem
= (WinSalMenuItem
*) mi
.dwItemData
;
262 if( !::RemoveMenu( pSalMenu
->mhMenu
, nItemId
, MF_BYCOMMAND
) )
263 myerr
= GetLastError();
267 pSalMenuItem
->mpSalMenu
= NULL
;
268 ImplDrawMenuBar( pSalMenu
);
272 void WinSalMenu::SetSubMenu( SalMenuItem
* pSalMenuItem
, SalMenu
* pSubMenu
, unsigned nPos
)
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
;
286 pWMenuItem
->mInfo
.hSubMenu
= NULL
;
289 pWMenuItem
->mInfo
.hSubMenu
= pWSubMenu
->mhMenu
;
290 pWSubMenu
->mpParentMenu
= this;
293 if(!::SetMenuItemInfoW( mhMenu
, nPos
, TRUE
, &pWMenuItem
->mInfo
) )
294 myerr
= GetLastError();
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
)
316 WinSalMenuItem
* pWItem
= static_cast<WinSalMenuItem
*>(pSalMenuItem
);
318 pWItem
->maBitmap
= rImage
.GetBitmapEx().GetBitmap();
320 pWItem
->maBitmap
= Bitmap();
324 void WinSalMenu::SetItemText( unsigned nPos
, SalMenuItem
* pSalMenuItem
, const XubString
& rText
)
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
;
335 if( pWItem
->mpMenu
&& !((Menu
*) pWItem
->mpMenu
)->IsMenuBar() )
336 pWItem
->mInfo
.fType
|= MFT_OWNERDRAW
;
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();
352 ImplDrawMenuBar( this );
356 void WinSalMenu::SetAccelerator( unsigned nPos
, SalMenuItem
* pSalMenuItem
, const KeyCode
&, const XubString
& rKeyName
)
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
;
365 if( pWItem
->mpMenu
&& !((Menu
*)pWItem
->mpMenu
)->IsMenuBar() )
366 pWItem
->mInfo
.fType
|= MFT_OWNERDRAW
;
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();
381 ImplDrawMenuBar( this );
385 void WinSalMenu::GetSystemMenuData( SystemMenuData
* pData
)
388 pData
->hMenu
= mhMenu
;
391 // =======================================================================
398 WinSalMenuItem::WinSalMenuItem()
400 memset( &mInfo
, 0, sizeof( MENUITEMINFOW
) );
406 WinSalMenuItem::~WinSalMenuItem()
409 ImplRemoveItemById( mpSalMenu
, mnId
);
412 // -------------------------------------------------------------------