MDI 子窗口创建失败
Posted
技术标签:
【中文标题】MDI 子窗口创建失败【英文标题】:MDI child window creation failing 【发布时间】:2014-12-03 17:08:20 【问题描述】:我有一个 MDI 应用程序,子窗口有 2 个不同的类。我的问题是如果第一个已经在屏幕上,我不能创建第二个的实例,但我可以用另一种方式来做;如果在 WndProc 中的 case ID_OPEN_NEW 上,我将类名更改为 g_szChildClassName2,然后在 MDIChildWndProc2 中取消注释 case WM_LBUTTONDOWN 的内容以创建 g_szChildClassName 的子窗口,那么这两个窗口将毫无问题地创建。
没有错误信息,它只是说操作成功完成。我想这与工具栏或 GDI+ 的绘画有关。
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow)
HWND hWnd;
MSG msg;
WNDCLASSEXW wc;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
g_instance = hInstance;
// Initialize GDI+.
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
wc.lpszClassName = g_szClassName;
wc.hIconSm = NULL;
if(!RegisterClassEx(&wc))
MessageBox(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
if(!SetUpMDIChildWindowClass(hInstance))
return 0;
if(!SetUpMDIChildWindowClass2(hInstance))
return 0;
hWnd = CreateWindowEx(
0,
g_szClassName,
L"Interactive music",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 480, 320,
NULL, NULL, hInstance, NULL);
if(hWnd == NULL)
MessageBox(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0) > 0)
if (!TranslateMDISysAccel(g_hMDIClient, &msg))
TranslateMessage(&msg);
DispatchMessage(&msg);
return msg.wParam;
GdiplusShutdown(gdiplusToken);
return msg.wParam;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
switch(message)
case WM_CREATE:
CLIENTCREATESTRUCT ccs;
ccs.idFirstChild = ID_MDI_FIRSTCHILD;
g_hMDIClient = CreateWindowEx(WS_EX_CLIENTEDGE, L"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)&ccs);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
case ID_OPEN_NEW:
CreateNewMDIChild(g_hMDIClient, g_szChildClassName);
break;
default:
if(LOWORD(wParam) >= ID_MDI_FIRSTCHILD)
DefFrameProc(hWnd, g_hMDIClient, WM_COMMAND, wParam, lParam);
else
HWND hChild = (HWND)SendMessage(g_hMDIClient, WM_MDIGETACTIVE,0,0);
if(hChild)
SendMessage(hChild, WM_COMMAND, wParam, lParam);
break;
default:
return DefFrameProc(hWnd, g_hMDIClient, message, wParam, lParam);
return 0;
LRESULT CALLBACK MDIChildWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
switch(msg)
case WM_CREATE:
g_hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
hwnd, (HMENU)IDC_MAIN_TOOL, GetModuleHandle(NULL), NULL);
if(g_hToolbar == NULL)
MessageBox(hwnd, L"Could not create tool bar.", L"Error", MB_OK | MB_ICONERROR);
SendMessage(g_hToolbar, TB_SETMAXTEXTROWS, 0, 0);
SendMessage(g_hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
HIMAGELIST hImageList = ImageList_Create(22,22, ILC_COLORDDB, 4, 0);
int what0 = ImageList_Add(hImageList, LoadBitmap(g_instance, MAKEINTRESOURCEW(IDB_BITMAP2)), NULL);
int what1 = ImageList_Add(hImageList, LoadBitmap(g_instance, MAKEINTRESOURCEW(IDB_BITMAP3)), NULL);
int what2 = ImageList_Add(hImageList, LoadBitmap(g_instance, MAKEINTRESOURCEW(IDB_BITMAP1)), NULL);
int what3 = ImageList_Add(hImageList, LoadBitmap(g_instance, MAKEINTRESOURCEW(IDB_BITMAP4)), NULL);
SendMessage(g_hToolbar, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)hImageList);
TBBUTTON tbb[4] =
what0, ID_NEW_STEP, TBSTATE_ENABLED, BTNS_AUTOSIZE, 0, 0, (INT_PTR)L"CreateStep",
what1, ID_DELETE_STEP, TBSTATE_ENABLED, BTNS_AUTOSIZE, 0, 0, (INT_PTR)L"DeleteStep",
what2, ID_NEW_SEGMENT, TBSTATE_ENABLED, BTNS_AUTOSIZE, 0, 0, (INT_PTR)L"CreateSegment",
what3, ID_DELETE_SEGMENT, TBSTATE_ENABLED, BTNS_AUTOSIZE, 0, 0, (INT_PTR)L"DeleteSegment",
;
SendMessage(g_hToolbar, TB_ADDBUTTONS, 4, (LPARAM)&tbb);
SendMessage(g_hToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(22, 22));
SendMessage(g_hToolbar, TB_AUTOSIZE, 0, 0);
ShowWindow(g_hToolbar, SW_SHOW);
g_MDIChildHwnd = hwnd;
m_nHScrollPos = 0;
SetUpMDIChildClientScrollbar();
break;
case WM_PAINT:
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd, &ps);
OnPaint(hdc);
EndPaint(hwnd, &ps);
break;
case WM_LBUTTONDBLCLK:
std::vector<CStep*>::iterator it = g_steps.begin();
while(it!=g_steps.end())
CStep& step = **it;
std::vector<CSegment*>::iterator its = step.m_segments.begin();
while(its != step.m_segments.end())
CSegment& seg = **its;
if(seg.m_bActive)
//create new window
CreateNewMDIChild(hwnd, g_szChildClassName2);
break;
its++;
it++;
break;
break;
case WM_SIZE:
SetUpMDIChildClientScrollbar();
default:
return DefMDIChildProc(hwnd, msg, wParam, lParam);
return 0;
LRESULT CALLBACK MDIChildWndProc2(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
switch(msg)
case WM_LBUTTONDOWN:
//CreateNewMDIChild(g_hMDIClient, g_szChildClassName);
default:
return DefMDIChildProc(hwnd, msg, wParam, lParam);
return 0;
bool SetUpMDIChildWindowClass(HINSTANCE hInstance)
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = MDIChildWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);//(HBRUSH)(COLOR_3DFACE+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szChildClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
MessageBox(0, L"Could Not Register Child Window", L"Oh Oh...",
MB_ICONEXCLAMATION | MB_OK);
return false;
else
return true;
bool SetUpMDIChildWindowClass2(HINSTANCE hInstance)
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MDIChildWndProc2;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;//LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);//(HBRUSH)(COLOR_3DFACE+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szChildClassName2;
wc.hIconSm = NULL;//LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
MessageBox(0, L"Could Not Register Child Window", L"Oh Oh...",
MB_ICONEXCLAMATION | MB_OK);
return false;
else
return true;
HWND CreateNewMDIChild(HWND hMDIClient, const wchar_t* childClassName)
MDICREATESTRUCT mcs;
HWND hChild;
mcs.szTitle = L"untitled";
mcs.szClass = childClassName;
mcs.hOwner = GetModuleHandle(NULL);
mcs.x = mcs.cx = CW_USEDEFAULT;
mcs.y = mcs.cy = CW_USEDEFAULT;
mcs.style = WS_HSCROLL;
hChild = (HWND)SendMessage(hMDIClient, WM_MDICREATE, 0, (LONG)&mcs);
DWORD dw = GetLastError();
if(!hChild)
wchar_t buffer[256];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,dw,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),buffer,256,0);
MessageBox(hMDIClient,buffer,L"Error",MB_OK|MB_ICONERROR);
return hChild;
【问题讨论】:
【参考方案1】:原来我使用了错误的句柄,我在应该使用 g_hMDIClient 时使用了 hwnd
【讨论】:
以上是关于MDI 子窗口创建失败的主要内容,如果未能解决你的问题,请参考以下文章