|
|
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.