Как сделать панель инструментов в MDI приложении в избранное

Тема в разделе "WASM.BEGINNERS", создана пользователем MikhailKM, 6 окт 2010.

  1. MikhailKM

    MikhailKM New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2010
    Сообщения:
    18
    Нужно написать программу MDI с панелью инструментов.
    Делаю так: при создании главного окна приложения (hwndFrame) в обработчике WM_CREATE создается панель инструментов вызовом
    hWndToolbar = CreateWindowEx( 0, TOOLBARCLASSNAME...
    На панель инструментов ставится переключатель вызовом
    hwndButton = CreateWindow( TEXT("button"), TEXT("check 1"), WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX...
    затем создается окно-клиент
    hwndClient = CreateWindow( TEXT("MDICLIENT")...

    Код (Text):
    1. case WM_CREATE: {
    2.     InitCommonControls();
    3.  
    4.     HWND hWndToolbar = CreateWindowEx( 0, TOOLBARCLASSNAME, 0, CCS_TOP | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPSIBLINGS, 0, 0, 20, 20, hwndFrame, 0, GetModuleHandle( 0 ), 0 );
    5.     if ( 0 == hWndToolbar ) LAST_ERROR_HANDLER;
    6.  
    7.     HWND hwndButton = CreateWindow( TEXT("button"), TEXT("check 1"), WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 0, 0, 50, 20, hwndFrame, reinterpret_cast<HMENU>( 2 ), GetModuleHandle( 0 ), 0 );
    8.     if ( 0 == hwndButton ) LAST_ERROR_HANDLER;
    9.  
    10.     CLIENTCREATESTRUCT clientcreate;
    11.     clientcreate.hWindowMenu = GetSubMenu( GetMenu( hwndFrame ), INIT_MENU_POS );
    12.     clientcreate.idFirstChild = IDM_FIRSTCHILD;
    13.  
    14.     hwndClient = CreateWindow( TEXT("MDICLIENT"), 0, WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, 0, 0, 0, 0, hwndFrame, reinterpret_cast<HMENU>( 1 ), GetModuleHandle( 0 ), &clientcreate );
    15.     if ( 0 == hwndClient ) LAST_ERROR_HANDLER;
    16.  
    17.     return 0; }
    Где-то есть ошибка, где не понимаю.
    Авточекбокс в приложении виден.
    Панель инструментов не видна.
    Однако панель инструментов есть, так как загораживает верхнюю часть клиентской области, например, не получается щелкнуть по заголовку окна если он расположен прямо под меню, щелчок происходит не по заголовку а по панели инструментов.
    Сама клиентская область про панель инструментов не знает, и при упорядочивании окон, например, каскадом помещает их под панелью инструментов.

    Полость код приложения ниже.
    Exe-файл приложен.

    Объясните, пожалуйста, как сделать правильно.
    Панель инструментов должна быть видна и клиентское окно не должно с ней перекрываться.




    Файл с++:
    Код (Text):
    1. #pragma warning( push, 4 )
    2.  
    3. #pragma comment( lib, "Comctl32.lib" )
    4.  
    5. #include <windows.h>
    6. #include <Commctrl.h>
    7. #include <TChar.h>
    8.  
    9. #include "res.h"
    10.  
    11.  
    12. #define LAST_ERROR_HANDLER { if ( GetLastError() ) __debugbreak(); }
    13.  
    14.  
    15. #define FRAME_CLASS_NAME TEXT( "FRAME_CLASS_NAME" )
    16. #define CHILD_CLASS_NAME TEXT( "CHILD_CLASS_NAME" )
    17.  
    18.  
    19. HWND hwndFrame = 0, hwndClient = 0;
    20.  
    21.  
    22.  
    23. BOOL CALLBACK CloseEnumProc( HWND hwnd, LPARAM /*lParam*/ ) {
    24.     if ( GetWindow( hwnd, GW_OWNER ) ) return TRUE;
    25.     SendMessage( GetParent( hwnd ), WM_MDIDESTROY, reinterpret_cast<WPARAM>( hwnd ), 0 );
    26.     return TRUE;
    27. }
    28.  
    29.  
    30. LRESULT CALLBACK ChildWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    31.     return DefMDIChildProc( hwnd, uMsg, wParam, lParam );
    32. }
    33.  
    34.  
    35. LRESULT CALLBACK FrameWndProc( HWND hwndFrame, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    36.  
    37.     switch ( uMsg ) {
    38.  
    39.     case WM_CREATE: {
    40.         InitCommonControls();
    41.  
    42.         HWND hWndToolbar = CreateWindowEx( 0, TOOLBARCLASSNAME, 0, CCS_TOP | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPSIBLINGS, 0, 0, 20, 20, hwndFrame, 0, GetModuleHandle( 0 ), 0 );
    43.         if ( 0 == hWndToolbar ) LAST_ERROR_HANDLER;
    44.  
    45.         HWND hwndButton = CreateWindow( TEXT("button"), TEXT("check 1"), WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 0, 0, 50, 20, hwndFrame, reinterpret_cast<HMENU>( 2 ), GetModuleHandle( 0 ), 0 );
    46.         if ( 0 == hwndButton ) LAST_ERROR_HANDLER;
    47.  
    48.         CLIENTCREATESTRUCT clientcreate;
    49.         clientcreate.hWindowMenu = GetSubMenu( GetMenu( hwndFrame ), INIT_MENU_POS );
    50.         clientcreate.idFirstChild = IDM_FIRSTCHILD;
    51.  
    52.         hwndClient = CreateWindow( TEXT("MDICLIENT"), 0, WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, 0, 0, 0, 0, hwndFrame, reinterpret_cast<HMENU>( 1 ), GetModuleHandle( 0 ), &clientcreate );
    53.         if ( 0 == hwndClient ) LAST_ERROR_HANDLER;
    54.  
    55.         return 0; }
    56.  
    57.     case WM_COMMAND :
    58.         switch ( wParam ) {
    59.         case IDM_NEW : {
    60.  
    61.             MDICREATESTRUCT mdicreate;
    62.             mdicreate.szClass    = CHILD_CLASS_NAME;
    63.             mdicreate.szTitle    = TEXT( "NoTitle" );
    64.             mdicreate.hOwner    = GetModuleHandle( 0 );
    65.             mdicreate.x            = CW_USEDEFAULT;
    66.             mdicreate.y            = CW_USEDEFAULT;
    67.             mdicreate.cx        = CW_USEDEFAULT;
    68.             mdicreate.cy        = CW_USEDEFAULT;
    69.             mdicreate.style        = WS_VSCROLL;
    70.             mdicreate.lParam    = 0;
    71.  
    72.             HWND hwndChild = reinterpret_cast<HWND>( SendMessage( hwndClient, WM_MDICREATE, 0, reinterpret_cast<LPARAM>( &mdicreate ) ) );
    73.             if ( 0 == hwndChild )  __debugbreak();  
    74.  
    75.             return 0; }
    76.         case IDM_CLOSE : {
    77.             HWND hwndChild = reinterpret_cast<HWND>( SendMessage( hwndClient, WM_MDIGETACTIVE, 0, 0 ) );
    78.             if ( 0 == hwndChild ) return 0;
    79.             if ( SendMessage( hwndChild, WM_QUERYENDSESSION, 0, 0 ) )
    80.                 SendMessage( hwndClient, WM_MDIDESTROY, reinterpret_cast<WPARAM>( hwndChild ), 0 );
    81.             return 0; }
    82.         case IDM_EXIT :
    83.             SendMessage( hwndFrame, WM_CLOSE, 0, 0 );
    84.             return 0;
    85.         case IDM_TILE :
    86.             SendMessage( hwndClient, WM_MDITILE, 0, 0 );
    87.             return 0;
    88.         case IDM_CASCADE :
    89.             SendMessage( hwndClient, WM_MDICASCADE, 0, 0 );
    90.             return 0;
    91.         case IDM_ARRANGE :
    92.             SendMessage( hwndClient, WM_MDIICONARRANGE, 0, 0 );
    93.             return 0;
    94.         case IDM_CLOSEALL : {
    95.             EnumChildWindows( hwndClient, &CloseEnumProc, 0 );
    96.             return 0; }
    97.         default : { // Pass to active child...
    98.             HWND hwndChild = reinterpret_cast<HWND>( SendMessage( hwndClient, WM_MDIGETACTIVE, 0, 0 ) );
    99.             if ( IsWindow( hwndChild ) )
    100.                 SendMessage( hwndChild, WM_COMMAND, wParam, lParam );
    101.             break; } // ...and then to DefFrameProc
    102.         }
    103.         break;
    104.  
    105.     case WM_QUERYENDSESSION :
    106.     case WM_CLOSE :
    107.         SendMessage( hwndFrame, WM_COMMAND, IDM_CLOSEALL, 0 );
    108.         if ( 0 != GetWindow( hwndClient, GW_CHILD ) ) return 0;
    109.         break;
    110.     case WM_DESTROY :
    111.         PostQuitMessage( 0 );
    112.         return 0;
    113.     }
    114.  
    115.     return DefFrameProc( hwndFrame, hwndClient, uMsg, wParam, lParam );
    116. }
    117.  
    118.  
    119. int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow ) {
    120.  
    121.     WNDCLASSEX wndclass;
    122.  
    123.     wndclass.cbSize            = sizeof( wndclass );
    124.     wndclass.style            = CS_HREDRAW | CS_VREDRAW;
    125.     wndclass.lpfnWndProc    = FrameWndProc;
    126.     wndclass.cbClsExtra        = 0;
    127.     wndclass.cbWndExtra        = 0;
    128.     wndclass.hInstance        = hInstance;
    129.     wndclass.hIcon            = 0;
    130.     wndclass.hCursor        = LoadCursor( 0, IDC_ARROW );
    131.     wndclass.hbrBackground    = reinterpret_cast<HBRUSH>( COLOR_APPWORKSPACE + 1 );
    132.     wndclass.lpszMenuName    = TEXT( "MdiMenu" );
    133.     wndclass.lpszClassName    = FRAME_CLASS_NAME;
    134.     wndclass.hIconSm        = 0;
    135.  
    136.     if ( 0 == RegisterClassEx( &wndclass ) ) LAST_ERROR_HANDLER;
    137.  
    138.     wndclass.cbSize            = sizeof( wndclass );
    139.     wndclass.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    140.     wndclass.lpfnWndProc    = ChildWndProc;
    141.     wndclass.cbClsExtra        = 0;
    142.     wndclass.cbWndExtra        = 0;
    143.     wndclass.hInstance        = hInstance;
    144.     wndclass.hIcon            = 0;
    145.     wndclass.hCursor        = LoadCursor( 0, IDC_ARROW );
    146.     wndclass.hbrBackground    = static_cast<HBRUSH>( GetStockObject( WHITE_BRUSH ) );
    147.     wndclass.lpszMenuName    = 0;
    148.     wndclass.lpszClassName    = CHILD_CLASS_NAME;
    149.     wndclass.hIconSm        = 0;
    150.  
    151.     if ( 0 == RegisterClassEx( &wndclass ) ) LAST_ERROR_HANDLER;
    152.  
    153.     hwndFrame = CreateWindow( FRAME_CLASS_NAME, TEXT("Caption"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle( 0 ), 0 );
    154.     if ( 0 == hwndFrame ) LAST_ERROR_HANDLER;
    155.  
    156.     ShowWindow( hwndFrame, nCmdShow );
    157.     UpdateWindow( hwndFrame );
    158.  
    159.     MSG msg;
    160.     for (;;) {
    161.         BOOL bRet = GetMessage( &msg, 0, 0, 0 );
    162.         if ( bRet == 0 ) break;
    163.         if ( bRet == -1 ) LAST_ERROR_HANDLER;
    164.  
    165.         TranslateMessage( &msg );
    166.         DispatchMessage( &msg );
    167.     }
    168.  
    169.     return 0;
    170. }
    Заголовочный файл res.h:
    Код (Text):
    1. #define INIT_MENU_POS        1
    2.  
    3.  
    4. #define IDM_NEW                10
    5. #define IDM_CLOSE            12
    6. #define IDM_EXIT            13
    7.  
    8. #define IDM_TILE            30
    9. #define IDM_CASCADE            31
    10. #define IDM_ARRANGE            32
    11. #define IDM_CLOSEALL        33
    12.  
    13.  
    14. #define IDM_FIRSTCHILD        100
    Файл ресурсов res.rc:
    Код (Text):
    1. #include <windows.h>
    2. #include "res.h"
    3.  
    4. MdiMenu MENU
    5. {
    6.     POPUP "&File"
    7.     {
    8.         MENUITEM "&New",                   IDM_NEW
    9.         MENUITEM "&Close",                 IDM_CLOSE
    10.         MENUITEM SEPARATOR
    11.         MENUITEM "E&xit",                  IDM_EXIT
    12.     }
    13.     POPUP "&Window"
    14.     {
    15.         MENUITEM "&Cascade",               IDM_CASCADE
    16.         MENUITEM "&Tile",                  IDM_TILE
    17.         MENUITEM "Arrange &Icons",         IDM_ARRANGE
    18.         MENUITEM "Close &All",             IDM_CLOSEALL
    19.     }
    20. }
     
  2. MikhailKM

    MikhailKM New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2010
    Сообщения:
    18
  3. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
  4. MikhailKM

    MikhailKM New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2010
    Сообщения:
    18
    Это я видел.
    Если из программы убрать создание клиентского окна
    hwndClient = CreateWindow( TEXT("MDICLIENT")...
    то панель инструментов видна видна, на ней есть переключатель, все замечательно.
    Не получается чтобы в программе была одновременно панель инструментов и было окно-клиент mdi.