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

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

MDI + SetParent + activation fixes

File size: 40.0 KB
Line 
1/* $Id: win32wmdiclient.cpp,v 1.32 2000-12-24 14:54:07 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 1
569 if( nActiveChildren )
570 {
571 INT j = i - nActiveChildren + 1;
572 char buffer[100];
573 UINT id,state;
574
575 for( ; i >= j ; i-- )
576 {
577 id = GetMenuItemID(hWindowMenu,i );
578 state = GetMenuState(hWindowMenu,i,MF_BYPOSITION);
579
580 GetMenuStringA(hWindowMenu, i, buffer, 100, MF_BYPOSITION);
581
582 DeleteMenu(hWindowMenu, i , MF_BYPOSITION);
583 InsertMenuA(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
584 id, buffer);
585 CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
586 }
587 }
588#else
589//doesn't work:
590 if( nActiveChildren )
591 {
592 INT j;
593 LPWSTR buffer = NULL;
594 MENUITEMINFOW mii;
595 INT nbWindowsMenuItems; /* num of documents shown + "More Windows..." if present */
596
597 if (nActiveChildren <= MDI_MOREWINDOWSLIMIT)
598 nbWindowsMenuItems = nActiveChildren;
599 else
600 nbWindowsMenuItems = MDI_MOREWINDOWSLIMIT + 1;
601
602 j = i - nbWindowsMenuItems + 1;
603
604 for( ; i >= j ; i-- )
605 {
606 memset(&mii, 0, sizeof(mii));
607 mii.cbSize = sizeof(mii);
608 mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE
609 | MIIM_SUBMENU | MIIM_TYPE | MIIM_BITMAP;
610
611 GetMenuItemInfoW(hWindowMenu, i, TRUE, &mii);
612 if(mii.cch) { /* Menu is MFT_STRING */
613 mii.cch++; /* add room for '\0' */
614 buffer = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
615 mii.cch * sizeof(WCHAR));
616 mii.dwTypeData = buffer;
617 GetMenuItemInfoW(hWindowMenu, i, TRUE, &mii);
618 }
619 DeleteMenu(hWindowMenu, i, MF_BYPOSITION);
620 InsertMenuItemW(hmenuWindow, pos, TRUE, &mii);
621 if(buffer) {
622 HeapFree(GetProcessHeap(), 0, buffer);
623 buffer = NULL;
624 }
625 }
626 }
627#endif
628 /* remove separator */
629 DeleteMenu(hWindowMenu, i, MF_BYPOSITION);
630
631 hWindowMenu = hmenuWindow;
632 }
633
634 if (hmenuFrame)
635 {
636 ::SetMenu(hwndFrame, hmenuFrame);
637
638 if( hmenuFrame!=oldFrameMenu )
639 {
640 if (maximizedChild)
641 augmentFrameMenu(maximizedChild);
642
643 return oldFrameMenu;
644 }
645 }
646 else
647 {
648 INT nItems = GetMenuItemCount(oldFrameMenu) - 1;
649 UINT iId = GetMenuItemID(oldFrameMenu,nItems) ;
650
651 if( !(iId == SC_RESTORE || iId == SC_CLOSE) )
652 {
653 /* SetMenu() may already have been called, meaning that this window
654 * already has its menu. But they may have done a SetMenu() on
655 * an MDI window, and called MDISetMenu() after the fact, meaning
656 * that the "if" to this "else" wouldn't catch the need to
657 * augment the frame menu.
658 */
659 if( maximizedChild )
660 augmentFrameMenu(maximizedChild);
661 }
662 }
663 return 0;
664}
665
666/**********************************************************************
667 * MDIRefreshMenu
668 */
669LRESULT Win32MDIClientWindow::refreshMDIMenu(HMENU hmenuFrame, HMENU hmenuWindow)
670{
671 HMENU oldFrameMenu = getParent()->GetMenu();
672
673// FIXME("partially function stub\n");
674
675 return oldFrameMenu;
676}
677/**********************************************************************
678 * MDI_RestoreFrameMenu
679 */
680BOOL Win32MDIClientWindow::restoreFrameMenu(Win32BaseWindow *child)
681{
682 MENUITEMINFOA menuInfo;
683 INT nItems = GetMenuItemCount(getParent()->GetMenu()) - 1;
684 UINT iId = GetMenuItemID(getParent()->GetMenu(),nItems) ;
685
686 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
687 return 0;
688
689 /*
690 * Remove the system menu, If that menu is the icon of the window
691 * as it is in win95, we have to delete the bitmap.
692 */
693 menuInfo.cbSize = sizeof(MENUITEMINFOA);
694 menuInfo.fMask = MIIM_DATA | MIIM_TYPE;
695
696 GetMenuItemInfoA(getParent()->GetMenu(),
697 0,
698 TRUE,
699 &menuInfo);
700
701 RemoveMenu(getParent()->GetMenu(),0,MF_BYPOSITION);
702
703//TODO: See augmentframemenu
704#if 0
705 if ((menuInfo.fType & MFT_BITMAP) &&
706 (LOWORD(menuInfo.dwTypeData)!=0) &&
707 (LOWORD(menuInfo.dwTypeData)!=hBmpClose) )
708 {
709 DeleteObject((HBITMAP)LOWORD(menuInfo.dwTypeData));
710 }
711#endif
712
713 /* close */
714 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
715
716 /* restore */
717 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
718 /* minimize */
719 DeleteMenu(getParent()->GetMenu(),GetMenuItemCount(getParent()->GetMenu()) - 1,MF_BYPOSITION);
720
721 DrawMenuBar(getParent()->getWindowHandle());
722
723 return 1;
724}
725
726Win32BaseWindow** Win32MDIClientWindow::buildWindowArray(UINT bwaFlags,PUINT total)
727{
728 Win32BaseWindow **list = NULL,*win32wnd,**pos;
729 UINT skipHidden;
730 DWORD skipFlags;
731
732 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
733 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
734 if (bwaFlags & BWA_SKIPICONIC) skipFlags |= WS_MINIMIZE;
735
736 /* First count the windows */
737 *total = 0;
738 win32wnd = (Win32BaseWindow*)this->getFirstChild();
739 while (win32wnd)
740 {
741 if (!(win32wnd->getStyle() & skipFlags) && (!skipHidden || (win32wnd->getStyle() & WS_VISIBLE)))
742 (*total)++;
743 win32wnd = (Win32BaseWindow*)win32wnd->getNextChild();
744 }
745
746 if (*total)
747 {
748 /* Now build the list of all windows */
749 list = (Win32BaseWindow**)HeapAlloc(GetProcessHeap(),0,sizeof(Win32BaseWindow*)*(*total+1));
750 if (list)
751 {
752 for (win32wnd = (Win32BaseWindow*)this->getFirstChild(),pos = list;win32wnd;win32wnd = (Win32BaseWindow*)win32wnd->getNextChild())
753 {
754 if ((win32wnd->getStyle() & skipFlags));
755 else if(!skipHidden || win32wnd->getStyle() & WS_VISIBLE)
756 *pos++ = win32wnd;
757 }
758 *pos = NULL;
759 }
760 }
761
762 return list;
763}
764
765void Win32MDIClientWindow::releaseWindowArray(Win32BaseWindow **wndArray)
766{
767 HeapFree(GetProcessHeap(),0,wndArray);
768}
769
770/**********************************************************************
771 * MDI_CalcDefaultChildPos
772 *
773 * It seems that the default height is about 2/3 of the client rect
774 */
775void Win32MDIClientWindow::calcDefaultChildPos(WORD n,LPPOINT lpPos,INT delta)
776{
777 INT nstagger;
778 RECT rect;
779 INT spacing = GetSystemMetrics(SM_CYCAPTION) +
780 GetSystemMetrics(SM_CYFRAME) - 1;
781
782 getClientRect(&rect);
783 if( rect.bottom - rect.top - delta >= spacing )
784 rect.bottom -= delta;
785
786 nstagger = (rect.bottom - rect.top)/(3 * spacing);
787 lpPos[1].x = (rect.right - rect.left - nstagger * spacing);
788 lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing);
789 lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1));
790}
791
792/**********************************************************************
793 * MDICascade
794 */
795BOOL Win32MDIClientWindow::cascade(UINT fuCascade)
796{
797 Win32BaseWindow **list;
798 UINT total = 0;
799
800 if (getMaximizedChild())
801 SendInternalMessageA(WM_MDIRESTORE, (WPARAM)getMaximizedChild()->getWindowHandle(), 0);
802
803 if (nActiveChildren == 0) return 0;
804
805 list = buildWindowArray(BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC,&total);
806 if (list)
807 {
808 Win32BaseWindow** heapPtr = list;
809 if (total)
810 {
811 INT delta = 0,n = 0;
812 POINT pos[2];
813
814
815 if (total < nActiveChildren)
816 delta = GetSystemMetrics(SM_CYICONSPACING)+GetSystemMetrics(SM_CYICON);
817
818 // walk the list (backwards) and move windows
819 while (*list) list++;
820 while (list != heapPtr)
821 {
822 list--;
823
824 calcDefaultChildPos(n++,pos,delta);
825 ::SetWindowPos((*list)->getWindowHandle(),0,pos[0].x,pos[0].y,pos[1].x,pos[1].y,SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
826 }
827 }
828 releaseWindowArray(heapPtr);
829 }
830
831 if (total < nActiveChildren)
832 ArrangeIconicWindows(Win32Hwnd);
833
834 return TRUE;
835}
836
837/**********************************************************************
838 * MDITile
839 */
840BOOL Win32MDIClientWindow::tile(UINT fuTile)
841{
842 Win32BaseWindow** list;
843 UINT total = 0;
844
845 if (getMaximizedChild())
846 SendInternalMessageA(WM_MDIRESTORE, (WPARAM)getMaximizedChild()->getWindowHandle(), 0);
847
848 if (nActiveChildren == 0) return TRUE;
849
850 list = buildWindowArray(BWA_SKIPHIDDEN | BWA_SKIPOWNED | BWA_SKIPICONIC |
851 ((fuTile & MDITILE_SKIPDISABLED)? BWA_SKIPDISABLED : 0), &total );
852
853 if (list)
854 {
855 Win32BaseWindow** heapPtr = list;
856
857 if (total)
858 {
859 RECT rect;
860 int x, y, xsize, ysize;
861 int rows, columns, r, c, i;
862
863 GetClientRect(Win32Hwnd,&rect);
864 rows = (int) sqrt((double)total);
865 columns = total / rows;
866
867 if( fuTile & MDITILE_HORIZONTAL ) // version >= 3.1
868 {
869 i = rows;
870 rows = columns; // exchange r and c
871 columns = i;
872 }
873
874 if( total != nActiveChildren)
875 {
876 y = rect.bottom - 2 * GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
877 rect.bottom = ( y - GetSystemMetrics(SM_CYICON) < rect.top )? rect.bottom: y;
878 }
879
880 ysize = rect.bottom / rows;
881 xsize = rect.right / columns;
882
883 for (x = i = 0, c = 1; c <= columns && *list; c++)
884 {
885 if (c == columns)
886 {
887 rows = total - i;
888 ysize = rect.bottom / rows;
889 }
890
891 y = 0;
892 for (r = 1; r <= rows && *list; r++, i++)
893 {
894 ::SetWindowPos((*list)->getWindowHandle(), 0, x, y, xsize, ysize,
895 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
896 y += ysize;
897 list++;
898 }
899 x += xsize;
900 }
901 }
902 releaseWindowArray(heapPtr);
903 }
904
905 if( total < nActiveChildren ) ArrangeIconicWindows(Win32Hwnd);
906
907 return TRUE;
908}
909
910/* ----------------------- Frame window ---------------------------- */
911
912/**********************************************************************
913 * MDI_AugmentFrameMenu
914 */
915BOOL Win32MDIClientWindow::augmentFrameMenu(Win32MDIChildWindow *child)
916{
917 HMENU hSysPopup = 0,hFrameMenu = ::GetMenu(getParent()->getWindowHandle()),hSysMenu = ::GetSystemMenu(child->getWindowHandle(),FALSE);
918 HBITMAP hSysMenuBitmap = 0;
919
920 if (!hFrameMenu || !hSysMenu)
921 return 0;
922
923 // create a copy of sysmenu popup and insert it into frame menu bar
924
925 if (!(hSysPopup = LoadMenuA(GetModuleHandleA("USER32"), "SYSMENU")))
926 return 0;
927
928 //TRACE("\tgot popup %04x in sysmenu %04x\n",
929 // hSysPopup, child->hSysMenu);
930
931 AppendMenuA(hFrameMenu,MF_HELP | MF_BITMAP,
932 SC_MINIMIZE, (LPSTR)(DWORD)HBMMENU_MBAR_MINIMIZE ) ;
933 AppendMenuA(hFrameMenu,MF_HELP | MF_BITMAP,
934 SC_RESTORE, (LPSTR)(DWORD)HBMMENU_MBAR_RESTORE );
935
936 // In Win 95 look, the system menu is replaced by the child icon
937
938 /* Find icon */
939 HICON hIcon = child->IconForWindow(ICON_SMALL);
940
941 if (hIcon)
942 {
943 HDC hMemDC;
944 HBITMAP hBitmap, hOldBitmap;
945 HBRUSH hBrush;
946 HDC hdc = GetDC(child->getWindowHandle());
947
948 if (hdc)
949 {
950 int cx, cy;
951
952 cx = GetSystemMetrics(SM_CXSMICON);
953 cy = GetSystemMetrics(SM_CYSMICON);
954 hMemDC = CreateCompatibleDC(hdc);
955 hBitmap = CreateCompatibleBitmap(hdc, cx, cy);
956 hOldBitmap = SelectObject(hMemDC, hBitmap);
957 SetMapMode(hMemDC, MM_TEXT);
958 hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
959 DrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, hBrush, DI_NORMAL);
960 SelectObject (hMemDC, hOldBitmap);
961 DeleteObject(hBrush);
962 DeleteDC(hMemDC);
963 ReleaseDC(child->getWindowHandle(), hdc);
964 hSysMenuBitmap = hBitmap;
965 }
966 }
967
968 if( !InsertMenuA(hFrameMenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
969 hSysPopup, (LPSTR)(DWORD)hSysMenuBitmap))
970 {
971 //TRACE("not inserted\n");
972 DestroyMenu(hSysPopup);
973 return 0;
974 }
975
976 // The close button is only present in Win 95 look
977
978 AppendMenuA(hFrameMenu,MF_HELP | MF_BITMAP,
979 SC_CLOSE, (LPSTR)(DWORD)HBMMENU_MBAR_CLOSE );
980
981 EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
982 EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
983 EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
984 SetMenuDefaultItem(hSysPopup, SC_CLOSE, FALSE);
985
986 // redraw menu
987 DrawMenuBar(getParent()->getWindowHandle());
988
989 return 1;
990}
991
992/**********************************************************************
993 * MDI_RestoreFrameMenu
994 */
995BOOL Win32MDIClientWindow::restoreFrameMenu(Win32MDIChildWindow *child)
996{
997 MENUITEMINFOA menuInfo;
998 HMENU hFrameMenu = ::GetMenu(getParent()->getWindowHandle());
999 INT nItems = GetMenuItemCount(hFrameMenu) - 1;
1000 UINT iId = GetMenuItemID(hFrameMenu,nItems) ;
1001
1002 //TRACE("frameWnd %p,child %04x\n",frameWnd,hChild);
1003
1004 if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
1005 return 0;
1006
1007 /*
1008 * Remove the system menu, If that menu is the icon of the window
1009 * as it is in win95, we have to delete the bitmap.
1010 */
1011
1012 menuInfo.cbSize = sizeof(MENUITEMINFOA);
1013 menuInfo.fMask = MIIM_DATA | MIIM_TYPE;
1014
1015 GetMenuItemInfoA(hFrameMenu,
1016 0,
1017 TRUE,
1018 &menuInfo);
1019
1020 RemoveMenu(hFrameMenu,0,MF_BYPOSITION);
1021
1022#if 0 //CB: hBmpClose not (yet) defined
1023 if ( (menuInfo.fType & MFT_BITMAP) &&
1024 (LOWORD(menuInfo.dwTypeData)!=0) &&
1025 (LOWORD(menuInfo.dwTypeData)!=hBmpClose) )
1026 {
1027 DeleteObject((HBITMAP)LOWORD(menuInfo.dwTypeData));
1028 }
1029#endif
1030
1031 // close
1032 DeleteMenu(hFrameMenu,GetMenuItemCount(hFrameMenu) - 1,MF_BYPOSITION);
1033
1034 // restore
1035 DeleteMenu(hFrameMenu,GetMenuItemCount(hFrameMenu) - 1,MF_BYPOSITION);
1036 // minimize
1037 DeleteMenu(hFrameMenu,GetMenuItemCount(hFrameMenu) - 1,MF_BYPOSITION);
1038
1039 DrawMenuBar(getParent()->getWindowHandle());
1040
1041 return 1;
1042}
1043
1044/***********************************************************************
1045 * CalcChildScroll (USER.462)
1046 */
1047void WINAPI CalcChildScroll(HWND hwnd,WORD scroll)
1048{
1049 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
1050 SCROLLINFO info;
1051 RECT childRect, clientRect;
1052 INT vmin, vmax, hmin, hmax, vpos, hpos;
1053
1054 if (!win32wnd) return;
1055
1056 GetClientRect( hwnd, &clientRect );
1057 SetRectEmpty( &childRect );
1058
1059 //TODO: Check if this goes correctly
1060 for (win32wnd = (Win32BaseWindow*)win32wnd->getFirstChild();win32wnd;win32wnd = (Win32BaseWindow*)win32wnd->getNextChild())
1061 {
1062 if( win32wnd->getStyle() & WS_MAXIMIZE )
1063 {
1064 ShowScrollBar(hwnd, SB_BOTH, FALSE);
1065 return;
1066 }
1067 UnionRect(&childRect,win32wnd->getWindowRect(),&childRect);
1068 }
1069 UnionRect( &childRect, &clientRect, &childRect );
1070
1071 hmin = childRect.left; hmax = childRect.right - clientRect.right;
1072 hpos = clientRect.left - childRect.left;
1073 vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
1074 vpos = clientRect.top - childRect.top;
1075
1076 switch( scroll )
1077 {
1078 case SB_HORZ:
1079 vpos = hpos; vmin = hmin; vmax = hmax;
1080 case SB_VERT:
1081 info.cbSize = sizeof(info);
1082 info.nMax = vmax; info.nMin = vmin; info.nPos = vpos;
1083 info.fMask = SIF_POS | SIF_RANGE;
1084 SetScrollInfo(hwnd, scroll, &info, TRUE);
1085 break;
1086 case SB_BOTH:
1087 {
1088 SCROLLINFO vInfo, hInfo;
1089
1090 vInfo.cbSize = hInfo.cbSize = sizeof(SCROLLINFO);
1091 vInfo.nMin = vmin;
1092 hInfo.nMin = hmin;
1093 vInfo.nMax = vmax;
1094 hInfo.nMax = hmax;
1095 vInfo.nPos = vpos;
1096 hInfo.nPos = hpos;
1097 vInfo.fMask = hInfo.fMask = SIF_RANGE | SIF_POS;
1098
1099 SetScrollInfo(hwnd,SB_VERT,&vInfo,TRUE);
1100 SetScrollInfo(hwnd,SB_HORZ,&hInfo,TRUE);
1101 }
1102 }
1103}
1104
1105/***********************************************************************
1106 * ScrollChildren32 (USER32.448)
1107 */
1108void WINAPI ScrollChildren(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
1109{
1110 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hWnd);
1111 INT newPos = -1;
1112 INT curPos, length, minPos, maxPos, shift;
1113
1114 if (!win32wnd) return;
1115
1116 if (uMsg == WM_HSCROLL)
1117 {
1118 GetScrollRange(hWnd,SB_HORZ,&minPos,&maxPos);
1119 curPos = GetScrollPos(hWnd,SB_HORZ);
1120 length = win32wnd->getClientWidth()/2;
1121 shift = GetSystemMetrics(SM_CYHSCROLL);
1122 } else if (uMsg == WM_VSCROLL)
1123 {
1124 GetScrollRange(hWnd,SB_VERT,&minPos,&maxPos);
1125 curPos = GetScrollPos(hWnd,SB_VERT);
1126 length = win32wnd->getClientHeight()/2;
1127 shift = GetSystemMetrics(SM_CXVSCROLL);
1128 } else return;
1129
1130 switch( wParam )
1131 {
1132 case SB_LINEUP:
1133 newPos = curPos - shift;
1134 break;
1135
1136 case SB_LINEDOWN:
1137 newPos = curPos + shift;
1138 break;
1139
1140 case SB_PAGEUP:
1141 newPos = curPos - length;
1142 break;
1143
1144 case SB_PAGEDOWN:
1145 newPos = curPos + length;
1146 break;
1147
1148 case SB_THUMBPOSITION:
1149 newPos = LOWORD(lParam);
1150 break;
1151
1152 case SB_THUMBTRACK:
1153 return;
1154
1155 case SB_TOP:
1156 newPos = minPos;
1157 break;
1158
1159 case SB_BOTTOM:
1160 newPos = maxPos;
1161 break;
1162
1163 case SB_ENDSCROLL:
1164 CalcChildScroll(hWnd,(uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ);
1165 return;
1166 }
1167
1168 if( newPos > maxPos )
1169 newPos = maxPos;
1170 else
1171 if( newPos < minPos )
1172 newPos = minPos;
1173
1174 SetScrollPos(hWnd, (uMsg == WM_VSCROLL)?SB_VERT:SB_HORZ , newPos, TRUE);
1175
1176 if( uMsg == WM_VSCROLL )
1177 ScrollWindowEx(hWnd ,0 ,curPos - newPos, NULL, NULL, 0, NULL,
1178 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
1179 else
1180 ScrollWindowEx(hWnd ,curPos - newPos, 0, NULL, NULL, 0, NULL,
1181 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
1182}
1183
1184/*****************************************************************************
1185 * Name : WORD WIN32API CascadeWindows
1186 * Purpose : The CascadeWindows function cascades the specified windows or
1187 * the child windows of the specified parent window.
1188 * Parameters: HWND hwndParent handle of parent window
1189 * UINT wHow types of windows not to arrange
1190 * CONST RECT * lpRect rectangle to arrange windows in
1191 * UINT cKids number of windows to arrange
1192 * const HWND FAR * lpKids array of window handles
1193 * Variables :
1194 * Result : If the function succeeds, the return value is the number of windows arranged.
1195 * If the function fails, the return value is zero.
1196 * Remark :
1197 * Status : UNTESTED STUB
1198 *
1199 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
1200 *****************************************************************************/
1201WORD WIN32API CascadeWindows(HWND hwndParent,
1202 UINT wHow,
1203 CONST LPRECT lpRect,
1204 UINT cKids,
1205 const HWND *lpKids)
1206{
1207 dprintf(("USER32:CascadeWindows(%08xh,%u,%08xh,%u,%08x) not implemented.\n",
1208 hwndParent,
1209 wHow,
1210 lpRect,
1211 cKids,
1212 lpKids));
1213
1214 return (0);
1215}
1216
1217/*****************************************************************************
1218 * Name : BOOL WIN32API CascadeChildWindows
1219 * Purpose : Unknown
1220 * Parameters: Unknown
1221 * Variables :
1222 * Result :
1223 * Remark :
1224 * Status : UNTESTED UNKNOWN STUB
1225 *
1226 * Author : Patrick Haller [Wed, 1998/06/16 11:55]
1227 *****************************************************************************/
1228BOOL WIN32API CascadeChildWindows(DWORD x1,
1229 DWORD x2)
1230{
1231 dprintf(("USER32: CascadeChildWindows(%08xh,%08xh) not implemented.\n",
1232 x1,
1233 x2));
1234
1235 return (FALSE); /* default */
1236}
1237
1238/*****************************************************************************
1239 * Name : WORD WIN32API TileWindows
1240 * Purpose : The TileWindows function tiles the specified windows, or the child
1241 * windows of the specified parent window.
1242 * Parameters: HWND hwndParent handle of parent window
1243 * WORD wFlags types of windows not to arrange
1244 * LPCRECT lpRect rectangle to arrange windows in
1245 * WORD cChildrenb number of windows to arrange
1246 * const HWND *ahwndChildren array of window handles
1247 * Variables :
1248 * Result : If the function succeeds, the return value is the number of
1249 * windows arranged.
1250 * If the function fails, the return value is zero.
1251 * Remark :
1252 * Status : UNTESTED STUB
1253 *
1254 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
1255 *****************************************************************************/
1256WORD WIN32API TileWindows(HWND hwndParent,
1257 UINT wFlags,
1258 const LPRECT lpRect,
1259 UINT cChildrenb,
1260 const HWND *ahwndChildren)
1261{
1262 dprintf(("USER32:TileWindows (%08xh,%08xh,%08xh,%08xh,%08x) not implemented.\n",
1263 hwndParent,
1264 wFlags,
1265 lpRect,
1266 cChildrenb,
1267 ahwndChildren));
1268
1269 return (0);
1270}
1271
1272/*****************************************************************************
1273 * Name : BOOL WIN32API TileChildWindows
1274 * Purpose : Unknown
1275 * Parameters: Unknown
1276 * Variables :
1277 * Result :
1278 * Remark :
1279 * Status : UNTESTED UNKNOWN STUB
1280 *
1281 * Author : Patrick Haller [Wed, 1998/06/16 11:55]
1282 *****************************************************************************/
1283BOOL WIN32API TileChildWindows(DWORD x1,
1284 DWORD x2)
1285{
1286 dprintf(("USER32: TileChildWindows(%08xh,%08xh) not implemented.\n",
1287 x1,
1288 x2));
1289
1290 return (FALSE); /* default */
1291}
1292
1293/* -------- Miscellaneous service functions ----------
1294 *
1295 * MDI_GetChildByID
1296 */
1297Win32MDIChildWindow *Win32MDIClientWindow::getChildByID(INT id)
1298{
1299 Win32MDIChildWindow *child;
1300
1301 for (child = (Win32MDIChildWindow *)getFirstChild() ; child; child = (Win32MDIChildWindow *)child->getNextChild())
1302 if (child->getWindowId() == id) return child;
1303
1304 return 0;
1305}
1306
1307void Win32MDIClientWindow::postUpdate(WORD recalc)
1308{
1309 if( !(mdiFlags & MDIF_NEEDUPDATE) )
1310 {
1311 mdiFlags |= MDIF_NEEDUPDATE;
1312 PostMessageA(getWindowHandle(), WM_MDICALCCHILDSCROLL, 0, 0);
1313 }
1314 sbRecalc = recalc;
1315}
1316//******************************************************************************
1317//******************************************************************************
1318BOOL MDICLIENT_Register()
1319{
1320 WNDCLASSA wndClass;
1321
1322//SvL: Don't check this now
1323// if (GlobalFindAtomA(MDICLIENTCLASSNAMEA)) return FALSE;
1324
1325 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
1326 wndClass.style = CS_GLOBALCLASS;
1327 wndClass.lpfnWndProc = (WNDPROC)MDIClientWndProc;
1328 wndClass.cbClsExtra = 0;
1329 wndClass.cbWndExtra = 0;
1330 wndClass.hCursor = 0;
1331 wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
1332 wndClass.lpszClassName = MDICLIENTCLASSNAMEA;
1333
1334 return RegisterClassA(&wndClass);
1335}
1336//******************************************************************************
1337//******************************************************************************
1338BOOL MDICLIENT_Unregister()
1339{
1340 if (GlobalFindAtomA(MDICLIENTCLASSNAMEA))
1341 return UnregisterClassA(MDICLIENTCLASSNAMEA,(HINSTANCE)NULL);
1342 else return FALSE;
1343}
1344//******************************************************************************
1345//******************************************************************************
Note: See TracBrowser for help on using the repository browser.