'menu'에 해당되는 글 1건

  1. MFC에서 .NET스타일의 메뉴를 사용해 보자 (5)

MFC에서 .NET스타일의 메뉴를 사용해 보자


NewMenu


The NewMenu is published on
CodeProject
. There you will find the discussion board.






This is a prerelease of NewMenu 1.13 (will be published shortly)





Released NewMenu 1.11 (Published on codeproject)
















STYLE_XPSTYLE_ICYSTYLE_ORIGINAL


Introduction


This class, CNewMenu, implements owner drawn menus derived
from the CMenu class. The coal of this class is to have menus with
the same look as the new menu from the Microsoft products. In the other hand an
easy use of a new menu class with Icons and Title support.
I was inspired from the great class BCMenu from Brent Corkum. I took some ideas
and almost every function, but reimplemented almost the whole code and expanded
it with some other nice functions. It was a hard work to change the look of the
whole menu that belongs to an application, changing border and adding shading.
Furthermore, it was tricky changing all menus under windows 2000 or system menu
under Windows XP when you are using themes. Over all, I hope it's now easy
enough for you to use this class in new applications.


This new menu works under Windows 95/98/Me and Windows NT4.0/2000/XP. When you
like to use Chinese or some other special characters, you have to compile your
project with Unicode. But keep in mind you must have installed the Unicode
libraries with the Visual studio otherwise you get a linking error.


Additional when you want that your program works on all platforms, you have to
compile it with the Visual Studio 6.0. I did not find out why the drawing don't
work fine when it is compiled with the Visual Studio 7.0 under Windows NT 4.0.
Furthermore when you do not like the flat border you can use the
STYLE_XXX_NOBORDER and then menus will have the standard menu border from the
system.


Nice Title in Menus











Oh yes, its also possible to add a title to menu. You can add a title on the
top or on the left side of a menu. You can have a gradient or a solid color as
background. With the function SetMenuTitle you can add or remove a
title from a menu. The gradient drawing works also on Windows 95.
// Set a title to the system menu 
m_SystemNewMenu.SetMenuTitle(_T("New Menu Sample"),
MFT_GRADIENT|MFT_LINE|MFT_CENTER);

New icons effects brightening, glooming and graying








Under menu style XP you have the possibility to enable or
disable the additional drawing style to icons. Disabled icons become a grayed
look and non selected icons become a gloom look. You can see the
different between those drawing styles in the sample.

How to use the CNewMenu in a project




  1. The easiest way is to replace all CDialog, CFrameWnd, CMDIFrameWnd,
    CMDIChildWnd, CMiniFrameWnd
    and CMultiDocTemplate through
    the new classes CNewDialog, CNewFrameWnd,
    CNewMDIFrameWnd, CNewMDIChildWnd, CNewMiniFrameWnd

    and CNewMultiDocTemplate
    in your project.

  2. Set in the application, derived from CWinApp, the menustyle just
    before you create the frame or a dialog window in the function InitInstance.
    // Set drawing style of all menus to XP-Mode or STYLE_ORIGINAL
    CNewMenu::SetMenuDrawMode(CNewMenu::STYLE_XP);


  3. When you have a multi document template, add the loading code for menu icons
    just after creating the template.
    CNewMultiDocTemplate* pDocTemplate; 
    pDocTemplate = new CNewMultiDocTemplate(IDR_MDINEWTYPE,
    RUNTIME_CLASS(CMDINewMenuDoc),
    // custom MDI child frame
    RUNTIME_CLASS(CChildFrame),
    RUNTIME_CLASS(CMDINewMenuView));

    AddDocTemplate(pDocTemplate);


    // Loading toolbar icons into the menu
    pDocTemplate->m_NewMenuShared.LoadToolBar(IDR_DRAWBAR);



  4. Insert at the end of OnCreate function of the MainFrame the loading code for
    the icons. For example:
    m_DefaultNewMenu.LoadToolBar(IDR_MAINFRAME);


  5. Finally don't forget to include the definition from the "NewMenu.h" in stdafx.h
    and add NewMenu.cpp to the project.


  6. Now you are ready to use the class.

How to use the CNewMenu in a dialog-Application




  1. Set in the application the menustyle before you create the dialog in the
    function InitInstance.
    // Set drawing style of all menus to XP-Mode
    CNewMenu::SetMenuDrawMode(CNewMenu::STYLE_XP);


  2. Replace all CDialog to CNewDialog in your Project.
    For example base class from CAboutDlg.


  3. For loading bitmaps in to the menu the best place is in OnInitDialog
    function after calling the base class function.
    // CDialogDlg could be your Dialog.
    BOOL CDialogDlg::OnInitDialog()
    {
    // Call the baseclass
    CNewDialog::OnInitDialog();


    // Load icons to the menu


    m_DefaultNewMenu.LoadToolBar(IDR_MAINFRAME);
    }


  4. Don't forget to include the the definition from the "NewMenu.h" in stdafx.h and
    add NewMenu.cpp to the project.



How to use the CNewMenu in a special frame window




  1. Normally you should overwrite measureitem, menuchar and
    initmenupopup. For this purpose I use the CNewFrame template
    class. So you can replace 'CYourSpecialBase' with 'CNewFrame'
    in your project.


  2. But don't change it in IMPLEMENT_DYNAMIC, IMPLEMENT_SERIAL
    or IMPLEMENT_DYNACREATE the base class to the new one.
    IMPLEMENT_DYNAMIC(CYourNewSpecialFrame, CYourSpecialBase)


  3. Don't forget to change the baseclass in BEGIN_MESSAGE_MAP.
    BEGIN_MESSAGE_MAP(CYourNewSpecialFrame, CNewFrame) 
    //{{AFX_MSG_MAP(CYourNewSpecialFrame)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()


  4. For loading bitmaps in to the menu, you can add the code in OnCreate
    function.


  5. Finally don't forget to include the the definition from the "NewMenu.h" in
    stdafx.h and add NewMenu.cpp to the project.



How to use the CNewMenu in a MDI-Application




  1. Change in the the application class in the BOOL InitInstance() function
    the CMultiDocTemplate to CNewMultiDocTemplate
    CNewMultiDocTemplate* pDocTemplate; 
    pDocTemplate = new CNewMultiDocTemplate(IDR_MDINEWTYPE,
    RUNTIME_CLASS(CMDINewMenuDoc),
    // custom MDI child frame
    RUNTIME_CLASS(CChildFrame),
    RUNTIME_CLASS(CMDINewMenuView));
    AddDocTemplate(pDocTemplate);


  2. Now insert the following code for loading additional bitmaps from a toolbar
    into the menus.
    // Loading toolbar icons into the menu 
    pDocTemplate->m_NewMenuShared.LoadToolBar(IDR_DRAWBAR);


    // Set drawing style of all menus to XP-Mode
    CNewMenu::SetMenuDrawMode(CNewMenu::STYLE_XP);


  3. Change the base class from the main frame class (CMainFrame) from
    CMDIFrameWnd
    to CNewMDIFrame in definition and
    implementation file.
      // Change the base class in the following makro
    IMPLEMENT_DYNAMIC(CMainFrame, CNewMDIFrameWnd)

    // don't forget to change here the baseclass
    BEGIN_MESSAGE_MAP(CMainFrame, CNewMDIFrameWnd)
    //{{AFX_MSG_MAP(CMainFrame)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    // DO NOT EDIT what you see in these blocks of generated code !
    ON_WM_CREATE()
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()


  4. Add at the end of int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    for loading bitmap in the default menu.
    m_DefaultNewMenu.LoadToolBar(IDR_MAINFRAME);


  5. Finally change the baseclass of the child frame from CMDIChildWnd to
    CNewMDIChildWnd. Do the same for all derived class CDialog
    to the base class of CNewDialog.


  6. Don't forget to include the the definition from the "NewMenu.h" in stdafx.h and
    add NewMenu.cpp to the project.



How to use the CNewMenu in a SDI-Application




  1. Set in the application the menustyle before you create the dialog in the
    function InitInstance.
    // Set drawing style of all menus to XP-Mode
    CNewMenu::SetMenuDrawMode(CNewMenu::STYLE_XP);


  2. Replace all CDialog to CNewDialog in your Project.


  3. Change the base class from the main frame class (CMainFrame) from
    CFrameWnd
    to CNewFrameWnd
    in definition and implementation file.

  4. Add at the end of int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    for loading bitmap in the default menu.
    m_DefaultNewMenu.LoadToolBar(IDR_MAINFRAME);


  5. Don't forget to include the the definition from the "NewMenu.h" in stdafx.h and
    add NewMenu.cpp to the project.



How to replace system menu in system dialogs


Sometimes it would be pretty to change the menu in MessageBox or in
CFileDialog too. But unfortunately a MessageBox has no base class for
owerwriting. An other problem has the file dialog, there are at least two
dialog and the CFileDialog does only subclass the child dialog of the shown
FileDialog. For those dialog, and some more, I added a special subclassing
mechanism for our work.


// Subclass dialog with system menu 
CNewMenuHelper myHelper(NEW_MENU_DIALOG_SUBCLASS|NEW_MENU_DIALOG_SYSTEM_MENU);
AfxMessageBox(_T("You must restart the application"),MB_OK);

Even thought what can I do when I do not want to have a menu border
replacing in the next shown dialog? It is very simple! Just place the
CNewMenuHelper before your call like in the following sample.


// Subclass dialog with normal border painting 
CNewMenuHelper myHelper(NEW_MENU_DEFAULT_BORDER);
AfxMessageBox(_T("You must restart the application"),MB_OK);

Color replacing of bitmaps with 16 colors


The MFC replace some colors depended of the chosen system colors. So when you
use a black line in the bitmap, the color black will be replaced with the
system color of COLOR_BTNTEXT. Following the color mapping map. By
the way, it is the same color mapping of the toolbars.


The color RGB(0x00,0x00,0x00) will be changed to COLOR_BTNTEXT       // black
The color RGB(0x80,0x80,0x80) will be changed to COLOR_BTNSHADOW // dark gray
The color RGB(0xC0,0xC0,0xC0) will be changed to COLOR_BTNFACE // bright gray
The color RGB(0xFF,0xFF,0xFF) will be changed to COLOR_BTNHIGHLIGHT // white

Adding Icons to Menus


There are several possibilities adding icons to menu. An easy way is with a
toolbar resource. But the developer studio support only 16 color for
toolbar-bitmaps. What you can do is: first define your toolbar; then replace
the saved toolbar-bitmap with a hicolor bitmap by hand. Additional you can
define every icon in a different bitmap and assign it to a menuitem. My way was
define a bitmap like in an image list, make a helper table with the resource id
of the bitmap, size of an icon and followed by the ids of the icons. The end of
the table must be marked with an id number NULL.


// Define the table
static WORD ToolId[] =
{ IDR_NEWMENU256, // Resource id of the bitmap-icons
16, 15, // Dimension of each icon


ID_FILE_NEW, // First icon's ID
ID_FILE_OPEN, // Second icon's ID
ID_FILE_SAVE, // and so on...

NULL}; // Marker for end of table

//Load the definition into menu with transparent color
m_DefaultNewMenu.LoadToolBar(ToolId,RGB(192,192,192));

How to add an icon to a submenu


It is very simple to add or change the title of a submenu entry when you know
the menu text. The helper function ModifyODMenu can be used.


// set the icon IDB_MORE_C to the submenu "More A"
m_NewMenuShared.ModifyODMenu(0,_T("More A"),IDB_MORE_C);

Menu under Windows 2000


It was a strange thing to detect, that under Windows 2000, you have a window
menu with handle 0x10012, which is shared to all application. (I think under
Windows 98 is the menu 0x0090). I don't know why, but this is also a reason of
the specialty for some effects belonging to subclassing menu. First when you
have disabled menu effects, the menu windows are alternating created or showed.
That means, first showed menu is mostly the special menu, never created nor
destroyed only showed and disabled, and the second is normal created and
destroyed after closing. The third time, sometime, the special window is showed
again and then the next menu is created normal. For this reason, when you
subclass the special menu, you are responsible to restore all values before
unsubclassing it. Be careful when you changing some flags or styles, because
the other applications like having the standard menu. You can also receive
bluescreen when you forget to unsubclass or when changing painting areas
belongs to that menu. Really ugly!!! Second, when you enabled menu effects
every shown menu is created new from scratch. For this reason it doesn't matter
when you don't restore all flags or styles!


But almost I forgot to explain how I got the goal to subclass all menus. Well,
for first, you can't subclass the system menu class #32768 from an application;
also I was looking for other possibility. I decide to create a windows hook for
all windows messages and catching all messages for creating a window. After
checking for the window class, when I found the menu class, I subclassed it.
But, how I can subclass the special menu, which is never created? I found, that
one of the first messages, which were sending to that menu, was 0x01E2 and one
of the latest WM_SHOWWINDOW. So I caught these messages for sub-
and unsubclassing the special menu. Only between those two messages you have
access to the special window!! Why? I don't know, but be careful.


How to paint the border


Well after I got it to subclass the menu window I can draw the border by
myself by processing WM_NCPAINT message. But how is the shade
made? Just before the menu is showed on the screen I save the menu region in a
bitmap, this is a reason why it does not work when the underground has been
changed, and combine it with a shade drawing. An other way would be using
layered windows, but this will not work on all systems like windows 95/98.


System menu under Windows XP


I thought owner drawing a menu is all time easy. But on Windows XP, with
themes enabled, it is a curious thing. Especially the main frame when the
system menu were displayed. Instead of owner drawing, the menu items were drawn
by the frame. The frame had painted the windows button of the width of the menu
at the place of the menu item :-) instead of drawing it. Strange! So I found a
workaround. I increased the menu items identifier before showing the menu and
restored after closing it. So, it works under Windows 2000 and XP.


Important info for debugging the new menu under Windows 2000


You should never stop debugging when you are in middle painting of the menus,
because the special menu wouldn't be restored nor unsubclassed. Furthermore
there were a lot of strange effects. It is not forbidden, but be careful and
have a lot time for rebooting the system when it doesn't work correctly after
stopping the debugger.


History


23 January 2003 - Version 1.13




  • SetMenuText fixed.

  • Menubar color with theme fixed.

  • Added some helper for borderhandling of non CNewMenu

10 November 2002 - Version 1.11




  • Border drawing with menu animation under Win 98 corrected.

  • Border drawing / repainting when submenu closed fixed.

  • New menu style ICY.

  • Helperclasses for changing system menu for CommonDialog.

30 July 2002 - Version 1.10




  • Sharing Icons between menu for saving GDI-Resources.

  • New effects for drawing icons under STYLE_XPxx.

  • Recoloring of menu icons by changing system colors.

  • Drawing of the scroll button by extreme big menus a little bit better.

  • Mixing different icon sizes in a menu is now supported but they are not zoomed
    to the same size.

Known bugs




  • Menu border with shade is not updated when underground has been changed.

  • Menu border is drawn in a wrong size after changing the menu border style under
    windows settings. But restart the application and then it will work again fine.

  • The High Contrast Mode is not supported with all right colors.






<출처>
http://www.podetti.com/NewMenu/