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