3 * Copyright 1994, Bob Amstadt
5 * This file contains routines to support MDI features.
14 /* #define DEBUG_MDI /* */
16 /**********************************************************************
20 MDIRecreateMenuList(MDICLIENTINFO
*ci
)
27 fprintf(stderr
, "MDIRecreateMenuList: hWindowMenu %04.4x\n",
31 id
= ci
->idFirstChild
;
32 while (DeleteMenu(ci
->hWindowMenu
, id
, MF_BYCOMMAND
))
36 fprintf(stderr
, "MDIRecreateMenuList: id %04.4x, idFirstChild %04.4x\n",
37 id
, ci
->idFirstChild
);
40 if (!ci
->flagMenuAltered
)
42 ci
->flagMenuAltered
= TRUE
;
43 AppendMenu(ci
->hWindowMenu
, MF_SEPARATOR
, 0, NULL
);
46 id
= ci
->idFirstChild
;
48 for (chi
= ci
->infoActiveChildren
; chi
!= NULL
; chi
= chi
->next
)
50 n
= sprintf(buffer
, "%d ", index
++);
51 GetWindowText(chi
->hwnd
, buffer
+ n
, sizeof(buffer
) - n
- 1);
54 fprintf(stderr
, "MDIRecreateMenuList: id %04.4x, '%s'\n",
58 AppendMenu(ci
->hWindowMenu
, MF_STRING
, id
++, buffer
);
62 /**********************************************************************
66 MDICreateClient(WND
*w
, MDICLIENTINFO
*ci
, HWND parent
, LPMDICREATESTRUCT cs
)
73 cs
->style
&= (WS_MINIMIZE
| WS_MAXIMIZE
| WS_HSCROLL
| WS_VSCROLL
);
75 hwnd
= CreateWindowEx(0, cs
->szClass
, cs
->szTitle
,
76 WS_CHILD
| WS_BORDER
| WS_CAPTION
| WS_CLIPSIBLINGS
|
77 WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
| WS_SYSMENU
|
78 WS_THICKFRAME
| WS_VISIBLE
| cs
->style
,
79 cs
->x
, cs
->y
, cs
->cx
, cs
->cy
, parent
, (HMENU
) 0,
80 w
->hInstance
, cs
->lParam
);
84 HANDLE h
= USER_HEAP_ALLOC(GMEM_MOVEABLE
, sizeof(MDICHILDINFO
));
85 MDICHILDINFO
*child_info
= USER_HEAP_ADDR(h
);
92 ci
->nActiveChildren
++;
94 child_info
->next
= ci
->infoActiveChildren
;
95 child_info
->prev
= NULL
;
96 child_info
->hwnd
= hwnd
;
98 if (ci
->infoActiveChildren
)
99 ci
->infoActiveChildren
->prev
= child_info
;
101 ci
->infoActiveChildren
= child_info
;
103 SendMessage(parent
, WM_CHILDACTIVATE
, 0, 0);
109 /**********************************************************************
113 MDIDestroyClient(WND
*w_parent
, MDICLIENTINFO
*ci
, HWND parent
, HWND child
,
118 chi
= ci
->infoActiveChildren
;
119 while (chi
&& chi
->hwnd
!= child
)
125 chi
->prev
->next
= chi
->next
;
127 chi
->next
->prev
= chi
->prev
;
128 if (ci
->infoActiveChildren
== chi
)
129 ci
->infoActiveChildren
= chi
->next
;
131 ci
->nActiveChildren
--;
133 if (chi
->hwnd
== ci
->hwndActiveChild
)
134 SendMessage(parent
, WM_CHILDACTIVATE
, 0, 0);
136 USER_HEAP_FREE((HANDLE
) chi
);
139 DestroyWindow(child
);
145 /**********************************************************************
148 void MDIBringChildToTop(HWND parent
, WORD id
, WORD by_id
)
155 w
= WIN_FindWndPtr(parent
);
156 ci
= (MDICLIENTINFO
*) w
->wExtra
;
159 fprintf(stderr
, "MDIBringToTop: id %04.4x, by_id %d\n", id
, by_id
);
163 id
-= ci
->idFirstChild
;
164 if (!by_id
|| id
< ci
->nActiveChildren
)
166 chi
= ci
->infoActiveChildren
;
170 for (i
= 0; i
< id
; i
++)
175 while (chi
&& chi
->hwnd
!= id
)
183 fprintf(stderr
, "MDIBringToTop: child %04.4x\n", chi
->hwnd
);
185 if (chi
!= ci
->infoActiveChildren
)
187 SetWindowPos(chi
->hwnd
, HWND_TOP
, 0, 0, 0, 0,
188 SWP_NOMOVE
| SWP_NOSIZE
);
191 chi
->next
->prev
= chi
->prev
;
194 chi
->prev
->next
= chi
->next
;
197 chi
->next
= ci
->infoActiveChildren
;
198 chi
->next
->prev
= chi
;
199 ci
->infoActiveChildren
= chi
;
201 SendMessage(parent
, WM_CHILDACTIVATE
, 0, 0);
205 fprintf(stderr
, "MDIBringToTop: pos %04.4x, hwnd %04.4x\n",
211 /**********************************************************************
214 LONG
MDIChildActivated(WND
*w
, MDICLIENTINFO
*ci
, HWND parent
)
222 fprintf(stderr
, "MDIChildActivate: top %04.4x\n", w
->hwndChild
);
225 chi
= ci
->infoActiveChildren
;
228 deact_hwnd
= ci
->hwndActiveChild
;
229 act_hwnd
= chi
->hwnd
;
230 lParam
= ((LONG
) deact_hwnd
<< 16) | act_hwnd
;
233 fprintf(stderr
, "MDIChildActivate: deact %04.4x, act %04.4x\n",
234 deact_hwnd
, act_hwnd
);
237 ci
->hwndActiveChild
= act_hwnd
;
239 if (deact_hwnd
!= act_hwnd
)
241 MDIRecreateMenuList(ci
);
242 SendMessage(deact_hwnd
, WM_NCACTIVATE
, FALSE
, 0);
243 SendMessage(deact_hwnd
, WM_MDIACTIVATE
, FALSE
, lParam
);
246 SendMessage(act_hwnd
, WM_NCACTIVATE
, TRUE
, 0);
247 SendMessage(act_hwnd
, WM_MDIACTIVATE
, TRUE
, lParam
);
250 if (chi
|| ci
->nActiveChildren
== 0)
252 MDIRecreateMenuList(ci
);
253 DrawMenuBar(GetParent(parent
));
259 /**********************************************************************
262 LONG
MDICascade(HWND parent
, MDICLIENTINFO
*ci
)
266 int spacing
, xsize
, ysize
;
269 GetClientRect(parent
, &rect
);
270 spacing
= GetSystemMetrics(SM_CYCAPTION
) + GetSystemMetrics(SM_CYFRAME
);
271 ysize
= abs(rect
.bottom
- rect
.top
) - 8 * spacing
;
272 xsize
= abs(rect
.right
- rect
.left
) - 8 * spacing
;
276 "MDICascade: Client wnd at (%d,%d) - (%d,%d), spacing %d\n",
277 rect
.left
, rect
.top
, rect
.right
, rect
.bottom
, spacing
);
278 fprintf(stderr
, "MDICascade: searching for last child\n");
280 for (chi
= ci
->infoActiveChildren
; chi
->next
!= NULL
; chi
= chi
->next
)
284 fprintf(stderr
, "MDICascade: last child is %04.4x\n", chi
->hwnd
);
288 for ( ; chi
!= NULL
; chi
= chi
->prev
)
291 fprintf(stderr
, "MDICascade: move %04.4x to (%d,%d) size [%d,%d]\n",
292 chi
->hwnd
, x
, y
, xsize
, ysize
);
294 SetWindowPos(chi
->hwnd
, 0, x
, y
, xsize
, ysize
,
295 SWP_DRAWFRAME
| SWP_NOACTIVATE
| SWP_NOZORDER
);
304 /**********************************************************************
307 * This function is the handler for all MDI requests.
310 MDIClientWndProc(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
313 LPCLIENTCREATESTRUCT ccs
;
318 w
= WIN_FindWndPtr(hwnd
);
319 ci
= (MDICLIENTINFO
*) w
->wExtra
;
323 case WM_CHILDACTIVATE
:
324 return MDIChildActivated(w
, ci
, hwnd
);
327 cs
= (LPCREATESTRUCT
) lParam
;
328 ccs
= (LPCLIENTCREATESTRUCT
) cs
->lpCreateParams
;
329 ci
->hWindowMenu
= ccs
->hWindowMenu
;
330 ci
->idFirstChild
= ccs
->idFirstChild
;
331 ci
->infoActiveChildren
= NULL
;
332 ci
->flagMenuAltered
= FALSE
;
333 ci
->flagChildMaximized
= FALSE
;
334 w
->dwStyle
|= WS_CLIPCHILDREN
;
336 GetClientRect(w
->hwndParent
, &rect
);
337 MoveWindow(hwnd
, 0, 0, rect
.right
, rect
.bottom
, 1);
342 MDIBringChildToTop(hwnd
, wParam
, FALSE
);
346 return MDICascade(hwnd
, ci
);
349 return MDICreateClient(w
, ci
, hwnd
, (LPMDICREATESTRUCT
) lParam
);
352 return MDIDestroyClient(w
, ci
, hwnd
, wParam
, TRUE
);
354 case WM_MDIGETACTIVE
:
355 return ((LONG
) ci
->hwndActiveChild
|
356 ((LONG
) ci
->flagChildMaximized
<< 16));
358 case WM_MDIICONARRANGE
:
359 /* return MDIIconArrange(...) */
363 ci
->flagChildMaximized
= TRUE
;
364 MDIBringChildToTop(hwnd
, wParam
, FALSE
);
368 SendMessage(ci
->hwndActiveChild
, message
, wParam
, lParam
);
371 case WM_PARENTNOTIFY
:
372 if (wParam
== WM_DESTROY
)
373 return MDIDestroyClient(w
, ci
, hwnd
, LOWORD(lParam
), FALSE
);
374 else if (wParam
== WM_LBUTTONDOWN
)
375 MDIBringChildToTop(hwnd
, ci
->hwndHitTest
, FALSE
);
380 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
383 /**********************************************************************
384 * DefFrameProc (USER.445)
388 DefFrameProc(HWND hwnd
, HWND hwndMDIClient
, WORD message
,
389 WORD wParam
, LONG lParam
)
394 MDIBringChildToTop(hwndMDIClient
, wParam
, TRUE
);
398 SendMessage(hwndMDIClient
, message
, wParam
, lParam
);
402 SendMessage(hwndMDIClient
, WM_SETFOCUS
, wParam
, lParam
);
406 MoveWindow(hwndMDIClient
, 0, 0, LOWORD(lParam
), HIWORD(lParam
), TRUE
);
411 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
414 /**********************************************************************
415 * DefMDIChildProc (USER.447)
419 DefMDIChildProc(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
424 w
= WIN_FindWndPtr(GetParent(hwnd
));
425 ci
= (MDICLIENTINFO
*) w
->wExtra
;
430 ci
->hwndHitTest
= hwnd
;
434 return NC_DoNCPaint(hwnd
, (HRGN
)1,
435 hwnd
== ci
->hwndActiveChild
);
438 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
441 /**********************************************************************
442 * TranslateMDISysAccel (USER.451)
445 BOOL
TranslateMDISysAccel(HWND hwndClient
, LPMSG msg
)