Release 950202
[wine] / windows / mdi.c
1 /* MDI.C
2  *
3  * Copyright 1994, Bob Amstadt
4  *
5  * This file contains routines to support MDI features.
6  */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <math.h>
10 #include "windows.h"
11 #include "win.h"
12 #include "nonclient.h"
13 #include "mdi.h"
14 #include "user.h"
15 #include "menu.h"
16 #include "sysmetrics.h"
17 #include "stddebug.h"
18 /* #define DEBUG_MDI */
19 #include "debug.h"
20
21 /**********************************************************************
22  *                                      MDIRecreateMenuList
23  */
24 void
25 MDIRecreateMenuList(MDICLIENTINFO *ci)
26 {
27     MDICHILDINFO *chi;
28     char buffer[128];
29     int id, n, index;
30
31     dprintf_mdi(stddeb, "MDIRecreateMenuList: hWindowMenu %0x\n", 
32             ci->hWindowMenu);
33     
34     id = ci->idFirstChild; 
35     while (DeleteMenu(ci->hWindowMenu, id, MF_BYCOMMAND))
36         id++;
37
38     dprintf_mdi(stddeb, "MDIRecreateMenuList: id %04x, idFirstChild %04x\n", 
39             id, ci->idFirstChild);
40
41     if (!ci->flagMenuAltered)
42     {
43         ci->flagMenuAltered = TRUE;
44         AppendMenu(ci->hWindowMenu, MF_SEPARATOR, 0, NULL);
45     }
46     
47     id = ci->idFirstChild;
48     index = 1;
49     for (chi = ci->infoActiveChildren; chi != NULL; chi = chi->next)
50     {
51         n = sprintf(buffer, "%d ", index++);
52         GetWindowText(chi->hwnd, buffer + n, sizeof(buffer) - n - 1);
53
54         dprintf_mdi(stddeb, "MDIRecreateMenuList: id %04x, '%s'\n", 
55                 id, buffer);
56
57         AppendMenu(ci->hWindowMenu, MF_STRING, id++, buffer);
58     }
59 }
60
61 /**********************************************************************
62  *                                      MDICreateChild
63  */
64 HWND 
65 MDICreateChild(WND *w, MDICLIENTINFO *ci, HWND parent, LPMDICREATESTRUCT cs)
66 {
67     HWND hwnd;
68
69     /*
70      * Create child window
71      */
72     cs->style &= (WS_MINIMIZE | WS_MAXIMIZE | WS_HSCROLL | WS_VSCROLL);
73     
74     hwnd = CreateWindowEx(0, cs->szClass, cs->szTitle, 
75                           WS_CHILD | WS_BORDER | WS_CAPTION | WS_CLIPSIBLINGS |
76                           WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU |
77                           WS_THICKFRAME | WS_VISIBLE | cs->style,
78                           cs->x, cs->y, cs->cx, cs->cy, parent, (HMENU) 0,
79                           w->hInstance, (LPSTR) cs);
80
81     if (hwnd)
82     {
83         HANDLE h = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(MDICHILDINFO));
84         MDICHILDINFO *child_info = USER_HEAP_ADDR(h);
85         if (!h)
86         {
87             DestroyWindow(hwnd);
88             return 0;
89         }
90
91         ci->nActiveChildren++;
92         
93         child_info->next = ci->infoActiveChildren;
94         child_info->prev = NULL;
95         child_info->hwnd = hwnd;
96
97         if (ci->infoActiveChildren)
98             ci->infoActiveChildren->prev = child_info;
99
100         ci->infoActiveChildren = child_info;
101
102         SendMessage(parent, WM_CHILDACTIVATE, 0, 0);
103     }
104         
105     return hwnd;
106 }
107
108 /**********************************************************************
109  *                                      MDIDestroyChild
110  */
111 HWND 
112 MDIDestroyChild(WND *w_parent, MDICLIENTINFO *ci, HWND parent, HWND child,
113                  BOOL flagDestroy)
114 {
115     MDICHILDINFO  *chi;
116     
117     chi = ci->infoActiveChildren;
118     while (chi && chi->hwnd != child)
119         chi = chi->next;
120
121     if (chi)
122     {
123         if (chi->prev)
124             chi->prev->next = chi->next;
125         if (chi->next)
126             chi->next->prev = chi->prev;
127         if (ci->infoActiveChildren == chi)
128             ci->infoActiveChildren = chi->next;
129
130         ci->nActiveChildren--;
131         
132         if (chi->hwnd == ci->hwndActiveChild)
133             SendMessage(parent, WM_CHILDACTIVATE, 0, 0);
134
135         USER_HEAP_FREE((HANDLE) (LONG) chi);
136         
137         if (flagDestroy)
138             DestroyWindow(child);
139     }
140     
141     return 0;
142 }
143
144 /**********************************************************************
145  *                                      MDIBringChildToTop
146  */
147 void MDIBringChildToTop(HWND parent, WORD id, WORD by_id, BOOL send_to_bottom)
148 {
149     MDICHILDINFO  *chi;
150     MDICLIENTINFO *ci;
151     WND           *w;
152     int            i;
153
154     w  = WIN_FindWndPtr(parent);
155     ci = (MDICLIENTINFO *) w->wExtra;
156     
157     dprintf_mdi(stddeb, "MDIBringToTop: id %04x, by_id %d\n", id, by_id);
158
159     if (by_id)
160         id -= ci->idFirstChild;
161     if (!by_id || id < ci->nActiveChildren)
162     {
163         chi = ci->infoActiveChildren;
164
165         if (by_id)
166         {
167             for (i = 0; i < id; i++)
168                 chi = chi->next;
169         }
170         else
171         {
172             while (chi && chi->hwnd != id)
173                 chi = chi->next;
174         }
175
176         if (!chi)
177             return;
178
179         dprintf_mdi(stddeb, "MDIBringToTop: child %04x\n", chi->hwnd);
180         if (chi != ci->infoActiveChildren)
181         {
182             if (ci->flagChildMaximized)
183             {
184                 RECT rectOldRestore, rect;
185
186                 w = WIN_FindWndPtr(chi->hwnd);
187                 
188                 rectOldRestore = ci->rectRestore;
189                 GetWindowRect(chi->hwnd, &ci->rectRestore);
190
191                 rect.top    = (ci->rectMaximize.top -
192                                (w->rectClient.top - w->rectWindow.top));
193                 rect.bottom = (ci->rectMaximize.bottom + 
194                                (w->rectWindow.bottom - w->rectClient.bottom));
195                 rect.left   = (ci->rectMaximize.left - 
196                                (w->rectClient.left - w->rectWindow.left));
197                 rect.right  = (ci->rectMaximize.right +
198                                (w->rectWindow.right - w->rectClient.right));
199                 w->dwStyle |= WS_MAXIMIZE;
200                 SetWindowPos(chi->hwnd, HWND_TOP, rect.left, rect.top, 
201                              rect.right - rect.left + 1, 
202                              rect.bottom - rect.top + 1, 0);
203                 SendMessage(chi->hwnd, WM_SIZE, SIZE_MAXIMIZED,
204                             MAKELONG(w->rectClient.right-w->rectClient.left,
205                                      w->rectClient.bottom-w->rectClient.top));
206
207                 w = WIN_FindWndPtr(ci->hwndActiveChild);
208                 w->dwStyle &= ~WS_MAXIMIZE;
209                 SetWindowPos(ci->hwndActiveChild, HWND_BOTTOM, 
210                              rectOldRestore.left, rectOldRestore.top, 
211                              rectOldRestore.right - rectOldRestore.left + 1, 
212                              rectOldRestore.bottom - rectOldRestore.top + 1,
213                              SWP_NOACTIVATE | 
214                              (send_to_bottom ? 0 : SWP_NOZORDER));
215             }
216             else
217             {
218                 SetWindowPos(chi->hwnd, HWND_TOP, 0, 0, 0, 0, 
219                              SWP_NOMOVE | SWP_NOSIZE );
220                 if (send_to_bottom)
221                 {
222                     SetWindowPos(ci->hwndActiveChild, HWND_BOTTOM, 0, 0, 0, 0, 
223                                  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
224                 }
225             }
226                 
227             if (chi->next)
228                 chi->next->prev    = chi->prev;
229
230             if (chi->prev)
231                 chi->prev->next    = chi->next;
232             
233             chi->prev              = NULL;
234             chi->next              = ci->infoActiveChildren;
235             chi->next->prev        = chi;
236             ci->infoActiveChildren = chi;
237
238             SendMessage(parent, WM_CHILDACTIVATE, 0, 0);
239         }
240         
241         dprintf_mdi(stddeb, "MDIBringToTop: pos %04x, hwnd %04x\n", 
242                 id, chi->hwnd);
243     }
244 }
245
246 /**********************************************************************
247  *                                      MDIMaximizeChild
248  */
249 LONG MDIMaximizeChild(HWND parent, HWND child, MDICLIENTINFO *ci)
250 {
251     WND *w = WIN_FindWndPtr(child);
252     RECT rect;
253     
254     MDIBringChildToTop(parent, child, FALSE, FALSE);
255     ci->rectRestore = w->rectWindow;
256
257     rect.top    = (ci->rectMaximize.top -
258                    (w->rectClient.top - w->rectWindow.top));
259     rect.bottom = (ci->rectMaximize.bottom + 
260                    (w->rectWindow.bottom - w->rectClient.bottom));
261     rect.left   = (ci->rectMaximize.left - 
262                    (w->rectClient.left - w->rectWindow.left));
263     rect.right  = (ci->rectMaximize.right +
264                    (w->rectWindow.right - w->rectClient.right));
265     w->dwStyle |= WS_MAXIMIZE;
266     SetWindowPos(child, 0, rect.left, rect.top, 
267                  rect.right - rect.left + 1, rect.bottom - rect.top + 1,
268                  SWP_NOACTIVATE | SWP_NOZORDER);
269     
270     ci->flagChildMaximized = TRUE;
271     
272     SendMessage(child, WM_SIZE, SIZE_MAXIMIZED,
273                 MAKELONG(w->rectClient.right-w->rectClient.left,
274                          w->rectClient.bottom-w->rectClient.top));
275     SendMessage(GetParent(parent), WM_NCPAINT, 0, 0);
276
277     return 0;
278 }
279
280 /**********************************************************************
281  *                                      MDIRestoreChild
282  */
283 LONG MDIRestoreChild(HWND parent, MDICLIENTINFO *ci)
284 {
285     HWND    child;
286
287     dprintf_mdi(stddeb,"restoring mdi child\n");
288
289     child = ci->hwndActiveChild;
290     ci->flagChildMaximized = FALSE;
291
292     ShowWindow(child, SW_RESTORE);              /* display the window */
293     MDIBringChildToTop(parent, child, FALSE, FALSE);
294
295     return 0;
296 }
297
298 /**********************************************************************
299  *                                      MDIChildActivated
300  */
301 LONG MDIChildActivated(WND *w, MDICLIENTINFO *ci, HWND parent)
302 {
303     MDICHILDINFO *chi;
304     HWND          deact_hwnd;
305     HWND          act_hwnd;
306     LONG          lParam;
307
308     dprintf_mdi(stddeb, "MDIChildActivate: top %04x\n", w->hwndChild);
309
310     chi = ci->infoActiveChildren;
311     if (chi)
312     {
313         deact_hwnd = ci->hwndActiveChild;
314         act_hwnd   = chi->hwnd;
315         lParam     = ((LONG) deact_hwnd << 16) | act_hwnd;
316
317         dprintf_mdi(stddeb, "MDIChildActivate: deact %04x, act %04x\n",
318                deact_hwnd, act_hwnd);
319
320         ci->hwndActiveChild = act_hwnd;
321
322         if (deact_hwnd != act_hwnd)
323         {
324             MDIRecreateMenuList(ci);
325             SendMessage(deact_hwnd,  WM_NCACTIVATE, FALSE, 0);
326             SendMessage(deact_hwnd, WM_MDIACTIVATE, FALSE, lParam);
327         }
328         
329         SendMessage(act_hwnd,  WM_NCACTIVATE, TRUE, 0);
330         SendMessage(act_hwnd, WM_MDIACTIVATE, TRUE, lParam);
331     }
332
333     if (chi || ci->nActiveChildren == 0)
334     {
335         MDIRecreateMenuList(ci);
336         SendMessage(GetParent(parent), WM_NCPAINT, 0, 0);
337     }
338     
339     return 0;
340 }
341
342 /**********************************************************************
343  *                                      MDICascade
344  */
345 LONG MDICascade(HWND parent, MDICLIENTINFO *ci)
346 {
347     MDICHILDINFO *chi;
348     RECT          rect;
349     int           spacing, xsize, ysize;
350     int           x, y;
351
352     if (ci->flagChildMaximized)
353         MDIRestoreChild(parent, ci);
354
355     /* If there aren't any children, don't even bother.
356      */
357     if (ci->nActiveChildren == 0)
358         return 0;
359
360     GetClientRect(parent, &rect);
361     spacing = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
362     ysize   = rect.bottom - 8 * spacing;
363     xsize   = rect.right  - 8 * spacing;
364     
365     dprintf_mdi(stddeb, 
366             "MDICascade: Client wnd at (%d,%d) - (%d,%d), spacing %d\n", 
367             rect.left, rect.top, rect.right, rect.bottom, spacing);
368     dprintf_mdi(stddeb, "MDICascade: searching for last child\n");
369     for (chi = ci->infoActiveChildren; chi->next != NULL; chi = chi->next)
370         ;
371     
372     dprintf_mdi(stddeb, "MDICascade: last child is %04x\n", chi->hwnd);
373     x = 0;
374     y = 0;
375     for ( ; chi != NULL; chi = chi->prev)
376     {
377         dprintf_mdi(stddeb, "MDICascade: move %04x to (%d,%d) size [%d,%d]\n", 
378                 chi->hwnd, x, y, xsize, ysize);
379         SetWindowPos(chi->hwnd, 0, x, y, xsize, ysize, 
380                      SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
381
382         x += spacing;
383         y += spacing;
384     }
385
386     return 0;
387 }
388
389 /**********************************************************************
390  *                                      MDITile
391  */
392 LONG MDITile(HWND parent, MDICLIENTINFO *ci)
393 {
394     MDICHILDINFO *chi;
395     RECT          rect;
396     int           xsize, ysize;
397     int           x, y;
398     int           rows, columns;
399     int           r, c;
400     int           i;
401
402     if (ci->flagChildMaximized)
403         MDIRestoreChild(parent, ci);
404
405     /* If there aren't any children, don't even bother.
406      */
407     if (ci->nActiveChildren == 0)
408         return 0;
409
410     GetClientRect(parent, &rect);
411     rows    = (int) sqrt((double) ci->nActiveChildren);
412     columns = ci->nActiveChildren / rows;
413     ysize   = rect.bottom / rows;
414     xsize   = rect.right  / columns;
415     
416     chi     = ci->infoActiveChildren;
417     x       = 0;
418     i       = 0;
419     for (c = 1; c <= columns; c++)
420     {
421         if (c == columns)
422         {
423             rows  = ci->nActiveChildren - i;
424             ysize = rect.bottom / rows;
425         }
426
427         y = 0;
428         for (r = 1; r <= rows; r++, i++, chi = chi->next)
429         {
430             SetWindowPos(chi->hwnd, 0, x, y, xsize, ysize, 
431                          SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
432
433             y += ysize;
434         }
435
436         x += xsize;
437     }
438     
439
440     return 0;
441 }
442
443 /**********************************************************************
444  *                                      MDIHandleLButton
445  */
446 BOOL MDIHandleLButton(HWND hwndFrame, HWND hwndClient, 
447                       WORD wParam, LONG lParam)
448 {
449     MDICLIENTINFO *ci;
450     WND           *w;
451     RECT           rect;
452     WORD           x;
453
454     w  = WIN_FindWndPtr(hwndClient);
455     ci = (MDICLIENTINFO *) w->wExtra;
456
457     if (wParam == HTMENU && ci->flagChildMaximized)
458     {
459         x = LOWORD(lParam);
460         
461         NC_GetInsideRect(hwndFrame, &rect);
462         if (x < rect.left + SYSMETRICS_CXSIZE)
463         {
464             SendMessage(ci->hwndActiveChild, WM_SYSCOMMAND, 
465                         SC_CLOSE, lParam);
466             return TRUE;
467         }
468         else if (x >= rect.right - SYSMETRICS_CXSIZE)
469         {
470             SendMessage(ci->hwndActiveChild, WM_SYSCOMMAND, 
471                         SC_RESTORE, lParam);
472             return TRUE;
473         }
474     }
475
476     return FALSE;
477 }
478
479 /**********************************************************************
480  *                                      MDIPaintMaximized
481  */
482 LONG MDIPaintMaximized(HWND hwndFrame, HWND hwndClient, WORD message,
483                        WORD wParam, LONG lParam)
484 {
485     static HBITMAP hbitmapClose     = 0;
486     static HBITMAP hbitmapMaximized = 0;
487     
488     MDICLIENTINFO *ci;
489     WND           *w;
490     HDC            hdc, hdcMem;
491     RECT           rect;
492     WND           *wndPtr = WIN_FindWndPtr(hwndFrame);
493
494     w  = WIN_FindWndPtr(hwndClient);
495     ci = (MDICLIENTINFO *) w->wExtra;
496
497     dprintf_mdi(stddeb, 
498                 "MDIPaintMaximized: frame %04x,  client %04x"
499                 ",  max flag %d,  menu %04x\n", 
500                 hwndFrame, hwndClient, 
501                 ci->flagChildMaximized, wndPtr ? wndPtr->wIDmenu : 0);
502
503     if (ci->flagChildMaximized && wndPtr && wndPtr->wIDmenu != 0)
504     {
505         NC_DoNCPaint( hwndFrame, wParam, TRUE);
506
507         hdc = GetDCEx(hwndFrame, 0, DCX_CACHE | DCX_WINDOW);
508         if (!hdc) return 0;
509
510         hdcMem = CreateCompatibleDC(hdc);
511
512         if (hbitmapClose == 0)
513         {
514             hbitmapClose     = LoadBitmap(0, MAKEINTRESOURCE(OBM_OLD_CLOSE));
515             hbitmapMaximized = LoadBitmap(0, MAKEINTRESOURCE(OBM_RESTORE));
516         }
517
518         dprintf_mdi(stddeb, 
519                 "MDIPaintMaximized: hdcMem %04x, close bitmap %04x, "
520                 "maximized bitmap %04x\n",
521                 hdcMem, hbitmapClose, hbitmapMaximized);
522
523         NC_GetInsideRect(hwndFrame, &rect);
524         rect.top   += ((wndPtr->dwStyle & WS_CAPTION) ? 
525                        SYSMETRICS_CYSIZE + 1 :  0);
526         SelectObject(hdcMem, hbitmapClose);
527         BitBlt(hdc, rect.left, rect.top + 1, 
528                SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
529                hdcMem, 1, 1, SRCCOPY);
530         
531         NC_GetInsideRect(hwndFrame, &rect);
532         rect.top   += ((wndPtr->dwStyle & WS_CAPTION) ? 
533                        SYSMETRICS_CYSIZE + 1 :  0);
534         rect.left   = rect.right - SYSMETRICS_CXSIZE;
535         SelectObject(hdcMem, hbitmapMaximized);
536         BitBlt(hdc, rect.left, rect.top + 1, 
537                SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
538                hdcMem, 1, 1, SRCCOPY);
539         
540         NC_GetInsideRect(hwndFrame, &rect);
541         rect.top   += ((wndPtr->dwStyle & WS_CAPTION) ? 
542                        SYSMETRICS_CYSIZE + 1 :  0);
543         rect.left  += SYSMETRICS_CXSIZE;
544         rect.right -= SYSMETRICS_CXSIZE;
545         rect.bottom = rect.top + SYSMETRICS_CYMENU;
546
547         MENU_DrawMenuBar(hdc, &rect, hwndFrame, FALSE);
548         
549         DeleteDC(hdcMem);
550         ReleaseDC(hwndFrame, hdc);
551     }
552     else
553         DefWindowProc(hwndFrame, message, wParam, lParam);
554
555     return 0;
556 }
557
558 /**********************************************************************
559  *                                      MDIClientWndProc
560  *
561  * This function is the handler for all MDI requests.
562  */
563 LONG 
564 MDIClientWndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
565 {
566     LPCREATESTRUCT       cs;
567     LPCLIENTCREATESTRUCT ccs;
568     MDICLIENTINFO       *ci;
569     WND                 *w;
570
571     w  = WIN_FindWndPtr(hwnd);
572     ci = (MDICLIENTINFO *) w->wExtra;
573     
574     switch (message)
575     {
576       case WM_CHILDACTIVATE:
577         return MDIChildActivated(w, ci, hwnd);
578
579       case WM_CREATE:
580         cs                      = (LPCREATESTRUCT) lParam;
581         ccs                     = (LPCLIENTCREATESTRUCT) cs->lpCreateParams;
582         ci->hWindowMenu         = ccs->hWindowMenu;
583         ci->idFirstChild        = ccs->idFirstChild;
584         ci->infoActiveChildren  = NULL;
585         ci->flagMenuAltered     = FALSE;
586         ci->flagChildMaximized  = FALSE;
587         w->dwStyle             |= WS_CLIPCHILDREN;
588
589         GetClientRect(w->hwndParent, &ci->rectMaximize);
590         MoveWindow(hwnd, 0, 0, 
591                    ci->rectMaximize.right, ci->rectMaximize.bottom, 1);
592
593         return 0;
594
595       case WM_MDIACTIVATE:
596         MDIBringChildToTop(hwnd, wParam, FALSE, FALSE);
597         return 0;
598
599       case WM_MDICASCADE:
600         return MDICascade(hwnd, ci);
601
602       case WM_MDICREATE:
603         return MDICreateChild(w, ci, hwnd, (LPMDICREATESTRUCT) lParam);
604
605       case WM_MDIDESTROY:
606         return MDIDestroyChild(w, ci, hwnd, wParam, TRUE);
607
608       case WM_MDIGETACTIVE:
609         return ((LONG) ci->hwndActiveChild | 
610                 ((LONG) ci->flagChildMaximized << 16));
611
612       case WM_MDIICONARRANGE:
613         /* return MDIIconArrange(...) */
614         break;
615         
616       case WM_MDIMAXIMIZE:
617         return MDIMaximizeChild(hwnd, wParam, ci);
618
619       case WM_MDINEXT:
620         MDIBringChildToTop(hwnd, wParam, FALSE, TRUE);
621         break;
622         
623       case WM_MDIRESTORE:
624         return MDIRestoreChild(hwnd, ci);
625
626       case WM_MDISETMENU:
627         /* return MDISetMenu(...) */
628         break;
629         
630       case WM_MDITILE:
631         return MDITile(hwnd, ci);
632         
633       case WM_NCACTIVATE:
634         SendMessage(ci->hwndActiveChild, message, wParam, lParam);
635         break;
636         
637       case WM_PARENTNOTIFY:
638         if (wParam == WM_DESTROY)
639             return MDIDestroyChild(w, ci, hwnd, LOWORD(lParam), FALSE);
640         else if (wParam == WM_LBUTTONDOWN)
641             MDIBringChildToTop(hwnd, ci->hwndHitTest, FALSE, FALSE);
642         break;
643
644       case WM_SIZE:
645         GetClientRect(w->hwndParent, &ci->rectMaximize);
646         break;
647
648     }
649     
650     return DefWindowProc(hwnd, message, wParam, lParam);
651 }
652
653 /**********************************************************************
654  *                                      DefFrameProc (USER.445)
655  *
656  */
657 LONG 
658 DefFrameProc(HWND hwnd, HWND hwndMDIClient, WORD message, 
659              WORD wParam, LONG lParam)
660 {
661     if (hwndMDIClient)
662     {
663         switch (message)
664         {
665           case WM_COMMAND:
666             MDIBringChildToTop(hwndMDIClient, wParam, TRUE, FALSE);
667             break;
668
669           case WM_NCLBUTTONDOWN:
670             if (MDIHandleLButton(hwnd, hwndMDIClient, wParam, lParam))
671                 return 0;
672             break;
673             
674           case WM_NCACTIVATE:
675             SendMessage(hwndMDIClient, message, wParam, lParam);
676             return MDIPaintMaximized(hwnd, hwndMDIClient, 
677                                      message, wParam, lParam);
678
679           case WM_NCPAINT:
680             return MDIPaintMaximized(hwnd, hwndMDIClient, 
681                                      message, wParam, lParam);
682         
683           case WM_SETFOCUS:
684             SendMessage(hwndMDIClient, WM_SETFOCUS, wParam, lParam);
685             break;
686
687           case WM_SIZE:
688             MoveWindow(hwndMDIClient, 0, 0, 
689                        LOWORD(lParam), HIWORD(lParam), TRUE);
690             break;
691         }
692     }
693     
694     return DefWindowProc(hwnd, message, wParam, lParam);
695 }
696
697 /**********************************************************************
698  *                                      DefMDIChildProc (USER.447)
699  *
700  */
701 LONG 
702 DefMDIChildProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
703 {
704     MDICLIENTINFO       *ci;
705     WND                 *w;
706
707     w  = WIN_FindWndPtr(GetParent(hwnd));
708     ci = (MDICLIENTINFO *) w->wExtra;
709     
710     switch (message)
711     {
712       case WM_NCHITTEST:
713         ci->hwndHitTest = hwnd;
714         break;
715         
716       case WM_NCPAINT:
717         NC_DoNCPaint( hwnd, hwnd == ci->hwndActiveChild, FALSE );
718         return 0;
719
720       case WM_SYSCOMMAND:
721         switch (wParam)
722         {
723           case SC_MAXIMIZE:
724             return SendMessage(GetParent(hwnd), WM_MDIMAXIMIZE, hwnd, 0);
725
726           case SC_RESTORE:
727             return SendMessage(GetParent(hwnd), WM_MDIRESTORE, hwnd, 0);
728         }
729         break;
730         
731     }
732         
733     return DefWindowProc(hwnd, message, wParam, lParam);
734 }
735
736 /**********************************************************************
737  *                                      TranslateMDISysAccel (USER.451)
738  *
739  */
740 BOOL TranslateMDISysAccel(HWND hwndClient, LPMSG msg)
741 {
742     return 0;
743 }