Sign in to follow this  

MDI and Toolbars

This topic is 4199 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I need some help with MDI and toolbars. I've created a toolbar using:
BOOL AuxInitToolbar(HWND hParent)
{
	InitCommonControls();

	hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, "", WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
		hParent, (HMENU) IDC_MAIN_TOOLBAR, GetModuleHandle(NULL), NULL);

	if(!hToolbar)
	{
		IError::ThrowWin32("CreateWindowEx");
		return FALSE;
	}

	SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);

	TBBUTTON tbButtons[3];
	TBADDBITMAP tbBitmap;

	tbBitmap.hInst = HINST_COMMCTRL;
	tbBitmap.nID = IDB_STD_SMALL_COLOR;

	SendMessage(hToolbar, TB_ADDBITMAP, 0, (LPARAM) &tbBitmap);
	ZeroMemory(tbButtons, sizeof(tbButtons));

    tbButtons[0].iBitmap = STD_FILENEW;
    tbButtons[0].fsState = TBSTATE_ENABLED;
    tbButtons[0].fsStyle = TBSTYLE_BUTTON;
    tbButtons[0].idCommand = ID_FILE_NEW40018;

    tbButtons[1].iBitmap = STD_FILEOPEN;
    tbButtons[1].fsState = TBSTATE_ENABLED;
    tbButtons[1].fsStyle = TBSTYLE_BUTTON;
    tbButtons[1].idCommand = ID_FILE_OPEN40017;

    tbButtons[2].iBitmap = STD_FILESAVE;
    tbButtons[2].fsState = TBSTATE_ENABLED;
    tbButtons[2].fsStyle = TBSTYLE_BUTTON;
    tbButtons[2].idCommand = ID_FILE_SAVE40015;

    SendMessage(hToolbar, TB_ADDBUTTONS, sizeof(tbButtons) / sizeof(TBBUTTON), (LPARAM) &tbButtons);

	return TRUE;
}

After MDI Client creation...
CLIENTCREATESTRUCT cc;

				cc.hWindowMenu = GetSubMenu(GetMenu(hWnd), 4);
				cc.idFirstChild = ID_MDI_FIRSTCHILD;

				mdiClient = CreateWindowEx(WS_EX_CLIENTEDGE, "MDICLIENT", NULL, WS_CHILD | WS_CLIPCHILDREN |
					WS_VSCROLL | WS_HSCROLL | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
					CW_USEDEFAULT, hWnd, (HMENU) IDC_MAIN_MDI, GetModuleHandle(NULL), (LPVOID) &cc);

				if(!mdiClient)
					IError::ThrowWin32("CreateWindowEx");

				AuxInitToolbar(hWnd);

Now, the problem is, the toolbar is erased whenever I drag an MDI client window over it. It's supposed to look like this: Can anyone help?

Share this post


Link to post
Share on other sites
yeah, you for control bars you have to layout all child windows, including the MDI client, yourself. do not let the default WM_SIZE occur for the frame window. the reason why you get what you're getting is because the MDI client and your toolbar windows are overlapping. when the frame is resized, the DefFrameProc resizes the MDI client to the full client dimensions, but doesn't resize the toolbars (or status bar). this is why your toolbar won't repaint.

take a look at the following code (though it's for status bars). note i have a function called LayoutWindows. the important part is where i resize the MDI client so that the MDI client and status bars do not overlap. your job is to make your MDI client and toolbar not overlap (just change the values). every time WM_SIZE is called, i call LayoutWindows, and then return 0. returning 0 is a must. if you call DefFrameProc the frame will resize the client again to its full dimensions.

file.cpp

#include<windows.h>
#include<commctrl.h>
#include "stdres.h"

static HINSTANCE basead;
static HWND hMDIFrame;
static HWND hMDIClient;
static HWND hMDIChild;
static HWND hStatusBar;
static int current = 0;
LRESULT CALLBACK MDIFrameWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK MDIChildWndProc(HWND, UINT, WPARAM, LPARAM);

void LayoutWindows(void)
{
if(!hMDIFrame || !hStatusBar) return;

// get client area of frame window
RECT clientRect;
GetClientRect(hMDIFrame, &clientRect);
int frame_dx = clientRect.right - clientRect.left;
int frame_dy = clientRect.bottom - clientRect.top;

// get client area of status bar
RECT statusRect;
GetClientRect(hStatusBar, &statusRect);
int status_dy = statusRect.bottom - statusRect.top;

// position the MDIClient such that it doesn't overlap with status bar
MoveWindow(hMDIClient, 0, 0, frame_dx, frame_dy - status_dy, TRUE);

// size status bar
SendMessage(hStatusBar, WM_SIZE, 0, 0);
}

int WINAPI WinMain(HINSTANCE handle, HINSTANCE, LPTSTR, int)
{
InitCommonControls();
basead = handle;

// register MDIFrame window
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)MDIFrameWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = basead;
wcex.hIcon = LoadIcon(basead, IDI_APPLICATION);
wcex.hCursor = LoadCursor(0, IDC_ARROW);
wcex.hbrBackground = 0;
wcex.lpszMenuName = "IDRES_MENU";
wcex.lpszClassName = "MDIFRAMEWINDOW";
wcex.hIconSm = 0;
RegisterClassEx(&wcex);

// register MDIChild window
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)MDIChildWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(int);
wcex.hInstance = basead;
wcex.hIcon = LoadIcon(basead, IDI_APPLICATION);
wcex.hCursor = LoadCursor(0, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcex.lpszMenuName = 0;
wcex.lpszClassName = "MDICHILDWINDOW";
wcex.hIconSm = 0;
RegisterClassEx(&wcex);

// now create MDI Frame
hMDIFrame = CreateWindow("MDIFRAMEWINDOW", "Krytos Engine Editor v1.0", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, basead, 0);
ShowWindow(hMDIFrame, SW_SHOW);
UpdateWindow(hMDIFrame);
LayoutWindows();

// message loop
MSG msg;
while(GetMessage(&msg, 0, 0, 0)) {
if(!TranslateMDISysAccel(hMDIClient, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}

LRESULT CALLBACK MDIFrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message) {
case(WM_CREATE) :
{
// create client window
CLIENTCREATESTRUCT ccs = { 0, current++ };
hMDIClient = CreateWindow("MDICLIENT", 0, WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL, 0, 0, 0, 0, hWnd, (HMENU)0xCAC, basead, (LPSTR)&ccs);
ShowWindow(hMDIClient, SW_SHOW);

// make status bar
hStatusBar = CreateWindowEx(0, STATUSCLASSNAME, 0, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hWnd, 0, basead, 0);
int x[4] = {200, 350, 450, -1};
SendMessage(hStatusBar, SB_SETPARTS, 4, (LPARAM)x);

return DefFrameProc(hWnd, hMDIClient, message, wParam, lParam);
}
case(WM_SIZE) : {
// layout windows
LayoutWindows();
return 0; // do not do default, if you do, the frame will resize the
// MDI client to fill the entire client area, and you don't
// want it to the MDI client to overlap with the status bar.
}
case(WM_COMMAND) : {
int id = LOWORD(wParam);
int event = HIWORD(wParam);
if(id == IDC_EXIT) SendMessage(hWnd, WM_CLOSE, 0, 0);
if(id == IDC_NEW) {
MDICREATESTRUCT mcs;
mcs.szTitle = "Untitled";
mcs.szClass = "MDICHILDWINDOW";
mcs.hOwner = basead;
mcs.x = mcs.cx = CW_USEDEFAULT;
mcs.y = mcs.cy = CW_USEDEFAULT;
mcs.style = WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW;
SendMessage(hMDIClient, WM_MDICREATE, 0, (LONG)(LPMDICREATESTRUCT)&mcs);
}
return DefFrameProc(hWnd, hMDIClient, message, wParam, lParam);
}
case(WM_DESTROY) : {
PostQuitMessage(0);
break;
}
default: return DefFrameProc(hWnd, hMDIClient, message, wParam, lParam);
}
return 0;
}

LRESULT CALLBACK MDIChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return DefMDIChildProc(hWnd, message, wParam, lParam);
}



stdres.h

#include<windows.h>

#define IDC_NEW 100
#define IDC_EXIT 101




stdres.rc

#include "stdres.h"

IDRES_MENU MENU
{
POPUP "&File"
{
MENUITEM "&New", IDC_NEW
MENUITEM "E&xit", IDC_EXIT
}
}

Share this post


Link to post
Share on other sites

This topic is 4199 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this