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>
34 #include <vcl/salgdi.hxx>
36 #include <vcl/menu.hxx>
37 #include <vcl/sysdata.hxx>
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
48 // =======================================================================
50 sal_Bool
SalData::IsKnownMenuHandle( HMENU hMenu
)
52 if( mhMenuSet
.find( hMenu
) == mhMenuSet
.end() )
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
;
69 pSalMenu
->mhMenu
= ::CreateMenu();
71 pSalMenu
->mhMenu
= ::CreatePopupMenu();
73 if( pSalMenu
->mhMenu
)
74 GetSalData()->mhMenuSet
.insert( pSalMenu
->mhMenu
);
79 void WinSalInstance::DestroyMenu( SalMenu
* pSalMenu
)
85 SalMenuItem
* WinSalInstance::CreateMenuItem( const SalItemParams
* pItemData
)
90 WinSalMenuItem
*pSalMenuItem
= new WinSalMenuItem();
91 memset( &pSalMenuItem
->mInfo
, 0, sizeof( MENUITEMINFOW
) );
92 pSalMenuItem
->mInfo
.cbSize
= sizeof( MENUITEMINFOW
);
94 if( pItemData
->eType
== MENUITEM_SEPARATOR
)
97 pSalMenuItem
->mInfo
.fMask
= MIIM_TYPE
;
98 pSalMenuItem
->mInfo
.fType
= MFT_SEPARATOR
;
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
;
114 if( pItemData
->pMenu
&& !pItemData
->pMenu
->IsMenuBar() )
115 pSalMenuItem
->mInfo
.fType
|= MFT_OWNERDRAW
;
116 pSalMenuItem
->mInfo
.fState
= MFS_ENABLED
;
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
128 void WinSalInstance::DestroyMenuItem( SalMenuItem
* 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 // =======================================================================
156 WinSalMenu::WinSalMenu()
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
179 // Nevertheless, the native menues are always created
180 // and the application will properly react to all native
186 void WinSalMenu::SetFrame( const SalFrame
*pFrame
)
189 mhWnd
= static_cast<const WinSalFrame
*>(pFrame
)->mhWnd
;
194 void WinSalMenu::InsertItem( SalMenuItem
* pSalMenuItem
, unsigned nPos
)
198 WinSalMenuItem
* pWItem
= static_cast<WinSalMenuItem
*>(pSalMenuItem
);
199 if( nPos
== MENU_APPEND
)
201 nPos
= ::GetMenuItemCount( mhMenu
);
206 if(!::InsertMenuItemW( mhMenu
, nPos
, TRUE
, &pWItem
->mInfo
))
207 myerr
= GetLastError();
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
;
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();
230 pSalMenuItem
= (WinSalMenuItem
*) mi
.dwItemData
;
232 if( !::RemoveMenu( mhMenu
, nPos
, MF_BYPOSITION
) )
233 myerr
= GetLastError();
237 pSalMenuItem
->mpSalMenu
= NULL
;
238 ImplDrawMenuBar( this );
243 void ImplRemoveItemById( WinSalMenu
*pSalMenu
, unsigned nItemId
)
248 WinSalMenuItem
*pSalMenuItem
= NULL
;
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();
257 pSalMenuItem
= (WinSalMenuItem
*) mi
.dwItemData
;
259 if( !::RemoveMenu( pSalMenu
->mhMenu
, nItemId
, MF_BYCOMMAND
) )
260 myerr
= GetLastError();
264 pSalMenuItem
->mpSalMenu
= NULL
;
265 ImplDrawMenuBar( pSalMenu
);
269 void WinSalMenu::SetSubMenu( SalMenuItem
* pSalMenuItem
, SalMenu
* pSubMenu
, unsigned nPos
)
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
;
283 pWMenuItem
->mInfo
.hSubMenu
= NULL
;
286 pWMenuItem
->mInfo
.hSubMenu
= pWSubMenu
->mhMenu
;
287 pWSubMenu
->mpParentMenu
= this;
290 if(!::SetMenuItemInfoW( mhMenu
, nPos
, TRUE
, &pWMenuItem
->mInfo
) )
291 myerr
= GetLastError();
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
)
313 WinSalMenuItem
* pWItem
= static_cast<WinSalMenuItem
*>(pSalMenuItem
);
315 pWItem
->maBitmap
= rImage
.GetBitmapEx().GetBitmap();
317 pWItem
->maBitmap
= Bitmap();
321 void WinSalMenu::SetItemText( unsigned nPos
, SalMenuItem
* pSalMenuItem
, const XubString
& rText
)
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
;
332 if( pWItem
->mpMenu
&& !((Menu
*) pWItem
->mpMenu
)->IsMenuBar() )
333 pWItem
->mInfo
.fType
|= MFT_OWNERDRAW
;
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();
349 ImplDrawMenuBar( this );
353 void WinSalMenu::SetAccelerator( unsigned nPos
, SalMenuItem
* pSalMenuItem
, const KeyCode
&, const XubString
& rKeyName
)
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
;
362 if( pWItem
->mpMenu
&& !((Menu
*)pWItem
->mpMenu
)->IsMenuBar() )
363 pWItem
->mInfo
.fType
|= MFT_OWNERDRAW
;
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();
378 ImplDrawMenuBar( this );
382 void WinSalMenu::GetSystemMenuData( SystemMenuData
* pData
)
385 pData
->hMenu
= mhMenu
;
388 // =======================================================================
395 WinSalMenuItem::WinSalMenuItem()
397 memset( &mInfo
, 0, sizeof( MENUITEMINFOW
) );
403 WinSalMenuItem::~WinSalMenuItem()
406 ImplRemoveItemById( mpSalMenu
, mnId
);
409 // -------------------------------------------------------------------