Нужно написать программу 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): case WM_CREATE: { InitCommonControls(); 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 ); if ( 0 == hWndToolbar ) LAST_ERROR_HANDLER; 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 ); if ( 0 == hwndButton ) LAST_ERROR_HANDLER; CLIENTCREATESTRUCT clientcreate; clientcreate.hWindowMenu = GetSubMenu( GetMenu( hwndFrame ), INIT_MENU_POS ); clientcreate.idFirstChild = IDM_FIRSTCHILD; hwndClient = CreateWindow( TEXT("MDICLIENT"), 0, WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, 0, 0, 0, 0, hwndFrame, reinterpret_cast<HMENU>( 1 ), GetModuleHandle( 0 ), &clientcreate ); if ( 0 == hwndClient ) LAST_ERROR_HANDLER; return 0; } Где-то есть ошибка, где не понимаю. Авточекбокс в приложении виден. Панель инструментов не видна. Однако панель инструментов есть, так как загораживает верхнюю часть клиентской области, например, не получается щелкнуть по заголовку окна если он расположен прямо под меню, щелчок происходит не по заголовку а по панели инструментов. Сама клиентская область про панель инструментов не знает, и при упорядочивании окон, например, каскадом помещает их под панелью инструментов. Полость код приложения ниже. Exe-файл приложен. Объясните, пожалуйста, как сделать правильно. Панель инструментов должна быть видна и клиентское окно не должно с ней перекрываться. Файл с++: Код (Text): #pragma warning( push, 4 ) #pragma comment( lib, "Comctl32.lib" ) #include <windows.h> #include <Commctrl.h> #include <TChar.h> #include "res.h" #define LAST_ERROR_HANDLER { if ( GetLastError() ) __debugbreak(); } #define FRAME_CLASS_NAME TEXT( "FRAME_CLASS_NAME" ) #define CHILD_CLASS_NAME TEXT( "CHILD_CLASS_NAME" ) HWND hwndFrame = 0, hwndClient = 0; BOOL CALLBACK CloseEnumProc( HWND hwnd, LPARAM /*lParam*/ ) { if ( GetWindow( hwnd, GW_OWNER ) ) return TRUE; SendMessage( GetParent( hwnd ), WM_MDIDESTROY, reinterpret_cast<WPARAM>( hwnd ), 0 ); return TRUE; } LRESULT CALLBACK ChildWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { return DefMDIChildProc( hwnd, uMsg, wParam, lParam ); } LRESULT CALLBACK FrameWndProc( HWND hwndFrame, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch ( uMsg ) { case WM_CREATE: { InitCommonControls(); 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 ); if ( 0 == hWndToolbar ) LAST_ERROR_HANDLER; 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 ); if ( 0 == hwndButton ) LAST_ERROR_HANDLER; CLIENTCREATESTRUCT clientcreate; clientcreate.hWindowMenu = GetSubMenu( GetMenu( hwndFrame ), INIT_MENU_POS ); clientcreate.idFirstChild = IDM_FIRSTCHILD; hwndClient = CreateWindow( TEXT("MDICLIENT"), 0, WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, 0, 0, 0, 0, hwndFrame, reinterpret_cast<HMENU>( 1 ), GetModuleHandle( 0 ), &clientcreate ); if ( 0 == hwndClient ) LAST_ERROR_HANDLER; return 0; } case WM_COMMAND : switch ( wParam ) { case IDM_NEW : { MDICREATESTRUCT mdicreate; mdicreate.szClass = CHILD_CLASS_NAME; mdicreate.szTitle = TEXT( "NoTitle" ); mdicreate.hOwner = GetModuleHandle( 0 ); mdicreate.x = CW_USEDEFAULT; mdicreate.y = CW_USEDEFAULT; mdicreate.cx = CW_USEDEFAULT; mdicreate.cy = CW_USEDEFAULT; mdicreate.style = WS_VSCROLL; mdicreate.lParam = 0; HWND hwndChild = reinterpret_cast<HWND>( SendMessage( hwndClient, WM_MDICREATE, 0, reinterpret_cast<LPARAM>( &mdicreate ) ) ); if ( 0 == hwndChild ) __debugbreak(); return 0; } case IDM_CLOSE : { HWND hwndChild = reinterpret_cast<HWND>( SendMessage( hwndClient, WM_MDIGETACTIVE, 0, 0 ) ); if ( 0 == hwndChild ) return 0; if ( SendMessage( hwndChild, WM_QUERYENDSESSION, 0, 0 ) ) SendMessage( hwndClient, WM_MDIDESTROY, reinterpret_cast<WPARAM>( hwndChild ), 0 ); return 0; } case IDM_EXIT : SendMessage( hwndFrame, WM_CLOSE, 0, 0 ); return 0; case IDM_TILE : SendMessage( hwndClient, WM_MDITILE, 0, 0 ); return 0; case IDM_CASCADE : SendMessage( hwndClient, WM_MDICASCADE, 0, 0 ); return 0; case IDM_ARRANGE : SendMessage( hwndClient, WM_MDIICONARRANGE, 0, 0 ); return 0; case IDM_CLOSEALL : { EnumChildWindows( hwndClient, &CloseEnumProc, 0 ); return 0; } default : { // Pass to active child... HWND hwndChild = reinterpret_cast<HWND>( SendMessage( hwndClient, WM_MDIGETACTIVE, 0, 0 ) ); if ( IsWindow( hwndChild ) ) SendMessage( hwndChild, WM_COMMAND, wParam, lParam ); break; } // ...and then to DefFrameProc } break; case WM_QUERYENDSESSION : case WM_CLOSE : SendMessage( hwndFrame, WM_COMMAND, IDM_CLOSEALL, 0 ); if ( 0 != GetWindow( hwndClient, GW_CHILD ) ) return 0; break; case WM_DESTROY : PostQuitMessage( 0 ); return 0; } return DefFrameProc( hwndFrame, hwndClient, uMsg, wParam, lParam ); } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow ) { WNDCLASSEX wndclass; wndclass.cbSize = sizeof( wndclass ); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = FrameWndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = 0; wndclass.hCursor = LoadCursor( 0, IDC_ARROW ); wndclass.hbrBackground = reinterpret_cast<HBRUSH>( COLOR_APPWORKSPACE + 1 ); wndclass.lpszMenuName = TEXT( "MdiMenu" ); wndclass.lpszClassName = FRAME_CLASS_NAME; wndclass.hIconSm = 0; if ( 0 == RegisterClassEx( &wndclass ) ) LAST_ERROR_HANDLER; wndclass.cbSize = sizeof( wndclass ); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wndclass.lpfnWndProc = ChildWndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = 0; wndclass.hCursor = LoadCursor( 0, IDC_ARROW ); wndclass.hbrBackground = static_cast<HBRUSH>( GetStockObject( WHITE_BRUSH ) ); wndclass.lpszMenuName = 0; wndclass.lpszClassName = CHILD_CLASS_NAME; wndclass.hIconSm = 0; if ( 0 == RegisterClassEx( &wndclass ) ) LAST_ERROR_HANDLER; hwndFrame = CreateWindow( FRAME_CLASS_NAME, TEXT("Caption"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle( 0 ), 0 ); if ( 0 == hwndFrame ) LAST_ERROR_HANDLER; ShowWindow( hwndFrame, nCmdShow ); UpdateWindow( hwndFrame ); MSG msg; for (;;) { BOOL bRet = GetMessage( &msg, 0, 0, 0 ); if ( bRet == 0 ) break; if ( bRet == -1 ) LAST_ERROR_HANDLER; TranslateMessage( &msg ); DispatchMessage( &msg ); } return 0; } Заголовочный файл res.h: Код (Text): #define INIT_MENU_POS 1 #define IDM_NEW 10 #define IDM_CLOSE 12 #define IDM_EXIT 13 #define IDM_TILE 30 #define IDM_CASCADE 31 #define IDM_ARRANGE 32 #define IDM_CLOSEALL 33 #define IDM_FIRSTCHILD 100 Файл ресурсов res.rc: Код (Text): #include <windows.h> #include "res.h" MdiMenu MENU { POPUP "&File" { MENUITEM "&New", IDM_NEW MENUITEM "&Close", IDM_CLOSE MENUITEM SEPARATOR MENUITEM "E&xit", IDM_EXIT } POPUP "&Window" { MENUITEM "&Cascade", IDM_CASCADE MENUITEM "&Tile", IDM_TILE MENUITEM "Arrange &Icons", IDM_ARRANGE MENUITEM "Close &All", IDM_CLOSEALL } }
Это я видел. Если из программы убрать создание клиентского окна hwndClient = CreateWindow( TEXT("MDICLIENT")... то панель инструментов видна видна, на ней есть переключатель, все замечательно. Не получается чтобы в программе была одновременно панель инструментов и было окно-клиент mdi.