From: <arn...@us...> - 2008-02-07 22:59:09
|
Revision: 992 http://dcplusplus.svn.sourceforge.net/dcplusplus/?rev=992&view=rev Author: arnetheduck Date: 2008-02-07 14:59:03 -0800 (Thu, 07 Feb 2008) Log Message: ----------- Fancy menus, language setting fix Modified Paths: -------------- dcplusplus/trunk/smartwin/include/smartwin/WidgetFactoryPlatformSmartWinDesktop.h dcplusplus/trunk/smartwin/include/smartwin/widgets/WidgetMenuExtended.h dcplusplus/trunk/win32/AppearancePage.cpp dcplusplus/trunk/win32/DCPlusPlus.rc dcplusplus/trunk/win32/MainWindow.cpp dcplusplus/trunk/win32/MainWindow.h dcplusplus/trunk/win32/PropPage.cpp dcplusplus/trunk/win32/PropPage.h dcplusplus/trunk/win32/resource.h Modified: dcplusplus/trunk/smartwin/include/smartwin/WidgetFactoryPlatformSmartWinDesktop.h =================================================================== --- dcplusplus/trunk/smartwin/include/smartwin/WidgetFactoryPlatformSmartWinDesktop.h 2008-02-06 09:37:07 UTC (rev 991) +++ dcplusplus/trunk/smartwin/include/smartwin/WidgetFactoryPlatformSmartWinDesktop.h 2008-02-07 22:59:03 UTC (rev 992) @@ -56,14 +56,12 @@ /// RichEditBox object type. typedef typename WidgetRichTextBox::ObjectType WidgetRichTextBoxPtr; -#ifdef PORT_ME /// ExtendedMenu class type. - typedef SmartWin::WidgetMenuExtended< EventHandlerClass > WidgetMenuExtended; + typedef SmartWin::WidgetMenuExtended WidgetMenuExtended; /// ExtendedMenu object type. typedef typename WidgetMenuExtended::ObjectType WidgetMenuExtendedPtr; -#endif - + /// ChooseFont class and object type. typedef SmartWin::WidgetChooseFont< SmartWin::Widget > WidgetChooseFont; @@ -115,17 +113,15 @@ return WidgetCreator< WidgetRichTextBox >::attach( this, id ); } -#ifdef PORT_ME /// Creates an Extended Menu /** The returned object is of type std::tr1::shared_ptr< WidgetMenuExtended >, but * you should use the typedef WidgetMenuExtendedPtr and not <br> * the shared_ptr itself since this may change in future releases. */ - WidgetMenuExtendedPtr createExtendedMenu() + WidgetMenuExtendedPtr createExtendedMenu(const typename WidgetMenuExtended::Seed& cs = WidgetMenuExtended::Seed()) { - return WidgetCreator< WidgetMenuExtended >::create( this ); + return WidgetCreator< WidgetMenuExtended >::create( this, cs ); } -#endif /// Creates a Tool Bar and returns a pointer to it. /** DON'T delete the returned pointer!!! Modified: dcplusplus/trunk/smartwin/include/smartwin/widgets/WidgetMenuExtended.h =================================================================== --- dcplusplus/trunk/smartwin/include/smartwin/widgets/WidgetMenuExtended.h 2008-02-06 09:37:07 UTC (rev 991) +++ dcplusplus/trunk/smartwin/include/smartwin/widgets/WidgetMenuExtended.h 2008-02-07 22:59:03 UTC (rev 992) @@ -5,14 +5,14 @@ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met : - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the SmartWin++ nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the SmartWin++ nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -29,10 +29,10 @@ #ifndef WidgetMenuExtended_h #define WidgetMenuExtended_h +#include "../Application.h" #include "../BasicTypes.h" #include "../CanvasClasses.h" -#include <boost/cast.hpp> -#ifdef PORT_ME + namespace SmartWin { // begin namespace SmartWin @@ -67,9 +67,9 @@ /// \ingroup GlobalStuff // MenuItemDataPtr type, contains rendering data for e.g. WidgetMenuExtended /** Helps easily create color values and so on for a WidgetMenuExtended item! <br> - * Each Menu Item can have different colors and so on, use this smart pointer to set - * those values! - */ +* Each Menu Item can have different colors and so on, use this smart pointer to set +* those values! +*/ typedef std::tr1::shared_ptr< MenuItemData > MenuItemDataPtr; namespace private_ @@ -101,10 +101,10 @@ // Wrapper Constructor ItemDataWrapper( HMENU owner, int itemIndex, MenuItemDataPtr itemData, bool isTitleItem = false ) - : menu( owner ) - , index( itemIndex ) - , isMenuTitleItem( isTitleItem ) - , data( itemData ) + : menu( owner ) + , index( itemIndex ) + , isMenuTitleItem( isTitleItem ) + , data( itemData ) {} ~ItemDataWrapper() @@ -114,8 +114,8 @@ /// Struct for coloring different areas of WidgetMenuExtended /** Contains the different color settings of the WidgetMenuExtended <br> - * Default values to constructor makes menu look roughly like MSVC++7.1 menus - */ +* Default values to constructor makes menu look roughly like MSVC++7.1 menus +*/ struct MenuColorInfo { /// Menu color @@ -141,9 +141,9 @@ /// Constructs MenuColorInfo objects /** If all the default arguments are used it will construct an object making - * menus look roughly like they do in MSVC++ 7.1 <br> - * Pass your own arguments to construct other color effects - */ + * menus look roughly like they do in MSVC++ 7.1 <br> + * Pass your own arguments to construct other color effects + */ MenuColorInfo( COLORREF menuColor = ColorUtilities::darkenColor( ::GetSysColor( COLOR_WINDOW ), 0.02 ), COLORREF stripColor = ColorUtilities::darkenColor( ::GetSysColor( COLOR_3DFACE ), 0.02 ), COLORREF titleColor = ColorUtilities::darkenColor( ::GetSysColor( COLOR_MENUBAR ), 0.1 ), @@ -161,905 +161,228 @@ {} }; -// /////////////////////////////////////////////////////////////////////////////// -// Default Menu Renderer, create your own by copying this and modyfying -// if you want your menus to be different! -// Basic process is to add Event Handlers for onDrawItem and onMeasureItem -// /////////////////////////////////////////////////////////////////////////////// -template< class MenuType > -class DefaultMenuRenderer -{ -public: - /// Rendering settting settings - static const int borderGap = 3; /// Gap between the border and item - static const int pointerGap = 5; /// Gap between item text and sub - menu pointer - static const int textIconGap = 8; /// Gap between text and icon - static const int textBorderGap = 4; /// Gap between text and rectangel border - static const int separatorHeight = 8; /// Defines default height for rectangle containing separator - static const int minSysMenuItemWidth = 130; /// Minimum width for system menu items - - static Point defaultImageSize; /// Default image size, used when no image is available - - // Default callback for WM_MEASUREITEM message processing - static bool measureItem( EventHandlerClass * parent, typename MenuType::ObjectType menu, MEASUREITEMSTRUCT * measureInfo ) - { - if ( measureInfo->CtlType != ODT_MENU ) // if not intended for us - return false; - - // get data wrapper - private_::ItemDataWrapper * wrapper = reinterpret_cast< private_::ItemDataWrapper * >( measureInfo->itemData ); - - xAssert( wrapper != 0, _T( "Unsupported menu item type in measureItem()" ) ); - - // this will contain item size - UINT & itemWidth = measureInfo->itemWidth; - UINT & itemHeight = measureInfo->itemHeight; - - // init struct for item info - MENUITEMINFO info; - memset( & info, 0, sizeof( MENUITEMINFO ) ); - info.cbSize = sizeof( MENUITEMINFO ); - - // set up flags - info.fMask = MIIM_FTYPE | MIIM_DATA | MIIM_CHECKMARKS | MIIM_STRING; - - // get menu handle - HMENU handle = reinterpret_cast< HMENU >( menu->handle() ); - - // try to get item info - if ( ::GetMenuItemInfo( handle, wrapper->index, TRUE, & info ) == FALSE ) - throw xCeption ( _T( "Couldn't get item info in measureItem()" ) ); - - // check if item is owner drawn - xAssert( ( info.fType & MFT_OWNERDRAW ) != 0, _T( "Not owner - drawn item encountered in measureItem()" ) ); - - // check if separator - if ( info.fType & MFT_SEPARATOR ) - { - itemWidth = 60; - itemHeight = separatorHeight; - return true; - } - - // are we processing menu bar ? - bool isMenuBar = ::GetMenu( parent->handle() ) == handle; - - // compute text width and height by simulating write to dc - // get its DC - HDC hdc = ::GetDC( menu->getParent()->handle() ); - - // get the item data - MenuItemDataPtr data = wrapper->data; - xAssert( data != 0, _T( "Couldn't find item data in measureItem()" ) ); - - // get item text - const int length = info.cch + 1; - std::vector< TCHAR > buffer ( length ); - int count = ::GetMenuString( handle, wrapper->index, & buffer[0], length, MF_BYPOSITION ); - SmartUtil::tstring itemText ( buffer.begin(), buffer.begin() + count ); - - // now get text extents - SIZE textSize; - memset( & textSize, 0, sizeof( SIZE ) ); - - HGDIOBJ oldFont = ::SelectObject( hdc, data->Font->getHandle() ); - ::GetTextExtentPoint32( hdc, itemText.c_str(), ( int ) itemText.size(), & textSize ); - ::SelectObject( hdc, oldFont ); - - // release DC - ::ReleaseDC( menu->handle(), hdc ); - - // adjust item size - itemWidth = textSize.cx + borderGap; - itemHeight = textSize.cy + borderGap; - - // check to see if item has an image - Point imageSize = data->Image->getBitmapSize(); - - // this will contain checked/unchecked image size - Point checkImageSize; - - // if item has check/unchecked state images, then get their sizes - if ( ( info.hbmpChecked != NULL ) && ( info.hbmpUnchecked != NULL ) ) - checkImageSize = ( info.fState & MFS_CHECKED ) == 0 - ? Bitmap::getBitmapSize( info.hbmpUnchecked ) - : Bitmap::getBitmapSize( info.hbmpChecked ); - - // take the maximum of all available images or set default image size - imageSize.x = (std::max)( imageSize.x, checkImageSize.x ); - imageSize.y = (std::max)( imageSize.y, checkImageSize.y ); - - bool hasImage = ( imageSize.x != 0 ) && ( imageSize.y != 0 ); - - // set default image size if no image is available - if ( !hasImage ) - { - imageSize.x = (std::max)( defaultImageSize.x, (std::max)( imageSize.x, checkImageSize.x ) ); - imageSize.y = (std::max)( defaultImageSize.y, (std::max)( imageSize.y, checkImageSize.y ) ); - } - - // adjust default image size - defaultImageSize.x = (std::max)( defaultImageSize.x, imageSize.x ); - defaultImageSize.y = (std::max)( defaultImageSize.y, imageSize.y ); - - // adjust width - if ( !isMenuBar || // if not menu bar item - ( isMenuBar && hasImage ) ) // or menu bar item with image - { - // adjust item width - itemWidth += imageSize.x + textIconGap + pointerGap; - - // adjust item height - itemHeight = (std::max)( itemHeight, ( UINT ) imageSize.y + borderGap ); - } - - // adjust width for system menu items - if ( menu->isSysMenu ) - itemWidth = (std::max)( ( UINT ) minSysMenuItemWidth, itemWidth ); - - // adjust width for sidebar - if ( menu->drawSidebar ) - { - // get title text extents - SIZE textSize; - memset( & textSize, 0, sizeof( SIZE ) ); - - ::GetTextExtentPoint32( hdc, menu->itsTitle.c_str(), ( int ) menu->itsTitle.size(), & textSize ); - - itemWidth += textSize.cy; - } - - // adjust item height - itemHeight = (std::max)( itemHeight, ( UINT )::GetSystemMetrics( SM_CYMENU ) ); - return true; - } - - // Default callback for WM_DRAWITEM message processing - static bool drawItem( EventHandlerClass * parent, typename MenuType::ObjectType menu, int controlID, const DRAWITEMSTRUCT & drawInfo ) - { - if ( ( controlID != 0 ) || ( drawInfo.CtlType != ODT_MENU ) ) // if not intended for us - return false; - - // setup colors - MenuColorInfo colorInfo = menu->itsColorInfo; - COLORREF colorMenuBar = colorInfo.colorMenuBar; - COLORREF colorTitle = colorInfo.colorTitle; - COLORREF colorMenuDraw = colorInfo.colorMenu; // color for drawing menu - COLORREF colorFillHighlighted = ColorUtilities::lightenColor( colorInfo.colorHighlight, 0.7 ); - - // get menu handle - HMENU handle = reinterpret_cast< HMENU >( menu->handle() ); - - // if processing menu bar - const bool isMenuBar = ::GetMenu( parent->handle() ) == handle; - - // change menu draw color for menubars - if ( isMenuBar ) - colorMenuDraw = colorMenuBar; - - // get item data wrapper - private_::ItemDataWrapper * wrapper = reinterpret_cast< private_::ItemDataWrapper * >( drawInfo.itemData ); - xAssert( wrapper != 0, _T( "Unsupported menu item in drawItem()" ) ) - - // init struct for menu item info - MENUITEMINFO info; - memset( & info, 0, sizeof( MENUITEMINFO ) ); - info.cbSize = sizeof( MENUITEMINFO ); - - // set flags - info.fMask = MIIM_CHECKMARKS | MIIM_FTYPE | MIIM_DATA | MIIM_STATE | MIIM_STRING; - - if ( ::GetMenuItemInfo( handle, wrapper->index, TRUE, & info ) == FALSE ) - throw xCeption ( _T( "Couldn't get menu item info in drawItem()" ) ); - - // check if item is owner drawn - xAssert( ( info.fType & MFT_OWNERDRAW ) != 0, _T( "Not a owner - drawn item in drawItem()" ) ) - - // get item data - MenuItemDataPtr data ( wrapper->data ); - xAssert( data != 0, _T( "Couldn't find item data in drawItem()" ) ) - - // get state info - bool isGrayed = ( drawInfo.itemState & ODS_GRAYED ) == ODS_GRAYED; - bool isChecked = ( drawInfo.itemState & ODS_CHECKED ) == ODS_CHECKED; - bool isDisabled = ( drawInfo.itemState & ODS_DISABLED ) == ODS_DISABLED; - bool isSelected = ( drawInfo.itemState & ODS_SELECTED ) == ODS_SELECTED; - bool isHighlighted = ( drawInfo.itemState & ODS_HOTLIGHT ) == ODS_HOTLIGHT; - - // this will contain item image - HBITMAP image = NULL; - - // if checked/unchecked image is avaiable - if ( ( info.hbmpChecked != NULL ) && ( info.hbmpUnchecked != NULL ) ) - image = isChecked ? info.hbmpChecked : info.hbmpUnchecked; - else // get normal image - image = data->Image->getBitmap(); - - // this will contain image size - Point imageSize = data->Image->getBitmapSize(); - - if ( ( imageSize.x == 0 ) && ( imageSize.y == 0 ) ) // no image - imageSize = defaultImageSize; // set default image size - - // compute strip width - int stripWidth = imageSize.x + textIconGap; - - // prepare item rectangle - Rectangle itemRectangle( drawInfo.rcItem.left, drawInfo.rcItem.top, // position - drawInfo.rcItem.right - drawInfo.rcItem.left, // width - drawInfo.rcItem.bottom - drawInfo.rcItem.top ); // height - - // setup buffered canvas - BufferedCanvas< FreeCanvas > canvas( menu->handle(), drawInfo.hDC ); - - // this will conain adjusted sidebar width - int sidebarWidth = 0; - - // this will contain logical information - // about title font - LOGFONT lf; - memset( & lf, 0, sizeof( LOGFONT ) ); - - // this will contain adjusted(rotated) title font for sidebar - HFONT titleFont = NULL; - - // get title font info and adjust item rectangle - if ( menu->drawSidebar ) - { - // get title font - std::tr1::shared_ptr< Font > font = menu->itsTitleFont; - - // get logical info for title font - ::GetObject( font->getHandle(), sizeof( LOGFONT ), & lf ); - - // 90 degree rotation and bold - lf.lfOrientation = lf.lfEscapement = 900; - - // create title font from logical info - titleFont = ::CreateFontIndirect( & lf ); - - // get title text size - SIZE textSize; - memset( & textSize, 0, sizeof( SIZE ) ); - - HGDIOBJ oldFont = ::SelectObject( canvas.getDc(), titleFont ); - ::GetTextExtentPoint32( canvas.getDc(), menu->itsTitle.c_str(), ( int ) menu->itsTitle.size(), & textSize ); - ::SelectObject( canvas.getDc(), oldFont ); - - // set sidebar width to text height - sidebarWidth = textSize.cy; - - // adjust item rectangle and item background - itemRectangle.pos.x += sidebarWidth; - itemRectangle.size.x -= sidebarWidth; - } - - // draw sidebar with menu title - if ( ( drawInfo.itemAction & ODA_DRAWENTIRE ) && ( menu->drawSidebar ) && !menu->itsTitle.empty() ) - { - // select title font and color - HGDIOBJ oldFont = ::SelectObject ( canvas.getDc(), titleFont ); - COLORREF oldColor = canvas.setTextColor( colorInfo.colorTitleText ); - - // set background mode to transparent - bool oldMode = canvas.setBkMode( true ); - - // get rect for sidebar - RECT rect; - ::GetClipBox( drawInfo.hDC, & rect ); - //rect.left -= borderGap; - - // set title rectangle - Rectangle textRectangle( 0, 0, sidebarWidth, rect.bottom - rect.top ); - - // draw background - Brush brush( canvas, colorInfo.colorTitle ); - canvas.fillRectangle( textRectangle, brush ); - - // draw title - textRectangle.pos.y += 10; - canvas.drawText( menu->itsTitle, textRectangle, DT_BOTTOM | DT_SINGLELINE ); - - // clear - canvas.setTextColor( oldColor ); - canvas.setBkMode( oldMode ); - - // set back old font - ::SelectObject( canvas.getDc(), oldFont ); - } - - // destroy title font - ::DeleteObject( titleFont ); - - // set item background - if ( wrapper->isMenuTitleItem ) // for title - { - Brush brush( canvas, colorTitle ); - canvas.fillRectangle( itemRectangle, brush ); - - // draw raised border - RECT rc( itemRectangle ); - ::DrawEdge( canvas.getDc(), & rc, EDGE_RAISED, BF_RECT ); - } - else // for normal items - { - Brush brush( canvas, colorMenuDraw ); - canvas.fillRectangle( itemRectangle, brush ); - } - - if ( isMenuBar && isSelected ) // draw selected menu bar item - { - // TODO: Simulate shadow - - // select pen for drawing broder - // and brush for filling item - COLORREF colorBorder = 0; - Pen pen ( canvas, colorBorder ); - Brush brush ( canvas, ColorUtilities::lightenColor( colorMenuBar, 0.5 ) ); - - canvas.rectangle( itemRectangle ); - } // end if - else if ( ( isSelected || isHighlighted ) && !isDisabled ) // draw selected or highlighted menu item (if not inactive) - { - // select pen for drawing broder - // and brush for filling item - Pen pen ( canvas, colorInfo.colorHighlight ); - Brush brush ( canvas, colorFillHighlighted ); - - canvas.rectangle( itemRectangle ); - } // end if - else if ( !isMenuBar && !wrapper->isMenuTitleItem ) // draw strip bar for menu items (except menu title item) - { - // create rectangle for strip bar - Rectangle stripRectangle ( itemRectangle ); - stripRectangle.size.x = stripWidth; - - // draw strip bar - Brush brush( canvas, colorInfo.colorStrip ); - canvas.fillRectangle( stripRectangle, brush ); - } // end if - - if ( !isMenuBar && info.fType & MFT_SEPARATOR ) // draw separator - { - // set up separator rectangle - Rectangle rectangle ( itemRectangle ); - - // center in the item rectangle - rectangle.pos.x += stripWidth + textIconGap; - rectangle.pos.y += rectangle.size.y / 2 - 1; - - // select color - Pen pen( canvas, ::GetSysColor( COLOR_GRAYTEXT ) ); - - // draw separator - canvas.moveTo( rectangle.pos.x, rectangle.pos.y ); - canvas.lineTo( rectangle.size.x, rectangle.pos.y ); - } // end if - else // not a seperator, then draw item text and icon - { - // get item text - const int length = info.cch + 1; - std::vector< TCHAR > buffer( length ); - int count = ::GetMenuString( handle, wrapper->index, & buffer[0], length, MF_BYPOSITION ); - SmartUtil::tstring itemText( buffer.begin(), buffer.begin() + count ); - - // index will contain accelerator position - size_t index = itemText.find_last_of( _T( '\t' ) ); - - // split item text to draw accelerator correctly - SmartUtil::tstring text = itemText.substr( 0, index ); - - // get accelerator - SmartUtil::tstring accelerator; - - if ( index != itemText.npos ) - accelerator = itemText.substr( index + 1 ); - - // set mode to transparent - bool oldMode = canvas.setBkMode( true ); - - // select item text color - canvas.setTextColor( isGrayed ? ::GetSysColor( COLOR_GRAYTEXT ) : wrapper->isMenuTitleItem ? colorInfo.colorTitleText : data->TextColor ); - - // Select item font if available - FontPtr font( data->Font ); - - HGDIOBJ oldFont = ::SelectObject( canvas.getDc(), font->getHandle() ); - - if ( !isMenuBar && !wrapper->isMenuTitleItem && !itemText.empty() ) // if menu item - { - // compute text rectangle - Rectangle textRectangle( itemRectangle ); - - // adjust rectangle - textRectangle.pos.x += stripWidth + textIconGap; - textRectangle.size.x -= stripWidth + textIconGap + borderGap; - - canvas.drawText( text, textRectangle, DT_LEFT | DT_VCENTER | DT_SINGLELINE ); - - // draw accelerator - if ( !accelerator.empty() ) - canvas.drawText( accelerator, textRectangle, DT_RIGHT | DT_VCENTER | DT_SINGLELINE ); - } // end if - else if ( !itemText.empty() ) // draw menu bar item text - { - Rectangle textRectangle( itemRectangle ); - - if ( image != NULL ) // has icon - textRectangle.pos.x += textIconGap; - - canvas.drawText( text, textRectangle, DT_CENTER | DT_VCENTER | DT_SINGLELINE ); - } // end if - - // set back old font - ::SelectObject( canvas.getDc(), oldFont ); - - // reset old mode - canvas.setBkMode( oldMode ); - - // set up image rectangle - Rectangle imageRectangle( itemRectangle.pos, imageSize ); - - // adjust icon rectangle - imageRectangle.pos.x += ( stripWidth - imageSize.x ) / 2; - imageRectangle.pos.y += ( itemRectangle.size.y - imageSize.y ) / 2; - - if ( image == NULL ) // drawing item without icon - { - if ( isChecked ) // needs checkmark - { - // draw the check mark or radio bullet - // prepare background - Brush brush( canvas, colorInfo.colorStrip ); - canvas.fillRectangle( imageRectangle, brush ); - - // create memory DC and set bitmap on it - HDC memoryDC = ::CreateCompatibleDC( canvas.getDc() ); - HGDIOBJ old = ::SelectObject( memoryDC, ::CreateCompatibleBitmap( canvas.getDc(), imageSize.x, imageSize.y ) ); - - // draw into memory - RECT rc( Rectangle( 0, 0, imageSize.x, imageSize.y ) ); - ::DrawFrameControl( memoryDC, & rc, DFC_MENU, ( info.fType & MFT_RADIOCHECK ) == 0 ? DFCS_MENUCHECK : DFCS_MENUBULLET ); - - const int adjustment = 2; // adjustment for mark to be in the center - - // bit - blast into out canvas - ::BitBlt( canvas.getDc(), imageRectangle.pos.x + adjustment, imageRectangle.pos.y, imageSize.x, imageSize.y, memoryDC, 0, 0, SRCAND ); - - // delete memory dc - ::DeleteObject( ::SelectObject( memoryDC, old ) ); - ::DeleteDC( memoryDC ); - } - } - else // drawing item with icon - { - if ( isSelected && !isDisabled ) // if selected and active, then imitate icon shadow - { - // adjust icon position for later drawing - imageRectangle.pos.x -= 1; - imageRectangle.pos.y -= 1; - - // setup brush for shadow emulation - Brush brush( canvas, ColorUtilities::darkenColor( colorInfo.colorStrip, 0.7 ) ); - - // draw the icon shadow - Rectangle shadowRectangle( imageRectangle ); - shadowRectangle.pos.x += 2; - shadowRectangle.pos.y += 2; - canvas.drawBitmap( image, shadowRectangle, colorInfo.colorImageBackground, true ); - } - - // draw normal icon - canvas.drawBitmap( image, imageRectangle, colorInfo.colorImageBackground, isGrayed ); - } - - if ( isChecked ) // draw surrounding rectangle for checked items - { - /*if ( image != NULL ) // adjust for icon - iconRectangle = iconRectangle.shrink( 1.20 );*/ - - // draw the surrounding rectangle - Pen pen( canvas, colorInfo.colorHighlight ); - canvas.line( imageRectangle ); - } - } - - // blast buffer into screen - if ( ( drawInfo.itemAction & ODA_DRAWENTIRE ) && menu->drawSidebar ) // adjustment for sidebar - { - itemRectangle.pos.x -= sidebarWidth; - itemRectangle.size.x += sidebarWidth; - } - - canvas.blast( itemRectangle ); - return true; - } -}; - -// Since this is a Dispatcher ONLY for Menus it CAN'T be a "non control", therefore -// we DON'T need the partial specialization for it... -template< class EventHandlerClass, class WidgetType, class MessageMapType > -class WidgetMenuExtendedDispatcher -{ - static EventHandlerClass * getParent( Widget * parentGiven ) - { - Widget * tmpParent = parentGiven; - EventHandlerClass * ptrMainParent; - while ( true ) - { - ptrMainParent = dynamic_cast< EventHandlerClass * >( tmpParent ); - if ( ptrMainParent != 0 ) - break; - tmpParent = tmpParent->getParent(); - if ( 0 == tmpParent ) - throw xCeption( _T( "Serious error while trying to get MainWindow parent to menu, menu probably not attached to Main WidgetFactory..." ) ); - } - return ptrMainParent; - } - -public: -#ifdef PORT_ME - static HRESULT dispatch( private_::SignalContent & params ) - { - EventHandlerClass * ptrMainParent = getParent( params.This->getParent() ); - typename WidgetType::menuExtendedVoidFunctionTakingUInt func = - reinterpret_cast< typename WidgetType::menuExtendedVoidFunctionTakingUInt >( params.Function ); - - StayAliveDeleter< WidgetType > deleter; - std::tr1::shared_ptr< WidgetType > ptrThis( boost::polymorphic_cast< WidgetType * >( params.This ), deleter ); - - func - ( dynamic_cast< EventHandlerClass * >( 0 ) - , ptrThis - , LOWORD( params.Msg.WParam ) - ); - return 1; - } - - static HRESULT dispatchThis( private_::SignalContent & params ) - { - EventHandlerClass * ptrMainParent = getParent( params.This->getParent() ); - typename WidgetType::itsVoidMenuExtendedFunctionTakingUInt func = - reinterpret_cast< typename WidgetType::itsVoidMenuExtendedFunctionTakingUInt >( params.FunctionThis ); - - StayAliveDeleter< WidgetType > deleter; - std::tr1::shared_ptr< WidgetType > ptrThis( boost::polymorphic_cast< WidgetType * >( params.This ), deleter ); - - ( ( * boost::polymorphic_cast< EventHandlerClass * >( ptrMainParent ) ).*func ) - ( ptrThis - , LOWORD( params.Msg.WParam ) - ); - return 1; - } - - static HRESULT dispatchDrawItem( private_::SignalContent & params ) - { - // get callback - typename WidgetType::boolDrawItemFunction func = - reinterpret_cast< typename WidgetType::boolDrawItemFunction >( params.Function ); - - StayAliveDeleter< WidgetType > deleter; - std::tr1::shared_ptr< WidgetType > ptrThis( boost::polymorphic_cast< WidgetType * >( params.This ), deleter ); - - // call the callback - bool handled = func - ( dynamic_cast< EventHandlerClass * >( params.This->getParent() ) - , ptrThis - , params.Msg.WParam // control id - , * reinterpret_cast< DRAWITEMSTRUCT * >( params.Msg.LParam ) - ); - return handled; - } - - static HRESULT dispatchDrawItemThis( private_::SignalContent & params ) - { - // get method pointer - typename WidgetType::itsBoolDrawItemFunction func = - reinterpret_cast< typename WidgetType::itsBoolDrawItemFunction >( params.FunctionThis ); - - StayAliveDeleter< WidgetType > deleter; - std::tr1::shared_ptr< WidgetType > ptrThis( boost::polymorphic_cast< WidgetType * >( params.This ), deleter ); - - // call method - bool handled = ( ( * boost::polymorphic_cast< EventHandlerClass * >( params.This->getParent() ) ).*func ) - ( ptrThis - , params.Msg.WParam // control id - , * reinterpret_cast< DRAWITEMSTRUCT * >( params.Msg.LParam ) - ); - return handled; - } - - static HRESULT dispatchMeasureItem( private_::SignalContent & params ) - { - // get callback - typename WidgetType::boolMeasureItemFunction func = - reinterpret_cast< typename WidgetType::boolMeasureItemFunction >( params.Function ); - - StayAliveDeleter< WidgetType > deleter; - std::tr1::shared_ptr< WidgetType > ptrThis( boost::polymorphic_cast< WidgetType * >( params.This ), deleter ); - - // call the callback - bool handled = func - ( dynamic_cast< EventHandlerClass * >( params.This->getParent() ) - , ptrThis - , reinterpret_cast< MEASUREITEMSTRUCT * >( params.Msg.LParam ) - ); - return handled; - } - - static HRESULT dispatchMeasureItemThis( private_::SignalContent & params ) - { - // get method pointer - typename WidgetType::itsBoolMeasureItemFunction func = - reinterpret_cast< typename WidgetType::itsBoolMeasureItemFunction >( params.FunctionThis ); - - StayAliveDeleter< WidgetType > deleter; - std::tr1::shared_ptr< WidgetType > ptrThis( boost::polymorphic_cast< WidgetType * >( params.This ), deleter ); - - // call method - bool handled = ( ( * boost::polymorphic_cast< EventHandlerClass * >( params.This->getParent() ) ).*func ) - ( ptrThis - , reinterpret_cast< MEASUREITEMSTRUCT * >( params.Msg.LParam ) - ); - return handled; - } - - static HRESULT dispatchPopup( private_::SignalContent & params ) - { - // get callback - typename WidgetType::voidPopupFunction func = - reinterpret_cast< typename WidgetType::voidPopupFunction >( params.Function ); - - StayAliveDeleter< WidgetType > deleter; - std::tr1::shared_ptr< WidgetType > ptrThis( boost::polymorphic_cast< WidgetType * >( params.This ), deleter ); - - // call the callback - func - ( dynamic_cast< EventHandlerClass * >( params.This->getParent() ) - , ptrThis - ); - return 0; - } - - static HRESULT dispatchPopupThis( private_::SignalContent & params ) - { - // get method pointer - typename WidgetType::itsVoidPopupFunction func = - reinterpret_cast< typename WidgetType::itsVoidPopupFunction >( params.FunctionThis ); - - StayAliveDeleter< WidgetType > deleter; - std::tr1::shared_ptr< WidgetType > ptrThis( boost::polymorphic_cast< WidgetType * >( params.This ), deleter ); - - // call method - ( ( * boost::polymorphic_cast< EventHandlerClass * >( params.This->getParent() ) ).*func ) - ( ptrThis - ); - return 0; - } -#endif -}; - -// Menu Renderer static data members initialization -template< class MenuType > -Point DefaultMenuRenderer< MenuType >::defaultImageSize = Point( 16, 16 ); - // Platform specific implementation template< class MenuType, Platform > class WidgetMenuExtendedPlatformImplementation; /// Specialized functions in menu for desktop Windows API version /** This class contains all the functions in the WidgetMenuExtended which only works - * in the Desktop Version of the OS. <br> - * Though WidgetMenuExtended class does not actually WORK on WinCE we plan to MAKE - * it work in future versions, therefore we have created the CurrentPlatform - * specialization classes for it here...!! - */ -template< class MenuType > -class WidgetMenuExtendedPlatformImplementation< MenuType, SmartWinDesktop > +* in the Desktop Version of the OS. <br> +* Though WidgetMenuExtended class does not actually WORK on WinCE we plan to MAKE +* it work in future versions, therefore we have created the CurrentPlatform +* specialization classes for it here...!! +*/ +template< typename MenuType > +class WidgetMenuExtendedPlatformImplementation< MenuType, SmartWinDesktop > { - // friends - friend class DefaultMenuRenderer< MenuType >; public: - typedef std::tr1::shared_ptr< MenuType > WidgetMenuExtendedPtr; - typedef WidgetMenuExtendedDispatcher< MenuType > Dispatcher; - /// Attaches the menu to a parent window - void attach( EventHandlerClass * mainWindow ); + struct Seed { + Seed(bool popup_) : popup(popup_) { } + Seed() : popup(false) { } + bool popup; + }; + HMENU handle() const { + return itsHandle; + } + + HWND getParent() const { + return itsParent ? itsParent->handle() : 0; + } + /// Actually creates the menu /** Creates the menu, the menu will be created initially empty! - */ - void create( bool isPopup = false ); + */ + void create(const Seed& cs); - /// Actually creates the menu - /** Copies the menu if copy is true, otherwise just hooks it - */ - void create( HMENU source, bool copy ); + /// Attaches the menu to the parent window + void attach(); /// Appends a popup to the menu /** Everything you "append" to a menu is added sequentially to the menu <br> - * This specific "append" function appends a "popup" menu which is a menu - * containing other menus. <br> - * With other words a menu which is not an "option" but rather a new "subgroup". - * <br> - * The "File" menu of most application is for instance a "popup" menu while the - * File/Print is often NOT a popup. <br> - * To append items to the popup created call one of the appendItem overloaded - * functions on the returned value of this function. <br> - * Also, although references to all menu objects must be kept ( since they're - * not collected automatically like other Widgets ) <br> - * you don't have to keep a reference to the return value of this function since - * it's being added as a reference to the children list of the "this" object. - * <br> - * A popup is basically another branch in the menu hierarchy <br> - * See the WidgetMenu project for a demonstration. - */ - WidgetMenuExtendedPtr appendPopup( const SmartUtil::tstring & text, MenuItemDataPtr itemData = MenuItemDataPtr( new MenuItemData() ) ); + * This specific "append" function appends a "popup" menu which is a menu + * containing other menus. <br> + * With other words a menu which is not an "option" but rather a new "subgroup". + * <br> + * The "File" menu of most application is for instance a "popup" menu while the + * File/Print is often NOT a popup. <br> + * To append items to the popup created call one of the appendItem overloaded + * functions on the returned value of this function. <br> + * Also, although references to all menu objects must be kept ( since they're + * not collected automatically like other Widgets ) <br> + * you don't have to keep a reference to the return value of this function since + * it's being added as a reference to the children list of the "this" object. + * <br> + * A popup is basically another branch in the menu hierarchy <br> + * See the WidgetMenu project for a demonstration. + */ + WidgetMenuExtendedPtr appendPopup( const SmartUtil::tstring & text, MenuItemDataPtr itemData = MenuItemDataPtr(new MenuItemData()) ); /// Returns the "System Menu" /** The system menu is a special menu that ( normally ) is accessed by pressing - * the "window icon" at the top left of the window. <br> - * In SmartWin++ this menu can ALSO be easily manipulated and added items to - * etc... <br> - * Also, although references to all menu objects must be kept ( since they're - * not collected automatically like other Widgets ) <br> - * you don't have to keep a reference to the return value of this function since - * it's being added as a reference to the children list <br> - * of the "this" object. <br> - * See the WidgetMenu sample project for a demonstration. - */ + * the "window icon" at the top left of the window. <br> + * In SmartWin++ this menu can ALSO be easily manipulated and added items to + * etc... <br> + * Also, although references to all menu objects must be kept ( since they're + * not collected automatically like other Widgets ) <br> + * you don't have to keep a reference to the return value of this function since + * it's being added as a reference to the children list <br> + * of the "this" object. <br> + * See the WidgetMenu sample project for a demonstration. + */ WidgetMenuExtendedPtr getSystemMenu(); -protected: - // Initializes menu with given handle - void init( HMENU handle ); + /// Rendering settting settings + static const int borderGap; /// Gap between the border and item + static const int pointerGap; /// Gap between item text and sub - menu pointer + static const int textIconGap; /// Gap between text and icon + static const int textBorderGap; /// Gap between text and rectangel border + static const int separatorHeight; /// Defines default height for rectangle containing separator + static const int minSysMenuItemWidth; /// Minimum width for system menu items + static Point defaultImageSize; /// Default image size, used when no image is available +protected: // its sub menus std::vector< WidgetMenuExtendedPtr > itsChildren; // its item data std::vector < private_::ItemDataWrapper * > itsItemData; + + HMENU itsHandle; + + Widget* itsParent; + + typedef std::map<unsigned, Widget::CallbackType> CallbackMap; + CallbackMap callbacks; + + void addCommands(Widget* widget); }; /// Extended Menu class /** \ingroup WidgetControls - * \WidgetUsageInfo - * \image html menuextended.png - * Class for creating an Extended Menu Control which then can be attached to e.g. a - * WidgetWindow. <br> - * Note for Desktop version only! <br> - * After you have created a menu you must call WidgetMenu::attach() to make it - * "attach" to the WidgetWindow you want it to belong to. <br> - * Do not be fooled, a WidgetMenuExtended is a much more advanced menu type then the - * "normal" WidgetMenu and contains support for visualizations far beyond the - * capabilities of the WidgetMenu. <br> - * If you need those truly awesome visual menu effects use this menu control instead - * of the WidgetMenu. - */ +* \WidgetUsageInfo +* \image html menuextended.png +* Class for creating an Extended Menu Control which then can be attached to e.g. a +* WidgetWindow. <br> +* Note for Desktop version only! <br> +* After you have created a menu you must call WidgetMenu::attach() to make it +* "attach" to the WidgetWindow you want it to belong to. <br> +* Do not be fooled, a WidgetMenuExtended is a much more advanced menu type then the +* "normal" WidgetMenu and contains support for visualizations far beyond the +* capabilities of the WidgetMenu. <br> +* If you need those truly awesome visual menu effects use this menu control instead +* of the WidgetMenu. +*/ class WidgetMenuExtended : - public WidgetMenuExtendedPlatformImplementation< CurrentPlatform > + public WidgetMenuExtendedPlatformImplementation< WidgetMenuExtended, CurrentPlatform >, + public boost::enable_shared_from_this< WidgetMenuExtended > { // friends - friend class DefaultMenuRenderer< WidgetMenuExtended >; - friend class WidgetMenuExtendedPlatformImplementation< CurrentPlatform >; + friend class WidgetMenuExtendedPlatformImplementation< WidgetMenuExtended, CurrentPlatform >; friend class WidgetCreator< WidgetMenuExtended >; - typedef WidgetMenuExtendedPlatformImplementation< CurrentPlatform > Implementation; - typedef SmartWin::DefaultMenuRenderer< WidgetMenuExtended > DefaultMenuRenderer; - typedef typename WidgetMenuExtendedPlatformImplementation< CurrentPlatform >::Dispatcher Dispatcher; + typedef WidgetMenuExtendedPlatformImplementation< WidgetMenuExtended, CurrentPlatform > Implementation; public: /// Type of object typedef WidgetMenuExtended ThisType; /// Object type - typedef typename WidgetMenuExtendedPlatformImplementation< CurrentPlatform >::WidgetMenuExtendedPtr ObjectType; + typedef WidgetMenuExtendedPlatformImplementation< WidgetMenuExtended, CurrentPlatform >::WidgetMenuExtendedPtr ObjectType; - /// Creational info - //TODO: empty because it is not used anywhere ... - class Seed - {}; + struct IdDispatcher + { + typedef std::tr1::function<void (unsigned)> F; - // Event Handlers signature typedefs + IdDispatcher(const F& f_) : f(f_) { } - /// \ingroup eventsSignatures - /// \typedef Typedef of a member function to the original class taking pointer to the this Widget and an unsigned int returning void - typedef void ( EventHandlerClass::* itsVoidMenuExtendedFunctionTakingUInt )( ObjectType, unsigned ); + bool operator()(const MSG& msg, LRESULT& ret) { + f(LOWORD(msg.wParam)); + return true; + } - /// \ingroup eventsSignatures - /// Typedef of a static/global function taking a pointer to the original class, a pointer to the this Widget class and an unsigned int returning void - typedef void ( * menuExtendedVoidFunctionTakingUInt )( EventHandlerClass *, ObjectType, unsigned ); + F f; + }; - /// \ingroup eventsSignatures - /// \typedef Typedef of a member function to the original class taking pointer to the this Widget and an unsigned int returning void - typedef bool ( EventHandlerClass::* itsBoolDrawItemFunction )( ObjectType, int, const DRAWITEMSTRUCT & ); + struct DrawItemDispatcher { + typedef std::tr1::function<bool (int, LPDRAWITEMSTRUCT)> F; - /// \ingroup eventsSignatures - /// Typedef of a static/global function taking a pointer to the original class, a pointer to the this Widget class and an unsigned int returning void - typedef bool ( * boolDrawItemFunction )( EventHandlerClass *, ObjectType, int, const DRAWITEMSTRUCT & ); + DrawItemDispatcher(const F& f_) : f(f_) { } - /// \ingroup eventsSignatures - /// \typedef Typedef of a member function to the original class taking pointer to the this Widget and an unsigned int returning void - typedef bool ( EventHandlerClass::* itsBoolMeasureItemFunction )( ObjectType, MEASUREITEMSTRUCT * ); + bool operator()(const MSG& msg, LRESULT& ret) { + return f(msg.wParam, reinterpret_cast<LPDRAWITEMSTRUCT>(msg.lParam)); + } - /// \ingroup eventsSignatures - /// Typedef of a static/global function taking a pointer to the original class, a pointer to the this Widget class and an unsigned int returning void - typedef bool ( * boolMeasureItemFunction )( EventHandlerClass *, ObjectType, MEASUREITEMSTRUCT * ); + F f; + }; - /// \ingroup eventsSignatures - /// \typedef Typedef of a member function to the original class taking pointer to the this Widget returning void - typedef void ( EventHandlerClass::* itsVoidPopupFunction )( ObjectType ); + struct MeasureItemDispatcher { + typedef std::tr1::function<bool (LPMEASUREITEMSTRUCT)> F; - /// \ingroup eventsSignatures - /// Typedef of a static/global function taking a pointer to the original class, a pointer to the this Widget class returning void - typedef void ( * voidPopupFunction )( EventHandlerClass *, ObjectType ); + MeasureItemDispatcher(const F& f_) : f(f_) { } - // Overriden to set default drawing - void create( bool isPopup = false ); + bool operator()(const MSG& msg, LRESULT& ret) { + return f(reinterpret_cast<LPMEASUREITEMSTRUCT>(msg.lParam)); + } - // Overriden to set default drawing - void create( HMENU source, bool copy ); + F f; + }; /// Setting event handler for Draw Item Event /** The Draw Item Event will be raised when the menu needs to draw itself, if you - * wish to truly be creative and be 100% in control you must handle this Event - * and do the actualy drawing of the Menu yourself, but for most people it will - * be enough to just manipulate the background colors etc of the MenuItemData - * given to the menu in the appendItem or to call the setColorInfo function <br> - * Note! <br> - * If this event is handled you also MUST handle the Measure Item Event!! - */ - void onDrawItem( boolDrawItemFunction eventHandler ); - void onDrawItem( itsBoolDrawItemFunction eventHandler ); + * wish to truly be creative and be 100% in control you must handle this Event + * and do the actualy drawing of the Menu yourself, but for most people it will + * be enough to just manipulate the background colors etc of the MenuItemData + * given to the menu in the appendItem or to call the setColorInfo function <br> + * Note! <br> + * If this event is handled you also MUST handle the Measure Item Event!! + */ + bool handleDrawItem(int id, LPDRAWITEMSTRUCT drawInfo); - /// Setting event handler for Draw Item Event + /// Setting event handler for Measure Item Event /** The Measure Item Event is nessecary to handle if you want to draw the menu - * yourself since it is inside this Event Handler you're telling the system how - * much space you need to actually do the drawing <br> - * Note! <br> - * If this event is handled you also MUST handle the Draw Item Event!! - */ - void onMeasureItem( boolMeasureItemFunction eventHandler ); - void onMeasureItem( itsBoolMeasureItemFunction eventHandler ); + * yourself since it is inside this Event Handler you're telling the system how + * much space you need to actually do the drawing <br> + * Note! <br> + * If this event is handled you also MUST handle the Draw Item Event!! + */ + bool handleMeasureItem(LPMEASUREITEMSTRUCT measureInfo); - /// Sets the event handler for the Popup event - void onPopup( voidPopupFunction eventHandler ); - - /// Sets the event handler for the Popup event - void onPopup( itsVoidPopupFunction eventHandler ); - /// Appends a separator item to the menu /** A menu separator is basically just "air" between menu items.< br > - * A separator cannot be "clicked" or "chosen". - */ + * A separator cannot be "clicked" or "chosen". + */ void appendSeparatorItem(); /// Appends a Menu Item /** eventHandler is the function that will receive the "click" event from the - * menu item. <br> - * Event handler's signature must be "void foo( WidgetMenuExtendedPtr, unsigned - * int )" and it must be contained as a member <br> - * of the class that is defined as the EventHandlerClass, normally either the - * WidgetWindow derived class or the class derived from WidgetMenu. <br> - * See e.g. WidgetMenu for an example. <br> - * The reason to why we have this "id" is because the same event handler can be - * defined for several menu items even in fact across menu objects, therefore - * this number should be unique across the application. - */ - void appendItem( unsigned itemID, const SmartUtil::tstring & text, MenuItemDataPtr itemData, itsVoidMenuExtendedFunctionTakingUInt eventHandler ); - void appendItem( unsigned itemID, const SmartUtil::tstring & text, MenuItemDataPtr itemData, menuExtendedVoidFunctionTakingUInt eventHandler ); + * menu item. <br> + * Event handler's signature must be "void foo( WidgetMenuExtendedPtr, unsigned + * int )" and it must be contained as a member <br> + * of the class that is defined as the Widget, normally either the + * WidgetWindow derived class or the class derived from WidgetMenu. <br> + * See e.g. WidgetMenu for an example. <br> + * The reason to why we have this "id" is because the same event handler can be + * defined for several menu items even in fact across menu objects, therefore + * this number should be unique across the application. + */ + void appendItem(unsigned int id, const SmartUtil::tstring & text, MenuItemDataPtr itemData = MenuItemDataPtr(new MenuItemData())); + void appendItem(unsigned int id, const SmartUtil::tstring & text, const IdDispatcher::F& f, MenuItemDataPtr itemData = MenuItemDataPtr(new MenuItemData())); + void appendItem(unsigned int id, const SmartUtil::tstring & text, BitmapPtr image); + void appendItem(unsigned int id, const SmartUtil::tstring & text, const IdDispatcher::F& f, BitmapPtr image); /// Removes specified item from this menu /** Call this function to actually DELETE a menu item from the menu hierarchy. - * Note that you have to specify the item position; and whenever you remove an item, - * all subsequent items change positions. To remove a range of items, remove from - * end to start. - */ + * Note that you have to specify the item position; and whenever you remove an item, + * all subsequent items change positions. To remove a range of items, remove from + * end to start. + */ void removeItem( unsigned itemIndex ); /// Remove all items from the menu /** Will also delete any submenus. - */ + */ void removeAllItems(); /// Return the number of items in the menu @@ -1067,69 +390,69 @@ /// Displays and handles a menu which can appear anywhere in the window. /** Typically called by a Right Mouse click. If both the x and the y coordinate - * is - 1 ( default ) it'll show the context menu on the position the mouse was - * at when the system last recieved a message, basically the "right" place... - * <br> - * Depending on the flags it might return the id of the menu item selected, or 0 - * if none was chosen. Flags with TPM_RETURNCMD will return the menu - item, but - * not do the menu command. - * < ul > - * < li >TPM_CENTERALIGN : Centers the shortcut menu horizontally relative to the coordinate specified by the x parameter< /li > - * < li >TPM_LEFTALIGN : Function positions the shortcut menu so that its left side is aligned with the coordinate specified by the x parameter< /li > - * < li >TPM_RIGHTALIGN : Opposite of LEFTALIGN< /li > - * < li >TPM_BOTTOMALIGN : Aligns menu bottoms to the coordinate specified by the y parameter< /li > - * < li >TPM_TOPALIGN : Opposite of BOTTOMALIGN< /li > - * < li >TPM_VCENTERALIGN : Centers vertically relative to the y parameter< /li > - * < li >TPM_NONOTIFY : Restricts the menu from sending notifications when user clicks item< /li > - * < li >TPM_RETURNCMD : returns the menu item identifier of the user's selection in the return value but DOES NOT carry out the event handler< /li > - * < li >TPM_LEFTBUTTON : Restricts users to selecting menu items with only left mouse button< /li > - * < li >TPM_RIGHTBUTTON : User can choose menu item with both mouse buttons< /li > - * < /ul > - * None of the following are used by default but can be manually chosen if you - * manually call SystemParametersInfo - * < ul > - * < li >TPM_HORNEGANIMATION : Animates the menu from right to left< /li > - * < li >TPM_HORPOSANIMATION : Animates the menu from left to right< /li > - * < li >TPM_NOANIMATION : Displays menu without animation< /li > - * < li >TPM_VERNEGANIMATION : Animates the menu from bottom to top< /li > - * < li >TPM_VERPOSANIMATION : Animates the menu from top to bottom< /li > - * < /ul > - */ - unsigned trackPopupMenu( EventHandlerClass * mainWindow, int x = - 1, int y = - 1, unsigned flags = 0 ); + * is - 1 ( default ) it'll show the context menu on the position the mouse was + * at when the system last recieved a message, basically the "right" place... + * <br> + * Depending on the flags it might return the id of the menu item selected, or 0 + * if none was chosen. Flags with TPM_RETURNCMD will return the menu - item, but + * not do the menu command. + * < ul > + * < li >TPM_CENTERALIGN : Centers the shortcut menu horizontally relative to the coordinate specified by the x parameter< /li > + * < li >TPM_LEFTALIGN : Function positions the shortcut menu so that its left side is aligned with the coordinate specified by the x parameter< /li > + * < li >TPM_RIGHTALIGN : Opposite of LEFTALIGN< /li > + * < li >TPM_BOTTOMALIGN : Aligns menu bottoms to the coordinate specified by the y parameter< /li > + * < li >TPM_TOPALIGN : Opposite of BOTTOMALIGN< /li > + * < li >TPM_VCENTERALIGN : Centers vertically relative to the y parameter< /li > + * < li >TPM_NONOTIFY : Restricts the menu from sending notifications when user clicks item< /li > + * < li >TPM_RETURNCMD : returns the menu item identifier of the user's selection in the return value but DOES NOT carry out the event handler< /li > + * < li >TPM_LEFTBUTTON : Restricts users to selecting menu items with only left mouse button< /li > + * < li >TPM_RIGHTBUTTON : User can choose menu item with both mouse buttons< /li > + * < /ul > + * None of the following are used by default but can be manually chosen if you + * manually call SystemParametersInfo + * < ul > + * < li >TPM_HORNEGANIMATION : Animates the menu from right to left< /li > + * < li >TPM_HORPOSANIMATION : Animates the menu from left to right< /li > + * < li >TPM_NOANIMATION : Displays menu without animation< /li > + * < li >TPM_VERNEGANIMATION : Animates the menu from bottom to top< /li > + * < li >TPM_VERPOSANIMATION : Animates the menu from top to bottom< /li > + * < /ul > + */ + unsigned trackPopupMenu( Widget * mainWindow, const ScreenCoordinate& sc, unsigned flags = 0 ); /// Sets menu title /** A WidgetMenuExtended can have a title, this function sets that title - */ + */ void setTitle( const SmartUtil::tstring & title, bool drawSidebar = false ); /// Sets title font /** Create a font through e.g. createFont in WidgetFactory or similar and set the - * title font to the menu title through using this function - */ + * title font to the menu title through using this function + */ void setTitleFont( FontPtr font ); /// Removes menu title /** If clearSidebar is true, sidebar is removed - */ + */ void clearTitle( bool clearSidebar = false ); /// Enables or disables menu item /** If the second argument is true the menu item will be enabled, otherwise it'll - * be disabled - */ - void enableItem( unsigned itemID, bool setEnabled ); + * be disabled + */ + void enableItem( unsigned int id, bool setEnabled ); /// Set item state to checked/unchecked /** If second parameter is true the menu item will be checked, otherwise it'll be - * unchecked - */ - void checkItem( unsigned itemID, bool setChecked, bool radioMark ); + * unchecked + */ + void checkItem( unsigned int id, bool setChecked, bool radioMark ); /// Returns true if item is checked - bool isItemEnabled( unsigned itemID ); + bool isItemEnabled( unsigned int id ); /// Returns true if item is checked - bool isItemChecked( unsigned itemID ); + bool isItemChecked( unsigned int id ); /// Returns true if menu is "system menu" (icon in top left of window) bool isSystemMenu() @@ -1138,16 +461,16 @@ } /// Returns item text - SmartUtil::tstring getItemText( unsigned itemID ); + SmartUtil::tstring getItemText( unsigned int id ); /// Sets item text - void setItemText( unsigned itemID, SmartUtil::tstring text ); + void setItemText( unsigned int id, SmartUtil::tstring text ); /// Sets color information for the menu /** The MenuColorInfo declares which colors will be used for drawing the menu ( - * items ) <br> - * Have no effect if you override the onDrawItem/onMeasureItem - */ + * items ) <br> + * Have no effect if you override the onDrawItem/onMeasureItem + */ void setColorInfo( const MenuColorInfo & info ); /// Returns menu color information @@ -1181,136 +504,67 @@ MenuColorInfo itsColorInfo; // work around for gcc - std::vector< typename WidgetMenuExtendedPlatformImplementation< EventHandlerClass, CurrentPlatform > - ::WidgetMenuExtendedPtr > & itsChildrenRef; + std::vector< WidgetMenuExtendedPlatformImplementation< WidgetMenuExtended, CurrentPlatform > ::WidgetMenuExtendedPtr > & itsChildrenRef; + // work around for gcc std::vector < private_::ItemDataWrapper * > & itsItemDataRef; private: // Returns item index in the menu item list // If no item with specified id is found, - 1 is returned - int getItemIndex( unsigned itemID ); + int getItemIndex( unsigned int id ); - // Sets event handler for specified item (to process WM_COMMAND) - void setItemCommandHandler( unsigned itemID, menuExtendedVoidFunctionTakingUInt eventHandler ); - void setItemCommandHandler( unsigned itemID, itsVoidMenuExtendedFunctionTakingUInt eventHandler ); - - // TODO: Basically we have a copy constructor which is create( HMENU, bool ) WidgetMenuExtended( const WidgetMenuExtended & ); // Never implemented intentionally }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Implementation of class /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -template< class EventHandlerClass > -void WidgetMenuExtendedPlatformImplementation< EventHandlerClass, SmartWinDesktop >::attach( EventHandlerClass * mainWindow ) -{ - // get my handle - HMENU handle = reinterpret_cast< HMENU >( this->Widget::itsHandle ); +template< typename MenuType > +const int WidgetMenuExtendedPlatformImplementation< MenuType, SmartWinDesktop >::borderGap = 3; +template< typename MenuType > +const int WidgetMenuExtendedPlatformImplementation< MenuType, SmartWinDesktop >::pointerGap = 5; +template< typename MenuType > +const int WidgetMenuExtendedPlatformImplementation< MenuType, SmartWinDesktop >::textIconGap = 8; +template< typename MenuType > +const int WidgetMenuExtendedPlatformImplementation< MenuType, SmartWinDesktop >::textBorderGap = 4; +template< typename MenuType > +const int WidgetMenuExtendedPlatformImplementation< MenuType, SmartWinDesktop >::separatorHeight = 8; +template< typename MenuType > +const int WidgetMenuExtendedPlatformImplementation< MenuType, SmartWinDesktop >::minSysMenuItemWidth = 130; +template< typename MenuType > +Point WidgetMenuExtendedPlatformImplementation< MenuType, SmartWinDesktop >::defaultImageSize = Point( 16, 16 ); - // set menu - if ( ::SetMenu( mainWindow->handle(), handle ) == FALSE ) - throw xCeption( _T( "Couldn't attach menu to given parent" ) ); +template< typename MenuType > +void WidgetMenuExtendedPlatformImplementation< MenuType, SmartWinDesktop >::attach() +{ + addCommands(itsParent); + if ( ::SetMenu( getParent(), this->itsHandle ) == FALSE ) + throw xCeption( _T( "Couldn't attach menu to the parent window" ) ); } -template< class EventHandlerClass > -void WidgetMenuExtendedPlatformImplementation< EventHandlerClass, SmartWinDesktop >::create( bool isPopup ) +template< typename MenuType > +void WidgetMenuExtendedPlatformImplementation< MenuType, SmartWinDesktop >::create(const Seed& cs) { - HMENU handle = NULL; - // Create menu - if ( isPopup ) - handle = ::CreatePopupMenu(); + if(cs.popup) + itsHandle = ::CreatePopupMenu(); else - handle = ::CreateMenu(); - - // init newly created menu - init( handle ); -} - -template< class EventHandlerClass > -void WidgetMenuExtendedPlatformImplementation< EventHandlerClass, SmartWinDesktop >::create( HMENU source, bool copy ) -{ - if ( !::IsMenu( source ) ) // if source is not a valid menu, cancel - return; - - if ( copy ) - void create(); // create empty menu - else - init( source ); // init with the source - - // get handle to this menu - HMENU handle = reinterpret_cast< HMENU >( this->Widget::itsHandle ); - - // get source item count - int itemCount = ::GetMenuItemCount( source ); - - // variables used in the loop - int index = 0; - int length = 0; - MENUITEMINFO info; - for ( index = 0; index < itemCount; ++index ) + itsHandle = ::CreateMenu(); + if ( !itsHandle ) { - // init struct for menu item info - memset( & info, 0, sizeof( MENUITEMINFO ) ); - info.cbSize = sizeof( MENUITEMINFO ); - - // set mask - info.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_STRING | MIIM_FTYPE | - MIIM_ID | MIIM_STATE | MIIM_SUBMENU; - - if ( ::GetMenuItemInfo( source, index, TRUE, & info ) == FALSE ) - throw xCeption( _T( "Couldn't get menu item info in create()" ) ); - - // set item to owner - drawn - info.fType |= MFT_OWNERDRAW; - - // create item extended info - MenuItemDataPtr data( new MenuItemData() ); - std::auto_ptr< private_::ItemDataWrapper > wrapper( new private_::ItemDataWrapper( handle, index, data ) ); - - // modify item info data - info.dwItemData = reinterpret_cast< ULONG_PTR >( wrapper.get() ); - - // set item text - length = info.cch + 1; - boost::scoped_ptr< TCHAR > tmp( new TCHAR[ length ] ); - info.dwTypeData = tmp.get(); - memset( info.dwTypeData, 0, length ); - ::GetMenuString( source, index, info.dwTypeData, length, MF_BYPOSITION ); - - // process submenus - if ( info.hSubMenu != NULL ) - { - // create popup menu - WidgetMenuExtendedPtr popup ( new WidgetMenuExtended< EventHandlerClass >( this->getParent() ) ); - popup->create( info.hSubMenu, true /* copy */ ); - - // get new handle - info.hSubMenu = reinterpret_cast< HMENU >( popup->handle() ); - - // store as child - itsChildren.push_back( popup ); - } - - // set back item info - if ( ( copy && ::InsertMenuItem( handle, index, TRUE, & info ) ) || // insert new item or - ( !copy && ::SetMenuItemInfo( handle, index, TRUE, & info ) ) ) // change existing item info - { - itsItemData.push_back( wrapper.release() ); - } - else - throw xCeption( _T( "Couldn't insert/modify item in create()" ) ); + xCeption x( _T( "CreateMenu in WidgetMenuExtended::create fizzle... [truncated message content] |