|
|
1.1 root 1: /***************************************************************************\
2: * mdidoc.c - MDI application
3: *
4: * Created by Microsoft Corporation, 1989
5: \***************************************************************************/
6:
7: #define INCL_WINSYS
8: #define INCL_WINCOMMON
9: #define INCL_WINMESSAGEMGR
10: #define INCL_WINFRAMEMGR
11: #define INCL_WINPOINTERS
12: #define INCL_WINMENUS
13: #define INCL_WINWINDOWMGR
14: #define INCL_WINACCELERATORS
15: #define INCL_WININPUT
16: #define INCL_WINHEAP
17: #define INCL_WINSCROLLBARS
18: #define INCL_WINRECTANGLES
19: #define INCL_WINCOUNTRY
20: #define INCL_WINDIALOGS
21: #define INCL_GPIPRIMITIVES
22: #define INCL_GPILOGCOLORTABLE
23:
24: #include <os2.h>
25: #include <string.h>
26: #include <stdlib.h>
27: #include <stdio.h>
28: #include "app.h"
29: #include "appdata.h"
30: #include "mdi.h"
31: #include "mdidata.h"
32:
33: /* Function Prototypes */
34: VOID BuildWindowMenu(VOID);
35: VOID TrackSplitbars(HWND, USHORT, SHORT, SHORT);
36: MRESULT MDIFormatFrame(HWND hwnd, PSWP aswp, MPARAM mp2);
37: MRESULT MDIMinMaxFrame(HWND hwnd, MPARAM mp1, MPARAM mp2);
38:
39: #define WM_WINDOWPOSCHANGED 0x55
40:
41: VOID SetMainTitleText(HWND hwndDocFrame)
42: {
43: char szDocTitle[80], szMainTitle[80];
44:
45: /*
46: * Get the titlebar text for the specified document window.
47: */
48: WinQueryWindowText(hwndDocFrame, 80, (PSZ)szDocTitle);
49:
50: /*
51: * Build up the correct text for the main window.
52: */
53: strcpy(szMainTitle, " - ");
54: strcat(szMainTitle, szDocTitle);
55:
56: /*
57: * Set the main window's titlebar to the new text.
58: */
59: WinSetWindowText(hwndMDIFrame, szMainTitle);
60: }
61:
62:
63: VOID ClearMainTitleText(VOID)
64: {
65: WinSetWindowText(hwndMDIFrame, "");
66: }
67:
68:
69: VOID AddToWindowMenu(NPDOC npdocNew)
70: {
71: MENUITEM mi;
72: char szItemText[1];
73: char szTitleNew[128], szTitleCompare[128];
74: register NPDOC npdoc, npdocPrev;
75: USHORT usRes;
76:
77: cDocs++;
78:
79: /* build menuitem structure for this document */
80: mi.iPosition = MIT_END;
81: mi.afStyle = MIS_TEXT;
82: mi.afAttribute = 0;
83: mi.id = CMD_WINDOWITEMS + cDocs;
84: mi.hwndSubMenu = NULL;
85: mi.hItem = NULL;
86: szItemText[0] = '\0';
87:
88: /*
89: * Insert a blank item into the menu.
90: */
91: WinSendMsg(hwndWindowMenu, MM_INSERTITEM, MPFROMP(&mi),
92: MPFROMP(szItemText));
93:
94: /*
95: * Add the document to the DOCLIST.
96: */
97: if (npdocFirst == NULL) {
98: npdocFirst = npdocNew;
99:
100: /*
101: * Fill in the DOCLIST for this doc.
102: */
103: npdocNew->idMI = NULL;
104: npdocNew->npdocNext = NULL;
105:
106: } else {
107:
108: /*
109: * Add the item in the correct
110: * sorted location.
111: */
112: npdoc = npdocFirst;
113: npdocPrev = NULL;
114:
115: while (npdoc != NULL) {
116: WinQueryWindowText(npdoc->hwndFrame, 128, szTitleCompare);
117: WinQueryWindowText(npdocNew->hwndFrame, 128, szTitleNew);
118: WinUpper(NULL, NULL, NULL, szTitleCompare);
119: WinUpper(NULL, NULL, NULL, szTitleNew);
120:
121: usRes = WinCompareStrings(NULL, NULL, NULL, szTitleNew,
122: szTitleCompare, NULL);
123:
124: if (usRes == WCS_LT) {
125: if (npdocPrev == NULL) {
126: npdocFirst = npdocNew;
127: npdocFirst->npdocNext = npdoc;
128: } else {
129: npdocPrev->npdocNext = npdocNew;
130: npdocNew->npdocNext = npdoc;
131: }
132:
133: /*
134: * Fill in the DOC for this document.
135: */
136: npdocNew->idMI = NULL;
137: break;
138: } else if (npdoc->npdocNext == NULL) {
139: /*
140: * If we've made it to the end,
141: * just tack it on here.
142: */
143: npdoc->npdocNext = npdocNew;
144:
145: /*
146: * Fill in the DOC for this document.
147: */
148: npdocNew->idMI = NULL;
149: npdocNew->npdocNext = NULL;
150: }
151:
152: npdocPrev = npdoc;
153: npdoc = npdoc->npdocNext;
154: }
155: }
156:
157: BuildWindowMenu();
158: }
159:
160:
161: VOID RemoveFromWindowMenu(NPDOC npdocRemove)
162: {
163: register NPDOC npdoc, npdocPrev;
164:
165: VOID BuildWindowMenu(VOID);
166:
167: /*
168: * If the window menu is gone no need to
169: * do any of this stuff. This can happen
170: * when the MDI app is closing.
171: */
172: if (!WinIsWindow(hab, hwndWindowMenu))
173: return;
174:
175: /* Delete item from menu */
176: WinSendMsg(hwndWindowMenu, MM_DELETEITEM,
177: MPFROM2SHORT(npdocRemove->idMI, FALSE), NULL);
178:
179: /*
180: * Remove the DOC from the linked-list.
181: */
182: if (npdocFirst != NULL) {
183:
184: /*
185: * Initialize these for our while loop.
186: */
187: npdoc = npdocFirst;
188: npdocPrev = NULL;
189:
190: while (npdoc != NULL) {
191:
192: /*
193: * If we've found the element unlink
194: * it from the list.
195: */
196: if (npdoc == npdocRemove) {
197:
198: /*
199: * Unlink this document.
200: */
201: if (npdocPrev != NULL)
202: npdocPrev->npdocNext = npdoc->npdocNext;
203: else
204: npdocFirst = npdoc->npdocNext;
205:
206: /*
207: * Break out of the while loop,
208: * we're done here.
209: */
210: break;
211: }
212: npdocPrev = npdoc;
213: npdoc = npdoc->npdocNext;
214: }
215: }
216:
217: BuildWindowMenu();
218: }
219:
220:
221: VOID BuildWindowMenu(VOID)
222: {
223: register NPDOC npdoc;
224: char szDocTitle[80];
225: char szItemText[80];
226: USHORT idMI, posMI, cWindows;
227:
228: /*
229: * Get the position of the first
230: * window in the Window menu.
231: */
232: posMI = (USHORT)WinSendMsg(hwndWindowMenu, MM_ITEMPOSITIONFROMID,
233: MPFROM2SHORT(CMD_WINDOWITEMS, TRUE), NULL);
234: posMI++;
235:
236: npdoc = npdocFirst;
237: cWindows = 1;
238: while (npdoc != NULL) {
239:
240: /*
241: * Fill in the menuitem ID.
242: */
243: idMI = (USHORT)WinSendMsg(hwndWindowMenu, MM_ITEMIDFROMPOSITION,
244: MPFROMSHORT(posMI), NULL);
245: npdoc->idMI = idMI;
246:
247: /*
248: * Build the item string.
249: */
250: szItemText[0] = '~';
251: itoa(cWindows, szItemText + 1, 10);
252: strcat(szItemText, " ");
253: WinQueryWindowText(npdoc->hwndFrame, 80, (PSZ)szDocTitle);
254: strcat(szItemText, szDocTitle);
255:
256: /*
257: * Set the item text for the menuitem.
258: */
259: WinSendMsg(hwndWindowMenu, MM_SETITEMTEXT, MPFROMSHORT(idMI),
260: MPFROMP(szItemText));
261:
262: /*
263: * Clear out the previous attributes.
264: */
265: WinSendMsg(hwndWindowMenu, MM_SETITEMATTR, MPFROM2SHORT(idMI, FALSE),
266: MPFROM2SHORT(MIA_CHECKED, 0));
267:
268: posMI++;
269: cWindows++;
270: npdoc = npdoc->npdocNext;
271: }
272: }
273:
274:
275: NPDOC MdiNewDocument(USHORT fsStyle, PSZ pszClassName)
276: {
277: ULONG ctlData, flStyle;
278: HWND hwndNewFrame, hwndNewClient, hwndSysMenu;
279: register NPDOC npdocNew;
280: register NPVIEW npview;
281: char szDocTitle[80], szDocNumber[4];
282:
283: usDocNumber++;
284:
285: /*
286: * Setup the window's titlebar text.
287: */
288: itoa(usDocNumber, szDocNumber, 10);
289: strcpy(szDocTitle, "Untitled");
290: strcat(szDocTitle, szDocNumber);
291:
292: ctlData = FCF_TITLEBAR | FCF_MINMAX | FCF_SIZEBORDER |
293: FCF_VERTSCROLL | FCF_HORZSCROLL;
294:
295: hwndNewFrame = WinCreateStdWindow(hwndMDI,
296: FS_ICON | FS_ACCELTABLE,
297: (VOID FAR *)&ctlData,
298: pszClassName, szDocTitle,
299: WS_VISIBLE,
300: (HMODULE)NULL, IDR_MDIDOC,
301: (HWND FAR *)&hwndNewClient);
302:
303: npdocNew = (NPDOC)WinAllocMem(hHeap, sizeof(DOC));
304: if (npdocNew == NULL)
305: return (FALSE);
306:
307: npdocNew->hwndFrame = hwndNewFrame;
308: npdocNew->cxVertSplitPos = 0;
309: npdocNew->cyHorzSplitPos = 0;
310: npdocNew->fs = 0;
311: npdocNew->fsStyle = fsStyle;
312:
313: npview = NPVIEWFROMCLIENT(hwndNewClient);
314: npview->npdoc = npdocNew;
315:
316: /*
317: * Link in the VIEW for FID_CLIENT since we
318: * know it exists.
319: */
320: npdocNew->npviewFirst = npview;
321:
322: /*
323: * Create the 'splitbar' controls for the frame.
324: * This includes the splitbar and the extra client
325: * and scrollbar windows. This routine will also
326: * link the appropriate VIEWs into the DOC structure.
327: */
328: if (fsStyle & (DS_HORZSPLITBAR | DS_VERTSPLITBAR)) {
329: if (CreateSplitbarWindows(hwndNewFrame, npdocNew) == FALSE) {
330: WinDestroyWindow(hwndNewFrame);
331: return (FALSE);
332: }
333: }
334:
335: /*
336: * Load in the document window's system menu.
337: */
338: hwndSysMenu = WinLoadMenu(hwndNewFrame, (HMODULE)NULL, IDM_DOCSYSMENU);
339:
340: /*
341: * Make it look like a normal system menu to the frame manager so
342: * gets formatted correctly etc.
343: */
344: flStyle = WinQueryWindowULong(hwndSysMenu, QWL_STYLE);
345: WinSetWindowULong(hwndSysMenu, QWL_STYLE, flStyle | MS_TITLEBUTTON);
346: WinSetWindowUShort(hwndSysMenu, QWS_ID, FID_SYSMENU);
347:
348: /*
349: * Set the bitmap to the SBMP_CHILDSYSMENU bitmap.
350: */
351: WinSendMsg(hwndSysMenu, MM_SETITEMHANDLE, (MPARAM)SC_DOCSYSMENU,
352: (MPARAM)hbmChildSysMenu);
353:
354: /*
355: * Set the menu window handles in the DOC structure so these
356: * controls can be hidden/shown at the correct time.
357: */
358: npdocNew->hwndSysMenu = hwndSysMenu;
359: npdocNew->hwndMinmax = WinWindowFromID(hwndNewFrame, FID_MINMAX);
360:
361: /*
362: * Subclass the frame so we can handle the accelerators
363: * and other MDI stuff.
364: */
365: pfnFrameWndProc = WinSubclassWindow(hwndNewFrame,
366: (PFNWP)DocFrameWndProc);
367:
368: /*
369: * Add the window to the Window menu.
370: */
371: AddToWindowMenu(npdocNew);
372:
373: return (npdocNew);
374: }
375:
376:
377: VOID MDISetInitialDocPos(HWND hwndNewFrame)
378: {
379: WinSetWindowPos(hwndNewFrame, NULL, xNextNewDoc, yNextNewDoc,
380: cxNewDoc, cyNewDoc, SWP_MOVE | SWP_SIZE | SWP_SHOW);
381:
382: /*
383: * Insert logic to change xNextNewDoc/yNextNewDoc and cxNewDoc/cyNewDoc.
384: */
385: }
386:
387:
388: VOID AddAabSysMenu(VOID)
389: {
390: if (fAabSysMenu == FALSE) {
391: WinSendMsg(hwndMainMenu, MM_INSERTITEM, MPFROMP(&miAabSysMenu),
392: (MPARAM)NULL);
393: fAabSysMenu = TRUE;
394: }
395: }
396:
397:
398: VOID RemoveAabSysMenu(VOID)
399: {
400: if (fAabSysMenu == TRUE) {
401: WinSendMsg(hwndMainMenu, MM_REMOVEITEM,
402: MPFROMSHORT(IDM_AABDOCSYSMENU), (MPARAM)FALSE);
403: fAabSysMenu = FALSE;
404: }
405: }
406:
407:
408: BOOL MDICreate(HWND hwndClient)
409: {
410: register NPVIEW npview;
411:
412: /*
413: * Allocate the DOC structure for this window and stick it in
414: * the window structure of the client.
415: */
416: npview = (NPVIEW)WinAllocMem(hHeap, sizeof(VIEW));
417: if (npview == NULL)
418: return (FALSE);
419:
420: npview->xOrigin = 0;
421: npview->yOrigin = 0;
422: npview->fs = 0;
423: npview->npviewNext = NULL;
424: npview->hwndClient = hwndClient;
425:
426: WinSetWindowUShort(hwndClient, QWS_USER, (USHORT)npview);
427:
428: return (TRUE);
429: }
430:
431:
432: VOID MDIActivate(HWND hwndClient, BOOL fActivate)
433: {
434: HWND hwndFrame;
435: register NPDOC npdoc;
436:
437: hwndFrame = WinQueryWindow(hwndClient, QW_PARENT, FALSE);
438:
439: /*
440: * If our active status is changing, show/hide the AAB Sysmenu, check
441: * the correct item on the Window menu, and show/hide the titlebar
442: * frame controls.
443: */
444: npdoc = NPDOCFROMCLIENT(hwndClient);
445: if (fActivate != FALSE) {
446:
447: hwndActiveDoc = hwndFrame;
448: if (WinQueryWindowULong(hwndFrame, QWL_STYLE) & WS_MAXIMIZED)
449: AddAabSysMenu();
450: else
451: RemoveAabSysMenu();
452:
453: /*
454: * Check the appropriate item on the Window menu.
455: */
456: WinSendMsg(hwndWindowMenu, MM_SETITEMATTR,
457: MPFROM2SHORT(npdoc->idMI, FALSE),
458: MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED));
459:
460: /*
461: * Show the titlebar frame controls.
462: */
463: WinSetParent(npdoc->hwndSysMenu, hwndFrame, FALSE);
464: WinSetParent(npdoc->hwndMinmax, hwndFrame, FALSE);
465: WinSendMsg(hwndFrame, WM_UPDATEFRAME, 0L, 0L);
466:
467: } else {
468: /*
469: * Uncheck the appropriate item on the Window menu.
470: */
471: WinSendMsg(hwndWindowMenu, MM_SETITEMATTR,
472: MPFROM2SHORT(npdoc->idMI, FALSE),
473: MPFROM2SHORT(MIA_CHECKED, 0));
474: hwndActiveDoc = NULL;
475:
476: /*
477: * Hide the titlebar frame controls.
478: */
479: WinSetParent(npdoc->hwndSysMenu, HWND_OBJECT, FALSE);
480: WinSetParent(npdoc->hwndMinmax, HWND_OBJECT, FALSE);
481: WinSendMsg(hwndFrame, WM_UPDATEFRAME, 0L, 0L);
482: }
483: }
484:
485:
486: VOID MDIDestroy(HWND hwndClient)
487: {
488: WinFreeMem(hHeap, (NPBYTE)WinQueryWindowUShort(hwndClient, QWS_USER),
489: sizeof(VIEW));
490: }
491:
492:
493: VOID MDIClose(HWND hwndClient)
494: {
495: WinDestroyWindow(WinQueryWindow(hwndClient, QW_PARENT, FALSE));
496: }
497:
498:
499: MRESULT CALLBACK DocFrameWndProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
500: {
501: MRESULT mres;
502: USHORT cFrameCtls;
503: HWND hwndParent, hwndClient;
504: register NPDOC npdoc;
505: RECTL rclClient;
506:
507: switch (msg) {
508:
509: case WM_SYSCOMMAND:
510: if (SHORT1FROMMP(mp1) == SC_SPLIT) {
511: WinSetPointer(HWND_DESKTOP, hptrHVSplit);
512: TrackSplitbars(WinWindowFromID(hwnd, FID_CLIENT),
513: SPS_HORZ | SPS_VERT, -1, -1);
514: WinSetPointer(HWND_DESKTOP, hptrArrow);
515: } else if (SHORT1FROMMP(mp2) == CMDSRC_ACCELERATOR) {
516:
517: /*
518: * If the command was sent because of an accelerator
519: * we need to see if it goes to the document or the main
520: * frame window.
521: */
522: if ((WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000)) {
523:
524: /*
525: * If the control key is down we'll send it
526: * to the document's frame since that means
527: * it's either ctl-esc or one of the document
528: * window's accelerators.
529: */
530: return (*pfnFrameWndProc)(hwnd, msg, mp1, mp2);
531: } else if (SHORT1FROMMP(mp1) == SC_DOCSYSMENU) {
532:
533: /*
534: * If the window is maximized then we want
535: * to pull down the system menu on the main
536: * menu bar.
537: */
538: if ((WinQueryWindowULong(hwnd, QWL_STYLE) & WS_MAXIMIZED) &&
539: (SHORT1FROMMP(mp1) == SC_DOCSYSMENU)) {
540: WinPostMsg(miAabSysMenu.hwndSubMenu, MM_STARTMENUMODE,
541: MPFROM2SHORT(TRUE, FALSE), 0L);
542: return (0L);
543: } else {
544: WinPostMsg(WinWindowFromID(hwnd, FID_SYSMENU),
545: MM_STARTMENUMODE, MPFROM2SHORT(TRUE, FALSE), 0L);
546: }
547: } else {
548: /*
549: * Control isn't down so send it the main
550: * frame window.
551: */
552: return WinSendMsg(hwndMDIFrame, msg, mp1, mp2);
553: }
554: } else {
555: /*
556: * WM_SYSCOMMAND not caused by an accelerator
557: * so hwnd is the window we want to send the
558: * message to.
559: */
560: return (*pfnFrameWndProc)(hwnd, msg, mp1, mp2);
561: }
562: break;
563:
564: case WM_NEXTMENU:
565: /*
566: * Connect child sysmenu with application menus for cursor motion.
567: * Only return a value if we're the System Menu. We don't want the
568: * MinMax menu or any others that might be there to freak out.
569: */
570: if (WinQueryWindowUShort(HWNDFROMMP(mp1), QWS_ID) == FID_SYSMENU) {
571: if (SHORT1FROMMP(mp2)) {
572: return (MRESULT)hwndSysMenu;
573: } else {
574: return (MRESULT)hwndAppMenu;
575: }
576: } else {
577: return (0L);
578: }
579: break;
580:
581: case WM_MINMAXFRAME:
582: return (MDIMinMaxFrame(hwnd, mp1, mp2));
583: break;
584:
585: case WM_WINDOWPOSCHANGED:
586:
587: #define aswp ((PSWP)mp1)
588:
589: npdoc = NPDOCFROMCLIENT(WinWindowFromID(hwnd, FID_CLIENT));
590: if (((PSWP)mp1)->fs & SWP_SIZE) {
591:
592: if (npdoc->fs & (DF_SPLITHORZ | DF_HSPLITOVERFLOW)) {
593: /*
594: * If we were sized then adjust the horizontal splitbar
595: * to be top-aligned.
596: */
597: npdoc->cyHorzSplitPos += (aswp[0].cy - aswp[1].cy);
598:
599: /*
600: * Set or clear the DF_HSPLITOVERFLOW and DF_SPLITHORZ flags.
601: */
602: if (npdoc->cyHorzSplitPos < 0) {
603: npdoc->fs |= DF_HSPLITOVERFLOW;
604: npdoc->fs &= ~DF_SPLITHORZ;
605: } else {
606: npdoc->fs &= ~DF_HSPLITOVERFLOW;
607: npdoc->fs |= DF_SPLITHORZ;
608: }
609: }
610:
611: if (npdoc->fs & (DF_SPLITVERT | DF_VSPLITOVERFLOW)) {
612:
613: WinQueryWindowRect(hwnd, &rclClient);
614: WinCalcFrameRect(hwnd, &rclClient, TRUE);
615:
616: /*
617: * Set or clear the DF_VSPLITOVERFLOW and DF_SPLITVERT flags.
618: */
619: if (npdoc->cxVertSplitPos >
620: (((SHORT)rclClient.xRight - (SHORT)rclClient.xLeft) -
621: cxVertSplitbar)) {
622: npdoc->fs |= DF_VSPLITOVERFLOW;
623: npdoc->fs &= ~DF_SPLITVERT;
624: } else {
625: npdoc->fs &= ~DF_VSPLITOVERFLOW;
626: npdoc->fs |= DF_SPLITVERT;
627: }
628: }
629: }
630:
631: #undef aswp
632:
633: return (*pfnFrameWndProc)(hwnd, msg, mp1, mp2);
634: break;
635:
636: case WM_CALCVALIDRECTS:
637:
638: /*
639: * We do our own WM_CALCVALIDRECTS processing
640: * because the frame manager uses the window
641: * rectangle of FID_CLIENT, which in our case
642: * might be smaller than the 'client area' due
643: * to window splitting.
644: */
645:
646: #define prclOld ((PRECTL)&(((PRECTL)mp1)[0]))
647: #define prclNew ((PRECTL)&(((PRECTL)mp1)[1]))
648:
649: /*
650: * Calculate the client rectangle of hwnd in its
651: * parent's coordinates.
652: */
653: WinQueryWindowRect(hwnd, (PRECTL)prclOld);
654: hwndParent = WinQueryWindow(hwnd, QW_PARENT, FALSE);
655: WinMapWindowPoints(hwnd, hwndParent, (PPOINTL)prclOld, 2);
656: WinCalcFrameRect(hwnd, (PRECTL)prclOld, TRUE);
657:
658: /*
659: * Calculate the client rect for the
660: * destination of the frame window.
661: */
662: WinCalcFrameRect(hwnd, (PRECTL)prclNew, TRUE);
663:
664: /*
665: * Top align destination bits.
666: */
667: prclNew->yBottom += (prclNew->yTop - prclNew->yBottom) -
668: (prclOld->yTop - prclOld->yBottom);
669:
670: #undef prclOld
671: #undef prclNew
672:
673: /*
674: * Return 0 since we've already aligned the bits.
675: */
676: return(0);
677: break;
678:
679: case WM_QUERYFRAMECTLCOUNT:
680: cFrameCtls = (int)(*pfnFrameWndProc)(hwnd, WM_QUERYFRAMECTLCOUNT, mp1, mp2);
681:
682: /*
683: * Max number of additional frame controls is seven
684: * Two splitbars, two additional scrollbars, and three
685: * additional client windows. Throw in 3 more just to
686: * be sure we don't trash memory
687: */
688: return (MRFROMSHORT(cFrameCtls + 7 + 3));
689:
690: case WM_FORMATFRAME:
691: return (MDIFormatFrame(hwnd, ((PSWP)PVOIDFROMMP(mp1)), mp2));
692: break;
693:
694: case WM_BUTTON1UP:
695: mres = (*pfnFrameWndProc)(hwnd, msg, mp1, mp2);
696:
697: /*
698: * If we're minimized we need to do activation ourself
699: * and bring up the system menu.
700: */
701: if (!(WinQueryWindowUShort(hwnd, QWS_FLAGS) & FF_ACTIVE)) {
702:
703: /*
704: * Only do this if we're minimized.
705: */
706: if (WinQueryWindowULong(hwnd, QWL_STYLE) & WS_MINIMIZED) {
707:
708: WinSetActiveWindow(HWND_DESKTOP, hwnd);
709:
710: /*
711: * Bring up the system menu if there is one.
712: */
713: WinSendDlgItemMsg(hwnd, FID_SYSMENU, MM_STARTMENUMODE,
714: MPFROMSHORT(TRUE), 0L);
715: }
716: }
717: break;
718:
719: case WM_DESTROY:
720: /*
721: * If this document is maximized, remove the AabSysMenu.
722: */
723: if (WinQueryWindowULong(hwnd, QWL_STYLE) & WS_MAXIMIZED)
724: RemoveAabSysMenu();
725:
726: hwndClient = WinWindowFromID(hwnd, FID_CLIENT);
727: npdoc = NPDOCFROMCLIENT(hwndClient);
728:
729: /*
730: * Make sure these windows are on the frame so they
731: * get destroyed.
732: */
733: WinSetParent(npdoc->hwndSysMenu, hwnd, FALSE);
734: WinSetParent(npdoc->hwndMinmax, hwnd, FALSE);
735:
736: RemoveFromWindowMenu(npdoc);
737:
738: WinFreeMem(hHeap, (NPBYTE)npdoc, sizeof(DOC));
739:
740: return (*pfnFrameWndProc)(hwnd, msg, mp1, mp2);
741:
742: default:
743: return (*pfnFrameWndProc)(hwnd, msg, mp1, mp2);
744: }
745: }
746:
747: MRESULT MDIMinMaxFrame(HWND hwnd, MPARAM mp1, MPARAM mp2)
748: {
749: PSWP pswp;
750:
751: pswp = (PSWP)PVOIDFROMMP(mp1);
752: if ((pswp->fs & SWP_MAXIMIZE) &&
753: ((WinQueryWindowULong(hwnd, QWL_STYLE) & WS_MAXIMIZED) == 0L)) {
754: pswp->cy += cyTitlebar;
755: AddAabSysMenu();
756: SetMainTitleText(hwnd);
757: } else if (((pswp->fs & SWP_RESTORE) || (pswp->fs & SWP_MINIMIZE)) &&
758: (WinQueryWindowULong(hwnd, QWL_STYLE) & WS_MAXIMIZED)) {
759: RemoveAabSysMenu();
760: ClearMainTitleText();
761: }
762: return (*pfnFrameWndProc)(hwnd, WM_MINMAXFRAME, mp1, mp2);
763: }
764:
765: MRESULT MDIFormatFrame(HWND hwnd, PSWP aswp, MPARAM mp2)
766: {
767: SWP swpClient;
768: PSWP pswpHScroll, pswpVScroll;
769: USHORT chwnd, iswpNext;
770: register NPDOC npdoc;
771: SHORT cyHorzSplitPos, cxVertSplitPos;
772:
773: iswpNext = chwnd = (USHORT)(*pfnFrameWndProc)(hwnd, WM_FORMATFRAME,
774: aswp, mp2);
775:
776: FindSwp(aswp, chwnd, FID_HORZSCROLL, (PSWP FAR *)&pswpHScroll);
777: FindSwp(aswp, chwnd, FID_VERTSCROLL, (PSWP FAR *)&pswpVScroll);
778:
779: npdoc = NPDOCFROMCLIENT(aswp[chwnd - 1].hwnd);
780:
781: cyHorzSplitPos = npdoc->cyHorzSplitPos;
782: cxVertSplitPos = npdoc->cxVertSplitPos;
783:
784: /*
785: * Save the client rectangle away because we
786: * want to do thing based on the original
787: * client rectangle as well as move the
788: * client's ordering in the SWP list behind
789: * the other client windows.
790: */
791: swpClient = aswp[chwnd - 1];
792:
793: /*
794: * Start from the client window's SWP
795: * since we're going to move it to
796: * the end.
797: */
798: iswpNext = (chwnd - 1);
799:
800: if (npdoc->fsStyle & DS_VERTSPLITBAR) {
801:
802: /*
803: * If the horizontal scrollbar is being hidden
804: * then we certainly don't need to be around...
805: */
806: if (pswpHScroll->fs & SWP_HIDE) {
807:
808: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT2),
809: &iswpNext);
810: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_HORZSCROLL2),
811: &iswpNext);
812: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_VERTSPLITBAR),
813: &iswpNext);
814:
815: } else if (npdoc->fs & DF_VSPLITOVERFLOW) {
816:
817: /*
818: * First hide CLIENT3 and VERTSCROLL2
819: * since we know they're going away.
820: */
821: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT2),
822: &iswpNext);
823: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_HORZSCROLL2),
824: &iswpNext);
825:
826: /*
827: * Hide CLIENT4 since it won't be needed for now.
828: */
829: if (npdoc->fsStyle & DS_HORZSPLITBAR) {
830: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT4),
831: &iswpNext);
832: }
833:
834: /*
835: * If there isn't any room for even the hidden
836: * representation then get rid of it...
837: */
838: if (pswpHScroll->cx < (cxVertSplitbar * 3)) {
839: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_VERTSPLITBAR),
840: &iswpNext);
841: } else {
842: SetSwpPos(&aswp[iswpNext++],
843: WinWindowFromID(hwnd, ID_VERTSPLITBAR), NULL,
844: pswpHScroll->x + pswpHScroll->cx - cxVertSplitbar,
845: pswpHScroll->y + cyBorder, cxVertSplitbar,
846: pswpHScroll->cy - cyBorder, pswpHScroll->fs);
847:
848: pswpHScroll->cx -= cxVertSplitbar;
849: }
850:
851: } else if (npdoc->fs & DF_SPLITVERT) {
852:
853: /*
854: * Format the client windows.
855: *
856: * If we're split horzintally as well then we
857: * need to show the fourth client.
858: */
859:
860: /*
861: * If we're split horizontally and there was
862: * enough room to be split then format
863: * the 'fourth' client window.
864: */
865: if ((npdoc->fs & DF_SPLITHORZ) &&
866: (pswpVScroll->cy > (cyHorzSplitbar * 3))) {
867: aswp[iswpNext].hwnd = WinWindowFromID(hwnd, ID_CLIENT4);
868: aswp[iswpNext].hwndInsertBehind = NULL;
869: aswp[iswpNext].x = swpClient.x +
870: (cxVertSplitPos + cxVertSplitbar);
871: aswp[iswpNext].cx = swpClient.cx -
872: (cxVertSplitPos + cxVertSplitbar);
873: aswp[iswpNext].y = swpClient.y;
874: aswp[iswpNext].cy = cyHorzSplitPos;
875: aswp[iswpNext].fs = swpClient.fs | SWP_SHOW;
876:
877: iswpNext++;
878: }
879:
880: aswp[iswpNext].hwnd = WinWindowFromID(hwnd, ID_CLIENT2);
881: aswp[iswpNext].hwndInsertBehind = NULL;
882: aswp[iswpNext].x = swpClient.x +
883: (cxVertSplitPos + cxVertSplitbar);
884: aswp[iswpNext].cx = swpClient.cx -
885: (cxVertSplitPos + cxVertSplitbar);
886: /*
887: * If we're split horizontally and there was
888: * enough room to be split then format
889: * the 'second' client window against the
890: * 'fourth' client window.
891: */
892: if ((npdoc->fs & DF_SPLITHORZ) &&
893: (pswpVScroll->cy > (cyHorzSplitbar * 3))) {
894: aswp[iswpNext].y = swpClient.y +
895: (cyHorzSplitPos + cyHorzSplitbar);
896: aswp[iswpNext].cy = swpClient.cy -
897: (cyHorzSplitPos + cyHorzSplitbar);
898: } else {
899: aswp[iswpNext].y = swpClient.y;
900: aswp[iswpNext].cy = swpClient.cy;
901: }
902: aswp[iswpNext].fs = swpClient.fs | SWP_SHOW;
903:
904: iswpNext++;
905:
906: } else {
907: /*
908: * If we're not split then format the window with the
909: * splitbar to the left of the horizontal scrollbar.
910: */
911: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_HORZSCROLL2),
912: &iswpNext);
913: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT2),
914: &iswpNext);
915:
916: /*
917: * Hide ID_CLIENT4 since it won't be needed for now.
918: */
919: if (npdoc->fsStyle & DS_HORZSPLITBAR) {
920: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT4),
921: &iswpNext);
922: }
923:
924: aswp[iswpNext].hwnd = WinWindowFromID(hwnd, ID_VERTSPLITBAR);
925: aswp[iswpNext].hwndInsertBehind = NULL;
926: aswp[iswpNext].x = pswpHScroll->x;
927: aswp[iswpNext].y = pswpHScroll->y + cyBorder;
928: aswp[iswpNext].cx = cxVertSplitbar;
929: aswp[iswpNext].cy = pswpHScroll->cy - cyBorder;
930: aswp[iswpNext].fs = pswpHScroll->fs;
931: pswpHScroll->x += cxVertSplitbar;
932: pswpHScroll->cx -= cxVertSplitbar;
933:
934: iswpNext++;
935: }
936: }
937:
938: if (npdoc->fsStyle & DS_HORZSPLITBAR) {
939: /*
940: * If the horizontal scrollbar is being hidden
941: * then we certainly don't need to be around...
942: */
943: if (pswpVScroll->fs & SWP_HIDE) {
944:
945: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT3),
946: &iswpNext);
947: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_VERTSCROLL2),
948: &iswpNext);
949: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_HORZSPLITBAR),
950: &iswpNext);
951:
952: } else if (npdoc->fs & DF_HSPLITOVERFLOW) {
953:
954: /*
955: * First hide CLIENT3 and VERTSCROLL2
956: * since we know they're going away.
957: */
958: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT3),
959: &iswpNext);
960: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_VERTSCROLL2),
961: &iswpNext);
962:
963: /*
964: * Hide CLIENT4 since it won't be needed for now.
965: */
966: if (npdoc->fsStyle & DS_VERTSPLITBAR) {
967: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT4),
968: &iswpNext);
969: }
970:
971: /*
972: * If there isn't any room for even the hidden
973: * representation then get rid of it
974: */
975: if (pswpVScroll->cy < (cyHorzSplitbar * 3)) {
976: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_HORZSPLITBAR),
977: &iswpNext);
978: } else {
979: SetSwpPos(&aswp[iswpNext++],
980: WinWindowFromID(hwnd, ID_HORZSPLITBAR), NULL,
981: pswpVScroll->x, pswpVScroll->y, pswpVScroll->cx - cxBorder,
982: cyHorzSplitbar, pswpVScroll->fs);
983:
984: pswpVScroll->y += cyHorzSplitbar;
985: pswpVScroll->cy -= cyHorzSplitbar;
986: }
987:
988: } else if (npdoc->fs & DF_SPLITHORZ) {
989:
990: if (pswpVScroll->cy > (cyHorzSplitbar * 3)) {
991: /*
992: * Format the client windows.
993: */
994: SetSwpPos(&aswp[iswpNext++],
995: WinWindowFromID(hwnd, ID_CLIENT3), NULL,
996: swpClient.x, swpClient.y,
997: /*
998: * If we're split vertically then format
999: * the client against the vertical splitbar
1000: * as well as the horzontal splitbar.
1001: */
1002: (npdoc->fs & DF_SPLITVERT) ? cxVertSplitPos : swpClient.cx,
1003: cyHorzSplitPos, swpClient.fs | SWP_SHOW);
1004:
1005: } else {
1006: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT3),
1007: &iswpNext);
1008:
1009: /*
1010: * Hide CLIENT4 since it won't be needed for now.
1011: */
1012: if (npdoc->fsStyle & DS_VERTSPLITBAR) {
1013: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT4),
1014: &iswpNext);
1015: }
1016: }
1017:
1018: } else {
1019: /*
1020: * If we're not split then format the window with the
1021: * splitbar at the top of the vertical scrollbar.
1022: */
1023: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_VERTSCROLL2),
1024: &iswpNext);
1025:
1026: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT3),
1027: &iswpNext);
1028:
1029: if (npdoc->fsStyle & DS_VERTSPLITBAR) {
1030: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT4),
1031: &iswpNext);
1032: }
1033:
1034: if (pswpVScroll->cy > (cyHorzSplitbar * 3)) {
1035: SetSwpPos(&aswp[iswpNext++],
1036: WinWindowFromID(hwnd, ID_HORZSPLITBAR), NULL,
1037: pswpVScroll->x, pswpVScroll->y + pswpVScroll->cy -
1038: cyHorzSplitbar,
1039: pswpVScroll->cx - cxBorder, cyHorzSplitbar, pswpVScroll->fs);
1040:
1041: pswpVScroll->cy -= cyHorzSplitbar;
1042: } else {
1043: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_HORZSPLITBAR),
1044: &iswpNext);
1045: }
1046: }
1047: }
1048:
1049: /*
1050: * Now format the original client window.
1051: */
1052: aswp[iswpNext] = swpClient;
1053:
1054: if (npdoc->fs & (DF_SPLITHORZ | DF_SPLITVERT)) {
1055:
1056: /*
1057: * Adjust the main client window for the splitbars.
1058: */
1059: if (npdoc->fs & DF_SPLITVERT) {
1060: aswp[iswpNext].cx = cxVertSplitPos;
1061: }
1062:
1063: if ((npdoc->fs & DF_SPLITHORZ) &&
1064: (pswpVScroll->cy > (cyHorzSplitbar * 3))) {
1065: aswp[iswpNext].y += (cyHorzSplitPos + cyHorzSplitbar);
1066: aswp[iswpNext].cy -= (cyHorzSplitPos + cyHorzSplitbar);
1067: }
1068: }
1069:
1070: iswpNext++;
1071:
1072: if (npdoc->fs & DF_SPLITHORZ) {
1073: /*
1074: * Format the scrollbars and the splitbar.
1075: */
1076: if (pswpVScroll->cy > (cyHorzSplitbar * 3)) {
1077: SetSwpPos(&aswp[iswpNext++],
1078: WinWindowFromID(hwnd, ID_HORZSPLITBAR), NULL,
1079: swpClient.x, swpClient.y + cyHorzSplitPos,
1080: swpClient.cx + pswpVScroll->cx - cxBorder, cyHorzSplitbar,
1081: pswpVScroll->fs | SWP_SHOW);
1082:
1083: SetSwpPos(&aswp[iswpNext++],
1084: WinWindowFromID(hwnd, ID_VERTSCROLL2), NULL,
1085: pswpVScroll->x, pswpVScroll->y,
1086: pswpVScroll->cx, cyHorzSplitPos + (cyBorder * 2),
1087: pswpVScroll->fs | SWP_SHOW);
1088:
1089: pswpVScroll->y += (cyHorzSplitPos + cyHorzSplitbar);
1090: pswpVScroll->cy -= (cyHorzSplitPos + cyHorzSplitbar);
1091:
1092: } else {
1093: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_VERTSCROLL2),
1094: &iswpNext);
1095: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_HORZSPLITBAR),
1096: &iswpNext);
1097: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT3),
1098: &iswpNext);
1099: if (npdoc->fsStyle & DS_VERTSPLITBAR)
1100: HideSwp(&aswp[iswpNext], WinWindowFromID(hwnd, ID_CLIENT4),
1101: &iswpNext);
1102: }
1103: }
1104:
1105: if (npdoc->fs & DF_SPLITVERT) {
1106:
1107: SetSwpPos(&aswp[iswpNext++],
1108: WinWindowFromID(hwnd, ID_VERTSPLITBAR), NULL,
1109: swpClient.x + cxVertSplitPos, pswpHScroll->y + cyBorder,
1110: cxVertSplitbar, swpClient.cy + pswpHScroll->cy - cyBorder,
1111: pswpHScroll->fs);
1112:
1113: SetSwpPos(&aswp[iswpNext++],
1114: WinWindowFromID(hwnd, ID_HORZSCROLL2), NULL,
1115: swpClient.x + cxVertSplitPos + cxVertSplitbar - cyBorder,
1116: pswpHScroll->y, pswpHScroll->cx - (cxVertSplitPos + cxVertSplitbar),
1117: pswpHScroll->cy, pswpVScroll->fs | SWP_SHOW);
1118:
1119: pswpHScroll->cx = cxVertSplitPos + (cxBorder * 2);
1120: }
1121:
1122: return (iswpNext);
1123: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.