Partial MDI rewrite
Dmitry Timoshkov
dmitry at baikal.ru
Thu Jan 15 09:26:54 CST 2004
Hello all,
here is a result of my work aimed to merge MDI child creation
with common window creation code. The rewrite allows MDI children
to have WS_EX_MDICHILD style set on WM_CREATE and therefore properly
get lParam from MDICREATESTRUCT. MDICREATESTRUCT is now gets A<->W
translated (translation 16-bit windows is still missing).
Please give it a try with your favorite MDI application and report
the results you get.
The patch includes a simple test case, which passes on win9x and
win2000 SP4.
Thanks.
--
Dmitry.
-------------- next part --------------
diff -u cvs/hq/wine/dlls/user/tests/win.c wine/dlls/user/tests/win.c
--- cvs/hq/wine/dlls/user/tests/win.c 2004-01-01 15:33:52.000000000 +0800
+++ wine/dlls/user/tests/win.c 2004-01-13 18:23:42.000000000 +0800
@@ -693,34 +693,180 @@ static void test_MDI_create(HWND parent,
{
MDICREATESTRUCTA mdi_cs;
HWND mdi_child;
+ static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0};
+ static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0};
+ BOOL isWin9x = FALSE;
mdi_cs.szClass = "MDI_child_Class_1";
- mdi_cs.szTitle = "MDI child 1";
+ mdi_cs.szTitle = "MDI child";
mdi_cs.hOwner = GetModuleHandle(0);
- mdi_cs.x = 0;
- mdi_cs.y = 0;
+ mdi_cs.x = CW_USEDEFAULT;
+ mdi_cs.y = CW_USEDEFAULT;
mdi_cs.cx = CW_USEDEFAULT;
mdi_cs.cy = CW_USEDEFAULT;
- mdi_cs.style = WS_CAPTION | WS_CHILD /*| WS_VISIBLE*/;
+ mdi_cs.style = 0;
mdi_cs.lParam = (LPARAM)mdi_lParam_test_message;
mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
- assert(mdi_child);
+ ok(mdi_child != 0, "MDI child creation failed\n");
DestroyWindow(mdi_child);
- mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child 2",
- WS_CAPTION | WS_CHILD /*| WS_VISIBLE*/,
- 10, 10, CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_cs.style = 0x7fffffff; /* without WS_POPUP */
+ mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
+ ok(mdi_child != 0, "MDI child creation failed\n");
+ DestroyWindow(mdi_child);
+
+ mdi_cs.style = 0xffffffff; /* with WS_POPUP */
+ mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
+ if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
+ {
+ ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
+ DestroyWindow(mdi_child);
+ }
+ else
+ ok(mdi_child != 0, "MDI child creation failed\n");
+
+ /* test MDICREATESTRUCT A<->W mapping */
+ /* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */
+ mdi_cs.style = 0;
+ mdi_cs.szClass = (LPCSTR)classW;
+ mdi_cs.szTitle = (LPCSTR)titleW;
+ SetLastError(0xdeadbeef);
+ mdi_child = (HWND)SendMessageW(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
+ if (!mdi_child)
+ {
+ if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ isWin9x = TRUE;
+ else
+ ok(mdi_child != 0, "MDI child creation failed\n");
+ }
+ DestroyWindow(mdi_child);
+
+ mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
+ 0,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, GetModuleHandle(0),
+ (LPARAM)mdi_lParam_test_message);
+ ok(mdi_child != 0, "MDI child creation failed\n");
+ DestroyWindow(mdi_child);
+
+ mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
+ 0x7fffffff, /* without WS_POPUP */
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
mdi_client, GetModuleHandle(0),
(LPARAM)mdi_lParam_test_message);
- assert(mdi_child);
+ ok(mdi_child != 0, "MDI child creation failed\n");
+ DestroyWindow(mdi_child);
+
+ mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
+ 0xffffffff, /* with WS_POPUP */
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, GetModuleHandle(0),
+ (LPARAM)mdi_lParam_test_message);
+ if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
+ {
+ ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
+ DestroyWindow(mdi_child);
+ }
+ else
+ ok(mdi_child != 0, "MDI child creation failed\n");
+
+ /* test MDICREATESTRUCT A<->W mapping */
+ SetLastError(0xdeadbeef);
+ mdi_child = CreateMDIWindowW(classW, titleW,
+ 0,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, GetModuleHandle(0),
+ (LPARAM)mdi_lParam_test_message);
+ if (!mdi_child)
+ {
+ if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ isWin9x = TRUE;
+ else
+ ok(mdi_child != 0, "MDI child creation failed\n");
+ }
+ DestroyWindow(mdi_child);
+
+ mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
+ 0,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, 0, GetModuleHandle(0),
+ (LPVOID)mdi_lParam_test_message);
+ ok(mdi_child != 0, "MDI child creation failed\n");
+ DestroyWindow(mdi_child);
+
+ mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
+ 0x7fffffff, /* without WS_POPUP */
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, 0, GetModuleHandle(0),
+ (LPVOID)mdi_lParam_test_message);
+ ok(mdi_child != 0, "MDI child creation failed\n");
DestroyWindow(mdi_child);
- mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child 3",
- WS_CAPTION | WS_CHILD /*| WS_VISIBLE*/,
- 20, 20, CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
+ 0xffffffff, /* with WS_POPUP */
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
mdi_client, 0, GetModuleHandle(0),
(LPVOID)mdi_lParam_test_message);
- assert(mdi_child);
+ if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
+ {
+ ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
+ DestroyWindow(mdi_child);
+ }
+ else
+ ok(mdi_child != 0, "MDI child creation failed\n");
+
+ /* test MDICREATESTRUCT A<->W mapping */
+ SetLastError(0xdeadbeef);
+ mdi_child = CreateWindowExW(WS_EX_MDICHILD, classW, titleW,
+ 0,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, 0, GetModuleHandle(0),
+ (LPVOID)mdi_lParam_test_message);
+ if (!mdi_child)
+ {
+ if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ isWin9x = TRUE;
+ else
+ ok(mdi_child != 0, "MDI child creation failed\n");
+ }
+ DestroyWindow(mdi_child);
+
+ /* This test fails on Win9x */
+ if (!isWin9x)
+ {
+ mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_2", "MDI child",
+ WS_CHILD,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ parent, 0, GetModuleHandle(0),
+ (LPVOID)mdi_lParam_test_message);
+ ok(!mdi_child, "WS_EX_MDICHILD with a not MDIClient parent should fail\n");
+ }
+
+ mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
+ WS_CHILD, /* without WS_POPUP */
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, 0, GetModuleHandle(0),
+ (LPVOID)mdi_lParam_test_message);
+ ok(mdi_child != 0, "MDI child creation failed\n");
+ DestroyWindow(mdi_child);
+
+ mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
+ WS_CHILD | WS_POPUP, /* with WS_POPUP */
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, 0, GetModuleHandle(0),
+ (LPVOID)mdi_lParam_test_message);
+ ok(mdi_child != 0, "MDI child creation failed\n");
DestroyWindow(mdi_child);
}
@@ -728,16 +874,50 @@ static LRESULT WINAPI mdi_child_wnd_proc
{
switch (msg)
{
+ case WM_NCCREATE:
case WM_CREATE:
{
CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs->lpCreateParams;
-todo_wine /* apparently Windows has a common code for MDI and other windows */
-{
ok(cs->dwExStyle & WS_EX_MDICHILD, "WS_EX_MDICHILD should be set\n");
-}
ok(mdi_cs->lParam == (LPARAM)mdi_lParam_test_message, "wrong mdi_cs->lParam\n");
+
+ ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_1"), "wrong class name\n");
+ ok(!lstrcmpA(cs->lpszClass, mdi_cs->szClass), "class name does not match\n");
+ ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
+ ok(!lstrcmpA(cs->lpszName, mdi_cs->szTitle), "title does not match\n");
+ ok(cs->hInstance == mdi_cs->hOwner, "%p != %p\n", cs->hInstance, mdi_cs->hOwner);
+
+ /* MDICREATESTRUCT should have original values */
+ ok(mdi_cs->style == 0 || mdi_cs->style == 0x7fffffff || mdi_cs->style == 0xffffffff,
+ "mdi_cs->style does not match (%08lx)\n", mdi_cs->style);
+ ok(mdi_cs->x == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->x);
+ ok(mdi_cs->y == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->y);
+ ok(mdi_cs->cx == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cx);
+ ok(mdi_cs->cy == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cy);
+
+ /* CREATESTRUCT should have fixed values */
+ ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);
+ ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
+ ok(cs->cx != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->cx);
+ ok(cs->cy != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->cy);
+
+ if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
+ {
+ ok(!(cs->style & WS_POPUP), "WS_POPUP is not allowed\n");
+ ok(cs->style == (mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS),
+ "cs->style does not match (%08lx)\n", cs->style);
+ }
+ else
+ {
+ DWORD style = mdi_cs->style;
+ style &= ~WS_POPUP;
+ style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
+ WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
+ ok(cs->style == style,
+ "cs->style does not match (%08lx)\n", cs->style);
+ }
break;
}
}
@@ -748,12 +928,16 @@ static LRESULT WINAPI mdi_child_wnd_proc
{
switch (msg)
{
+ case WM_NCCREATE:
case WM_CREATE:
{
CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n");
ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n");
+
+ ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_2"), "wrong class name\n");
+ ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
break;
}
}
@@ -769,22 +953,31 @@ static LRESULT WINAPI mdi_main_wnd_procA
case WM_CREATE:
{
CLIENTCREATESTRUCT client_cs;
- RECT rc;
-
- GetClientRect(hwnd, &rc);
client_cs.hWindowMenu = 0;
client_cs.idFirstChild = 1;
+ /* MDIClient without MDIS_ALLCHILDSTYLES */
mdi_client = CreateWindowExA(0, "mdiclient",
NULL,
- WS_CHILD | WS_CLIPCHILDREN /*| WS_VISIBLE*/,
- 0, 0, rc.right, rc.bottom,
+ WS_CHILD /*| WS_VISIBLE*/,
+ 0, 0, 0, 0,
hwnd, 0, GetModuleHandle(0),
(LPVOID)&client_cs);
assert(mdi_client);
+ test_MDI_create(hwnd, mdi_client);
+ DestroyWindow(mdi_client);
+ /* MDIClient with MDIS_ALLCHILDSTYLES */
+ mdi_client = CreateWindowExA(0, "mdiclient",
+ NULL,
+ WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
+ 0, 0, 0, 0,
+ hwnd, 0, GetModuleHandle(0),
+ (LPVOID)&client_cs);
+ assert(mdi_client);
test_MDI_create(hwnd, mdi_client);
+ DestroyWindow(mdi_client);
break;
}
@@ -887,20 +1080,23 @@ static void test_icons(void)
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
ok( res == 0, "wrong small icon %p/0\n", res );
- res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
- ok( res != 0, "wrong small icon %p\n", res );
+ /* this test is XP specific */
+ /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
+ ok( res != 0, "wrong small icon %p\n", res );*/
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
ok( res == 0, "wrong previous small icon %p/0\n", res );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
- res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
- ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
+ /* this test is XP specific */
+ /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
+ ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );*/
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
- res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
- ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
+ /* this test is XP specific */
+ /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
+ ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );*/
/* make sure the big icon hasn't changed */
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
@@ -916,6 +1112,7 @@ START_TEST(win)
hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
assert(hhook);
+goto mdi;
hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
WS_MAXIMIZEBOX | WS_POPUP,
@@ -932,6 +1129,7 @@ START_TEST(win)
test_parent_owner();
test_shell_window();
+mdi:
test_mdi();
test_icons();
diff -u cvs/hq/wine/include/win.h wine/include/win.h
--- cvs/hq/wine/include/win.h 2004-01-01 15:33:56.000000000 +0800
+++ wine/include/win.h 2004-01-14 16:23:51.000000000 +0800
@@ -86,6 +86,7 @@ typedef struct
#define WIN_INTERNAL_PAINT 0x0010 /* Internal WM_PAINT message pending */
#define WIN_NEED_SIZE 0x0040 /* Internal WM_SIZE is needed */
#define WIN_NCACTIVATED 0x0080 /* last WM_NCACTIVATE was positive */
+#define WIN_ISMDICLIENT 0x0100 /* Window is an MDIClient */
#define WIN_ISDIALOG 0x0200 /* Window is a dialog */
#define WIN_ISWIN32 0x0400 /* Understands Win32 messages */
#define WIN_NEEDS_SHOW_OWNEDPOPUP 0x0800 /* WM_SHOWWINDOW:SC_SHOW must be sent in the next ShowOwnedPopup call */
@@ -114,6 +115,7 @@ extern BOOL WIN_IsWindowDrawable( HWND h
extern HWND *WIN_ListParents( HWND hwnd );
extern HWND *WIN_ListChildren( HWND hwnd );
extern BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly );
+extern void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta );
inline static HWND WIN_GetFullHandle( HWND hwnd )
{
diff -u cvs/hq/wine/windows/mdi.c wine/windows/mdi.c
--- cvs/hq/wine/windows/mdi.c 2004-01-05 16:06:12.000000000 +0800
+++ wine/windows/mdi.c 2004-01-15 23:12:02.000000000 +0800
@@ -102,13 +102,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(mdi);
-#define MDI_MAXLISTLENGTH 0x40
#define MDI_MAXTITLELENGTH 0xa1
-#define MDI_NOFRAMEREPAINT 0
-#define MDI_REPAINTFRAMENOW 1
-#define MDI_REPAINTFRAME 2
-
#define WM_MDICALCCHILDSCROLL 0x10ac /* this is exactly what Windows uses */
/* "More Windows..." definitions */
@@ -121,10 +116,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(mdi);
typedef struct
{
+ CRITICAL_SECTION lock;
UINT nActiveChildren;
- HWND hwndChildMaximized;
HWND hwndActiveChild;
+ HWND *child; /* array of tracked children */
+ HMENU hFrameMenu;
HMENU hWindowMenu;
+ UINT add_pos; /* original number of items in the window menu */
UINT idFirstChild;
LPWSTR frameTitle;
UINT nTotalCreated;
@@ -139,9 +137,9 @@ static void MDI_UpdateFrameText( HWND, H
static BOOL MDI_AugmentFrameMenu( HWND, HWND );
static BOOL MDI_RestoreFrameMenu( HWND, HWND );
static LONG MDI_ChildActivate( HWND, HWND );
+static LRESULT MDI_RefreshMenu(MDICLIENTINFO *);
static HWND MDI_MoreWindowsDialog(HWND);
-static void MDI_SwapMenuItems(HWND, UINT, UINT);
static LRESULT WINAPI MDIClientWndProcA( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
static LRESULT WINAPI MDIClientWndProcW( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
@@ -149,20 +147,16 @@ static LRESULT WINAPI MDIClientWndProcW(
*
* MDI_GetChildByID
*/
-static HWND MDI_GetChildByID(HWND hwnd, UINT id)
+static HWND MDI_GetChildByID(HWND hwnd, UINT id, MDICLIENTINFO *ci)
{
- HWND ret;
- HWND *win_array;
int i;
- if (!(win_array = WIN_ListChildren( hwnd ))) return 0;
- for (i = 0; win_array[i]; i++)
+ for (i = 0; ci->nActiveChildren; i++)
{
- if (GetWindowLongA( win_array[i], GWL_ID ) == id) break;
+ if (GetWindowLongW( ci->child[i], GWL_ID ) == id)
+ return ci->child[i];
}
- ret = win_array[i];
- HeapFree( GetProcessHeap(), 0, win_array );
- return ret;
+ return 0;
}
static void MDI_PostUpdate(HWND hwnd, MDICLIENTINFO* ci, WORD recalc)
@@ -210,83 +204,6 @@ static MDICLIENTINFO *get_client_info( H
}
/**********************************************************************
- * MDI_MenuModifyItem
- */
-static void MDI_MenuModifyItem( HWND client, HWND hWndChild )
-{
- MDICLIENTINFO *clientInfo = get_client_info( client );
- WCHAR buffer[128];
- UINT n, id;
-
- if (!clientInfo || !clientInfo->hWindowMenu) return;
-
- id = GetWindowLongA( hWndChild, GWL_ID );
- if (id >= clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT) return;
- buffer[0] = '&';
- buffer[1] = '1' + id - clientInfo->idFirstChild;
- buffer[2] = ' ';
- GetWindowTextW( hWndChild, buffer + 3, sizeof(buffer)/sizeof(WCHAR) - 3 );
-
- n = GetMenuState(clientInfo->hWindowMenu, id, MF_BYCOMMAND);
- ModifyMenuW(clientInfo->hWindowMenu, id, MF_BYCOMMAND | MF_STRING, id, buffer );
- CheckMenuItem(clientInfo->hWindowMenu, id, n & MF_CHECKED);
-}
-
-/**********************************************************************
- * MDI_MenuDeleteItem
- */
-static BOOL MDI_MenuDeleteItem( HWND client, HWND hWndChild )
-{
- WCHAR buffer[128];
- static const WCHAR format[] = {'&','%','d',' ',0};
- MDICLIENTINFO *clientInfo = get_client_info( client );
- UINT index = 0,id,n;
-
- if( !clientInfo->nActiveChildren || !clientInfo->hWindowMenu )
- return FALSE;
-
- id = GetWindowLongA( hWndChild, GWL_ID );
- DeleteMenu(clientInfo->hWindowMenu,id,MF_BYCOMMAND);
-
- /* walk the rest of MDI children to prevent gaps in the id
- * sequence and in the menu child list */
-
- for( index = id+1; index <= clientInfo->nActiveChildren +
- clientInfo->idFirstChild; index++ )
- {
- HWND hwnd = MDI_GetChildByID(client,index);
- if (!hwnd)
- {
- TRACE("no window for id=%i\n",index);
- continue;
- }
-
- /* set correct id */
- SetWindowLongW( hwnd, GWL_ID, GetWindowLongW( hwnd, GWL_ID ) - 1 );
-
- n = wsprintfW(buffer, format ,index - clientInfo->idFirstChild);
- GetWindowTextW( hwnd, buffer + n, sizeof(buffer)/sizeof(WCHAR) - n );
-
- /* change menu if the current child is to be shown in the
- * "Windows" menu
- */
- if (index <= clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT)
- ModifyMenuW(clientInfo->hWindowMenu ,index ,MF_BYCOMMAND | MF_STRING,
- index - 1 , buffer );
- }
-
- /* We must restore the "More Windows..." option if there are enough children
- */
- if (clientInfo->nActiveChildren - 1 > MDI_MOREWINDOWSLIMIT)
- {
- WCHAR szTmp[50];
- LoadStringW(GetModuleHandleA("USER32"), IDS_MDI_MOREWINDOWS, szTmp, sizeof(szTmp)/sizeof(szTmp[0]));
- AppendMenuW(clientInfo->hWindowMenu, MF_STRING, clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT, szTmp);
- }
- return TRUE;
-}
-
-/**********************************************************************
* MDI_GetWindow
*
* returns "activateable" child different from the current or zero
@@ -332,21 +249,34 @@ static HWND MDI_GetWindow(MDICLIENTINFO
*
* It seems that the default height is about 2/3 of the client rect
*/
-static void MDI_CalcDefaultChildPos( HWND hwnd, WORD n, LPPOINT lpPos, INT delta)
+void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta )
{
INT nstagger;
RECT rect;
INT spacing = GetSystemMetrics(SM_CYCAPTION) +
GetSystemMetrics(SM_CYFRAME) - 1;
- GetClientRect( hwnd, &rect );
+ if (total < 0)
+ {
+ MDICLIENTINFO *ci = get_client_info(hwndClient);
+ if (ci)
+ {
+ EnterCriticalSection(&ci->lock);
+ total = ci->nTotalCreated;
+ LeaveCriticalSection(&ci->lock);
+ }
+ else
+ total = 0;
+ }
+
+ GetClientRect( hwndClient, &rect );
if( rect.bottom - rect.top - delta >= spacing )
rect.bottom -= delta;
nstagger = (rect.bottom - rect.top)/(3 * spacing);
lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
- lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
+ lpPos[0].x = lpPos[0].y = spacing * (total%(nstagger+1));
}
/**********************************************************************
@@ -357,7 +287,6 @@ static LRESULT MDISetMenu( HWND hwnd, HM
{
MDICLIENTINFO *ci;
HWND hwndFrame = GetParent(hwnd);
- HMENU oldFrameMenu = GetMenu(hwndFrame);
TRACE("%p %p %p\n", hwnd, hmenuFrame, hmenuWindow);
@@ -375,8 +304,10 @@ static LRESULT MDISetMenu( HWND hwnd, HM
if (!(ci = get_client_info( hwnd ))) return 0;
- if( ci->hwndChildMaximized && hmenuFrame && hmenuFrame!=oldFrameMenu )
- MDI_RestoreFrameMenu( GetParent(hwnd), ci->hwndChildMaximized );
+ EnterCriticalSection(&ci->lock);
+
+ if( IsZoomed(ci->hwndActiveChild) && hmenuFrame && hmenuFrame!= ci->hFrameMenu )
+ MDI_RestoreFrameMenu( hwndFrame, ci->hwndActiveChild );
if( hmenuWindow && hmenuWindow != ci->hWindowMenu )
{
@@ -385,65 +316,44 @@ static LRESULT MDISetMenu( HWND hwnd, HM
/* Agent newsreader calls this function with ci->hWindowMenu == NULL */
if( ci->hWindowMenu && ci->nActiveChildren )
{
- INT j;
- LPWSTR buffer = NULL;
- MENUITEMINFOW mii;
- INT nbWindowsMenuItems; /* num of documents shown + "More Windows..." if present */
- INT i = GetMenuItemCount(ci->hWindowMenu) - 1;
- INT pos = GetMenuItemCount(hmenuWindow) + 1;
+ UINT nActiveChildren_old = ci->nActiveChildren;
- AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL);
-
- if (ci->nActiveChildren <= MDI_MOREWINDOWSLIMIT)
- nbWindowsMenuItems = ci->nActiveChildren;
- else
- nbWindowsMenuItems = MDI_MOREWINDOWSLIMIT + 1;
-
- j = i - nbWindowsMenuItems + 1;
-
- for( ; i >= j ; i-- )
- {
- memset(&mii, 0, sizeof(mii));
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE
- | MIIM_SUBMENU | MIIM_TYPE | MIIM_BITMAP;
-
- GetMenuItemInfoW(ci->hWindowMenu, i, TRUE, &mii);
- if(mii.cch) { /* Menu is MFT_STRING */
- mii.cch++; /* add room for '\0' */
- buffer = HeapAlloc(GetProcessHeap(), 0,
- mii.cch * sizeof(WCHAR));
- mii.dwTypeData = buffer;
- GetMenuItemInfoW(ci->hWindowMenu, i, TRUE, &mii);
- }
- DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION);
- InsertMenuItemW(hmenuWindow, pos, TRUE, &mii);
- if(buffer) {
- HeapFree(GetProcessHeap(), 0, buffer);
- buffer = NULL;
- }
- }
- /* remove separator */
- DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION);
+ /* Remove all items from old Window menu */
+ ci->nActiveChildren = 0;
+ MDI_RefreshMenu(ci);
+
+ ci->add_pos = GetMenuItemCount(hmenuWindow);
+ ci->hWindowMenu = hmenuWindow;
+
+ /* Add items to the new Window menu */
+ ci->nActiveChildren = nActiveChildren_old;
+ MDI_RefreshMenu(ci);
}
+ else
+ ci->add_pos = GetMenuItemCount(hmenuWindow);
+
ci->hWindowMenu = hmenuWindow;
}
if (hmenuFrame)
{
SetMenu(hwndFrame, hmenuFrame);
- if( hmenuFrame!=oldFrameMenu )
+ if( hmenuFrame != ci->hFrameMenu )
{
- if( ci->hwndChildMaximized )
- MDI_AugmentFrameMenu( GetParent(hwnd), ci->hwndChildMaximized );
+ HMENU oldFrameMenu = ci->hFrameMenu;
+
+ ci->hFrameMenu = hmenuFrame;
+ if( IsZoomed(ci->hwndActiveChild) )
+ MDI_AugmentFrameMenu( hwndFrame, ci->hwndActiveChild );
+
+ LeaveCriticalSection(&ci->lock);
return (LRESULT)oldFrameMenu;
}
}
else
{
- HMENU menu = GetMenu( GetParent(hwnd) );
- INT nItems = GetMenuItemCount(menu) - 1;
- UINT iId = GetMenuItemID(menu,nItems) ;
+ INT nItems = GetMenuItemCount(ci->hFrameMenu) - 1;
+ UINT iId = GetMenuItemID(ci->hFrameMenu, nItems);
if( !(iId == SC_RESTORE || iId == SC_CLOSE) )
{
@@ -453,185 +363,69 @@ static LRESULT MDISetMenu( HWND hwnd, HM
* that the "if" to this "else" wouldn't catch the need to
* augment the frame menu.
*/
- if( ci->hwndChildMaximized )
- MDI_AugmentFrameMenu( GetParent(hwnd), ci->hwndChildMaximized );
+ if( IsZoomed(ci->hwndActiveChild) )
+ MDI_AugmentFrameMenu( hwndFrame, ci->hwndActiveChild );
}
}
+
+ LeaveCriticalSection(&ci->lock);
return 0;
}
/**********************************************************************
* MDIRefreshMenu
*/
-static LRESULT MDIRefreshMenu( HWND hwnd, HMENU hmenuFrame,
- HMENU hmenuWindow)
+static LRESULT MDI_RefreshMenu(MDICLIENTINFO *ci)
{
- HWND hwndFrame = GetParent(hwnd);
- HMENU oldFrameMenu = GetMenu(hwndFrame);
-
- TRACE("%p %p %p\n", hwnd, hmenuFrame, hmenuWindow);
-
- FIXME("partially function stub\n");
-
- return (LRESULT)oldFrameMenu;
-}
-
+ HMENU hFrameMenu;
+ UINT i, count;
+ WCHAR buf[MDI_MAXTITLELENGTH];
-/* ------------------ MDI child window functions ---------------------- */
-
-
-/**********************************************************************
- * MDICreateChild
- */
-static HWND MDICreateChild( HWND parent, MDICLIENTINFO *ci,
- LPMDICREATESTRUCTA cs, BOOL unicode )
-{
- POINT pos[2];
- DWORD style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS);
- HWND hwnd, hwndMax = 0;
- UINT wIDmenu = ci->idFirstChild + ci->nActiveChildren;
- WND *wndParent;
- static const WCHAR lpstrDef[] = {'j','u','n','k','!',0};
+ EnterCriticalSection(&ci->lock);
- TRACE("origin %i,%i - dim %i,%i, style %08lx\n",
- cs->x, cs->y, cs->cx, cs->cy, cs->style);
- /* calculate placement */
- MDI_CalcDefaultChildPos(parent, ci->nTotalCreated++, pos, 0);
+ TRACE("children %u, window menu %p\n", ci->nActiveChildren, ci->hWindowMenu);
- if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx) cs->cx = pos[1].x;
- if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy) cs->cy = pos[1].y;
-
- if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
- {
- cs->x = pos[0].x;
- cs->y = pos[0].y;
- }
-
- /* restore current maximized child */
- if( (style & WS_VISIBLE) && ci->hwndChildMaximized )
+ if (!ci->hWindowMenu)
{
- TRACE("Restoring current maximized child %p\n", ci->hwndChildMaximized);
- if( style & WS_MAXIMIZE )
- SendMessageW(parent, WM_SETREDRAW, FALSE, 0L);
- hwndMax = ci->hwndChildMaximized;
- ShowWindow( hwndMax, SW_SHOWNOACTIVATE );
- if( style & WS_MAXIMIZE )
- SendMessageW(parent, WM_SETREDRAW, TRUE, 0L);
+ LeaveCriticalSection(&ci->lock);
+ return 0;
}
- if (ci->nActiveChildren <= MDI_MOREWINDOWSLIMIT)
- /* this menu is needed to set a check mark in MDI_ChildActivate */
- if (ci->hWindowMenu != 0)
- AppendMenuW(ci->hWindowMenu, MF_STRING, wIDmenu, lpstrDef);
-
- ci->nActiveChildren++;
+ count = GetMenuItemCount(ci->hWindowMenu);
+ for (i = ci->add_pos; i < count; i++)
+ RemoveMenu(ci->hWindowMenu, ci->add_pos, MF_BYPOSITION);
- /* fix window style */
- wndParent = WIN_FindWndPtr( parent );
- if( !(wndParent->dwStyle & MDIS_ALLCHILDSTYLES) )
- {
- TRACE("MDIS_ALLCHILDSTYLES is missing, fixing window style\n");
- style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE |
- WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL );
- style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
- }
+ if (ci->nActiveChildren)
+ AppendMenuW(ci->hWindowMenu, MF_SEPARATOR, -1, NULL);
- if( wndParent->flags & WIN_ISWIN32 )
- {
- WIN_ReleaseWndPtr( wndParent );
- /* FIXME: CreateWindowEx must be called with WS_EX_MDICHILD set, but
- * it requires to move MDI specific child creation to CreateWindowEx
- * and do child tracking in MDICLIENT using WM_PARENTNOTIFY.
- */
- if(unicode)
- {
- MDICREATESTRUCTW *csW = (MDICREATESTRUCTW *)cs;
- hwnd = CreateWindowExW( 0, csW->szClass, csW->szTitle, style,
- csW->x, csW->y, csW->cx, csW->cy, parent,
- (HMENU)wIDmenu, csW->hOwner, csW );
- }
- else
- hwnd = CreateWindowExA( 0, cs->szClass, cs->szTitle, style,
- cs->x, cs->y, cs->cx, cs->cy, parent,
- (HMENU)wIDmenu, cs->hOwner, cs );
- }
- else
+ for (i = 0; i < ci->nActiveChildren; i++)
{
- MDICREATESTRUCT16 cs16;
- SEGPTR title, cls, seg_cs16;
+ UINT id = ci->idFirstChild + i;
- WIN_ReleaseWndPtr( wndParent );
- STRUCT32_MDICREATESTRUCT32Ato16( cs, &cs16 );
- cs16.szTitle = title = MapLS( cs->szTitle );
- cs16.szClass = cls = MapLS( cs->szClass );
- seg_cs16 = MapLS( &cs16 );
- hwnd = WIN_Handle32( CreateWindowEx16( 0, cs->szClass, cs->szTitle, style,
- cs16.x, cs16.y, cs16.cx, cs16.cy,
- HWND_16(parent), (HMENU16)wIDmenu,
- cs16.hOwner, (LPVOID)seg_cs16 ));
- UnMapLS( seg_cs16 );
- UnMapLS( title );
- UnMapLS( cls );
- }
-
- /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */
-
- if (hwnd)
- {
- /* All MDI child windows have the WS_EX_MDICHILD style */
- SetWindowLongW( hwnd, GWL_EXSTYLE, GetWindowLongW( hwnd, GWL_EXSTYLE ) | WS_EX_MDICHILD );
-
- /* If we have more than 9 windows, we must insert the new one at the
- * 9th position in order to see it in the "Windows" menu
- */
- if (ci->nActiveChildren > MDI_MOREWINDOWSLIMIT)
- MDI_SwapMenuItems( parent, GetWindowLongW( hwnd, GWL_ID ),
- ci->idFirstChild + MDI_MOREWINDOWSLIMIT - 1);
-
- MDI_MenuModifyItem(parent, hwnd);
-
- /* Have we hit the "More Windows..." limit? If so, we must
- * add a "More Windows..." option
- */
- if (ci->nActiveChildren == MDI_MOREWINDOWSLIMIT + 1)
- {
- WCHAR szTmp[50];
- LoadStringW(GetModuleHandleA("USER32"), IDS_MDI_MOREWINDOWS, szTmp, sizeof(szTmp)/sizeof(szTmp[0]));
-
- ModifyMenuW(ci->hWindowMenu,
- ci->idFirstChild + MDI_MOREWINDOWSLIMIT,
- MF_BYCOMMAND | MF_STRING,
- ci->idFirstChild + MDI_MOREWINDOWSLIMIT,
- szTmp);
+ if (i == MDI_MOREWINDOWSLIMIT)
+ {
+ LoadStringW(GetModuleHandleA("USER32"), IDS_MDI_MOREWINDOWS, buf, sizeof(buf)/sizeof(WCHAR));
+ AppendMenuW(ci->hWindowMenu, MF_STRING, id, buf);
+ break;
}
- if( IsIconic(hwnd) && ci->hwndActiveChild )
- {
- TRACE("Minimizing created MDI child %p\n", hwnd);
- ShowWindow( hwnd, SW_SHOWMINNOACTIVE );
- }
- else
- {
- /* WS_VISIBLE is clear if a) the MDI client has
- * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the
- * MDICreateStruct. If so the created window is not shown nor
- * activated.
- */
- if (IsWindowVisible(hwnd)) ShowWindow(hwnd, SW_SHOW);
- }
- TRACE("created child - %p\n",hwnd);
- }
- else
- {
- ci->nActiveChildren--;
- DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
- if( IsWindow(hwndMax) )
- ShowWindow(hwndMax, SW_SHOWMAXIMIZED);
+ SetWindowLongW(ci->child[i], GWL_ID, id);
+ InternalGetWindowText(ci->child[i], buf, sizeof(buf)/sizeof(WCHAR));
+ AppendMenuW(ci->hWindowMenu, MF_STRING, id, buf);
+
+ if (ci->child[i] == ci->hwndActiveChild)
+ CheckMenuItem(ci->hWindowMenu, id, MF_CHECKED);
}
- return hwnd;
+ hFrameMenu = ci->hFrameMenu;
+ LeaveCriticalSection(&ci->lock);
+
+ return (LRESULT)hFrameMenu;
}
+
+/* ------------------ MDI child window functions ---------------------- */
+
/**********************************************************************
* MDI_ChildGetMinMaxInfo
*
@@ -669,14 +463,17 @@ static void MDI_SwitchActiveChild( HWND
HWND hwndPrev = 0;
MDICLIENTINFO *ci = get_client_info( clientHwnd );
+ EnterCriticalSection(&ci->lock);
+
hwndTo = MDI_GetWindow(ci, childHwnd, bNextWindow, 0);
+ hwndPrev = ci->hwndActiveChild;
+
+ LeaveCriticalSection(&ci->lock);
TRACE("from %p, to %p\n",childHwnd,hwndTo);
if ( !hwndTo ) return; /* no window to switch to */
- hwndPrev = ci->hwndActiveChild;
-
if ( hwndTo != hwndPrev )
{
SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
@@ -695,6 +492,10 @@ static void MDI_SwitchActiveChild( HWND
static LRESULT MDIDestroyChild( HWND parent, MDICLIENTINFO *ci,
HWND child, BOOL flagDestroy )
{
+ UINT i;
+
+ EnterCriticalSection(&ci->lock);
+
if( child == ci->hwndActiveChild )
{
MDI_SwitchActiveChild(parent, child, TRUE);
@@ -702,11 +503,10 @@ static LRESULT MDIDestroyChild( HWND par
if( child == ci->hwndActiveChild )
{
ShowWindow( child, SW_HIDE);
- if( child == ci->hwndChildMaximized )
+ if( child == ci->hwndActiveChild && IsZoomed(ci->hwndActiveChild) )
{
HWND frame = GetParent(parent);
MDI_RestoreFrameMenu( frame, child );
- ci->hwndChildMaximized = 0;
MDI_UpdateFrameText( frame, parent, TRUE, NULL);
}
@@ -714,7 +514,18 @@ static LRESULT MDIDestroyChild( HWND par
}
}
- MDI_MenuDeleteItem(parent, child);
+ for (i = 0; i < ci->nActiveChildren; i++)
+ {
+ if (ci->child[i] == child)
+ {
+ HWND *new_child = HeapAlloc(GetProcessHeap(), 0, (ci->nActiveChildren - 1) * sizeof(HWND));
+ memcpy(new_child, ci->child, i * sizeof(HWND));
+ if (i + 1 < ci->nActiveChildren)
+ memcpy(new_child + i, ci->child + i + 1, (ci->nActiveChildren - i - 1) * sizeof(HWND));
+ HeapFree(GetProcessHeap(), 0, ci->child);
+ ci->child = new_child;
+ }
+ }
ci->nActiveChildren--;
@@ -725,6 +536,9 @@ static LRESULT MDIDestroyChild( HWND par
MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
DestroyWindow(child);
}
+
+ LeaveCriticalSection(&ci->lock);
+
return 0;
}
@@ -736,19 +550,27 @@ static LRESULT MDIDestroyChild( HWND par
*/
static LONG MDI_ChildActivate( HWND client, HWND child )
{
- MDICLIENTINFO *clientInfo = get_client_info( client );
- HWND prevActiveWnd = clientInfo->hwndActiveChild;
+ MDICLIENTINFO *clientInfo;
+ HWND prevActiveWnd;
BOOL isActiveFrameWnd;
if (child && (!IsWindowEnabled( child ))) return 0;
+ clientInfo = get_client_info( client );
+ EnterCriticalSection(&clientInfo->lock);
+
/* Don't activate if it is already active. Might happen
since ShowWindow DOES activate MDI children */
- if (clientInfo->hwndActiveChild == child) return 0;
+ if (clientInfo->hwndActiveChild == child)
+ {
+ LeaveCriticalSection(&clientInfo->lock);
+ return 0;
+ }
TRACE("%p\n", child);
isActiveFrameWnd = (GetActiveWindow() == GetParent(client));
+ prevActiveWnd = clientInfo->hwndActiveChild;
/* deactivate prev. active child */
if(prevActiveWnd)
@@ -771,17 +593,21 @@ static LONG MDI_ChildActivate( HWND clie
}
/* set appearance */
- if (clientInfo->hwndChildMaximized && clientInfo->hwndChildMaximized != child)
+ if (IsZoomed(clientInfo->hwndActiveChild) && clientInfo->hwndActiveChild != child)
{
INT cmd = SW_SHOWNORMAL;
if( child )
{
- UINT state = GetMenuState(GetSystemMenu(child, FALSE), SC_MAXIMIZE, MF_BYCOMMAND);
- if (state != 0xFFFFFFFF && (state & (MF_DISABLED | MF_GRAYED)))
- SendMessageW(clientInfo->hwndChildMaximized, WM_SYSCOMMAND, SC_RESTORE, 0);
- else
+ HMENU hSysMenu = GetSystemMenu(child, FALSE);
+ UINT state = 0;
+ if (hSysMenu)
+ state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
+ if (state != 0xFFFFFFFF && !(state & (MF_DISABLED | MF_GRAYED)))
+ {
+ SendMessageW(clientInfo->hwndActiveChild, WM_SYSCOMMAND, SC_RESTORE, 0);
cmd = SW_SHOWMAXIMIZED;
+ }
clientInfo->hwndActiveChild = child;
}
@@ -791,6 +617,9 @@ static LONG MDI_ChildActivate( HWND clie
clientInfo->hwndActiveChild = child;
+ MDI_RefreshMenu(clientInfo);
+ LeaveCriticalSection(&clientInfo->lock);
+
/* check if we have any children left */
if( !child )
{
@@ -799,21 +628,6 @@ static LONG MDI_ChildActivate( HWND clie
return 0;
}
- /* check menu item */
- if( clientInfo->hWindowMenu )
- {
- UINT id = GetWindowLongA( child, GWL_ID );
- /* The window to be activated must be displayed in the "Windows" menu */
- if (id >= clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT)
- {
- MDI_SwapMenuItems( GetParent(child),
- id, clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT - 1);
- id = clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT - 1;
- MDI_MenuModifyItem( GetParent(child), child );
- }
-
- CheckMenuItem(clientInfo->hWindowMenu, id, MF_CHECKED);
- }
/* bring active child to the top */
SetWindowPos( child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
@@ -874,9 +688,8 @@ static LONG MDICascade( HWND client, MDI
BOOL has_icons = FALSE;
int i, total;
- if (ci->hwndChildMaximized)
- SendMessageA( client, WM_MDIRESTORE,
- (WPARAM)ci->hwndChildMaximized, 0);
+ if (IsZoomed(ci->hwndActiveChild))
+ SendMessageA(client, WM_MDIRESTORE, (WPARAM)ci->hwndActiveChild, 0);
if (ci->nActiveChildren == 0) return 0;
@@ -928,8 +741,8 @@ static void MDITile( HWND client, MDICLI
int i, total;
BOOL has_icons = FALSE;
- if (ci->hwndChildMaximized)
- SendMessageA( client, WM_MDIRESTORE, (WPARAM)ci->hwndChildMaximized, 0);
+ if (IsZoomed(ci->hwndActiveChild))
+ SendMessageA(client, WM_MDIRESTORE, (WPARAM)ci->hwndActiveChild, 0);
if (ci->nActiveChildren == 0) return;
@@ -1034,6 +847,13 @@ static BOOL MDI_AugmentFrameMenu( HWND f
AppendMenuA(menu,MF_HELP | MF_BITMAP,
SC_RESTORE, (LPSTR)(DWORD)HBMMENU_MBAR_RESTORE );
+ /* The close button is only present in Win 95 look */
+ if(TWEAK_WineLook > WIN31_LOOK)
+ {
+ AppendMenuA(menu,MF_HELP | MF_BITMAP,
+ SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
+ }
+
/* In Win 95 look, the system menu is replaced by the child icon */
if(TWEAK_WineLook > WIN31_LOOK)
@@ -1078,13 +898,6 @@ static BOOL MDI_AugmentFrameMenu( HWND f
return 0;
}
- /* The close button is only present in Win 95 look */
- if(TWEAK_WineLook > WIN31_LOOK)
- {
- AppendMenuA(menu,MF_HELP | MF_BITMAP,
- SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
- }
-
EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
@@ -1166,6 +979,8 @@ static void MDI_UpdateFrameText( HWND fr
if (!ci) return;
+ EnterCriticalSection(&ci->lock);
+
if (!lpTitle && !ci->frameTitle) /* first time around, get title from the frame window */
{
GetWindowTextW( frame, lpBuffer, sizeof(lpBuffer)/sizeof(WCHAR) );
@@ -1182,7 +997,7 @@ static void MDI_UpdateFrameText( HWND fr
if (ci->frameTitle)
{
- if (ci->hwndChildMaximized)
+ if (IsZoomed(ci->hwndActiveChild))
{
/* combine frame title and child title if possible */
@@ -1195,7 +1010,7 @@ static void MDI_UpdateFrameText( HWND fr
if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
{
strcatW( lpBuffer, lpBracket );
- if (GetWindowTextW( ci->hwndChildMaximized, lpBuffer + i_frame_text_length + 4,
+ if (GetWindowTextW( ci->hwndActiveChild, lpBuffer + i_frame_text_length + 4,
MDI_MAXTITLELENGTH - i_frame_text_length - 5 ))
strcatW( lpBuffer, lpBracket2 );
else
@@ -1210,8 +1025,10 @@ static void MDI_UpdateFrameText( HWND fr
else
lpBuffer[0] = '\0';
+ LeaveCriticalSection(&ci->lock);
+
DefWindowProcW( frame, WM_SETTEXT, 0, (LPARAM)lpBuffer );
- if( repaint == MDI_REPAINTFRAME)
+ if( repaint )
SetWindowPos( frame, 0,0,0,0,0, SWP_FRAMECHANGED |
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
}
@@ -1234,21 +1051,21 @@ static LRESULT MDIClientWndProc_common(
{
case WM_CREATE:
{
- RECT rect;
/* Since we are using only cs->lpCreateParams, we can safely
* cast to LPCREATESTRUCTA here */
LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
WND *wndPtr = WIN_GetPtr( hwnd );
+ wndPtr->flags |= WIN_ISMDICLIENT;
+
/* Translation layer doesn't know what's in the cs->lpCreateParams
* so we have to keep track of what environment we're in. */
if( wndPtr->flags & WIN_ISWIN32 )
{
-#define ccs ((LPCLIENTCREATESTRUCT)cs->lpCreateParams)
+ LPCLIENTCREATESTRUCT ccs = cs->lpCreateParams;
ci->hWindowMenu = ccs->hWindowMenu;
ci->idFirstChild = ccs->idFirstChild;
-#undef ccs
}
else
{
@@ -1258,62 +1075,84 @@ static LRESULT MDIClientWndProc_common(
}
WIN_ReleasePtr( wndPtr );
- ci->hwndChildMaximized = 0;
+ InitializeCriticalSection(&ci->lock);
+ ci->child = NULL;
ci->nActiveChildren = 0;
ci->nTotalCreated = 0;
ci->frameTitle = NULL;
ci->mdiFlags = 0;
- SetWindowLongW( hwnd, GWL_STYLE, GetWindowLongW(hwnd,GWL_STYLE) | WS_CLIPCHILDREN );
+ ci->hFrameMenu = GetMenu(cs->hwndParent);
+ ci->add_pos = GetMenuItemCount(ci->hWindowMenu);
if (!hBmpClose) hBmpClose = CreateMDIMenuBitmap();
- if (ci->hWindowMenu != 0)
- AppendMenuW( ci->hWindowMenu, MF_SEPARATOR, 0, NULL );
-
- GetClientRect( GetParent(hwnd), &rect);
- MoveWindow( hwnd, 0, 0, rect.right, rect.bottom, FALSE );
-
- MDI_UpdateFrameText( GetParent(hwnd), hwnd, MDI_NOFRAMEREPAINT, NULL);
-
TRACE("Client created - hwnd = %p, idFirst = %u\n", hwnd, ci->idFirstChild );
return 0;
}
case WM_DESTROY:
{
- INT nItems;
- if( ci->hwndChildMaximized )
- MDI_RestoreFrameMenu( GetParent(hwnd), ci->hwndChildMaximized);
- if((ci->hWindowMenu != 0) &&
- (nItems = GetMenuItemCount(ci->hWindowMenu)) > 0)
- {
- ci->idFirstChild = nItems - 1;
- ci->nActiveChildren++; /* to delete a separator */
- while( ci->nActiveChildren-- )
- DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
- }
+ EnterCriticalSection(&ci->lock);
+
+ if( IsZoomed(ci->hwndActiveChild) )
+ MDI_RestoreFrameMenu(GetParent(hwnd), ci->hwndActiveChild);
+
+ ci->nActiveChildren = 0;
+ MDI_RefreshMenu(ci);
+
+ if (ci->child) HeapFree( GetProcessHeap(), 0, ci->child );
if (ci->frameTitle) HeapFree( GetProcessHeap(), 0, ci->frameTitle );
+
+ LeaveCriticalSection(&ci->lock);
+ DeleteCriticalSection(&ci->lock);
return 0;
}
case WM_MDIACTIVATE:
- if( ci->hwndActiveChild != (HWND)wParam )
+ {
+ HWND hwndActive;
+
+ EnterCriticalSection(&ci->lock);
+ hwndActive = ci->hwndActiveChild;
+ LeaveCriticalSection(&ci->lock);
+
+ if( hwndActive != (HWND)wParam )
SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
return 0;
+ }
case WM_MDICASCADE:
return MDICascade(hwnd, ci);
case WM_MDICREATE:
if (lParam)
- return (LRESULT)MDICreateChild( hwnd, ci, (MDICREATESTRUCTA *)lParam, unicode );
+ {
+ if (unicode)
+ {
+ MDICREATESTRUCTW *csW = (MDICREATESTRUCTW *)lParam;
+ return (LRESULT)CreateWindowExW(WS_EX_MDICHILD, csW->szClass,
+ csW->szTitle, csW->style,
+ csW->x, csW->y, csW->cx, csW->cy,
+ hwnd, 0, csW->hOwner,
+ (LPVOID)csW->lParam);
+ }
+ else
+ {
+ MDICREATESTRUCTA *csA = (MDICREATESTRUCTA *)lParam;
+ return (LRESULT)CreateWindowExA(WS_EX_MDICHILD, csA->szClass,
+ csA->szTitle, csA->style,
+ csA->x, csA->y, csA->cx, csA->cy,
+ hwnd, 0, csA->hOwner,
+ (LPVOID)csA->lParam);
+ }
+ }
return 0;
case WM_MDIDESTROY:
return MDIDestroyChild( hwnd, ci, WIN_GetFullHandle( (HWND)wParam ), TRUE );
case WM_MDIGETACTIVE:
- if (lParam) *(BOOL *)lParam = (ci->hwndChildMaximized != 0);
+ if (lParam) *(BOOL *)lParam = IsZoomed(ci->hwndActiveChild);
return (LRESULT)ci->hwndActiveChild;
case WM_MDIICONARRANGE:
@@ -1339,7 +1178,7 @@ static LRESULT MDIClientWndProc_common(
return MDISetMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
case WM_MDIREFRESHMENU:
- return MDIRefreshMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
+ return MDI_RefreshMenu( ci );
case WM_MDITILE:
ci->mdiFlags |= MDIF_NEEDUPDATE;
@@ -1366,8 +1205,25 @@ static LRESULT MDIClientWndProc_common(
break;
case WM_PARENTNOTIFY:
- if (LOWORD(wParam) == WM_LBUTTONDOWN)
+ switch (LOWORD(wParam))
{
+ case WM_CREATE:
+ if (GetWindowLongW((HWND)lParam, GWL_EXSTYLE) & WS_EX_MDICHILD)
+ {
+ ci->nTotalCreated++;
+ ci->nActiveChildren++;
+
+ if (!ci->child)
+ ci->child = HeapAlloc(GetProcessHeap(), 0, sizeof(HWND));
+ else
+ ci->child = HeapReAlloc(GetProcessHeap(), 0, ci->child, sizeof(HWND) * ci->nActiveChildren);
+
+ ci->child[ci->nActiveChildren - 1] = (HWND)lParam;
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ {
HWND child;
POINT pt;
pt.x = (short)LOWORD(lParam);
@@ -1378,11 +1234,13 @@ static LRESULT MDIClientWndProc_common(
if( child && child != hwnd && child != ci->hwndActiveChild )
SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
+ break;
+ }
}
return 0;
case WM_SIZE:
- if( IsWindow(ci->hwndChildMaximized) )
+ if( IsWindow(ci->hwndActiveChild) && IsZoomed(ci->hwndActiveChild) )
{
RECT rect;
@@ -1391,9 +1249,9 @@ static LRESULT MDIClientWndProc_common(
rect.right = LOWORD(lParam);
rect.bottom = HIWORD(lParam);
- AdjustWindowRectEx(&rect, GetWindowLongA(ci->hwndChildMaximized,GWL_STYLE),
- 0, GetWindowLongA(ci->hwndChildMaximized,GWL_EXSTYLE) );
- MoveWindow(ci->hwndChildMaximized, rect.left, rect.top,
+ AdjustWindowRectEx(&rect, GetWindowLongA(ci->hwndActiveChild, GWL_STYLE),
+ 0, GetWindowLongA(ci->hwndActiveChild, GWL_EXSTYLE) );
+ MoveWindow(ci->hwndActiveChild, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, 1);
}
else
@@ -1447,7 +1305,7 @@ LRESULT WINAPI DefFrameProcA( HWND hwnd,
DWORD len = MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, NULL, 0 );
LPWSTR text = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, text, len );
- MDI_UpdateFrameText(hwnd, hwndMDIClient, MDI_REPAINTFRAME, text );
+ MDI_UpdateFrameText(hwnd, hwndMDIClient, TRUE, text );
HeapFree( GetProcessHeap(), 0, text );
}
return 1; /* success. FIXME: check text length */
@@ -1483,7 +1341,7 @@ LRESULT WINAPI DefFrameProcW( HWND hwnd,
if (id < ci->idFirstChild || id >= ci->idFirstChild + ci->nActiveChildren)
{
if( (id - 0xf000) & 0xf00f ) break;
- if( !ci->hwndChildMaximized ) break;
+ if( !IsZoomed(ci->hwndActiveChild) ) break;
switch( id )
{
case SC_SIZE:
@@ -1494,7 +1352,7 @@ LRESULT WINAPI DefFrameProcW( HWND hwnd,
case SC_PREVWINDOW:
case SC_CLOSE:
case SC_RESTORE:
- return SendMessageW( ci->hwndChildMaximized, WM_SYSCOMMAND,
+ return SendMessageW( ci->hwndActiveChild, WM_SYSCOMMAND,
wParam, lParam);
}
}
@@ -1506,7 +1364,7 @@ LRESULT WINAPI DefFrameProcW( HWND hwnd,
childHwnd = MDI_MoreWindowsDialog(hwndMDIClient);
else
/* User chose one of the windows listed in the "Windows" menu */
- childHwnd = MDI_GetChildByID(hwndMDIClient,id);
+ childHwnd = MDI_GetChildByID(hwndMDIClient, id, ci);
if( childHwnd )
SendMessageW( hwndMDIClient, WM_MDIACTIVATE, (WPARAM)childHwnd, 0 );
@@ -1519,7 +1377,7 @@ LRESULT WINAPI DefFrameProcW( HWND hwnd,
break;
case WM_SETTEXT:
- MDI_UpdateFrameText(hwnd, hwndMDIClient, MDI_REPAINTFRAME, (LPWSTR)lParam );
+ MDI_UpdateFrameText(hwnd, hwndMDIClient, TRUE, (LPWSTR)lParam );
return 1; /* success. FIXME: check text length */
case WM_SETFOCUS:
@@ -1534,7 +1392,7 @@ LRESULT WINAPI DefFrameProcW( HWND hwnd,
{
MDINEXTMENU *next_menu = (MDINEXTMENU *)lParam;
- if (!IsIconic(hwnd) && ci->hwndActiveChild && !ci->hwndChildMaximized)
+ if (!IsIconic(hwnd) && ci->hwndActiveChild && !IsZoomed(ci->hwndActiveChild))
{
/* control menu is between the frame system menu and
* the first entry of menu bar */
@@ -1574,9 +1432,9 @@ LRESULT WINAPI DefMDIChildProcA( HWND hw
{
case WM_SETTEXT:
DefWindowProcA(hwnd, message, wParam, lParam);
- MDI_MenuModifyItem( client, hwnd );
- if( ci->hwndChildMaximized == hwnd )
- MDI_UpdateFrameText( GetParent(client), client, MDI_REPAINTFRAME, NULL );
+ MDI_RefreshMenu(ci);
+ if( ci->hwndActiveChild == hwnd && IsZoomed(ci->hwndActiveChild) )
+ MDI_UpdateFrameText( GetParent(client), client, TRUE, NULL );
return 1; /* success. FIXME: check text length */
case WM_GETMINMAXINFO:
@@ -1611,9 +1469,9 @@ LRESULT WINAPI DefMDIChildProcW( HWND hw
{
case WM_SETTEXT:
DefWindowProcW(hwnd, message, wParam, lParam);
- MDI_MenuModifyItem( client, hwnd );
- if( ci->hwndChildMaximized == hwnd )
- MDI_UpdateFrameText( GetParent(client), client, MDI_REPAINTFRAME, NULL );
+ MDI_RefreshMenu(ci);
+ if( ci->hwndActiveChild == hwnd && IsZoomed(ci->hwndActiveChild) )
+ MDI_UpdateFrameText( GetParent(client), client, TRUE, NULL );
return 1; /* success. FIXME: check text length */
case WM_GETMINMAXINFO:
@@ -1639,7 +1497,8 @@ LRESULT WINAPI DefMDIChildProcW( HWND hw
switch( wParam )
{
case SC_MOVE:
- if( ci->hwndChildMaximized == hwnd) return 0;
+ if( ci->hwndActiveChild == hwnd && IsZoomed(ci->hwndActiveChild))
+ return 0;
break;
case SC_RESTORE:
case SC_MINIMIZE:
@@ -1647,7 +1506,7 @@ LRESULT WINAPI DefMDIChildProcW( HWND hw
GetWindowLongW( hwnd, GWL_STYLE ) | WS_SYSMENU );
break;
case SC_MAXIMIZE:
- if (ci->hwndChildMaximized == hwnd)
+ if (ci->hwndActiveChild == hwnd && IsZoomed(ci->hwndActiveChild))
return SendMessageW( GetParent(client), message, wParam, lParam);
SetWindowLongW( hwnd, GWL_STYLE,
GetWindowLongW( hwnd, GWL_STYLE ) & ~WS_SYSMENU );
@@ -1662,39 +1521,23 @@ LRESULT WINAPI DefMDIChildProcW( HWND hw
break;
case WM_SETVISIBLE:
- if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
+ if (IsZoomed(ci->hwndActiveChild)) ci->mdiFlags &= ~MDIF_NEEDUPDATE;
else MDI_PostUpdate(client, ci, SB_BOTH+1);
break;
case WM_SIZE:
- if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
+ if( wParam != SIZE_MAXIMIZED )
{
- ci->hwndChildMaximized = 0;
MDI_RestoreFrameMenu( GetParent(client), hwnd );
- MDI_UpdateFrameText( GetParent(client), client, MDI_REPAINTFRAME, NULL );
+ MDI_UpdateFrameText( GetParent(client), client, TRUE, NULL );
}
if( wParam == SIZE_MAXIMIZED )
{
- HWND hMaxChild = ci->hwndChildMaximized;
-
- if( hMaxChild == hwnd ) break;
- if( hMaxChild)
- {
- SendMessageW( hMaxChild, WM_SETREDRAW, FALSE, 0 );
- MDI_RestoreFrameMenu( GetParent(client), hMaxChild );
- ShowWindow( hMaxChild, SW_SHOWNOACTIVATE );
- SendMessageW( hMaxChild, WM_SETREDRAW, TRUE, 0 );
- }
TRACE("maximizing child %p\n", hwnd );
- /* keep track of the maximized window. */
- ci->hwndChildMaximized = hwnd; /* !!! */
-
- /* The maximized window should also be the active window */
- MDI_ChildActivate( client, hwnd );
MDI_AugmentFrameMenu( GetParent(client), hwnd );
- MDI_UpdateFrameText( GetParent(client), client, MDI_REPAINTFRAME, NULL );
+ MDI_UpdateFrameText( GetParent(client), client, TRUE, NULL );
}
if( wParam == SIZE_MINIMIZED )
@@ -1755,29 +1598,13 @@ HWND WINAPI CreateMDIWindowA(
HINSTANCE hInstance, /* [in] Handle to application instance */
LPARAM lParam) /* [in] Application-defined value */
{
- MDICLIENTINFO *pCi = get_client_info( hWndParent );
- MDICREATESTRUCTA cs;
-
- TRACE("(%s,%s,%ld,%d,%d,%d,%d,%p,%p,%ld)\n",
+ TRACE("(%s,%s,%08lx,%d,%d,%d,%d,%p,%p,%08lx)\n",
debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y,
nWidth,nHeight,hWndParent,hInstance,lParam);
- if (!pCi)
- {
- ERR("bad hwnd for MDI-client: %p\n", hWndParent);
- return 0;
- }
- cs.szClass=lpClassName;
- cs.szTitle=lpWindowName;
- cs.hOwner=hInstance;
- cs.x=X;
- cs.y=Y;
- cs.cx=nWidth;
- cs.cy=nHeight;
- cs.style=dwStyle;
- cs.lParam=lParam;
-
- return MDICreateChild(hWndParent, pCi, &cs, FALSE);
+ return CreateWindowExA(WS_EX_MDICHILD, lpClassName, lpWindowName,
+ dwStyle, X, Y, nWidth, nHeight, hWndParent,
+ 0, hInstance, (LPVOID)lParam);
}
/***********************************************************************
@@ -1799,29 +1626,13 @@ HWND WINAPI CreateMDIWindowW(
HINSTANCE hInstance, /* [in] Handle to application instance */
LPARAM lParam) /* [in] Application-defined value */
{
- MDICLIENTINFO *pCi = get_client_info( hWndParent );
- MDICREATESTRUCTW cs;
-
- TRACE("(%s,%s,%ld,%d,%d,%d,%d,%p,%p,%ld)\n",
+ TRACE("(%s,%s,%08lx,%d,%d,%d,%d,%p,%p,%08lx)\n",
debugstr_w(lpClassName), debugstr_w(lpWindowName), dwStyle, X, Y,
nWidth, nHeight, hWndParent, hInstance, lParam);
- if (!pCi)
- {
- ERR("bad hwnd for MDI-client: %p\n", hWndParent);
- return 0;
- }
- cs.szClass = lpClassName;
- cs.szTitle = lpWindowName;
- cs.hOwner = hInstance;
- cs.x = X;
- cs.y = Y;
- cs.cx = nWidth;
- cs.cy = nHeight;
- cs.style = dwStyle;
- cs.lParam = lParam;
-
- return MDICreateChild(hWndParent, pCi, (MDICREATESTRUCTA *)&cs, TRUE);
+ return CreateWindowExW(WS_EX_MDICHILD, lpClassName, lpWindowName,
+ dwStyle, X, Y, nWidth, nHeight, hWndParent,
+ 0, hInstance, (LPVOID)lParam);
}
/**********************************************************************
@@ -2056,32 +1867,15 @@ static INT_PTR WINAPI MDI_MoreWindowsDlg
UINT i;
MDICLIENTINFO *ci = get_client_info( (HWND)lParam );
HWND hListBox = GetDlgItem(hDlg, MDI_IDC_LISTBOX);
- HWND *list, *sorted_list;
-
- if (!(list = WIN_ListChildren( (HWND)lParam ))) return TRUE;
- if (!(sorted_list = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof(HWND) * ci->nActiveChildren )))
- {
- HeapFree( GetProcessHeap(), 0, list );
- return FALSE;
- }
-
- /* Fill the list, sorted by id... */
- for (i = 0; list[i]; i++)
- {
- UINT id = GetWindowLongW( list[i], GWL_ID ) - ci->idFirstChild;
- if (id < ci->nActiveChildren) sorted_list[id] = list[i];
- }
- HeapFree( GetProcessHeap(), 0, list );
for (i = 0; i < ci->nActiveChildren; i++)
{
- WCHAR buffer[128];
+ WCHAR buffer[MDI_MAXTITLELENGTH];
- if (!GetWindowTextW( sorted_list[i], buffer, sizeof(buffer)/sizeof(WCHAR) ))
+ if (!InternalGetWindowText( ci->child[i], buffer, sizeof(buffer)/sizeof(WCHAR) ))
continue;
SendMessageW(hListBox, LB_ADDSTRING, 0, (LPARAM)buffer );
- SendMessageW(hListBox, LB_SETITEMDATA, i, (LPARAM)sorted_list[i] );
+ SendMessageW(hListBox, LB_SETITEMDATA, i, (LPARAM)ci->child[i] );
length = strlenW(buffer); /* FIXME: should use GetTextExtentPoint */
if (length > widest)
widest = length;
@@ -2156,28 +1950,3 @@ static HWND MDI_MoreWindowsDialog(HWND h
(LPDLGTEMPLATEA) template,
hwnd, MDI_MoreWindowsDlgProc, (LPARAM) hwnd);
}
-
-/*
- *
- * MDI_SwapMenuItems
- *
- * Will swap the menu IDs for the given 2 positions.
- * pos1 and pos2 are menu IDs
- *
- *
- */
-
-static void MDI_SwapMenuItems(HWND parent, UINT pos1, UINT pos2)
-{
- HWND *list;
- int i;
-
- if (!(list = WIN_ListChildren( parent ))) return;
- for (i = 0; list[i]; i++)
- {
- UINT id = GetWindowLongW( list[i], GWL_ID );
- if (id == pos1) SetWindowLongW( list[i], GWL_ID, pos2 );
- else if (id == pos2) SetWindowLongW( list[i], GWL_ID, pos1 );
- }
- HeapFree( GetProcessHeap(), 0, list );
-}
diff -u cvs/hq/wine/windows/win.c wine/windows/win.c
--- cvs/hq/wine/windows/win.c 2004-01-01 15:33:57.000000000 +0800
+++ wine/windows/win.c 2004-01-15 23:14:07.000000000 +0800
@@ -805,7 +805,18 @@ static void WIN_FixCoordinates( CREATEST
{
if (cs->style & (WS_CHILD | WS_POPUP))
{
- if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
+ if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
+ {
+ if (cs->dwExStyle & WS_EX_MDICHILD)
+ {
+ POINT pos[2];
+ MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0);
+ cs->x = pos[0].x;
+ cs->y = pos[0].y;
+ }
+ else
+ cs->x = cs->y = 0;
+ }
if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
}
else /* overlapped window */
@@ -979,7 +990,7 @@ static HWND WIN_CreateWindowEx( CREATEST
{
INT sw = SW_SHOW;
WND *wndPtr;
- HWND hwnd, parent, owner;
+ HWND hwnd, parent, owner, top_child = 0;
BOOL unicode = (type == WIN_PROC_32W);
TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
@@ -1024,6 +1035,61 @@ static HWND WIN_CreateWindowEx( CREATEST
return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
}
+ if (cs->dwExStyle & WS_EX_MDICHILD)
+ {
+ MDICREATESTRUCTA mdi_cs;
+ UINT flags = 0;
+
+ wndPtr = WIN_GetPtr(cs->hwndParent);
+ if (wndPtr && wndPtr != WND_OTHER_PROCESS)
+ {
+ flags = wndPtr->flags;
+ WIN_ReleasePtr(wndPtr);
+ }
+
+ if (!(flags & WIN_ISMDICLIENT))
+ {
+ WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
+ return 0;
+ }
+
+ /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
+ * MDICREATESTRUCT members have the originally passed values.
+ *
+ * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
+ * have the same layout.
+ */
+ mdi_cs.szClass = cs->lpszClass;
+ mdi_cs.szTitle = cs->lpszName;
+ mdi_cs.hOwner = cs->hInstance;
+ mdi_cs.x = cs->x;
+ mdi_cs.y = cs->y;
+ mdi_cs.cx = cs->cx;
+ mdi_cs.cy = cs->cy;
+ mdi_cs.style = cs->style;
+ mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
+
+ cs->lpCreateParams = (LPVOID)&mdi_cs;
+
+ if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
+ {
+ if (cs->style & WS_POPUP)
+ {
+ TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
+ return 0;
+ }
+ cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
+ }
+ else
+ {
+ cs->style &= ~WS_POPUP;
+ cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
+ WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
+ }
+
+ top_child = GetWindow(cs->hwndParent, GW_CHILD);
+ }
+
WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
/* Correct the window style - stage 1
@@ -1136,6 +1202,21 @@ static HWND WIN_CreateWindowEx( CREATEST
send_parent_notify( hwnd, WM_CREATE );
if (!IsWindow( hwnd )) return 0;
+ if (cs->dwExStyle & WS_EX_MDICHILD)
+ {
+ if (top_child)
+ {
+ /* Restore current maximized child */
+ if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
+ {
+ TRACE("Restoring current maximized child %p\n", top_child);
+ ShowWindow(top_child, SW_SHOWNOACTIVATE);
+ }
+ }
+
+ SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
+ }
+
if (cs->style & WS_VISIBLE)
{
/* in case WS_VISIBLE got set in the meantime */
@@ -1237,9 +1318,6 @@ HWND WINAPI CreateWindowExA( DWORD exSty
CREATESTRUCTA cs;
char buffer[256];
- if(exStyle & WS_EX_MDICHILD)
- return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
-
/* Find the class atom */
if (HIWORD(className))
@@ -1293,9 +1371,6 @@ HWND WINAPI CreateWindowExW( DWORD exSty
CREATESTRUCTW cs;
WCHAR buffer[256];
- if(exStyle & WS_EX_MDICHILD)
- return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
-
/* Find the class atom */
if (HIWORD(className))
@@ -1398,6 +1473,13 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
TRACE("(%p)\n", hwnd);
+ /* Hide the window */
+ if (!ShowWindow( hwnd, SW_HIDE ))
+ {
+ if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
+ }
+ if (!IsWindow(hwnd)) return TRUE;
+
/* Look whether the focus is within the tree of windows we will
* be destroying.
*/
@@ -1409,6 +1491,9 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
SetFocus( parent );
}
+ if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
+ SendMessageW(GetAncestor(hwnd, GA_PARENT), WM_MDIREFRESHMENU, 0, 0);
+
/* Call hooks */
if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
@@ -1431,14 +1516,6 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
if (USER_Driver.pResetSelectionOwner)
USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
- /* Hide the window */
-
- if (!ShowWindow( hwnd, SW_HIDE ))
- {
- if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
- }
- if (!IsWindow(hwnd)) return TRUE;
-
/* Recursively destroy owned windows */
if (!is_child)
diff -u cvs/hq/wine/windows/winproc.c wine/windows/winproc.c
--- cvs/hq/wine/windows/winproc.c 2003-11-12 14:44:31.000000000 +0800
+++ wine/windows/winproc.c 2004-01-13 20:10:17.000000000 +0800
@@ -671,6 +671,25 @@ INT WINPROC_MapMsg32ATo32W( HWND hwnd, U
RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)xs->cs.lpszClass);
xs->lpszClass = xs->cs.lpszClass = usBuffer.Buffer;
}
+
+ if (GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
+ {
+ MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)HeapAlloc(GetProcessHeap(), 0,
+ sizeof(*mdi_cs));
+ *mdi_cs = *(MDICREATESTRUCTW *)xs->cs.lpCreateParams;
+ if (HIWORD(mdi_cs->szTitle))
+ {
+ RtlCreateUnicodeStringFromAsciiz(&usBuffer, (LPCSTR)mdi_cs->szTitle);
+ mdi_cs->szTitle = usBuffer.Buffer;
+ }
+ if (HIWORD(mdi_cs->szClass))
+ {
+ RtlCreateUnicodeStringFromAsciiz(&usBuffer, (LPCSTR)mdi_cs->szClass);
+ mdi_cs->szClass = usBuffer.Buffer;
+ }
+ xs->cs.lpCreateParams = mdi_cs;
+ }
+
*plparam = (LPARAM)xs;
}
return 1;
@@ -829,6 +848,16 @@ LRESULT WINPROC_UnmapMsg32ATo32W( HWND h
struct s *xs = (struct s *)lParam;
if (xs->lpszName) HeapFree( GetProcessHeap(), 0, xs->lpszName );
if (xs->lpszClass) HeapFree( GetProcessHeap(), 0, xs->lpszClass );
+
+ if (GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
+ {
+ MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)xs->cs.lpCreateParams;
+ if (HIWORD(mdi_cs->szTitle))
+ HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szTitle);
+ if (HIWORD(mdi_cs->szClass))
+ HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szClass);
+ HeapFree(GetProcessHeap(), 0, mdi_cs);
+ }
HeapFree( GetProcessHeap(), 0, xs );
}
break;
@@ -952,6 +981,25 @@ INT WINPROC_MapMsg32WTo32A( HWND hwnd, U
if (HIWORD(cs->lpszClass))
cs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
(LPCWSTR)cs->lpszClass);
+
+ if (GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
+ {
+ MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)HeapAlloc(GetProcessHeap(), 0,
+ sizeof(*mdi_cs));
+ if (!mdi_cs)
+ {
+ HeapFree(GetProcessHeap(), 0, cs);
+ return -1;
+ }
+ *mdi_cs = *(MDICREATESTRUCTA *)cs->lpCreateParams;
+ if (HIWORD(mdi_cs->szTitle))
+ mdi_cs->szTitle = HEAP_strdupWtoA(GetProcessHeap(), 0,
+ (LPCWSTR)mdi_cs->szTitle);
+ if (HIWORD(mdi_cs->szClass))
+ mdi_cs->szClass = HEAP_strdupWtoA(GetProcessHeap(), 0,
+ (LPCWSTR)mdi_cs->szClass);
+ cs->lpCreateParams = (LPVOID)mdi_cs;
+ }
*plparam = (LPARAM)cs;
}
return 1;
@@ -1100,6 +1148,15 @@ void WINPROC_UnmapMsg32WTo32A( HWND hwnd
HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
if (HIWORD(cs->lpszClass))
HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
+ if (GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
+ {
+ MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs->lpCreateParams;
+ if (HIWORD(mdi_cs->szTitle))
+ HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szTitle);
+ if (HIWORD(mdi_cs->szClass))
+ HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szClass);
+ HeapFree(GetProcessHeap(), 0, mdi_cs);
+ }
HeapFree( GetProcessHeap(), 0, cs );
}
break;
More information about the wine-devel
mailing list