source: trunk/src/user32/win32wmdiclient.cpp@ 4825

Last change on this file since 4825 was 4825, checked in by sandervl, 25 years ago

hook, mdi & focus fixes

File size: 39.4 KB
Line 
1/* $Id: win32wmdiclient.cpp,v 1.31 2000-12-17 15:04:12 sandervl Exp $ */
2/*
3 * Win32 MDI Client Window Class for OS/2
4 *
5 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999 Daniela Engert (dani@ngrt.de)
7 *
8 * Parts based on Corel WINE (window\mdi.c: 20000317)
9 * (Parts based on Wine (windows\mdi.c) (990815))
10 *
11 * Copyright 1994, Bob Amstadt
12 * 1995,1996 Alex Korobka
13 *
14 * Project Odin Software License can be found in LICENSE.TXT
15 *
16 */
17#include <os2win.h>
18#include <win.h>
19#include <stdlib.h>
20#include <math.h>
21#include <string.h>
22#include <stdarg.h>
23#include <assert.h>
24#include <misc.h>
25#include <heapstring.h>
26#include <win32wnd.h>
27#include <win32wmdiclient.h>
28#include <spy.h>
29#include "wndmsg.h"
30#include <oslibwin.h>
31#include <oslibutil.h>
32#include <oslibgdi.h>
33#include <oslibres.h>
34#include "oslibdos.h"
35#include "syscolor.h"
36#include "win32wndhandle.h"
37
38#define DBG_LOCALLOG DBG_win32wmdiclient
39#include "dbglocal.h"
40
41
42//******************************************************************************
43//******************************************************************************
44Win32MDIClientWindow::Win32MDIClientWindow(CREATESTRUCTA *lpCreateStructA, ATOM classAtom, BOOL isUnicode)
45 : maximizedChild(0), activeChild(0), nActiveChildren(0), nTotalCreated(0),
46 frameTitle(NULL), mdiFlags(0), idFirstChild(0), hWindowMenu(0),
47 sbRecalc(0),
48 Win32BaseWindow(OBJTYPE_WINDOW)
49{
50 Init();
51 this->isUnicode = isUnicode;
52 CreateWindowExA(lpCreateStructA, classAtom);
53}
54//******************************************************************************
55//******************************************************************************
56Win32MDIClientWindow::~Win32MDIClientWindow()
57{
58 if(frameTitle)
59 HeapFree(GetProcessHeap(), 0, frameTitle);
60}
61//******************************************************************************
62//******************************************************************************
63BOOL Win32MDIClientWindow::isMDIClient()
64{
65 return TRUE;
66}
67//******************************************************************************
68//******************************************************************************
69LRESULT Win32MDIClientWindow::MDIClientWndProc(UINT message, WPARAM wParam, LPARAM lParam)
70{
71 LPCREATESTRUCTA cs;
72 LPCLIENTCREATESTRUCT ccs;
73 RECT rect;
74 INT nItems;
75 LRESULT retvalue;
76 Win32Window *frameWnd;
77 Win32MDIChildWindow *mdichild;
78
79 frameWnd = (Win32Window *)getParent();
80 if(frameWnd == NULL) {
81 return 0;
82 }
83
84 switch (message)
85 {
86 case WM_CREATE:
87 cs = (LPCREATESTRUCTA)lParam;
88 ccs = (LPCLIENTCREATESTRUCT)cs->lpCreateParams;
89
90 hWindowMenu = ccs->hWindowMenu;
91 idFirstChild = ccs->idFirstChild;
92
93 maximizedChild = 0;
94 activeChild = 0;
95 nActiveChildren = 0;
96 nTotalCreated = 0;
97 frameTitle = NULL;
98 mdiFlags = 0;
99
100 setStyle(getStyle() | WS_CLIPCHILDREN);
101
102 updateFrameText(MDI_NOFRAMEREPAINT, getParent()->getWindowNameA());
103
104 AppendMenuA( hWindowMenu, MF_SEPARATOR, 0, NULL );
105
106 setClientRect(frameWnd->getClientRectPtr());
107
108 dprintf(("MDIClient created - hwnd = %04x, idFirst = %u\n", getWindowHandle(), idFirstChild ));
109
110 retvalue = 0;
111 goto END;
112
113 case WM_DESTROY:
114 if( maximizedChild ) restoreFrameMenu(getParent());
115
116 if((nItems = GetMenuItemCount(hWindowMenu)) > 0)
117 {
118 idFirstChild = nItems - 1;
119 nActiveChildren++; /* to delete a separator */
120 while( nActiveChildren-- )
121 DeleteMenu(hWindowMenu,MF_BYPOSITION,idFirstChild--);
122 }
123 retvalue = 0;
124 goto END;
125
126 case WM_MDIACTIVATE:
127 if( activeChild && activeChild->getWindowHandle() != (HWND)wParam )
128 {
129 mdichild = (Win32MDIChildWindow *)GetWindowFromHandle((HWND)wParam);
130 if(mdichild) {
131 mdichild->SetWindowPos(0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
132 }
133 }
134 retvalue = 0;
135 goto END;
136
137 case WM_MDICASCADE:
138 retvalue = cascade(wParam);
139 goto END;
140
141 case WM_MDICREATE:
142 if (lParam) {
143 retvalue = Win32MDIChildWindow::createChild( this, (MDICREATESTRUCTA*)lParam );
144 }
145 else retvalue = 0;
146 goto END;
147
148 case WM_MDIDESTROY:
149 mdichild = (Win32MDIChildWindow *)GetWindowFromHandle((HWND)wParam);
150 if(mdichild) {
151 retvalue = destroyChild(mdichild, TRUE );
152 }
153 goto END;
154
155 case WM_MDIGETACTIVE:
156 dprintf(("WM_MDIGETACTIVE: %x %x", this, (activeChild) ? activeChild->getWindowHandle() : 0));
157 if (lParam)
158 *(BOOL *)lParam = (maximizedChild != 0);
159
160 retvalue = (activeChild) ? activeChild->getWindowHandle() : 0;
161 goto END;
162
163 case WM_MDIICONARRANGE:
164 mdiFlags |= MDIF_NEEDUPDATE;
165 ArrangeIconicWindows(Win32Hwnd);
166 sbRecalc = SB_BOTH+1;
167 SendMessageA(WM_MDICALCCHILDSCROLL,0,0L);
168 retvalue = 0;
169 goto END;
170
171 case WM_MDIMAXIMIZE:
172 ::ShowWindow( (HWND)wParam, SW_MAXIMIZE );
173 retvalue = 0;
174 goto END;
175
176 case WM_MDINEXT: /* lParam != 0 means previous window */
177 mdichild = (Win32MDIChildWindow *)GetWindowFromHandle((HWND)wParam);
178 if(mdichild) {
179 switchActiveChild(mdichild, (lParam)? FALSE : TRUE );
180 }
181 break;
182
183 case WM_MDIRESTORE:
184 ::SendMessageA( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
185 retvalue = 0;
186 goto END;
187 case WM_MDISETMENU:
188 retvalue = setMDIMenu((HMENU)wParam, (HMENU)lParam );
189 goto END;
190
191 case WM_MDIREFRESHMENU:
192 retvalue = refreshMDIMenu((HMENU)wParam, (HMENU)lParam );
193 goto END;
194
195 case WM_MDITILE:
196 mdiFlags |= MDIF_NEEDUPDATE;
197 ShowScrollBar(Win32Hwnd,SB_BOTH,FALSE);
198 tile(wParam);
199 mdiFlags &= ~MDIF_NEEDUPDATE;
200 retvalue = 0;
201 goto END;
202
203 case WM_VSCROLL:
204 case WM_HSCROLL:
205 mdiFlags |= MDIF_NEEDUPDATE;
206 ScrollChildren(Win32Hwnd, message, wParam, lParam);
207 mdiFlags &= ~MDIF_NEEDUPDATE;
208 retvalue = 0;
209 goto END;
210
211 case WM_SETFOCUS:
212 if( activeChild )
213 {
214 if( !(activeChild->getStyle() & WS_MINIMIZE) )
215 ::SetFocus(activeChild->getWindowHandle());
216 }
217 retvalue = 0;
218 goto END;
219
220 case WM_NCACTIVATE:
221 if( activeChild )
222 activeChild->SendInternalMessageA(message, wParam, lParam);
223 break;
224
225 case WM_PARENTNOTIFY:
226 if (LOWORD(wParam) == WM_LBUTTONDOWN)
227 {
228 POINTS pt = MAKEPOINTS(lParam);
229 POINT point;
230
231 point.x = pt.x;
232 point.y = pt.y;
233
234 HWND child = ChildWindowFromPoint(getWindowHandle(), point);
235
236 if( child && child != getWindowHandle() && (!activeChild || activeChild->getWindowHandle() != child) )
237 ::SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
238 }
239 retvalue = 0;
240 goto END;
241
242 case WM_SIZE:
243 if( maximizedChild && maximizedChild->IsWindow() )
244 {
245 RECT rect;
246
247 rect.left = 0;
248 rect.top = 0;
249 rect.right = LOWORD(lParam);
250 rect.bottom = HIWORD(lParam);
251
252 AdjustWindowRectEx(&rect, maximizedChild->getStyle(), 0, maximizedChild->getExStyle());
253 ::MoveWindow(maximizedChild->getWindowHandle(), rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 1);
254 }
255 else postUpdate(SB_BOTH+1);
256 break;
257
258 case WM_MDICALCCHILDSCROLL:
259 if( (mdiFlags & MDIF_NEEDUPDATE) && sbRecalc )
260 {
261 CalcChildScroll(Win32Hwnd, sbRecalc-1);
262 sbRecalc = 0;
263 mdiFlags &= ~MDIF_NEEDUPDATE;
264 }
265 retvalue = 0;
266 goto END;
267 }
268 retvalue = DefWindowProcA(message, wParam, lParam );
269END:
270 return retvalue;
271}
272/**********************************************************************
273 * MDIClientWndProc
274 *
275 * This function handles all MDI requests.
276 */
277LRESULT WINAPI MDIClientWndProc( HWND hwnd, UINT message, WPARAM wParam,
278 LPARAM lParam )
279{
280 Win32MDIClientWindow *window;
281
282 window = (Win32MDIClientWindow *)Win32BaseWindow::GetWindowFromHandle(hwnd);
283 if(!window) {
284 dprintf(("MDIClientWndProc, window %x not found", hwnd));
285 return 0;
286 }
287 return window->MDIClientWndProc(message, wParam, lParam);
288}
289/**********************************************************************
290 * MDI_GetWindow
291 *
292 * returns "activateable" child different from the current or zero
293 */
294Win32MDIChildWindow *Win32MDIClientWindow::getWindow(Win32MDIChildWindow *actchild, BOOL bNext,
295 DWORD dwStyleMask)
296{
297 Win32MDIChildWindow *lastchild = 0, *curchild;
298
299 dwStyleMask |= WS_DISABLED | WS_VISIBLE;
300
301 if( !actchild ) actchild = getActiveChild();
302 if( !actchild) return 0;
303
304 for ( curchild = (Win32MDIChildWindow *)actchild->getNextChild(); ; curchild = (Win32MDIChildWindow *)curchild->getNextChild())
305 {
306 if (!curchild ) curchild = (Win32MDIChildWindow *)getFirstChild();
307
308 if ( curchild == actchild ) break; /* went full circle */
309
310 if (!curchild->getOwner() && (curchild->getStyle() & dwStyleMask) == WS_VISIBLE )
311 {
312 lastchild = curchild;
313 if ( bNext ) break;
314 }
315 }
316 return lastchild;
317}
318/**********************************************************************
319 * MDI_ChildActivate
320 *
321 * Note: hWndChild is NULL when last child is being destroyed
322 */
323LONG Win32MDIClientWindow::childActivate(Win32MDIChildWindow *child)
324{
325 BOOL isActiveFrameWnd = 0;
326 LONG retvalue;
327 Win32MDIChildWindow *prevActive = activeChild;
328
329 if( child && child->getStyle() & WS_DISABLED )
330 {
331 return 0;
332 }
333
334 /* Don't activate if it is already active. Might happen
335 since ShowWindow DOES activate MDI children */
336 if(activeChild == child)
337 {
338 return 0;
339 }
340
341 if( GetActiveWindow() == getParent()->getWindowHandle())
342 isActiveFrameWnd = TRUE;
343
344 /* deactivate prev. active child */
345 if( prevActive )
346 {
347 prevActive->setStyle(prevActive->getStyle() | WS_SYSMENU);
348 prevActive->SendInternalMessageA( WM_NCACTIVATE, FALSE, 0L );
349 prevActive->SendInternalMessageA( WM_MDIACTIVATE, (WPARAM)prevActive->getWindowHandle(), (LPARAM)(child) ? child->getWindowHandle() : 0);
350
351 /* uncheck menu item */
352 if( getMDIMenu() )
353 CheckMenuItem(getMDIMenu(), prevActive->getWindowId(), 0);
354 }
355
356 /* set appearance */
357 if( maximizedChild)
358 {
359 if( maximizedChild != child) {
360 if( child ) {
361 activeChild = child;
362 child->ShowWindow(SW_SHOWMAXIMIZED);
363 }
364 else
365 if(activeChild) activeChild->ShowWindow( SW_SHOWNORMAL );
366 }
367 }
368
369 dprintf(("childActivate: %x %x", this, (child) ? child->getWindowHandle() : 0));
370 activeChild = child;
371
372 /* check if we have any children left */
373 if( !activeChild )
374 {
375 if( isActiveFrameWnd )
376 SetFocus(getWindowHandle());
377
378 return 0;
379 }
380
381 /* check menu item */
382 if( getMDIMenu() )
383 CheckMenuItem(getMDIMenu(), child->getWindowId(), MF_CHECKED);
384
385 /* bring active child to the top */
386 child->SetWindowPos( 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
387
388 if( isActiveFrameWnd )
389 {
390 child->SendInternalMessageA( WM_NCACTIVATE, TRUE, 0L);
391 if( GetFocus() == getWindowHandle())
392 SendInternalMessageA( WM_SETFOCUS, (WPARAM)getWindowHandle(), 0L );
393 else
394 SetFocus( getWindowHandle() );
395 }
396
397 /* @@@PH prevActive may be NULL actually ?! */
398 child->SendInternalMessageA( WM_MDIACTIVATE,
399 prevActive ? (WPARAM)prevActive->getWindowHandle() : 0,
400 child->getWindowHandle());
401 return TRUE;
402}
403/**********************************************************************
404 * MDI_SwitchActiveChild
405 *
406 * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
407 * being activated
408 */
409void Win32MDIClientWindow::switchActiveChild(Win32MDIChildWindow *nextActiveChild, BOOL bNextWindow )
410{
411 Win32MDIChildWindow *prevActiveChild = 0;
412
413 if ( !nextActiveChild) return; /* no window to switch to */
414
415 prevActiveChild = getActiveChild();
416
417 if ( prevActiveChild != nextActiveChild)
418 {
419 BOOL bOptimize = 0;
420
421 if( getMaximizedChild() )
422 {
423 bOptimize = 1;
424 nextActiveChild->setStyle(nextActiveChild->getStyle()& ~WS_VISIBLE);
425 }
426
427 nextActiveChild->SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
428
429 if( bNextWindow && prevActiveChild )
430 prevActiveChild->SetWindowPos(HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
431
432 if( bOptimize )
433 ShowWindow(SW_SHOW );
434 }
435}
436
437
438/**********************************************************************
439 * MDIDestroyChild
440 */
441LRESULT Win32MDIClientWindow::destroyChild(Win32MDIChildWindow *child, BOOL flagDestroy )
442{
443 if( child == getActiveChild())
444 {
445 switchActiveChild(child, TRUE);
446
447 if( child == getActiveChild() )
448 {
449 ::ShowWindow(child->getWindowHandle(),SW_HIDE);
450 if( child == getMaximizedChild() )
451 {
452 restoreFrameMenu(child);
453 setMaximizedChild(NULL);
454 updateFrameText(TRUE,NULL);
455 }
456 childActivate(0);
457 }
458 }
459 child->menuDeleteItem();
460
461 decNrActiveChildren();
462
463 dprintf(("child destroyed - %04x\n", child->getWindowHandle()));
464
465 if (flagDestroy)
466 {
467 postUpdate(SB_BOTH+1);
468 ::DestroyWindow(child->getWindowHandle());
469 }
470
471 return 0;
472}
473/**********************************************************************
474 * MDI_UpdateFrameText
475 *
476 * used when child window is maximized/restored
477 *
478 * Note: lpTitle can be NULL
479 */
480void Win32MDIClientWindow::updateFrameText(BOOL repaint, LPCSTR lpTitle )
481{
482 char lpBuffer[MDI_MAXTITLELENGTH+1];
483
484 /* store new "default" title if lpTitle is not NULL */
485 if (lpTitle)
486 {
487 if (frameTitle) HeapFree( GetProcessHeap(), 0, frameTitle );
488 frameTitle = HEAP_strdupA( GetProcessHeap(), 0, lpTitle );
489 }
490
491 if (frameTitle)
492 {
493 Win32MDIChildWindow *childWnd = getMaximizedChild();
494
495 if( childWnd && childWnd->getWindowNameA() )
496 {
497 /* combine frame title and child title if possible */
498
499 LPCSTR lpBracket = " - [";
500 int i_frame_text_length = strlen(frameTitle);
501 int i_child_text_length = strlen(childWnd->getWindowNameA());
502
503 lstrcpynA( lpBuffer, frameTitle, MDI_MAXTITLELENGTH);
504
505 if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
506 {
507 strcat( lpBuffer, lpBracket );
508
509 if( i_frame_text_length + i_child_text_length + 6 < MDI_MAXTITLELENGTH )
510 {
511 strcat( lpBuffer, childWnd->getWindowNameA());
512 strcat( lpBuffer, "]" );
513 }
514 else
515 {
516 lstrcpynA(lpBuffer + i_frame_text_length + 4,
517 childWnd->getWindowNameA(), MDI_MAXTITLELENGTH - i_frame_text_length - 5 );
518 strcat( lpBuffer, "]" );
519 }
520 }
521 }
522 else
523 {
524 lstrcpynA(lpBuffer, frameTitle, MDI_MAXTITLELENGTH );
525 lpBuffer[MDI_MAXTITLELENGTH]='\0';
526 }
527 }
528 else
529 lpBuffer[0] = '\0';
530
531 getParent()->SetWindowTextA(lpBuffer);
532 if( repaint == MDI_REPAINTFRAME)
533 getParent()->SetWindowPos(0,0,0,0,0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
534}
535/**********************************************************************
536 * MDISetMenu
537 */
538LRESULT Win32MDIClientWindow::setMDIMenu(HMENU hmenuFrame, HMENU hmenuWindow)
539{
540 HWND hwndFrame = ::GetParent(getWindowHandle());
541 HMENU oldFrameMenu = ::GetMenu(hwndFrame);
542
543 if (hmenuFrame && !IsMenu(hmenuFrame))
544 {
545 dprintf(("Win32MDIClientWindow::setMDIMenu: hmenuFrame is not a menu handle\n"));
546 return 0L;
547 }
548
549 if (hmenuWindow && !IsMenu(hmenuWindow))
550 {
551 dprintf(("Win32MDIClientWindow::setMDIMenu: hmenuWindow is not a menu handle\n"));
552 return 0L;
553 }
554
555 if( maximizedChild && hmenuFrame && hmenuFrame!=oldFrameMenu )
556 restoreFrameMenu(maximizedChild);
557
558 if( hmenuWindow && hmenuWindow != hWindowMenu )
559 {
560 /* delete menu items from ci->hWindowMenu
561 * and add them to hmenuWindow */
562
563 INT i = GetMenuItemCount(hWindowMenu) - 1;
564 INT pos = GetMenuItemCount(hmenuWindow) + 1;
565
566 AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL);
567
568 if( nActiveChildren )
569 {
570 INT j;
571 LPWSTR buffer = NULL;
572 MENUITEMINFOW mii;
573 INT nbWindowsMenuItems; /* num of documents shown + "More Windows..." if present */
574
575 if (nActiveChildren <= MDI_MOREWINDOWSLIMIT)
576 nbWindowsMenuItems = nActiveChildren;
577 else
578 nbWindowsMenuItems = MDI_MOREWINDOWSLIMIT + 1;
579
580 j = i - nbWindowsMenuItems + 1;
581
582 for( ; i >= j ; i-- )
583 {
584 memset(&mii, 0, sizeof(mii));
585 mii.cbSize = sizeof(mii);
586 mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE
587 | MIIM_SUBMENU | MIIM_TYPE | MIIM_BITMAP;
588
589 GetMenuItemInfoW(hWindowMenu, i, TRUE, &mii);
590 if(mii.cch) { /* Menu is MFT_STRING */
591 mii.cch++; /* add room for '\0' */
592 buffer = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
593 mii.cch * sizeof(WCHAR));
594 mii.dwTypeData = buffer;
595 GetMenuItemInfoW(hWindowMenu, i, TRUE, &mii);
596 }
597 DeleteMenu(hWindowMenu, i, MF_BYPOSITION);
598 InsertMenuItemW(hmenuWindow, pos, TRUE, &mii);
599 if(buffer) {
600 HeapFree(GetProcessHeap(), 0, buffer);
601 buffer = NULL;
602 }
603 }
604 }
605
606 /* remove separator */
607 DeleteMenu(hWindowMenu, i, MF_BYPOSITION);
608
609 hWindowMenu = hmenuWindow;
610 }
611
612 if (hmenuFrame)
613 {
614 ::SetMenu(hwndFrame, hmenuFrame);
615
616 if( hmenuFrame!=oldFrameMenu )
617 {
618 if (maximizedChild)
619 augmentFrameMenu(maximizedChild);
620
621 return oldFrameMenu;
622 }
623 }
624 else
625 {
626 INT nItems = GetMenuItemCount(oldFrameMenu) - 1;
627 UINT iId = GetMenuItemID(oldFrameMenu,nItems) ;
628
629 if( !(iId == SC_RESTORE || iId == SC_CLOSE) )
630 {
631 /* SetMenu() may already have been called, meaning that this window
632 * already has its menu. But they may have done a SetMenu() on
633 * an MDI window, and called MDISetMenu() after the fact, meaning
634 * that the "if" to this "else" wouldn't catch the need to
635 * augment the frame menu.
636 */
637 if( maximizedChild )
638 augmentFrameMenu(maximizedChild);
639 }
640 }
641 return 0;
642}
643
644/**********************************************************************
645 * MDIRefreshMenu
646 */
647LRESULT Win32MDIClientWindow::refreshMDIMenu(HMENU hmenuFrame, HMENU hmenuWindow)
648{
649 HMENU oldFrameMenu = getParent()->GetMenu();
650
651// FIXME("partially function stub\n");
652
653 return oldFrameMenu;
654}
655/**********************************************************************
656 * MDI_RestoreFrameMenu
657 */
658BOOL Win32MDIClientWindow::restoreFrameMenu(Win32BaseWindow *child)
659{
660 MENUITEMINFOA menuInfo;
661 INT nItems = GetMenuItemCount(getParent()->GetMenu()) - 1;
662 UINT iId = GetMenuItemID(getParent()->GetMenu(),nItems) ;
663
664 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
665 return 0;
666
667 /*
668 * Remove the system menu, If that menu is the icon of the window
669 * as it is in win95, we have to delete the bitmap.
670 */
671 menuInfo.cbSize = sizeof(MENUITEMINFOA);
672 menuInfo.fMask = MIIM_DATA | MIIM_TYPE;
673
674 GetMenuItemInfoA(getParent()->GetMenu(),
675 0,
676 TRUE,
677 &menuInfo);
678
679 RemoveMenu(getParent()->GetMenu(),0,MF_BYPOSITION);
680
681//TODO: See augmentframemenu
682#if 0
683 if ((menuInfo.fType & MFT_BITMAP) &&
684 (LOWORD(menuInfo.dwTypeData)!=0) &&
685 (LOWORD(menuInfo.dwTypeData)!=hBmpClose) )
686 {
687 DeleteObject((HBITMAP)LOWORD(menuInfo.dwTypeData));
688 }
689#endif
690
691 /* close */
692 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
693
694 /* restore */
695 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
696 /* minimize */
697 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
698
699 DrawMenuBar(getParent()->getWindowHandle());
700
701 return 1;
702}
703
704Win32BaseWindow** Win32MDIClientWindow::buildWindowArray(UINT bwaFlags,PUINT total)
705{
706 Win32BaseWindow **list = NULL,*win32wnd,**pos;
707 UINT skipHidden;
708 DWORD skipFlags;
709
710 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
711 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
712 if (bwaFlags & BWA_SKIPICONIC) skipFlags |= WS_MINIMIZE;
713
714 /* First count the windows */
715 *total = 0;
716 win32wnd = (Win32BaseWindow*)this->getFirstChild();
717 while (win32wnd)
718 {
719 if (!(win32wnd->getStyle() & skipFlags) && (!skipHidden || (win32wnd->getStyle() & WS_VISIBLE)))
720 (*total)++;
721 win32wnd = (Win32BaseWindow*)win32wnd->getNextChild();
722 }
723
724 if (*total)
725 {
726 /* Now build the list of all windows */
727 list = (Win32BaseWindow**)HeapAlloc(GetProcessHeap(),0,sizeof(Win32BaseWindow*)*(*total+1));
728 if (list)
729 {
730 for (win32wnd = (Win32BaseWindow*)this->getFirstChild(),pos = list;win32wnd;win32wnd = (Win32BaseWindow*)win32wnd->getNextChild())
731 {
732 if ((win32wnd->getStyle() & skipFlags));
733 else if(!skipHidden || win32wnd->getStyle() & WS_VISIBLE)
734 *pos++ = win32wnd;
735 }
736 *pos = NULL;
737 }
738 }
739
740 return list;
741}
742
743void Win32MDIClientWindow::releaseWindowArray(Win32BaseWindow **wndArray)
744{
745 HeapFree(GetProcessHeap(),0,wndArray);
746}
747
748/**********************************************************************
749 * MDI_CalcDefaultChildPos
750 *
751 * It seems that the default height is about 2/3 of the client rect
752 */
753void Win32MDIClientWindow::calcDefaultChildPos(WORD n,LPPOINT lpPos,INT delta)
754{
755 INT nstagger;
756 RECT rect;
757 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
758 GetSystemMetrics(SM_CYFRAME) - 1;
759
760 getClientRect(&rect);
761 if( rect.bottom - rect.top - delta >= spacing )
762 rect.bottom -= delta;
763
764 nstagger = (rect.bottom - rect.top)/(3 * spacing);
765 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
766 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
767 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
768}
769
770/**********************************************************************
771 * MDICascade
772 */
773BOOL Win32MDIClientWindow::cascade(UINT fuCascade)
774{
775 Win32BaseWindow **list;
776 UINT total = 0;
777
778 if (getMaximizedChild())
779 SendInternalMessageA(WM_MDIRESTORE, (WPARAM)getMaximizedChild()->getWindowHandle(), 0);
780
781 if (nActiveChildren == 0) return 0;
782
783 list = buildWindowArray(BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC,&total);
784 if (list)
785 {
786 Win32BaseWindow** heapPtr = list;
787 if (total)
788 {
789 INT delta = 0,n = 0;
790 POINT pos[2];
791
792
793 if (total < nActiveChildren)
794 delta = GetSystemMetrics(SM_CYICONSPACING)+GetSystemMetrics(SM_CYICON);
795
796 // walk the list (backwards) and move windows
797 while (*list) list++;
798 while (list != heapPtr)
799 {
800 list--;
801
802 calcDefaultChildPos(n++,pos,delta);
803 ::SetWindowPos((*list)->getWindowHandle(),0,pos[0].x,pos[0].y,pos[1].x,pos[1].y,SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
804 }
805 }
806 releaseWindowArray(heapPtr);
807 }
808
809 if (total < nActiveChildren)
810 ArrangeIconicWindows(Win32Hwnd);
811
812 return TRUE;
813}
814
815/**********************************************************************
816 * MDITile
817 */
818BOOL Win32MDIClientWindow::tile(UINT fuTile)
819{
820 Win32BaseWindow** list;
821 UINT total = 0;
822
823 if (getMaximizedChild())
824 SendInternalMessageA(WM_MDIRESTORE, (WPARAM)getMaximizedChild()->getWindowHandle(), 0);
825
826 if (nActiveChildren == 0) return TRUE;
827
828 list = buildWindowArray(BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC |
829 ((fuTile & MDITILE_SKIPDISABLED)? BWA_SKIPDISABLED : 0), &total );
830
831 if (list)
832 {
833 Win32BaseWindow** heapPtr = list;
834
835 if (total)
836 {
837 RECT rect;
838 int x, y, xsize, ysize;
839 int rows, columns, r, c, i;
840
841 GetClientRect(Win32Hwnd,&rect);
842 rows = (int) sqrt((double)total);
843 columns = total / rows;
844
845 if( fuTile & MDITILE_HORIZONTAL ) // version >= 3.1
846 {
847 i = rows;
848 rows = columns; // exchange r and c
849 columns = i;
850 }
851
852 if( total != nActiveChildren)
853 {
854 y = rect.bottom - 2 * GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
855 rect.bottom = ( y - GetSystemMetrics(SM_CYICON) < rect.top )? rect.bottom: y;
856 }
857
858 ysize = rect.bottom / rows;
859 xsize = rect.right / columns;
860
861 for (x = i = 0, c = 1; c <= columns && *list; c++)
862 {
863 if (c == columns)
864 {
865 rows = total - i;
866 ysize = rect.bottom / rows;
867 }
868
869 y = 0;
870 for (r = 1; r <= rows && *list; r++, i++)
871 {
872 ::SetWindowPos((*list)->getWindowHandle(), 0, x, y, xsize, ysize,
873 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
874 y += ysize;
875 list++;
876 }
877 x += xsize;
878 }
879 }
880 releaseWindowArray(heapPtr);
881 }
882
883 if( total < nActiveChildren ) ArrangeIconicWindows(Win32Hwnd);
884
885 return TRUE;
886}
887
888/* ----------------------- Frame window ---------------------------- */
889
890/**********************************************************************
891 * MDI_AugmentFrameMenu
892 */
893BOOL Win32MDIClientWindow::augmentFrameMenu(Win32MDIChildWindow *child)
894{
895 HMENU hSysPopup = 0,hFrameMenu = ::GetMenu(getParent()->getWindowHandle()),hSysMenu = ::GetSystemMenu(child->getWindowHandle(),FALSE);
896 HBITMAP hSysMenuBitmap = 0;
897
898 if (!hFrameMenu || !hSysMenu)
899 return 0;
900
901 // create a copy of sysmenu popup and insert it into frame menu bar
902
903 if (!(hSysPopup = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU")))
904 return 0;
905
906 //TRACE("\tgot popup %04x in sysmenu %04x\n",
907 // hSysPopup, child->hSysMenu);
908
909 AppendMenuA(hFrameMenu,MF_HELP | MF_BITMAP,
910 SC_MINIMIZE, (LPSTR)(DWORD)HBMMENU_MBAR_MINIMIZE ) ;
911 AppendMenuA(hFrameMenu,MF_HELP | MF_BITMAP,
912 SC_RESTORE, (LPSTR)(DWORD)HBMMENU_MBAR_RESTORE );
913
914 // In Win 95 look, the system menu is replaced by the child icon
915
916 /* Find icon */
917 HICON hIcon = child->IconForWindow(ICON_SMALL);
918
919 if (hIcon)
920 {
921 HDC hMemDC;
922 HBITMAP hBitmap, hOldBitmap;
923 HBRUSH hBrush;
924 HDC hdc = GetDC(child->getWindowHandle());
925
926 if (hdc)
927 {
928 int cx, cy;
929
930 cx = GetSystemMetrics(SM_CXSMICON);
931 cy = GetSystemMetrics(SM_CYSMICON);
932 hMemDC = CreateCompatibleDC(hdc);
933 hBitmap = CreateCompatibleBitmap(hdc, cx, cy);
934 hOldBitmap = SelectObject(hMemDC, hBitmap);
935 SetMapMode(hMemDC, MM_TEXT);
936 hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
937 DrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, hBrush, DI_NORMAL);
938 SelectObject (hMemDC, hOldBitmap);
939 DeleteObject(hBrush);
940 DeleteDC(hMemDC);
941 ReleaseDC(child->getWindowHandle(), hdc);
942 hSysMenuBitmap = hBitmap;
943 }
944 }
945
946 if( !InsertMenuA(hFrameMenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
947 hSysPopup, (LPSTR)(DWORD)hSysMenuBitmap))
948 {
949 //TRACE("not inserted\n");
950 DestroyMenu(hSysPopup);
951 return 0;
952 }
953
954 // The close button is only present in Win 95 look
955
956 AppendMenuA(hFrameMenu,MF_HELP | MF_BITMAP,
957 SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
958
959 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
960 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
961 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
962 SetMenuDefaultItem(hSysPopup, SC_CLOSE, FALSE);
963
964 // redraw menu
965 DrawMenuBar(getParent()->getWindowHandle());
966
967 return 1;
968}
969
970/**********************************************************************
971 * MDI_RestoreFrameMenu
972 */
973BOOL Win32MDIClientWindow::restoreFrameMenu(Win32MDIChildWindow *child)
974{
975 MENUITEMINFOA menuInfo;
976 HMENU hFrameMenu = ::GetMenu(getParent()->getWindowHandle());
977 INT nItems = GetMenuItemCount(hFrameMenu) - 1;
978 UINT iId = GetMenuItemID(hFrameMenu,nItems) ;
979
980 //TRACE("frameWnd %p,child %04x\n",frameWnd,hChild);
981
982 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
983 return 0;
984
985 /*
986 * Remove the system menu, If that menu is the icon of the window
987 * as it is in win95, we have to delete the bitmap.
988 */
989
990 menuInfo.cbSize = sizeof(MENUITEMINFOA);
991 menuInfo.fMask = MIIM_DATA | MIIM_TYPE;
992
993 GetMenuItemInfoA(hFrameMenu,
994 0,
995 TRUE,
996 &menuInfo);
997
998 RemoveMenu(hFrameMenu,0,MF_BYPOSITION);
999
1000#if 0 //CB: hBmpClose not (yet) defined
1001 if ( (menuInfo.fType & MFT_BITMAP) &&
1002 (LOWORD(menuInfo.dwTypeData)!=0) &&
1003 (LOWORD(menuInfo.dwTypeData)!=hBmpClose) )
1004 {
1005 DeleteObject((HBITMAP)LOWORD(menuInfo.dwTypeData));
1006 }
1007#endif
1008
1009 // close
1010 DeleteMenu(hFrameMenu,GetMenuItemCount(hFrameMenu) - 1,MF_BYPOSITION);
1011
1012 // restore
1013 DeleteMenu(hFrameMenu,GetMenuItemCount(hFrameMenu) - 1,MF_BYPOSITION);
1014 // minimize
1015 DeleteMenu(hFrameMenu,GetMenuItemCount(hFrameMenu) - 1,MF_BYPOSITION);
1016
1017 DrawMenuBar(getParent()->getWindowHandle());
1018
1019 return 1;
1020}
1021
1022/***********************************************************************
1023 * CalcChildScroll (USER.462)
1024 */
1025void WINAPI CalcChildScroll(HWND hwnd,WORD scroll)
1026{
1027 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
1028 SCROLLINFO info;
1029 RECT childRect, clientRect;
1030 INT vmin, vmax, hmin, hmax, vpos, hpos;
1031
1032 if (!win32wnd) return;
1033
1034 GetClientRect( hwnd, &clientRect );
1035 SetRectEmpty( &childRect );
1036
1037 //TODO: Check if this goes correctly
1038 for (win32wnd = (Win32BaseWindow*)win32wnd->getFirstChild();win32wnd;win32wnd = (Win32BaseWindow*)win32wnd->getNextChild())
1039 {
1040 if( win32wnd->getStyle() & WS_MAXIMIZE )
1041 {
1042 ShowScrollBar(hwnd, SB_BOTH, FALSE);
1043 return;
1044 }
1045 UnionRect(&childRect,win32wnd->getWindowRect(),&childRect);
1046 }
1047 UnionRect( &childRect, &clientRect, &childRect );
1048
1049 hmin = childRect.left; hmax = childRect.right - clientRect.right;
1050 hpos = clientRect.left - childRect.left;
1051 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
1052 vpos = clientRect.top - childRect.top;
1053
1054 switch( scroll )
1055 {
1056 case SB_HORZ:
1057 vpos = hpos; vmin = hmin; vmax = hmax;
1058 case SB_VERT:
1059 info.cbSize = sizeof(info);
1060 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
1061 info.fMask = SIF_POS | SIF_RANGE;
1062 SetScrollInfo(hwnd, scroll, &info, TRUE);
1063 break;
1064 case SB_BOTH:
1065 {
1066 SCROLLINFO vInfo, hInfo;
1067
1068 vInfo.cbSize = hInfo.cbSize = sizeof(SCROLLINFO);
1069 vInfo.nMin = vmin;
1070 hInfo.nMin = hmin;
1071 vInfo.nMax = vmax;
1072 hInfo.nMax = hmax;
1073 vInfo.nPos = vpos;
1074 hInfo.nPos = hpos;
1075 vInfo.fMask = hInfo.fMask = SIF_RANGE | SIF_POS;
1076
1077 SetScrollInfo(hwnd,SB_VERT,&vInfo,TRUE);
1078 SetScrollInfo(hwnd,SB_HORZ,&hInfo,TRUE);
1079 }
1080 }
1081}
1082
1083/***********************************************************************
1084 * ScrollChildren32 (USER32.448)
1085 */
1086void WINAPI ScrollChildren(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
1087{
1088 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hWnd);
1089 INT newPos = -1;
1090 INT curPos, length, minPos, maxPos, shift;
1091
1092 if (!win32wnd) return;
1093
1094 if (uMsg == WM_HSCROLL)
1095 {
1096 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
1097 curPos = GetScrollPos(hWnd,SB_HORZ);
1098 length = win32wnd->getClientWidth()/2;
1099 shift = GetSystemMetrics(SM_CYHSCROLL);
1100 } else if (uMsg == WM_VSCROLL)
1101 {
1102 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
1103 curPos = GetScrollPos(hWnd,SB_VERT);
1104 length = win32wnd->getClientHeight()/2;
1105 shift = GetSystemMetrics(SM_CXVSCROLL);
1106 } else return;
1107
1108 switch( wParam )
1109 {
1110 case SB_LINEUP:
1111 newPos = curPos - shift;
1112 break;
1113
1114 case SB_LINEDOWN:
1115 newPos = curPos + shift;
1116 break;
1117
1118 case SB_PAGEUP:
1119 newPos = curPos - length;
1120 break;
1121
1122 case SB_PAGEDOWN:
1123 newPos = curPos + length;
1124 break;
1125
1126 case SB_THUMBPOSITION:
1127 newPos = LOWORD(lParam);
1128 break;
1129
1130 case SB_THUMBTRACK:
1131 return;
1132
1133 case SB_TOP:
1134 newPos = minPos;
1135 break;
1136
1137 case SB_BOTTOM:
1138 newPos = maxPos;
1139 break;
1140
1141 case SB_ENDSCROLL:
1142 CalcChildScroll(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
1143 return;
1144 }
1145
1146 if( newPos > maxPos )
1147 newPos = maxPos;
1148 else
1149 if( newPos < minPos )
1150 newPos = minPos;
1151
1152 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
1153
1154 if( uMsg == WM_VSCROLL )
1155 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
1156 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
1157 else
1158 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
1159 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
1160}
1161
1162/*****************************************************************************
1163 * Name : WORD WIN32API CascadeWindows
1164 * Purpose : The CascadeWindows function cascades the specified windows or
1165 * the child windows of the specified parent window.
1166 * Parameters: HWND hwndParent handle of parent window
1167 * UINT wHow types of windows not to arrange
1168 * CONST RECT * lpRect rectangle to arrange windows in
1169 * UINT cKids number of windows to arrange
1170 * const HWND FAR * lpKids array of window handles
1171 * Variables :
1172 * Result : If the function succeeds, the return value is the number of windows arranged.
1173 * If the function fails, the return value is zero.
1174 * Remark :
1175 * Status : UNTESTED STUB
1176 *
1177 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
1178 *****************************************************************************/
1179WORD WIN32API CascadeWindows(HWND hwndParent,
1180 UINT wHow,
1181 CONST LPRECT lpRect,
1182 UINT cKids,
1183 const HWND *lpKids)
1184{
1185 dprintf(("USER32:CascadeWindows(%08xh,%u,%08xh,%u,%08x) not implemented.\n",
1186 hwndParent,
1187 wHow,
1188 lpRect,
1189 cKids,
1190 lpKids));
1191
1192 return (0);
1193}
1194
1195/*****************************************************************************
1196 * Name : BOOL WIN32API CascadeChildWindows
1197 * Purpose : Unknown
1198 * Parameters: Unknown
1199 * Variables :
1200 * Result :
1201 * Remark :
1202 * Status : UNTESTED UNKNOWN STUB
1203 *
1204 * Author : Patrick Haller [Wed, 1998/06/16 11:55]
1205 *****************************************************************************/
1206BOOL WIN32API CascadeChildWindows(DWORD x1,
1207 DWORD x2)
1208{
1209 dprintf(("USER32: CascadeChildWindows(%08xh,%08xh) not implemented.\n",
1210 x1,
1211 x2));
1212
1213 return (FALSE); /* default */
1214}
1215
1216/*****************************************************************************
1217 * Name : WORD WIN32API TileWindows
1218 * Purpose : The TileWindows function tiles the specified windows, or the child
1219 * windows of the specified parent window.
1220 * Parameters: HWND hwndParent handle of parent window
1221 * WORD wFlags types of windows not to arrange
1222 * LPCRECT lpRect rectangle to arrange windows in
1223 * WORD cChildrenb number of windows to arrange
1224 * const HWND *ahwndChildren array of window handles
1225 * Variables :
1226 * Result : If the function succeeds, the return value is the number of
1227 * windows arranged.
1228 * If the function fails, the return value is zero.
1229 * Remark :
1230 * Status : UNTESTED STUB
1231 *
1232 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
1233 *****************************************************************************/
1234WORD WIN32API TileWindows(HWND hwndParent,
1235 UINT wFlags,
1236 const LPRECT lpRect,
1237 UINT cChildrenb,
1238 const HWND *ahwndChildren)
1239{
1240 dprintf(("USER32:TileWindows (%08xh,%08xh,%08xh,%08xh,%08x) not implemented.\n",
1241 hwndParent,
1242 wFlags,
1243 lpRect,
1244 cChildrenb,
1245 ahwndChildren));
1246
1247 return (0);
1248}
1249
1250/*****************************************************************************
1251 * Name : BOOL WIN32API TileChildWindows
1252 * Purpose : Unknown
1253 * Parameters: Unknown
1254 * Variables :
1255 * Result :
1256 * Remark :
1257 * Status : UNTESTED UNKNOWN STUB
1258 *
1259 * Author : Patrick Haller [Wed, 1998/06/16 11:55]
1260 *****************************************************************************/
1261BOOL WIN32API TileChildWindows(DWORD x1,
1262 DWORD x2)
1263{
1264 dprintf(("USER32: TileChildWindows(%08xh,%08xh) not implemented.\n",
1265 x1,
1266 x2));
1267
1268 return (FALSE); /* default */
1269}
1270
1271/* -------- Miscellaneous service functions ----------
1272 *
1273 * MDI_GetChildByID
1274 */
1275Win32MDIChildWindow *Win32MDIClientWindow::getChildByID(INT id)
1276{
1277 Win32MDIChildWindow *child;
1278
1279 for (child = (Win32MDIChildWindow *)getFirstChild() ; child; child = (Win32MDIChildWindow *)child->getNextChild())
1280 if (child->getWindowId() == id) return child;
1281
1282 return 0;
1283}
1284
1285void Win32MDIClientWindow::postUpdate(WORD recalc)
1286{
1287 if( !(mdiFlags & MDIF_NEEDUPDATE) )
1288 {
1289 mdiFlags |= MDIF_NEEDUPDATE;
1290 PostMessageA(getWindowHandle(), WM_MDICALCCHILDSCROLL, 0, 0);
1291 }
1292 sbRecalc = recalc;
1293}
1294//******************************************************************************
1295//******************************************************************************
1296BOOL MDICLIENT_Register()
1297{
1298 WNDCLASSA wndClass;
1299
1300//SvL: Don't check this now
1301// if (GlobalFindAtomA(MDICLIENTCLASSNAMEA)) return FALSE;
1302
1303 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
1304 wndClass.style = CS_GLOBALCLASS;
1305 wndClass.lpfnWndProc = (WNDPROC)MDIClientWndProc;
1306 wndClass.cbClsExtra = 0;
1307 wndClass.cbWndExtra = 0;
1308 wndClass.hCursor = 0;
1309 wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
1310 wndClass.lpszClassName = MDICLIENTCLASSNAMEA;
1311
1312 return RegisterClassA(&wndClass);
1313}
1314//******************************************************************************
1315//******************************************************************************
1316BOOL MDICLIENT_Unregister()
1317{
1318 if (GlobalFindAtomA(MDICLIENTCLASSNAMEA))
1319 return UnregisterClassA(MDICLIENTCLASSNAMEA,(HINSTANCE)NULL);
1320 else return FALSE;
1321}
1322//******************************************************************************
1323//******************************************************************************
Note: See TracBrowser for help on using the repository browser.