Permalink
Browse files

Fixed: MDI dialogs and menu behavior in Windows.

  • Loading branch information...
1 parent 7a02777 commit 3145677cbbbd6c2dbc01726b168939e196e72dfb scuri committed Jun 21, 2012
Showing with 75 additions and 71 deletions.
  1. +2 −0 html/en/history3.html
  2. +0 −2 html/en/to_do.html
  3. +25 −10 src/win/iupwin_canvas.c
  4. +46 −51 src/win/iupwin_dialog.c
  5. +1 −1 src/win/iupwin_drv.h
  6. +1 −7 src/win/iupwin_menu.c
View
@@ -218,6 +218,8 @@ <h2 align="center">History of Changes in Version 3.x</h2>
<strong>IupText</strong> on Windows.</li>
<li><span class="hist_fixed">Fixed:</span> improved memory usage in variable
parameter attribute functions.</li>
+ <li><span class="hist_fixed">Fixed:</span> MDI dialogs and menu behavior in
+ Windows.</li>
</ul>
View
@@ -100,8 +100,6 @@ <h2 align="center">To Do</h2>
is still flicker when the dialog is resized. <strong>IupTabs</strong> in Windows Vista when
COMPOSITE=YES works only if MULTILINE=YES. (since 3.0)</li>
- <li><span class="style1">Known Issue:</span> the MDI Window menu is not
- properly updated when the child mdi is closed. (since 3.0)</li>
<li><span class="style1">Known Issue:</span> in Windows when CANFOCUS=NO
only the Tab key navigation is not done, when clicked the control will still
get the focus. The only exceptions are button and canvas.</li>
View
@@ -419,8 +419,14 @@ static int winCanvasProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
/* w=LOWORD (lp), h=HIWORD(lp) can not be used because an invalid size
at the first time of WM_SIZE with scroolbars. */
}
- *result = 0;
- return 1;
+
+ if (!iupAttribGetBoolean(ih, "MDICLIENT"))
+ {
+ /* If a MDI client, let the DefMDIChildProc do its work. */
+ *result = 0;
+ return 1;
+ }
+ break;
}
case WM_GETDLGCODE:
/* avoid beeps when keys are pressed */
@@ -541,13 +547,21 @@ static int winCanvasProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
ReleaseCapture();
break;
case WM_VSCROLL:
- winCanvasUpdateVerScroll(ih, LOWORD(wp));
- *result = 0;
- return 1;
+ if (!iupAttribGetBoolean(ih, "MDICLIENT"))
+ {
+ /* only update the scrollbar is not a MDI client */
+ winCanvasUpdateVerScroll(ih, LOWORD(wp));
+ *result = 0;
+ return 1;
+ }
case WM_HSCROLL:
- winCanvasUpdateHorScroll(ih, LOWORD(wp));
- *result = 0;
- return 1;
+ if (!iupAttribGetBoolean(ih, "MDICLIENT"))
+ {
+ /* only update the scrollbar is not a MDI client */
+ winCanvasUpdateHorScroll(ih, LOWORD(wp));
+ *result = 0;
+ return 1;
+ }
case WM_SETFOCUS:
if (!iupAttribGetBoolean(ih, "CANFOCUS"))
{
@@ -601,7 +615,8 @@ static int winCanvasMapMethod(Ihandle* ih)
Ihandle *winmenu = IupGetAttributeHandle(ih, "MDIMENU");
classname = "mdiclient";
- dwStyle = WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|MDIS_ALLCHILDSTYLES;
+ dwStyle = WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|MDIS_ALLCHILDSTYLES;
+ dwExStyle = WS_EX_CLIENTEDGE;
iupAttribSetStr(ih, "BORDER", "NO");
@@ -614,7 +629,7 @@ static int winCanvasMapMethod(Ihandle* ih)
for each additional MDI child window the application creates,
and reassigns identifiers when the application
destroys a window to keep the range of identifiers contiguous. */
- clientstruct.idFirstChild = IUP_MDICHILD_START;
+ clientstruct.idFirstChild = IUP_MDI_FIRSTCHILD;
}
else
classname = "IupCanvas";
View
@@ -204,6 +204,13 @@ int iupdrvDialogSetPlacement(Ihandle* ih)
return 1;
}
+static void winDialogMDIRefreshMenu(Ihandle* ih)
+{
+ /* We manually update the menu when a MDI child is added or removed. */
+ Ihandle* client = (Ihandle*)iupAttribGet(ih, "MDICLIENT_HANDLE");
+ PostMessage(client->handle, WM_MDIREFRESHMENU, 0, 0);
+}
+
static int winDialogMDICloseChildren(Ihandle* ih)
{
Ihandle* client = (Ihandle*)iupAttribGet(ih, "MDICLIENT_HANDLE");
@@ -334,6 +341,17 @@ static int winDialogBaseProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESUL
}
winDialogResize(ih, LOWORD(lp), HIWORD(lp));
+
+ if (iupAttribGetBoolean(ih, "MDICHILD"))
+ {
+ /* WORKAROUND: when a child MDI dialog is maximized,
+ its title is displayed inside the MDI client area.
+ So we force a MDI client size update */
+ RECT rect;
+ Ihandle* client = (Ihandle*)iupAttribGet(ih, "MDICLIENT_HANDLE");
+ GetClientRect(client->handle, &rect);
+ PostMessage(client->handle, WM_SIZE, (WPARAM)SIZE_RESTORED, MAKELPARAM(rect.right-rect.left, rect.bottom-rect.top));
+ }
break;
}
case SIZE_RESTORED:
@@ -351,8 +369,10 @@ static int winDialogBaseProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESUL
}
}
- if (iupAttribGet(ih, "MDIFRAME"))
+ if (iupAttribGetBoolean(ih, "MDIFRAME"))
{
+ /* We are going to manually position the MDI client,
+ so abort MDI frame processing. */
*result = 0;
return 1;
}
@@ -583,17 +603,13 @@ static LRESULT CALLBACK winDialogMDIChildProc(HWND hwnd, UINT msg, WPARAM wp, LP
return DefMDIChildProc(hwnd, msg, wp, lp);
}
- switch (msg)
+ if (msg == WM_MDIACTIVATE)
{
- case WM_MDIACTIVATE:
+ HWND hNewActive = (HWND)lp;
+ if (hNewActive == ih->handle)
{
- HWND hNewActive = (HWND)lp;
- if (hNewActive == ih->handle)
- {
- Icallback cb = (Icallback)IupGetCallback(ih, "MDIACTIVATE_CB");
- if (cb) cb(ih);
- }
- break;
+ Icallback cb = (Icallback)IupGetCallback(ih, "MDIACTIVATE_CB");
+ if (cb) cb(ih);
}
}
@@ -603,29 +619,6 @@ static LRESULT CALLBACK winDialogMDIChildProc(HWND hwnd, UINT msg, WPARAM wp, LP
return DefMDIChildProc(hwnd, msg, wp, lp);
}
-static Ihandle* winDialogGetMdiChildId(Ihandle* ih, int mdi_child_id)
-{
- int id, max_child_id, real_id = -1;
- char name[50];
- Ihandle* child;
-
- max_child_id = iupAttribGetInt(ih, "_IUPWIN_MAX_MDI_ID");
-
- for (id = 0; id < max_child_id; id++)
- {
- sprintf(name, "_IUPWIN_MDI_ID_[%d]", id);
- child = (Ihandle*)iupAttribGet(ih, name);
- if (iupObjectCheck(child))
- {
- real_id++;
- if (real_id == mdi_child_id)
- return child;
- }
- }
-
- return NULL;
-}
-
static LRESULT CALLBACK winDialogMDIFrameProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
LRESULT result;
@@ -651,18 +644,22 @@ static LRESULT CALLBACK winDialogMDIFrameProc(HWND hwnd, UINT msg, WPARAM wp, LP
if (winDialogBaseProc(ih, msg, wp, lp, &result))
return result;
- switch (msg)
+ if (msg == WM_MENUCOMMAND)
{
- case WM_MENUCOMMAND:
+ int menuId = GetMenuItemID((HMENU)lp, (int)wp);
+ if (menuId >= IUP_MDI_FIRSTCHILD && hWndClient)
{
- int menuId = GetMenuItemID((HMENU)lp, (int)wp);
- if (menuId >= IUP_MDICHILD_START && hWndClient)
- {
- Ihandle* child = winDialogGetMdiChildId(ih, menuId-IUP_MDICHILD_START);
- if (child)
- SendMessage(hWndClient, WM_MDIACTIVATE, (WPARAM)child->handle, 0);
- break;
- }
+ /* we manually activate the MDI child when its menu item is selected. */
+ HWND hChild = GetDlgItem(hWndClient, menuId);
+ if (hChild)
+ SendMessage(hWndClient, WM_MDIACTIVATE, (WPARAM)hChild, 0);
+ }
+ else if (menuId >= SC_SIZE && menuId <= SC_CONTEXTHELP)
+ {
+ /* we manually forward the message to the MDI child */
+ HWND hChild = (HWND)SendMessage(hWndClient, WM_MDIGETACTIVE, 0, 0);
+ if (hChild)
+ SendMessage(hChild, WM_SYSCOMMAND, (WPARAM)menuId, 0);
}
}
@@ -760,9 +757,7 @@ static int winDialogMapMethod(Ihandle* ih)
if (iupAttribGetBoolean(ih, "MDICHILD"))
{
- static int mdi_child_id = 0;
Ihandle *client;
- char name[50];
/* must have a parent dialog (the mdi frame) */
Ihandle* parent = IupGetAttributeHandle(ih, "PARENTDIALOG");
@@ -777,11 +772,6 @@ static int winDialogMapMethod(Ihandle* ih)
/* store the mdi client handle in each mdi child also */
iupAttribSetStr(ih, "MDICLIENT_HANDLE", (char*)client);
- sprintf(name, "_IUPWIN_MDI_ID_[%d]", mdi_child_id);
- iupAttribSetStr(parent, name, (char*)ih);
- mdi_child_id++;
- iupAttribSetInt(parent, "_IUPWIN_MAX_MDI_ID", mdi_child_id);
-
classname = "IupDialogMDIChild";
/* The actual parent is the mdi client */
@@ -826,7 +816,7 @@ static int winDialogMapMethod(Ihandle* ih)
}
}
- if (iupAttribGet(ih, "MDIFRAME"))
+ if (iupAttribGetBoolean(ih, "MDIFRAME"))
{
COLORREF color = GetSysColor(COLOR_BTNFACE);
iupAttribSetStrf(ih, "_IUPWIN_BACKGROUND_COLOR", "%d %d %d", (int)GetRValue(color),
@@ -909,6 +899,9 @@ static int winDialogMapMethod(Ihandle* ih)
/* Set the default CmdShow for ShowWindow */
ih->data->cmd_show = SW_SHOWNORMAL;
+ if (iupAttribGetBoolean(ih, "MDICHILD"))
+ winDialogMDIRefreshMenu(ih);
+
return IUP_NOERROR;
}
@@ -935,6 +928,8 @@ static void winDialogUnMapMethod(Ihandle* ih)
/* for MDICHILDs must send WM_MDIDESTROY, instead of calling DestroyWindow */
Ihandle* client = (Ihandle*)iupAttribGet(ih, "MDICLIENT_HANDLE");
SendMessage(client->handle, WM_MDIDESTROY, (WPARAM)ih->handle, 0);
+
+ winDialogMDIRefreshMenu(ih);
}
else
DestroyWindow(ih->handle); /* this will destroy the Windows children also. */
View
@@ -120,7 +120,7 @@ int iupwinGetScreenRes(void);
/* child window identifier of the first MDI child window created,
should not conflict with any other command identifiers. */
-#define IUP_MDICHILD_START 100000000
+#define IUP_MDI_FIRSTCHILD 100000000
#ifdef __cplusplus
View
@@ -102,12 +102,6 @@ static void winItemCheckToggle(Ihandle* ih)
}
}
-typedef struct _IchildId
-{
- int id, menuid;
- Ihandle* child;
-} IchildId;
-
void iupwinMenuDialogProc(Ihandle* ih_dialog, UINT msg, WPARAM wp, LPARAM lp)
{
/* called only from winDialogBaseProc */
@@ -172,7 +166,7 @@ void iupwinMenuDialogProc(Ihandle* ih_dialog, UINT msg, WPARAM wp, LPARAM lp)
Icallback cb;
Ihandle* ih;
- if (menuId >= IUP_MDICHILD_START)
+ if (menuId >= IUP_MDI_FIRSTCHILD)
break;
ih = iupwinMenuGetItemHandle((HMENU)lp, menuId);

0 comments on commit 3145677

Please sign in to comment.