blob: a22d1deb49093c0ff6dfa02773861787d060f8a8 [file] [log] [blame]
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001/* MDI.C
2 *
3 * Copyright 1994, Bob Amstadt
Alexandre Julliard7e56f681996-01-31 19:02:28 +00004 * 1995,1996 Alex Korobka
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00005 *
6 * This file contains routines to support MDI features.
Alexandre Julliardd4719651995-12-12 18:49:11 +00007 *
8 * Notes: Windows keeps ID of MDI menu item in the wIDenu field
9 * of corresponding MDI child.
10 *
11 * Basic child activation routine is MDI_ChildActivate and
Alexandre Julliard7e56f681996-01-31 19:02:28 +000012 * SetWindowPos(childHwnd,...) implicitly calls it if SWP_NOACTIVATE
Alexandre Julliardd4719651995-12-12 18:49:11 +000013 * is not used.
Alexandre Julliard7e56f681996-01-31 19:02:28 +000014 *
15 * To fix:
16 * Sticky client crollbars
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000017 */
Alexandre Julliardd4719651995-12-12 18:49:11 +000018
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000019#include <stdlib.h>
Alexandre Julliardd4719651995-12-12 18:49:11 +000020#include <string.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000021#include <stdio.h>
Alexandre Julliard490a27e1994-06-08 13:57:50 +000022#include <math.h>
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +000023#include "xmalloc.h"
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000024#include "windows.h"
25#include "win.h"
Alexandre Julliard18506551995-01-24 16:21:01 +000026#include "nonclient.h"
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000027#include "mdi.h"
28#include "user.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000029#include "menu.h"
Alexandre Julliard7e56f681996-01-31 19:02:28 +000030#include "stackframe.h"
Alexandre Julliard58199531994-04-21 01:20:00 +000031#include "sysmetrics.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000032#include "stddebug.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000033#include "debug.h"
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000034
Alexandre Julliard59730ae1996-03-24 16:20:51 +000035void MDI_UpdateFrameText(WND *, HWND, BOOL, LPCSTR);
36BOOL MDI_AugmentFrameMenu(MDICLIENTINFO*, WND *, HWND);
37BOOL MDI_RestoreFrameMenu(WND *, HWND);
Alexandre Julliard7e56f681996-01-31 19:02:28 +000038
Alexandre Julliardd4719651995-12-12 18:49:11 +000039void ScrollChildren(HWND , UINT , WPARAM , LPARAM );
40void CalcChildScroll(HWND, WORD);
41
42/* ----------------- declarations ----------------- */
43
44static LONG MDI_ChildActivate(WND* ,HWND );
45
46/* -------- Miscellaneous service functions ----------
47 *
48 * MDI_GetChildByID
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000049 */
Alexandre Julliardd4719651995-12-12 18:49:11 +000050
Alexandre Julliard59730ae1996-03-24 16:20:51 +000051static HWND MDI_GetChildByID(WND* wndPtr,int id)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000052{
Alexandre Julliard59730ae1996-03-24 16:20:51 +000053 for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
54 if (wndPtr->wIDmenu == id) return wndPtr->hwndSelf;
55 return 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000056}
57
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000058/**********************************************************************
Alexandre Julliardd4719651995-12-12 18:49:11 +000059 * MDI_MenuAppendItem
60 */
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +000061#ifdef SUPERFLUOUS_FUNCTIONS
Alexandre Julliardd4719651995-12-12 18:49:11 +000062static BOOL MDI_MenuAppendItem(WND *clientWnd, HWND hWndChild)
63{
Alexandre Julliard7e56f681996-01-31 19:02:28 +000064 char buffer[128];
Alexandre Julliardd4719651995-12-12 18:49:11 +000065 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
66 WND *wndPtr = WIN_FindWndPtr(hWndChild);
67 LPSTR lpWndText = (LPSTR) USER_HEAP_LIN_ADDR(wndPtr->hText);
68 int n = sprintf(buffer, "%d ",
69 clientInfo->nActiveChildren);
70
71 if( !clientInfo->hWindowMenu ) return 0;
72
73 if( lpWndText )
74 strncpy(buffer + n, lpWndText, sizeof(buffer) - n - 1);
75 return AppendMenu(clientInfo->hWindowMenu,MF_STRING,
Alexandre Julliard7e56f681996-01-31 19:02:28 +000076 wndPtr->wIDmenu, MAKE_SEGPTR(buffer) );
Alexandre Julliardd4719651995-12-12 18:49:11 +000077}
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +000078#endif
Alexandre Julliardd4719651995-12-12 18:49:11 +000079
80/**********************************************************************
81 * MDI_MenuModifyItem
82 */
83static BOOL MDI_MenuModifyItem(WND* clientWnd, HWND hWndChild )
84{
85 char buffer[128];
86 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
87 WND *wndPtr = WIN_FindWndPtr(hWndChild);
88 LPSTR lpWndText = (LPSTR) USER_HEAP_LIN_ADDR(wndPtr->hText);
89 UINT n = sprintf(buffer, "%d ",
90 wndPtr->wIDmenu - clientInfo->idFirstChild + 1);
91 BOOL bRet = 0;
92
93 if( !clientInfo->hWindowMenu ) return 0;
94
Alexandre Julliard7e56f681996-01-31 19:02:28 +000095 if( lpWndText ) lstrcpyn(buffer + n, lpWndText, sizeof(buffer) - n );
Alexandre Julliardd4719651995-12-12 18:49:11 +000096
97 n = GetMenuState(clientInfo->hWindowMenu,wndPtr->wIDmenu ,MF_BYCOMMAND);
98 bRet = ModifyMenu(clientInfo->hWindowMenu , wndPtr->wIDmenu ,
Alexandre Julliard7e56f681996-01-31 19:02:28 +000099 MF_BYCOMMAND | MF_STRING, wndPtr->wIDmenu ,
100 MAKE_SEGPTR(buffer) );
101 CheckMenuItem(clientInfo->hWindowMenu ,wndPtr->wIDmenu , n & MF_CHECKED);
Alexandre Julliardd4719651995-12-12 18:49:11 +0000102 return bRet;
103}
104
105/**********************************************************************
106 * MDI_MenuDeleteItem
107 */
108static BOOL MDI_MenuDeleteItem(WND* clientWnd, HWND hWndChild )
109{
110 char buffer[128];
111 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
112 WND *wndPtr = WIN_FindWndPtr(hWndChild);
113 LPSTR lpWndText;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000114 UINT index = 0,id,n;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000115
116 if( !clientInfo->nActiveChildren ||
117 !clientInfo->hWindowMenu ) return 0;
118
119 id = wndPtr->wIDmenu;
120 DeleteMenu(clientInfo->hWindowMenu,id,MF_BYCOMMAND);
121
122 /* walk the rest of MDI children to prevent gaps in the id
123 * sequence and in the menu child list
124 */
125
126 for( index = id+1; index <= clientInfo->nActiveChildren +
127 clientInfo->idFirstChild; index++ )
128 {
129 wndPtr = WIN_FindWndPtr(MDI_GetChildByID(clientWnd,index));
130 if( !wndPtr )
131 {
132 dprintf_mdi(stddeb,"MDIMenuDeleteItem: no window for id=%i\n",index);
133 continue;
134 }
135
136 /* set correct id */
137 wndPtr->wIDmenu--;
138
139 n = sprintf(buffer, "%d ",index - clientInfo->idFirstChild);
140 lpWndText = (LPSTR) USER_HEAP_LIN_ADDR(wndPtr->hText);
141
142 if( lpWndText )
143 strncpy(buffer + n, lpWndText, sizeof(buffer) - n - 1);
144
145 /* change menu */
146 ModifyMenu(clientInfo->hWindowMenu ,index ,MF_BYCOMMAND | MF_STRING,
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000147 index - 1 , MAKE_SEGPTR(buffer) );
Alexandre Julliardd4719651995-12-12 18:49:11 +0000148 }
149 return 1;
150}
151
152/**********************************************************************
153 * MDI_GetWindow
154 *
155 * returns "activateable" child or zero
156 */
157HWND MDI_GetWindow(WND *clientWnd, HWND hWnd, WORD wTo )
158{
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000159 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientWnd->wExtra;
160 WND *wndPtr, *pWnd, *pWndLast;
161
162 if( !hWnd ) hWnd = clientInfo->hwndActiveChild;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000163
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000164 if( !(wndPtr = WIN_FindWndPtr(hWnd)) ) return 0;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000165
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000166 pWnd = wndPtr;
167 pWndLast = NULL;
168 for (;;)
Alexandre Julliardd4719651995-12-12 18:49:11 +0000169 {
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000170 pWnd = pWnd->next;
171 if (!pWnd) pWnd = wndPtr->parent->child;
172 if (pWnd == wndPtr) /* not found */
173 {
174 if (!wTo || !pWndLast) return 0;
175 break;
176 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000177
178 /* we are not interested in owned popups */
179 if ( !pWnd->owner &&
180 (pWnd->dwStyle & WS_VISIBLE) &&
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000181 !(pWnd->dwStyle & WS_DISABLED)) /* found one */
182 {
183 pWndLast = pWnd;
184 if (!wTo) break;
185 }
Alexandre Julliardd4719651995-12-12 18:49:11 +0000186 }
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000187 return pWndLast ? pWndLast->hwndSelf : 0;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000188}
189
190
191/**********************************************************************
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000192 * MDISetMenu
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000193 */
194HMENU MDISetMenu(HWND hwnd, BOOL fRefresh, HMENU hmenuFrame, HMENU hmenuWindow)
195{
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000196 WND *w = WIN_FindWndPtr(hwnd);
197 MDICLIENTINFO *ci;
198
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000199 dprintf_mdi(stddeb, "WM_MDISETMENU: %04x %04x %04x %04x\n",
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000200 hwnd, fRefresh, hmenuFrame, hmenuWindow);
201
202 ci = (MDICLIENTINFO *) w->wExtra;
203
204 if (!fRefresh)
205 {
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000206 HWND hwndFrame = GetParent(hwnd);
207 HMENU oldFrameMenu = GetMenu(hwndFrame);
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000208
209 if( ci->flagChildMaximized && hmenuFrame && hmenuFrame!=oldFrameMenu )
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000210 MDI_RestoreFrameMenu(w->parent, ci->flagChildMaximized );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000211
212 if( hmenuWindow && hmenuWindow!=ci->hWindowMenu )
213 {
214 /* delete menu items from ci->hWindowMenu
215 * and add them to hmenuWindow */
216
217 INT i = GetMenuItemCount(ci->hWindowMenu) - 1;
218 INT pos = GetMenuItemCount(hmenuWindow) + 1;
219
220 AppendMenu(hmenuWindow,MF_SEPARATOR,0,(SEGPTR)0);
221
222 if( ci->nActiveChildren )
223 {
224 INT j = i - ci->nActiveChildren + 1;
225 char buffer[100];
226 UINT id,state;
227
228 for( ; i >= j ; i-- )
229 {
230 id = GetMenuItemID(ci->hWindowMenu,i );
231 state = GetMenuState(ci->hWindowMenu,i,MF_BYPOSITION);
232
233 GetMenuString(ci->hWindowMenu, i, buffer, 100, MF_BYPOSITION);
234
235 DeleteMenu(ci->hWindowMenu, i , MF_BYPOSITION);
236 InsertMenu(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
237 id, MAKE_SEGPTR(buffer));
238 CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
239 }
240 }
241
242 /* remove separator */
243 DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION);
244
245 ci->hWindowMenu = hmenuWindow;
246 }
247
248 if( hmenuFrame && hmenuFrame!=oldFrameMenu)
249 {
250 SetMenu(hwndFrame, hmenuFrame);
251 if( ci->flagChildMaximized )
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000252 MDI_AugmentFrameMenu(ci, w->parent, ci->flagChildMaximized );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000253 return oldFrameMenu;
254 }
255
256 }
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000257 return 0;
258}
Alexandre Julliard2787be81995-05-22 18:23:01 +0000259
260/**********************************************************************
261 * MDIIconArrange
262 */
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000263WORD MDIIconArrange(HWND parent)
Alexandre Julliard2787be81995-05-22 18:23:01 +0000264{
265 return ArrangeIconicWindows(parent); /* Any reason why the */
266 /* existing icon arrange */
267 /* can't be used here? */
268 /* -DRP */
269}
270
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000271
272/* ------------------ MDI child window functions ---------------------- */
273
274
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000275/**********************************************************************
Alexandre Julliard58199531994-04-21 01:20:00 +0000276 * MDICreateChild
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000277 */
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000278HWND MDICreateChild(WND *w, MDICLIENTINFO *ci, HWND parent, LPARAM lParam )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000279{
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000280 MDICREATESTRUCT *cs = (MDICREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000281 HWND hwnd;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000282 WORD wIDmenu = ci->idFirstChild + ci->nActiveChildren;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000283 int spacing;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000284 char* lpstrDef="junk!";
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000285
286 /*
287 * Create child window
288 */
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000289
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000290 cs->style &= (WS_MINIMIZE | WS_MAXIMIZE | WS_HSCROLL | WS_VSCROLL);
Alexandre Julliard2787be81995-05-22 18:23:01 +0000291
292 /* The child windows should probably */
293 /* stagger, shouldn't they? -DRP */
294 spacing = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
295 cs->x = ci->nActiveChildren * spacing;
296 cs->y = ci->nActiveChildren * spacing;
297
Alexandre Julliardd4719651995-12-12 18:49:11 +0000298 /* this menu is needed to set a check mark in MDI_ChildActivate */
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000299 AppendMenu(ci->hWindowMenu ,MF_STRING ,wIDmenu, MAKE_SEGPTR(lpstrDef) );
Alexandre Julliardd4719651995-12-12 18:49:11 +0000300
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000301 ci->nActiveChildren++;
302
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000303 hwnd = CreateWindow( cs->szClass, cs->szTitle,
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000304 WS_CHILD | WS_BORDER | WS_CAPTION | WS_CLIPSIBLINGS |
305 WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU |
306 WS_THICKFRAME | WS_VISIBLE | cs->style,
Alexandre Julliardd4719651995-12-12 18:49:11 +0000307 cs->x, cs->y, cs->cx, cs->cy, parent,
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000308 (HMENU)(DWORD)(WORD)wIDmenu, w->hInstance,
309 (SEGPTR)lParam);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000310
311 if (hwnd)
312 {
Alexandre Julliardd4719651995-12-12 18:49:11 +0000313 MDI_MenuModifyItem(w ,hwnd);
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000314 dprintf_mdi(stddeb, "MDICreateChild: created child - %04x\n",hwnd);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000315 }
Alexandre Julliardd4719651995-12-12 18:49:11 +0000316 else
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000317 {
318 ci->nActiveChildren--;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000319 DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000320 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000321
322 return hwnd;
323}
324
325/**********************************************************************
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000326 * MDI_ChildGetMinMaxInfo
327 *
328 */
329void MDI_ChildGetMinMaxInfo(WND* clientWnd, HWND hwnd, MINMAXINFO* lpMinMax )
330{
331 WND* childWnd = WIN_FindWndPtr(hwnd);
332 RECT rect = clientWnd->rectClient;
333
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000334 MapWindowPoints(clientWnd->parent->hwndSelf,
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000335 ((MDICLIENTINFO*)clientWnd->wExtra)->self, (LPPOINT)&rect, 2);
336 AdjustWindowRectEx(&rect, childWnd->dwStyle, 0, childWnd->dwExStyle);
337
338 lpMinMax->ptMaxSize.x = rect.right -= rect.left;
339 lpMinMax->ptMaxSize.y = rect.bottom -= rect.top;
340
341 lpMinMax->ptMaxPosition.x = rect.left;
342 lpMinMax->ptMaxPosition.y = rect.top;
343}
344
345/**********************************************************************
Alexandre Julliardd4719651995-12-12 18:49:11 +0000346 * MDI_SwitchActiveChild
347 *
348 * Notes: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
349 * being activated
350 *
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000351 * wTo is basically lParam of WM_MDINEXT message or explicit
352 * window handle
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000353 */
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000354void MDI_SwitchActiveChild(HWND clientHwnd, HWND childHwnd, BOOL wTo )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000355{
Alexandre Julliardd4719651995-12-12 18:49:11 +0000356 WND *w = WIN_FindWndPtr(clientHwnd);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000357 HWND hwndTo = 0;
358 HWND hwndPrev = 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000359 MDICLIENTINFO *ci;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000360
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000361 hwndTo = MDI_GetWindow(w,childHwnd,(WORD)wTo);
362
Alexandre Julliardd4719651995-12-12 18:49:11 +0000363 ci = (MDICLIENTINFO *) w->wExtra;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000364
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000365 dprintf_mdi(stddeb, "MDI_SwitchActiveChild: from %04x, to %04x\n",childHwnd,hwndTo);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000366
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000367 if ( !hwndTo ) return;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000368
Alexandre Julliardd4719651995-12-12 18:49:11 +0000369 hwndPrev = ci->hwndActiveChild;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000370
Alexandre Julliardd4719651995-12-12 18:49:11 +0000371 if ( hwndTo != hwndPrev )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000372 {
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000373 BOOL bSA = 0;
374
375 if( ci->flagChildMaximized )
Alexandre Julliard58199531994-04-21 01:20:00 +0000376 {
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000377 bSA = 1;
378 w->dwStyle &= ~WS_VISIBLE;
Alexandre Julliard58199531994-04-21 01:20:00 +0000379 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000380
381 SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
382 SWP_NOMOVE | SWP_NOSIZE );
383 if( !wTo && hwndPrev )
Alexandre Julliard58199531994-04-21 01:20:00 +0000384 {
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000385 SetWindowPos( hwndPrev, HWND_BOTTOM, 0, 0, 0, 0,
386 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
Alexandre Julliard58199531994-04-21 01:20:00 +0000387 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000388
389 if( bSA )
390 ShowWindow( clientHwnd, SW_SHOW );
391 }
Alexandre Julliardd4719651995-12-12 18:49:11 +0000392}
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000393
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000394
Alexandre Julliardd4719651995-12-12 18:49:11 +0000395/**********************************************************************
396 * MDIDestroyChild
397 */
398HWND MDIDestroyChild(WND *w_parent, MDICLIENTINFO *ci, HWND parent,
399 HWND child, BOOL flagDestroy)
400{
401 WND *childPtr = WIN_FindWndPtr(child);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000402
Alexandre Julliardd4719651995-12-12 18:49:11 +0000403 if( childPtr )
404 {
405 if( child == ci->hwndActiveChild )
406 {
407 MDI_SwitchActiveChild(parent,child,0);
408
409 if( child == ci->hwndActiveChild )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000410 {
411 ShowWindow( child, SW_HIDE);
412 if( child == ci->flagChildMaximized )
413 {
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000414 MDI_RestoreFrameMenu(w_parent->parent, child);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000415 ci->flagChildMaximized = 0;
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000416 MDI_UpdateFrameText(w_parent->parent,parent,TRUE,NULL);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000417 }
Alexandre Julliardd4719651995-12-12 18:49:11 +0000418
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000419 MDI_ChildActivate(w_parent,0);
420 }
Alexandre Julliardd4719651995-12-12 18:49:11 +0000421 MDI_MenuDeleteItem(w_parent, child);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000422 }
423
Alexandre Julliardd4719651995-12-12 18:49:11 +0000424 ci->nActiveChildren--;
425
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000426 dprintf_mdi(stddeb,"MDIDestroyChild: child destroyed - %04x\n",child);
Alexandre Julliardd4719651995-12-12 18:49:11 +0000427
428 if (flagDestroy)
429 {
430 DestroyWindow(child);
431 PostMessage(parent,WM_MDICALCCHILDSCROLL,0,0L);
432 ci->sbRecalc |= (SB_BOTH+1);
433 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000434 }
Alexandre Julliardd4719651995-12-12 18:49:11 +0000435
436 return 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000437}
438
Alexandre Julliardd4719651995-12-12 18:49:11 +0000439
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000440/**********************************************************************
Alexandre Julliardd4719651995-12-12 18:49:11 +0000441 * MDI_ChildActivate
442 *
443 * Note: hWndChild is NULL when last child is being destroyed
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000444 */
Alexandre Julliardd4719651995-12-12 18:49:11 +0000445LONG MDI_ChildActivate(WND *clientPtr, HWND hWndChild)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000446{
Alexandre Julliardd4719651995-12-12 18:49:11 +0000447 MDICLIENTINFO *clientInfo = (MDICLIENTINFO*)clientPtr->wExtra;
448 HWND prevActiveWnd = clientInfo->hwndActiveChild;
449 WND *wndPtr = WIN_FindWndPtr( hWndChild );
450 WND *wndPrev = WIN_FindWndPtr( prevActiveWnd );
451 BOOL isActiveFrameWnd = 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000452
Alexandre Julliardd4719651995-12-12 18:49:11 +0000453 if( hWndChild == prevActiveWnd ) return 0L;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000454
Alexandre Julliardd4719651995-12-12 18:49:11 +0000455 if( wndPtr )
456 if( wndPtr->dwStyle & WS_DISABLED ) return 0L;
457
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000458 dprintf_mdi(stddeb,"MDI_ChildActivate: %04x\n", hWndChild);
Alexandre Julliardd4719651995-12-12 18:49:11 +0000459
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000460 if( GetActiveWindow() == clientPtr->parent->hwndSelf )
Alexandre Julliardd4719651995-12-12 18:49:11 +0000461 isActiveFrameWnd = TRUE;
462
463 /* deactivate prev. active child */
464 if( wndPrev )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000465 {
Alexandre Julliardd4719651995-12-12 18:49:11 +0000466 SendMessage( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L );
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000467#ifdef WINELIB32
468 SendMessage( prevActiveWnd, WM_MDIACTIVATE, (WPARAM)prevActiveWnd,
469 (LPARAM)hWndChild);
470#else
Alexandre Julliardd4719651995-12-12 18:49:11 +0000471 SendMessage( prevActiveWnd, WM_MDIACTIVATE, FALSE,
472 MAKELONG(hWndChild,prevActiveWnd));
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000473#endif
Alexandre Julliardd4719651995-12-12 18:49:11 +0000474 /* uncheck menu item */
475 if( clientInfo->hWindowMenu )
476 CheckMenuItem( clientInfo->hWindowMenu,
477 wndPrev->wIDmenu, 0);
478 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000479
Alexandre Julliardd4719651995-12-12 18:49:11 +0000480 /* set appearance */
481 if( clientInfo->flagChildMaximized )
482 if( clientInfo->flagChildMaximized != hWndChild )
483 if( hWndChild )
484 {
485 clientInfo->hwndActiveChild = hWndChild;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000486 ShowWindow( hWndChild, SW_SHOWMAXIMIZED);
Alexandre Julliardd4719651995-12-12 18:49:11 +0000487 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000488 else
489 ShowWindow( clientInfo->hwndActiveChild,
490 SW_SHOWNORMAL );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000491
Alexandre Julliardd4719651995-12-12 18:49:11 +0000492 clientInfo->hwndActiveChild = hWndChild;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000493
Alexandre Julliardd4719651995-12-12 18:49:11 +0000494 /* check if we have any children left */
495 if( !hWndChild )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000496 {
Alexandre Julliardd4719651995-12-12 18:49:11 +0000497 if( isActiveFrameWnd )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000498 SetFocus( clientInfo->self );
Alexandre Julliardd4719651995-12-12 18:49:11 +0000499 return 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000500 }
501
Alexandre Julliardd4719651995-12-12 18:49:11 +0000502 /* check menu item */
503 if( clientInfo->hWindowMenu )
504 CheckMenuItem( clientInfo->hWindowMenu,
505 wndPtr->wIDmenu, MF_CHECKED);
506
507 /* bring active child to the top */
508 SetWindowPos( hWndChild, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
509
510 if( isActiveFrameWnd )
511 {
512 SendMessage( hWndChild, WM_NCACTIVATE, TRUE, 0L);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000513 if( GetFocus() == clientInfo->self )
514 SendMessage( clientInfo->self, WM_SETFOCUS,
515 (WPARAM)clientInfo->self, 0L );
Alexandre Julliardd4719651995-12-12 18:49:11 +0000516 else
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000517 SetFocus( clientInfo->self );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000518 }
519
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000520#ifdef WINELIB32
521 SendMessage( hWndChild, WM_MDIACTIVATE, (WPARAM)hWndChild,
522 (LPARAM)prevActiveWnd );
523#else
Alexandre Julliardd4719651995-12-12 18:49:11 +0000524 SendMessage( hWndChild, WM_MDIACTIVATE, TRUE,
525 MAKELONG(prevActiveWnd,hWndChild) );
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000526#endif
Alexandre Julliardd4719651995-12-12 18:49:11 +0000527
528 return 1;
529}
530
531/**********************************************************************
532 * MDI_BuildWCL
533 *
534 * iTotal returns number of children available for tiling or cascading
535 */
536MDIWCL* MDI_BuildWCL(WND* clientWnd, int* iTotal)
537{
538 MDIWCL *listTop,*listNext;
539 WND *childWnd;
540
541 if (!(listTop = (MDIWCL*)malloc( sizeof(MDIWCL) ))) return NULL;
542
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000543 listTop->hChild = clientWnd->child ? clientWnd->child->hwndSelf : 0;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000544 listTop->prev = NULL;
545 *iTotal = 1;
546
547 /* build linked list from top child to bottom */
548
549 childWnd = WIN_FindWndPtr( listTop->hChild );
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000550 while( childWnd && childWnd->next )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000551 {
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000552 listNext = (MDIWCL*)xmalloc(sizeof(MDIWCL));
Alexandre Julliardd4719651995-12-12 18:49:11 +0000553
Alexandre Julliardd4719651995-12-12 18:49:11 +0000554 if( (childWnd->dwStyle & WS_DISABLED) ||
555 (childWnd->dwStyle & WS_MINIMIZE) ||
556 !(childWnd->dwStyle & WS_VISIBLE) )
557 {
558 listTop->hChild = 0;
559 (*iTotal)--;
560 }
561
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000562 listNext->hChild = childWnd->next->hwndSelf;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000563 listNext->prev = listTop;
564 listTop = listNext;
565 (*iTotal)++;
566
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000567 childWnd = childWnd->next;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000568 }
569
570 if( (childWnd->dwStyle & WS_DISABLED) ||
571 (childWnd->dwStyle & WS_MINIMIZE) ||
572 !(childWnd->dwStyle & WS_VISIBLE) )
573 {
574 listTop->hChild = 0;
575 (*iTotal)--;
576 }
577
578 return listTop;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000579}
580
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000581
582/* -------------------- MDI client window functions ------------------- */
583
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000584/**********************************************************************
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000585 * CreateMDIMenuBitmap
586 */
587HBITMAP CreateMDIMenuBitmap(void)
588{
589 HDC hDCSrc = CreateCompatibleDC(0);
590 HDC hDCDest = CreateCompatibleDC(hDCSrc);
591 HBITMAP hbClose = LoadBitmap(0, MAKEINTRESOURCE(OBM_CLOSE) );
592 HBITMAP hbCopy,hb_src,hb_dest;
593
594 hb_src = SelectObject(hDCSrc,hbClose);
595 hbCopy = CreateCompatibleBitmap(hDCSrc,SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE);
596 hb_dest = SelectObject(hDCDest,hbCopy);
597
598 BitBlt(hDCDest, 0, 0, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
599 hDCSrc, SYSMETRICS_CXSIZE, 0, SRCCOPY);
600
601 SelectObject(hDCSrc,hb_src);
602 SelectObject(hDCDest,hb_dest);
603
604 DeleteObject(hbClose);
605
606 DeleteDC(hDCDest);
607 DeleteDC(hDCSrc);
608
609 return hbCopy;
610}
611
612/**********************************************************************
613 * MDICascade
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000614 */
615LONG MDICascade(HWND parent, MDICLIENTINFO *ci)
616{
Alexandre Julliardd4719651995-12-12 18:49:11 +0000617 WND *clientWnd;
618 MDIWCL *listTop,*listPrev;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000619 RECT rect;
620 int spacing, xsize, ysize;
621 int x, y;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000622 int iToPosition = 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000623
Alexandre Julliard58199531994-04-21 01:20:00 +0000624 if (ci->flagChildMaximized)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000625 ShowWindow( ci->flagChildMaximized, SW_NORMAL);
Alexandre Julliard58199531994-04-21 01:20:00 +0000626
Alexandre Julliardd4719651995-12-12 18:49:11 +0000627 if (ci->nActiveChildren == 0) return 0;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000628
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000629 GetClientRect(parent, &rect);
630 spacing = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
Alexandre Julliard58199531994-04-21 01:20:00 +0000631 ysize = rect.bottom - 8 * spacing;
632 xsize = rect.right - 8 * spacing;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000633
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000634 dprintf_mdi(stddeb, "MDICascade: Client wnd at (%d,%d) - (%d,%d), spacing %d\n",
635 rect.left, rect.top, rect.right, rect.bottom, spacing);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000636
Alexandre Julliardd4719651995-12-12 18:49:11 +0000637 clientWnd = WIN_FindWndPtr( parent );
638
639 listTop = MDI_BuildWCL(clientWnd,&iToPosition);
640
641 if( !listTop ) return 0;
642
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000643 x = 0;
644 y = 0;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000645
646 /* walk list and move windows */
647 while ( listTop )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000648 {
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000649 dprintf_mdi(stddeb, "MDICascade: move %04x to (%d,%d) size [%d,%d]\n",
Alexandre Julliardd4719651995-12-12 18:49:11 +0000650 listTop->hChild, x, y, xsize, ysize);
651
652 if( listTop->hChild )
653 {
654 SetWindowPos(listTop->hChild, 0, x, y, xsize, ysize,
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000655 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
656
657 x += spacing;
658 y += spacing;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000659 }
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000660
Alexandre Julliardd4719651995-12-12 18:49:11 +0000661 listPrev = listTop->prev;
662 free(listTop);
663 listTop = listPrev;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000664 }
665
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000666 if( iToPosition < ci->nActiveChildren )
667 ArrangeIconicWindows( parent );
668
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000669 return 0;
670}
671
672/**********************************************************************
Alexandre Julliard58199531994-04-21 01:20:00 +0000673 * MDITile
Alexandre Julliardd4719651995-12-12 18:49:11 +0000674 *
Alexandre Julliard58199531994-04-21 01:20:00 +0000675 */
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000676LONG MDITile(HWND parent, MDICLIENTINFO *ci,WORD wParam)
Alexandre Julliard58199531994-04-21 01:20:00 +0000677{
Alexandre Julliardd4719651995-12-12 18:49:11 +0000678 WND *wndClient = WIN_FindWndPtr(parent);
679 MDIWCL *listTop,*listPrev;
Alexandre Julliard58199531994-04-21 01:20:00 +0000680 RECT rect;
681 int xsize, ysize;
682 int x, y;
683 int rows, columns;
684 int r, c;
685 int i;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000686 int iToPosition = 0;
Alexandre Julliard58199531994-04-21 01:20:00 +0000687
688 if (ci->flagChildMaximized)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000689 ShowWindow(ci->flagChildMaximized, SW_NORMAL);
Alexandre Julliard58199531994-04-21 01:20:00 +0000690
Alexandre Julliardd4719651995-12-12 18:49:11 +0000691 if (ci->nActiveChildren == 0) return 0;
692
693 listTop = MDI_BuildWCL(wndClient, &iToPosition);
694
695 dprintf_mdi(stddeb,"MDITile: %i windows to tile\n",iToPosition);
696
697 if( !listTop ) return 0;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000698
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000699 /* tile children */
700 if ( iToPosition )
701 {
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000702
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000703 GetClientRect(parent, &rect);
Alexandre Julliardd4719651995-12-12 18:49:11 +0000704
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000705 rows = (int) sqrt((double) iToPosition);
706 columns = iToPosition / rows;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000707
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000708 if (wParam == MDITILE_HORIZONTAL) /* version >= 3.1 */
Alexandre Julliardd4719651995-12-12 18:49:11 +0000709 {
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000710 i=rows;
711 rows=columns; /* exchange r and c */
712 columns=i;
713 }
Alexandre Julliardd4719651995-12-12 18:49:11 +0000714
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000715 /* hack */
716 if( iToPosition != ci->nActiveChildren)
717 {
718 y = rect.bottom - 2 * SYSMETRICS_CYICONSPACING - SYSMETRICS_CYICON;
719 rect.bottom = ( y - SYSMETRICS_CYICON < rect.top )? rect.bottom: y;
720 }
721
722 ysize = rect.bottom / rows;
723 xsize = rect.right / columns;
Alexandre Julliard58199531994-04-21 01:20:00 +0000724
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000725 x = 0;
726 i = 0;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000727
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000728 for (c = 1; c <= columns; c++)
729 {
730 if (c == columns)
731 {
732 rows = iToPosition - i;
733 ysize = rect.bottom / rows;
734 }
Alexandre Julliard58199531994-04-21 01:20:00 +0000735
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000736 y = 0;
737 for (r = 1; r <= rows; r++, i++)
738 {
739 /* shouldn't happen but... */
740 if( !listTop )
741 break;
742
743 if( listTop->hChild )
744 {
745 SetWindowPos(listTop->hChild, 0, x, y, xsize, ysize,
746 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
747 y += ysize;
748 }
749 listPrev = listTop->prev;
750 free(listTop);
751 listTop = listPrev;
752 }
753 x += xsize;
754 }
Alexandre Julliard58199531994-04-21 01:20:00 +0000755 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000756
Alexandre Julliardd4719651995-12-12 18:49:11 +0000757 /* free the rest if any */
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000758 while( listTop )
Alexandre Julliard58199531994-04-21 01:20:00 +0000759 {
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000760 listPrev = listTop->prev;
761 free(listTop);
762 listTop = listPrev;
Alexandre Julliard58199531994-04-21 01:20:00 +0000763 }
Alexandre Julliard58199531994-04-21 01:20:00 +0000764
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000765 if (iToPosition < ci->nActiveChildren )
766 ArrangeIconicWindows( parent );
Alexandre Julliard58199531994-04-21 01:20:00 +0000767
Alexandre Julliard18506551995-01-24 16:21:01 +0000768 return 0;
Alexandre Julliard58199531994-04-21 01:20:00 +0000769}
770
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000771/* ----------------------- Frame window ---------------------------- */
772
773
774/**********************************************************************
775 * MDI_AugmentFrameMenu
776 */
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000777BOOL MDI_AugmentFrameMenu(MDICLIENTINFO* ci, WND *frame, HWND hChild)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000778{
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000779 WND* child = WIN_FindWndPtr(hChild);
780 HMENU hSysPopup = 0;
781
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000782 dprintf_mdi(stddeb,"MDI_AugmentFrameMenu: frame %p,child %04x\n",frame,hChild);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000783
784 if( !frame->wIDmenu || !child->hSysMenu ) return 0;
785
786 hSysPopup = GetSystemMenu(hChild,FALSE);
787
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000788 dprintf_mdi(stddeb,"\t\tgot popup %04x\n in sysmenu %04x",hSysPopup,child->hSysMenu);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000789
790 if( !InsertMenu(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
791 hSysPopup, (SEGPTR)(DWORD)ci->obmClose) )
792 return 0;
793
794 if( !AppendMenu(frame->wIDmenu,MF_HELP | MF_BITMAP,
795 SC_RESTORE, (SEGPTR)(DWORD)ci->obmRestore) )
796 {
797 RemoveMenu(frame->wIDmenu,0,MF_BYPOSITION);
798 return 0;
799 }
800
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000801 /* FIXME: add a call to function that sets sysmenu items according
802 * to the window state. WS_MAXIMIZE -> no SC_SIZE, etc...
803 */
804
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000805 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
806 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
807 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
808
809 child->dwStyle &= ~WS_SYSMENU;
810
811 /* redraw frame */
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000812 SetWindowPos(frame->hwndSelf, 0,0,0,0,0, SWP_FRAMECHANGED | SWP_NOSIZE |
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000813 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
814
815 return 1;
816}
817
818/**********************************************************************
819 * MDI_RestoreFrameMenu
820 */
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000821BOOL MDI_RestoreFrameMenu( WND *frameWnd, HWND hChild)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000822{
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000823 WND* child = WIN_FindWndPtr(hChild);
824 INT nItems = GetMenuItemCount(frameWnd->wIDmenu) - 1;
825
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000826 dprintf_mdi(stddeb,"MDI_RestoreFrameMenu: for child %04x\n",hChild);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000827
828 if( GetMenuItemID(frameWnd->wIDmenu,nItems) != SC_RESTORE )
829 return 0;
830
831 child->dwStyle |= WS_SYSMENU;
832
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000833 /* FIXME: add a call to function that sets sysmenu items according
834 * to the window state. WS_MAXIMIZE -> no SC_SIZE, etc...
835 */
836
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000837 RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
838 DeleteMenu(frameWnd->wIDmenu,nItems-1,MF_BYPOSITION);
839
840 /* redraw frame */
841 SetWindowPos(hChild, 0,0,0,0,0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
842 SWP_NOACTIVATE | SWP_NOZORDER );
843 return 1;
844}
845
846/**********************************************************************
847 * MDI_UpdateFrameText
848 *
849 * used when child window is maximized/restored
850 *
851 * Note: lpTitle can be NULL
852 */
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000853void MDI_UpdateFrameText(WND *frameWnd, HWND hClient, BOOL repaint, LPCSTR lpTitle)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000854{
855 char lpBuffer[MDI_MAXTITLELENGTH+1];
856 LPSTR lpText = NULL;
857 WND* clientWnd = WIN_FindWndPtr(hClient);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000858
859 MDICLIENTINFO *ci = (MDICLIENTINFO *) clientWnd->wExtra;
860
861 dprintf_mdi(stddeb, "MDI: repaint %i, frameText %s\n", repaint, (lpTitle)?lpTitle:"NULL");
862
863 /* store new "default" title if lpTitle is not NULL */
864 if( lpTitle )
865 {
866 if( ci->hFrameTitle )
867 USER_HEAP_FREE( ci->hFrameTitle );
868 ci->hFrameTitle = USER_HEAP_ALLOC( strlen(lpTitle) + 1 );
869 lpText = (LPSTR) USER_HEAP_LIN_ADDR( ci->hFrameTitle );
870 strcpy( lpText, lpTitle );
871 }
872 else
873 lpText = (LPSTR) USER_HEAP_LIN_ADDR(ci->hFrameTitle);
874
875 if( ci->hFrameTitle )
876 {
877 WND* childWnd = WIN_FindWndPtr( ci->flagChildMaximized );
878
879 if( childWnd && childWnd->hText )
880 {
881 /* combine frame title and child title if possible */
882
883 LPCSTR lpBracket = " - [";
884 LPCSTR lpChildText = (LPCSTR) USER_HEAP_LIN_ADDR( childWnd->hText );
885
886 int i_frame_text_length = strlen(lpText);
887 int i_child_text_length = strlen(lpChildText);
888
889 strncpy( lpBuffer, lpText, MDI_MAXTITLELENGTH);
890 lpBuffer[MDI_MAXTITLELENGTH] = '\0';
891
892 if( i_frame_text_length + 5 < MDI_MAXTITLELENGTH )
893 {
894 strcat( lpBuffer, lpBracket );
895
896 if( i_frame_text_length + i_child_text_length + 5 < MDI_MAXTITLELENGTH )
897 {
898 strcat( lpBuffer, lpChildText );
899 *(short*)(lpBuffer + i_frame_text_length + i_child_text_length + 4) = (short)']';
900 }
901 else
902 {
903 memcpy( lpBuffer + i_frame_text_length + 4,
904 lpChildText,
905 MDI_MAXTITLELENGTH - i_frame_text_length - 4);
906 *(short*)(lpBuffer + MDI_MAXTITLELENGTH - 1) = (short)']';
907 }
908 }
909 }
910 else
911 {
912 strncpy(lpBuffer, lpText, MDI_MAXTITLELENGTH );
913 lpBuffer[MDI_MAXTITLELENGTH]='\0';
914 }
915 }
916 else
917 lpBuffer[0] = '\0';
918
919 if( frameWnd->hText )
920 USER_HEAP_FREE( frameWnd->hText );
921
922 frameWnd->hText = USER_HEAP_ALLOC( strlen(lpBuffer) + 1 );
923 lpText = (LPSTR) USER_HEAP_LIN_ADDR( frameWnd->hText );
924 strcpy( lpText, lpBuffer );
925
926 if( frameWnd->window )
927 XStoreName( display, frameWnd->window, lpBuffer );
928
929 if( repaint == MDI_REPAINTFRAME)
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000930 SetWindowPos(frameWnd->hwndSelf, 0,0,0,0,0, SWP_FRAMECHANGED |
931 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000932}
933
934
935/* ----------------------------- Interface ---------------------------- */
936
937
Alexandre Julliard58199531994-04-21 01:20:00 +0000938/**********************************************************************
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000939 * MDIClientWndProc
940 *
941 * This function is the handler for all MDI requests.
942 */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000943LRESULT MDIClientWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000944{
945 LPCREATESTRUCT cs;
946 LPCLIENTCREATESTRUCT ccs;
947 MDICLIENTINFO *ci;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000948 RECT rect;
949 WND *w = WIN_FindWndPtr(hwnd);
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000950 WND *frameWnd = w->parent;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000951
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000952 ci = (MDICLIENTINFO *) w->wExtra;
953
954 switch (message)
955 {
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000956 case WM_CREATE:
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000957 cs = (LPCREATESTRUCT) PTR_SEG_TO_LIN(lParam);
958 ccs = (LPCLIENTCREATESTRUCT) PTR_SEG_TO_LIN(cs->lpCreateParams);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000959
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000960 ci->hWindowMenu = ccs->hWindowMenu;
961 ci->idFirstChild = ccs->idFirstChild;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000962 ci->flagChildMaximized = 0;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000963 ci->nActiveChildren = 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000964 ci->hFrameTitle = frameWnd->hText;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000965 ci->sbStop = 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000966 ci->self = hwnd;
967 ci->obmClose = CreateMDIMenuBitmap();
968 ci->obmRestore = LoadBitmap(0, MAKEINTRESOURCE(OBM_RESTORE));
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000969 w->dwStyle |= WS_CLIPCHILDREN;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000970 frameWnd->hText = 0; /* will be restored in UpdateFrameText */
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000971
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000972 MDI_UpdateFrameText( frameWnd, hwnd, MDI_NOFRAMEREPAINT, NULL);
Alexandre Julliardd4719651995-12-12 18:49:11 +0000973
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000974 AppendMenu(ccs->hWindowMenu,MF_SEPARATOR,0,(SEGPTR)0);
975
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000976 GetClientRect(frameWnd->hwndSelf, &rect);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000977 NC_HandleNCCalcSize(hwnd, (NCCALCSIZE_PARAMS*) &rect);
978 w->rectClient = rect;
979
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000980 dprintf_mdi(stddeb,"MDI: Client created - hwnd = %04x, idFirst = %u\n",hwnd,ci->idFirstChild);
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000981
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000982 return 0;
983
984 case WM_DESTROY:
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000985 if( ci->flagChildMaximized ) MDI_RestoreFrameMenu(w, frameWnd->hwndSelf);
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000986
987 if(ci->obmClose) DeleteObject(ci->obmClose);
988 if(ci->obmRestore) DeleteObject(ci->obmRestore);
989
990 ci->idFirstChild = GetMenuItemCount(ci->hWindowMenu) - 1;
991 ci->nActiveChildren++; /* to delete a separator */
992
993 while( ci->nActiveChildren-- )
994 DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000995
996 return 0;
997
998 case WM_MDIACTIVATE:
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000999 if( ci->hwndActiveChild != (HWND)wParam )
1000 SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001001 return 0;
1002
1003 case WM_MDICASCADE:
1004 return MDICascade(hwnd, ci);
1005
1006 case WM_MDICREATE:
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001007 return (LONG)MDICreateChild(w, ci, hwnd, lParam );
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001008
1009 case WM_MDIDESTROY:
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +00001010 return (LONG)MDIDestroyChild(w, ci, hwnd, (HWND)wParam, TRUE);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001011
1012 case WM_MDIGETACTIVE:
1013 return ((LONG) ci->hwndActiveChild |
Alexandre Julliardd4719651995-12-12 18:49:11 +00001014 ((LONG) (ci->flagChildMaximized>0) << 16));
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001015
1016 case WM_MDIICONARRANGE:
Alexandre Julliardd4719651995-12-12 18:49:11 +00001017 ci->sbStop = TRUE;
1018 MDIIconArrange(hwnd);
1019 ci->sbStop = FALSE;
1020 SendMessage(hwnd,WM_MDICALCCHILDSCROLL,0,0L);
1021 return 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001022
1023 case WM_MDIMAXIMIZE:
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001024 ShowWindow((HWND)wParam, SW_MAXIMIZE);
1025 return 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001026
Alexandre Julliard58199531994-04-21 01:20:00 +00001027 case WM_MDINEXT:
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001028 MDI_SwitchActiveChild(hwnd, (HWND)wParam, (lParam)?1:0);
Alexandre Julliard58199531994-04-21 01:20:00 +00001029 break;
1030
1031 case WM_MDIRESTORE:
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001032 ShowWindow( (HWND)wParam, SW_NORMAL);
1033 return 0;
Alexandre Julliard58199531994-04-21 01:20:00 +00001034
1035 case WM_MDISETMENU:
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +00001036#ifdef WINELIB32
1037 return (LRESULT)MDISetMenu(hwnd, FALSE, (HMENU)wParam, (HMENU)lParam);
1038#else
1039 return (LRESULT)MDISetMenu(hwnd, wParam, LOWORD(lParam), HIWORD(lParam));
1040#endif
Alexandre Julliard58199531994-04-21 01:20:00 +00001041
1042 case WM_MDITILE:
Alexandre Julliardd4719651995-12-12 18:49:11 +00001043 ci->sbStop = TRUE;
1044 ShowScrollBar(hwnd,SB_BOTH,FALSE);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001045 MDITile(hwnd, ci,wParam);
Alexandre Julliardd4719651995-12-12 18:49:11 +00001046 ci->sbStop = FALSE;
1047 return 0;
1048
1049 case WM_VSCROLL:
1050 case WM_HSCROLL:
1051 ci->sbStop = TRUE;
1052 ScrollChildren(hwnd,message,wParam,lParam);
1053 ci->sbStop = FALSE;
1054 return 0;
1055
1056 case WM_SETFOCUS:
1057 if( ci->hwndActiveChild )
1058 {
1059 w = WIN_FindWndPtr( ci->hwndActiveChild );
1060 if( !(w->dwStyle & WS_MINIMIZE) )
1061 SetFocus( ci->hwndActiveChild );
1062 }
1063 return 0;
Alexandre Julliard58199531994-04-21 01:20:00 +00001064
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001065 case WM_NCACTIVATE:
Alexandre Julliardd4719651995-12-12 18:49:11 +00001066 if( ci->hwndActiveChild )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001067 SendMessage(ci->hwndActiveChild, message, wParam, lParam);
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001068 break;
1069
1070 case WM_PARENTNOTIFY:
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001071 if( wParam == WM_LBUTTONDOWN )
1072 {
1073 LPPOINT lppt = (LPPOINT)(void*)(&lParam);
1074 HWND child = ChildWindowFromPoint(hwnd, *lppt);
1075
1076 dprintf_mdi(stddeb,"MDIClient: notification from %04x (%i,%i)\n",child,lppt->x,lppt->y);
1077
1078 if( child && child != hwnd )
1079 {
1080 WND* wnd = WIN_FindWndPtr( child );
1081
1082 /* if we got owned popup */
1083 if( wnd->owner ) child = wnd->owner->hwndSelf;
1084
1085 if( child != ci->hwndActiveChild )
1086 SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
1087 }
1088 }
1089 return 0;
Alexandre Julliard58199531994-04-21 01:20:00 +00001090
1091 case WM_SIZE:
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001092 if( ci->flagChildMaximized )
1093 {
1094 WND* child = WIN_FindWndPtr(ci->flagChildMaximized);
1095 RECT rect = { 0, 0, LOWORD(lParam), HIWORD(lParam) };
1096
1097 AdjustWindowRectEx(&rect, child->dwStyle, 0, child->dwExStyle);
1098 MoveWindow(ci->flagChildMaximized, rect.left, rect.top,
1099 rect.right - rect.left, rect.bottom - rect.top, 1);
1100 }
1101 else
Alexandre Julliardd4719651995-12-12 18:49:11 +00001102 {
1103 PostMessage(hwnd,WM_MDICALCCHILDSCROLL,0,0L);
1104 ci->sbRecalc |= (SB_BOTH+1);
1105 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001106 break;
1107
Alexandre Julliardd4719651995-12-12 18:49:11 +00001108 case WM_MDICALCCHILDSCROLL:
1109 if( !ci->sbStop )
1110 if( ci->sbRecalc )
1111 {
1112 CalcChildScroll(hwnd, ci->sbRecalc-1);
1113 ci->sbRecalc = 0;
1114 }
1115 return 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001116 }
1117
1118 return DefWindowProc(hwnd, message, wParam, lParam);
1119}
1120
1121/**********************************************************************
1122 * DefFrameProc (USER.445)
1123 *
1124 */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001125LRESULT DefFrameProc(HWND hwnd, HWND hwndMDIClient, UINT message,
1126 WPARAM wParam, LPARAM lParam)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001127{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001128 HWND childHwnd;
1129 MDICLIENTINFO* ci;
1130 WND* wndPtr;
Alexandre Julliardd4719651995-12-12 18:49:11 +00001131
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00001132 if (hwndMDIClient)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001133 {
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00001134 switch (message)
1135 {
1136 case WM_COMMAND:
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001137 wndPtr = WIN_FindWndPtr(hwndMDIClient);
1138 ci = (MDICLIENTINFO*)wndPtr->wExtra;
1139
1140 /* check for possible system command codes */
1141
1142 if( wParam < ci->idFirstChild ||
1143 wParam >= ci->idFirstChild + ci->nActiveChildren )
1144 {
1145 if( (wParam - 0xF000) & 0xF00F ) break;
1146 switch( wParam )
1147 {
1148 case SC_SIZE:
1149 case SC_MOVE:
1150 case SC_MINIMIZE:
1151 case SC_MAXIMIZE:
1152 case SC_NEXTWINDOW:
1153 case SC_PREVWINDOW:
1154 case SC_CLOSE:
1155 case SC_RESTORE:
1156 if( ci->flagChildMaximized )
1157 return SendMessage( ci->flagChildMaximized, WM_SYSCOMMAND,
1158 wParam, lParam);
1159 }
1160 }
1161 else
1162 {
1163 childHwnd = MDI_GetChildByID( WIN_FindWndPtr(hwndMDIClient),
Alexandre Julliardd4719651995-12-12 18:49:11 +00001164 wParam );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001165 if( childHwnd )
1166 SendMessage(hwndMDIClient, WM_MDIACTIVATE, (WPARAM)childHwnd , 0L);
1167 }
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00001168 break;
Alexandre Julliard58199531994-04-21 01:20:00 +00001169
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00001170 case WM_NCACTIVATE:
1171 SendMessage(hwndMDIClient, message, wParam, lParam);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001172 break;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001173
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001174 case WM_SETTEXT:
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001175 MDI_UpdateFrameText(WIN_FindWndPtr(hwnd), hwndMDIClient,
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001176 MDI_REPAINTFRAME,
1177 (LPCSTR)PTR_SEG_TO_LIN(lParam));
1178 return 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001179
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00001180 case WM_SETFOCUS:
Alexandre Julliardd4719651995-12-12 18:49:11 +00001181 SetFocus(hwndMDIClient);
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00001182 break;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001183
Alexandre Julliard7cc9c0c1994-06-15 15:45:11 +00001184 case WM_SIZE:
1185 MoveWindow(hwndMDIClient, 0, 0,
1186 LOWORD(lParam), HIWORD(lParam), TRUE);
1187 break;
1188 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001189 }
1190
1191 return DefWindowProc(hwnd, message, wParam, lParam);
1192}
1193
1194/**********************************************************************
1195 * DefMDIChildProc (USER.447)
1196 *
1197 */
Alexandre Julliard0c126c71996-02-18 18:44:41 +00001198LRESULT DefMDIChildProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001199{
1200 MDICLIENTINFO *ci;
Alexandre Julliardd4719651995-12-12 18:49:11 +00001201 WND *clientWnd;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001202
Alexandre Julliardd4719651995-12-12 18:49:11 +00001203 clientWnd = WIN_FindWndPtr(GetParent(hwnd));
1204 ci = (MDICLIENTINFO *) clientWnd->wExtra;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001205
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001206 switch (message)
1207 {
Alexandre Julliardd4719651995-12-12 18:49:11 +00001208 case WM_SETTEXT:
1209 DefWindowProc(hwnd, message, wParam, lParam);
1210 MDI_MenuModifyItem(clientWnd,hwnd);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001211 if( ci->flagChildMaximized == hwnd )
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001212 MDI_UpdateFrameText( clientWnd->parent, ci->self,
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001213 MDI_REPAINTFRAME, NULL );
Alexandre Julliard18506551995-01-24 16:21:01 +00001214 return 0;
Alexandre Julliard58199531994-04-21 01:20:00 +00001215
Alexandre Julliardd4719651995-12-12 18:49:11 +00001216 case WM_CLOSE:
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001217 SendMessage(ci->self,WM_MDIDESTROY,(WPARAM)hwnd,0L);
Alexandre Julliardd4719651995-12-12 18:49:11 +00001218 return 0;
1219
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001220 case WM_SETFOCUS:
Alexandre Julliardd4719651995-12-12 18:49:11 +00001221 if( ci->hwndActiveChild != hwnd )
1222 MDI_ChildActivate(clientWnd, hwnd);
1223 break;
1224
1225 case WM_CHILDACTIVATE:
1226 MDI_ChildActivate(clientWnd, hwnd);
1227 return 0;
1228
1229 case WM_NCPAINT:
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001230 dprintf_mdi(stddeb,"DefMDIChildProc: WM_NCPAINT for %04x, active %04x\n",
Alexandre Julliardd4719651995-12-12 18:49:11 +00001231 hwnd, ci->hwndActiveChild );
1232 break;
1233
Alexandre Julliard58199531994-04-21 01:20:00 +00001234 case WM_SYSCOMMAND:
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001235 switch( wParam )
1236 {
1237 case SC_MOVE:
1238 if( ci->flagChildMaximized == hwnd) return 0;
1239 break;
1240 case SC_MAXIMIZE:
1241 if( ci->flagChildMaximized == hwnd)
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001242 return SendMessage( clientWnd->parent->hwndSelf,
1243 message, wParam, lParam);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001244 break;
1245 case SC_NEXTWINDOW:
1246 SendMessage( ci->self, WM_MDINEXT, 0, 0);
1247 return 0;
1248 case SC_PREVWINDOW:
1249 SendMessage( ci->self, WM_MDINEXT, 0, 1);
1250 return 0;
1251 }
Alexandre Julliard58199531994-04-21 01:20:00 +00001252 break;
1253
Alexandre Julliardd4719651995-12-12 18:49:11 +00001254 case WM_GETMINMAXINFO:
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001255 MDI_ChildGetMinMaxInfo(clientWnd, hwnd, (MINMAXINFO*) PTR_SEG_TO_LIN(lParam));
1256 return 0;
Alexandre Julliardd4719651995-12-12 18:49:11 +00001257
1258 case WM_SETVISIBLE:
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001259 if( !ci->sbStop && !ci->flagChildMaximized)
Alexandre Julliardd4719651995-12-12 18:49:11 +00001260 {
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001261 PostMessage(ci->self,WM_MDICALCCHILDSCROLL,0,0L);
Alexandre Julliardd4719651995-12-12 18:49:11 +00001262 ci->sbRecalc |= (SB_BOTH+1);
1263 }
1264 break;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001265
1266 case WM_SIZE:
1267 /* do not change */
1268
1269 if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED )
1270 {
1271 ci->flagChildMaximized = 0;
1272
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001273 MDI_RestoreFrameMenu( clientWnd->parent, hwnd);
1274 MDI_UpdateFrameText( clientWnd->parent, ci->self,
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001275 MDI_REPAINTFRAME, NULL );
1276 }
1277
1278 if( wParam == SIZE_MAXIMIZED )
1279 {
1280 HWND hMaxChild = ci->flagChildMaximized;
1281
1282 if( hMaxChild == hwnd ) break;
1283
1284 if( hMaxChild)
1285 {
1286 SendMessage( hMaxChild, WM_SETREDRAW, FALSE, 0L );
1287
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001288 MDI_RestoreFrameMenu( clientWnd->parent, hMaxChild);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001289 ShowWindow( hMaxChild, SW_SHOWNOACTIVATE);
1290
1291 SendMessage( hMaxChild, WM_SETREDRAW, TRUE, 0L );
1292 }
1293
1294 ci->flagChildMaximized = hwnd; /* !!! */
1295
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001296 MDI_AugmentFrameMenu( ci, clientWnd->parent, hwnd);
1297 MDI_UpdateFrameText( clientWnd->parent, ci->self,
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001298 MDI_REPAINTFRAME, NULL );
1299 }
1300
1301 if( wParam == SIZE_MINIMIZED )
1302 {
1303 HWND switchTo = MDI_GetWindow(clientWnd, hwnd, 0);
1304
1305 if( switchTo )
1306 SendMessage( switchTo, WM_CHILDACTIVATE, 0, 0L);
1307 }
1308
Alexandre Julliardd4719651995-12-12 18:49:11 +00001309 if( !ci->sbStop )
1310 {
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001311 PostMessage(ci->self,WM_MDICALCCHILDSCROLL,0,0L);
Alexandre Julliardd4719651995-12-12 18:49:11 +00001312 ci->sbRecalc |= (SB_BOTH+1);
1313 }
1314 break;
1315
1316 case WM_MENUCHAR:
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001317
1318 /* MDI children don't have menus */
1319 PostMessage( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
1320 (WPARAM)SC_KEYMENU, (LPARAM)wParam);
1321 return 0x00010000L;
1322
Alexandre Julliardd4719651995-12-12 18:49:11 +00001323 case WM_NEXTMENU:
1324 /* set current menu to child system menu */
1325
1326 break;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001327 }
1328
1329 return DefWindowProc(hwnd, message, wParam, lParam);
1330}
1331
1332/**********************************************************************
1333 * TranslateMDISysAccel (USER.451)
1334 *
1335 */
1336BOOL TranslateMDISysAccel(HWND hwndClient, LPMSG msg)
1337{
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001338 WND* clientWnd = WIN_FindWndPtr( hwndClient);
1339 WND* wnd;
1340 MDICLIENTINFO *ci = NULL;
1341 WPARAM wParam = 0;
1342
1343 if( (msg->message != WM_KEYDOWN && msg->message != WM_SYSKEYDOWN) || !clientWnd )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001344 return 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001345
1346 ci = (MDICLIENTINFO*) clientWnd->wExtra;
1347 wnd = WIN_FindWndPtr(ci->hwndActiveChild);
1348
1349 if( !wnd ) return 0;
1350
1351 if( wnd->dwStyle & WS_DISABLED ) return 0;
1352
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001353 if ((GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_MENU) & 0x8000))
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001354 switch( msg->wParam )
1355 {
1356 case VK_F6:
1357 case VK_SEPARATOR:
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001358 wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )? SC_NEXTWINDOW: SC_PREVWINDOW;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001359 break;
1360 case VK_RBUTTON:
1361 wParam = SC_CLOSE;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001362 break;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001363 default:
1364 return 0;
1365 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001366 else
1367 return 0;
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001368
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001369 dprintf_mdi(stddeb,"TranslateMDISysAccel: wParam = %04x\n", wParam);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001370
1371 SendMessage(ci->hwndActiveChild,WM_SYSCOMMAND, wParam, (LPARAM)msg->wParam);
1372 return 1;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00001373}
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001374
1375
1376/***********************************************************************
1377 * CalcChildScroll (USER.462)
1378 */
1379void CalcChildScroll( HWND hwnd, WORD scroll )
1380{
1381 RECT childRect, clientRect;
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001382 WND *pWnd;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001383
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001384 if (!(pWnd = WIN_FindWndPtr( hwnd ))) return;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001385 GetClientRect( hwnd, &clientRect );
1386 SetRectEmpty( &childRect );
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001387 for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
1388 UnionRect( &childRect, &pWnd->rectWindow, &childRect );
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001389 UnionRect( &childRect, &clientRect, &childRect );
1390
1391 if ((scroll == SB_HORZ) || (scroll == SB_BOTH))
1392 {
1393 SetScrollRange( hwnd, SB_HORZ, childRect.left,
1394 childRect.right - clientRect.right, FALSE );
1395 SetScrollPos( hwnd, SB_HORZ, clientRect.left - childRect.left, TRUE );
1396 }
1397 if ((scroll == SB_VERT) || (scroll == SB_BOTH))
1398 {
1399 SetScrollRange( hwnd, SB_VERT, childRect.top,
1400 childRect.bottom - clientRect.bottom, FALSE );
1401 SetScrollPos( hwnd, SB_HORZ, clientRect.top - childRect.top, TRUE );
1402 }
1403}
Alexandre Julliardd4719651995-12-12 18:49:11 +00001404
1405/***********************************************************************
1406 * ScrollChildren (USER.463)
1407 */
1408void ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1409{
1410 WND *wndPtr = WIN_FindWndPtr(hWnd);
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +00001411 short newPos=-1;
Alexandre Julliardd4719651995-12-12 18:49:11 +00001412 short curPos;
1413 short length;
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +00001414 INT minPos;
1415 INT maxPos;
Alexandre Julliardd4719651995-12-12 18:49:11 +00001416 short shift;
1417
1418 if( !wndPtr ) return;
1419
1420 if( uMsg == WM_HSCROLL )
1421 {
1422 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
1423 curPos = GetScrollPos(hWnd,SB_HORZ);
1424 length = (wndPtr->rectClient.right - wndPtr->rectClient.left)/2;
1425 shift = SYSMETRICS_CYHSCROLL;
1426 }
1427 else if( uMsg == WM_VSCROLL )
1428 {
1429 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
1430 curPos = GetScrollPos(hWnd,SB_VERT);
1431 length = (wndPtr->rectClient.bottom - wndPtr->rectClient.top)/2;
1432 shift = SYSMETRICS_CXVSCROLL;
1433 }
1434 else return;
1435
1436 switch( wParam )
1437 {
1438 case SB_LINEUP:
1439 newPos = curPos - shift;
1440 break;
1441 case SB_LINEDOWN:
1442 newPos = curPos + shift;
1443 break;
1444 case SB_PAGEUP:
1445 newPos = curPos - length;
1446 break;
1447 case SB_PAGEDOWN:
1448 newPos = curPos + length;
1449 break;
1450
1451 case SB_THUMBPOSITION:
1452 newPos = LOWORD(lParam);
1453 break;
1454
1455 case SB_THUMBTRACK:
1456 return;
1457
1458 case SB_TOP:
1459 newPos = minPos;
1460 break;
1461 case SB_BOTTOM:
1462 newPos = maxPos;
1463 break;
1464 case SB_ENDSCROLL:
1465 CalcChildScroll(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
1466 return;
1467 }
1468
1469 if( newPos > maxPos )
1470 newPos = maxPos;
1471 else if( newPos < minPos )
1472 newPos = minPos;
1473
1474 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
1475
1476 if( uMsg == WM_VSCROLL )
1477 ScrollWindow(hWnd ,0 ,curPos - newPos, NULL, NULL);
1478 else
1479 ScrollWindow(hWnd ,curPos - newPos, 0, NULL, NULL);
1480}
1481