/* *@@sourcefile cctl_xframe.c: * implementation for the "extended frame" common control. * This is a drop-in replacement for WinCreateStdWindow; * see ctlCreateStdWindow for an introduction. * * See comctl.c for an overview of the common controls. * * This is new with V1.0.1 (2002-11-30) [umoeller]. * * Note: Version numbering in this file relates to XWorkplace version * numbering. * *@@header "helpers\comctl.h" *@@added V1.0.1 (2002-11-30) [umoeller] */ /* * Copyright (C) 1997-2002 Ulrich M”ller. * This file is part of the "XWorkplace helpers" source package. * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, in version 2 as it comes in the * "COPYING" file of the XWorkplace main distribution. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #define OS2EMX_PLAIN_CHAR // this is needed for "os2emx.h"; if this is defined, // emx will define PSZ as _signed_ char, otherwise // as unsigned char #define INCL_WINWINDOWMGR #define INCL_WINFRAMEMGR #define INCL_WINSYS #define INCL_WINSTATICS #define INCL_WINSHELLDATA #include #include #include #include #include // needed for except.h #include // needed for except.h #include "setup.h" // code generation and debugging options #include "helpers\gpih.h" #include "helpers\linklist.h" #include "helpers\standards.h" #include "helpers\winh.h" #include "helpers\comctl.h" #pragma hdrstop /* *@@category: Helpers\PM helpers\Window classes\Extended frame windows * See comctl.c and ctlMakeMenuButton. */ /* ****************************************************************** * * Extended frame * ********************************************************************/ /* *@@ ctlFormatFrame: * implementation for WM_FORMATFRAME in fnwpSubclExtFrame. * * This can also be called externally if you have a frame * window proc that implements tool or status bars. * (XWorkplace status bars). * *@@changed V1.0.1 (2002-12-08) [umoeller]: didn't work if frame had no menu, fixed */ MRESULT ctlFormatExtFrame(HWND hwndFrame, const XFRAMECONTROLS *pxfc, MPARAM mp1, MPARAM mp2) { // query the number of standard frame controls ULONG c = (ULONG)pxfc->pfnwpOrig(hwndFrame, WM_FORMATFRAME, mp1, mp2), cOrig = c; // increment the number of frame controls // to include our tool and status bar if (pxfc->hwndToolBar) ++c; if (pxfc->hwndStatusBar) ++c; if (c != cOrig) { // we have something: // format client, status, and tool bar ULONG ul; PSWP paswp = (PSWP)mp1, pswpClient = NULL, pswpMenu = NULL, pswpTitleBar = NULL, pswpToolBar = NULL, pswpStatusBar = NULL, // first of the new SWP entries: pswpLast = paswp + cOrig; // PMREF says mp2 has a PRECTL to the client rectangle, // but we cannot rely on that since from my testing // that pointer is NULL if the frame has no client... // so calculate this manually POINTL ptlBorderSizes; RECTL rclFrame; WinSendMsg(hwndFrame, WM_QUERYBORDERSIZE, (MPARAM)&ptlBorderSizes, 0); WinQueryWindowRect(hwndFrame, &rclFrame); // find the client in the SWP array for (ul = 0; ul < cOrig; ul++) { switch (WinQueryWindowUShort(paswp[ul].hwnd, QWS_ID)) { case FID_CLIENT: pswpClient = &paswp[ul]; break; case FID_MENU: pswpMenu = &paswp[ul]; break; case FID_TITLEBAR: pswpTitleBar = &paswp[ul]; break; } } // position tool bar, if present if (pxfc->hwndToolBar) { pswpToolBar = pswpLast++; pswpToolBar->fl = SWP_MOVE | SWP_SIZE; // | SWP_NOADJUST; pswpToolBar->x = ptlBorderSizes.x; if (pswpMenu) pswpToolBar->y = pswpMenu->y - pxfc->lToolBarHeight; // if we don't have a menu, we need to use the title bar instead // or the toolbar will overlap it V1.0.1 (2002-12-08) [umoeller] else if (pswpTitleBar) pswpToolBar->y = pswpTitleBar->y - pxfc->lToolBarHeight; else pswpToolBar->y = rclFrame.yTop - ptlBorderSizes.y - pxfc->lToolBarHeight; pswpToolBar->cx = rclFrame.xRight - 2 * ptlBorderSizes.x; pswpToolBar->cy = pxfc->lToolBarHeight; pswpToolBar->hwndInsertBehind = HWND_TOP; pswpToolBar->hwnd = pxfc->hwndToolBar; } // position status bar, if present if (pxfc->hwndStatusBar) { pswpStatusBar = pswpLast++; pswpStatusBar->fl = SWP_MOVE | SWP_SIZE | SWP_NOADJUST; pswpStatusBar->x = ptlBorderSizes.x; pswpStatusBar->y = ptlBorderSizes.y; pswpStatusBar->cx = rclFrame.xRight - 2 * ptlBorderSizes.x; pswpStatusBar->cy = pxfc->lStatusBarHeight; pswpStatusBar->hwndInsertBehind = HWND_TOP; pswpStatusBar->hwnd = pxfc->hwndStatusBar; } // finally, reduce client if (pswpClient) { if (pswpStatusBar) { pswpClient->y += pswpStatusBar->cy; pswpClient->cy -= pswpStatusBar->cy; } if (pswpToolBar) { pswpClient->cy -= pswpToolBar->cy; } } } return (MRESULT)c; } /* *@@ ctlCalcExtFrameRect: * implementation for WM_CALCFRAMERECT in fnwpSubclExtFrame. * * This can also be called externally if you have a frame * window proc that implements tool or status bars * (XWorkplace status bars). * *@@added V1.0.0 (2002-08-28) [umoeller] *@@changed V1.0.1 (2002-11-30) [umoeller]: moved here from winh.c, renamed */ MRESULT ctlCalcExtFrameRect(HWND hwndFrame, const XFRAMECONTROLS *pxfc, MPARAM mp1, MPARAM mp2) { PRECTL prclPassed = (PRECTL)mp1; MRESULT mrc = pxfc->pfnwpOrig(hwndFrame, WM_CALCFRAMERECT, mp1, mp2); if (mp2) { // mp2 == TRUE: frame rectangle provided, calculate client // call default window procedure to subtract child frame // controls from the rectangle's height if (pxfc->hwndToolBar) prclPassed->yTop -= pxfc->lToolBarHeight; if (pxfc->hwndStatusBar) prclPassed->yBottom += pxfc->lStatusBarHeight; } else { // mp2 == FALSE: client area rectangle provided, calculate frame // call default window procedure to subtract child frame // controls from the rectangle's height; // set the origin of the frame and increase it based upon the // static text control's height if (pxfc->hwndToolBar) prclPassed->yTop += pxfc->lToolBarHeight; if (pxfc->hwndStatusBar) prclPassed->yBottom -= pxfc->lStatusBarHeight; } return mrc; } #define STATUS_BAR_HEIGHT 20 /* *@@ fnwpSubclExtFrame: * subclassed frame window proc for the extended frame * window (see ctlCreateStdWindow). * *@@added V0.9.16 (2001-09-29) [umoeller] *@@changed V1.0.1 (2002-11-30) [umoeller]: moved here from winh.c */ STATIC MRESULT EXPENTRY fnwpSubclExtFrame(HWND hwndFrame, ULONG msg, MPARAM mp1, MPARAM mp2) { MRESULT mrc = 0; PEXTFRAMEDATA pData = (PEXTFRAMEDATA)WinQueryWindowPtr(hwndFrame, QWL_USER); ULONG c; switch (msg) { case WM_QUERYFRAMECTLCOUNT: // query the standard frame controls count c = (ULONG)pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2); // increment the number of frame controls // to include our tool and status bar if (pData->xfc.hwndToolBar) ++c; if (pData->xfc.hwndStatusBar) ++c; mrc = (MPARAM)c; break; case WM_FORMATFRAME: mrc = ctlFormatExtFrame(hwndFrame, &pData->xfc, mp1, mp2); break; case WM_CALCFRAMERECT: // we have a status bar: calculate its rectangle mrc = ctlCalcExtFrameRect(hwndFrame, &pData->xfc, mp1, mp2); break; /* case WM_WINDOWPOSCHANGED: WinSendMsg(hwndFrame, WM_UPDATEFRAME, 0, 0); break; */ case WM_SYSCOMMAND: if ( (SHORT1FROMMP(mp1) == SC_CLOSE) && (pData->CData.hiniSaveWinPos) ) { SWP swp; WinQueryWindowPos(hwndFrame, &swp); PrfWriteProfileData(pData->CData.hiniSaveWinPos, (PSZ)pData->CData.pcszIniApp, (PSZ)pData->CData.pcszIniKey, &swp, sizeof(swp)); } mrc = pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2); break; case WM_DESTROY: WinSetWindowPtr(hwndFrame, QWL_USER, NULL); WinSubclassWindow(hwndFrame, pData->xfc.pfnwpOrig); free(pData); mrc = pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2); break; default: mrc = pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2); } return mrc; } /* *@@ ctlCreateStatusBar: * creates a status bar for a frame window. * * Normally there's no need to call this manually, * this gets called by ctlCreateStdWindow * automatically. * *@@added V0.9.16 (2001-09-29) [umoeller] *@@changed V1.0.1 (2002-11-30) [umoeller]: moved here from winh.c, renamed */ HWND ctlCreateStatusBar(HWND hwndFrame, HWND hwndOwner, const char *pcszText, // in: initial status bar text const char *pcszFont, // in: font to use for status bar LONG lColor) // in: foreground color for status bar { // create status bar HWND hwndReturn = NULLHANDLE; PPRESPARAMS ppp = winhCreateDefaultPresparams(); hwndReturn = WinCreateWindow(hwndFrame, WC_STATIC, (PSZ)pcszText, SS_TEXT | DT_VCENTER | WS_VISIBLE, 0, 0, 0, 0, hwndOwner, HWND_TOP, FID_STATUSBAR, NULL, ppp); free(ppp); return hwndReturn; } /* *@@ ctlCreateStdWindow: * creates an extended frame window. Use this * instead of WinCreateStdWindow if you want a * quick way to add an enhanced frame window with * status or tool bars. * * pData must point to an EXTFRAMECDATA structure * which contains a copy of the parameters to be * passed to winhCreateStdWindow. In addition, * this contains the flExtFlags field, which allows * you to automatically create a status and tool bar * for the frame. * * Note that we subclass the frame here and require * QWL_USER for that. The frame's QWL_USER points * to an EXTFRAMEDATA structure whose pUser parameter * you may use for additional data, if you want to * do further subclassing. * * For tool bars to work, you must call ctlRegisterToolbar * beforehand. * * This has the following extra features: * * -- To have a status bar created automatically, * pass in XFCF_STATUSBAR with EXTFRAMECDATA.flExtFrame. * The status bar is a frame control and can be * queried with WinWindowFromID(hwndFrame, FID_STATUSBAR). * It is a subclassed static and thus supports plain * WinSetWindowText and the like. * * -- To have a tool bar created automatically, * pass in XFCF_TOOLBAR with EXTFRAMECDATA.flExtFrame * and an array of TOOLBARCONTROL structures for the * list of controls to be created in the tool bar. * See cctl_toolbar.c for details. The tool bar can be * queried with WinWindowFromID(hwndFrame, FID_TOOLBAR). * * -- You can specify pswpFrame for the initial window * position. If it is NULL, the extended frame will * resize itself to fill most of the screen with about * 20 pixels border around it. * * -- If you specify hiniSaveWinPos, pcszIniApp, and * pcszIniKey with EXTFRAMECDATA, the frame supports * saving its window position automatically. Only if * no window position is found in that key, pswpFrame * is respected. * * -- The frame will only be visible and activated when this * function returns if you specify WS_VISIBLE with flStyleFrame. * The SWP_SHOW, SWP_HIDE, and SWP_ACTIVATE flags are * always filtered out from the given pswpFrame. If * WS_VISIBLE is set, the frame will be activated also. * *@@added V0.9.16 (2001-09-29) [umoeller] *@@changed V1.0.1 (2002-11-30) [umoeller]: moved here from winh.c, renamed *@@changed V1.0.1 (2002-11-30) [umoeller]: added support for saving window pos automatically */ HWND ctlCreateStdWindow(PEXTFRAMECDATA pData, // in: extended frame data PHWND phwndClient) // out: created client wnd { HWND hwndFrame; SWP swpFrame; ULONG cb = sizeof(swpFrame); if ( (!pData->hiniSaveWinPos) || (!PrfQueryProfileData(pData->hiniSaveWinPos, (PSZ)pData->pcszIniApp, (PSZ)pData->pcszIniKey, &swpFrame, &cb)) || (cb != sizeof(swpFrame)) ) { // window pos not loaded: // try to use the specified one if (pData->pswpFrame) memcpy(&swpFrame, pData->pswpFrame, sizeof(SWP)); else { swpFrame.hwndInsertBehind = HWND_TOP; swpFrame.x = 20; swpFrame.y = 20; swpFrame.cx = G_cxScreen - 2 * 20; swpFrame.cy = G_cyScreen - 2 * 20; swpFrame.fl = SWP_MOVE | SWP_SIZE; } } swpFrame.fl &= ~ SWP_SHOW | SWP_HIDE | SWP_ACTIVATE; if (hwndFrame = winhCreateStdWindow(HWND_DESKTOP, &swpFrame, pData->flFrame | WS_CLIPCHILDREN, pData->flStyleFrame & ~ WS_VISIBLE, // do not show before we have formatted // the frame correctly pData->pcszFrameTitle, pData->ulResourcesID, pData->pcszClassClient, pData->flStyleClient, pData->ulID, pData->pClientCtlData, phwndClient)) { PEXTFRAMEDATA pFrameData; // subclass frame for supporting status bar and msgs if (pFrameData = NEW(EXTFRAMEDATA)) { ZERO(pFrameData), memcpy(&pFrameData->CData, pData, sizeof(pFrameData->CData)); if (pFrameData->xfc.pfnwpOrig = WinSubclassWindow(hwndFrame, fnwpSubclExtFrame)) { WinSetWindowPtr(hwndFrame, QWL_USER, pFrameData); if (pData->flExtFrame & XFCF_TOOLBAR) { HWND hwndControlsOwner; // determine owner for the tool bar controls: // client, if present and XFCF_FORCETBOWNER is // not set if ( (!(hwndControlsOwner = *phwndClient)) || (pData->flExtFrame & XFCF_FORCETBOWNER) ) hwndControlsOwner = hwndFrame; // create tool bar as frame control if (pFrameData->xfc.hwndToolBar = ctlCreateToolBar(hwndFrame, hwndFrame, WS_VISIBLE | TBS_TOOLTIPS | TBS_AUTORESIZE, // owner for controls: // client, if it exists hwndControlsOwner, pData->cTBControls, pData->paTBControls)) { WinQueryWindowPos(pFrameData->xfc.hwndToolBar, &swpFrame); pFrameData->xfc.lToolBarHeight = swpFrame.cy; } } if (pData->flExtFrame & XFCF_STATUSBAR) { // create status bar as frame control pFrameData->xfc.hwndStatusBar = ctlCreateStatusBar(hwndFrame, hwndFrame, "", "9.WarpSans", CLR_BLACK); pFrameData->xfc.lStatusBarHeight = STATUS_BAR_HEIGHT; } WinSendMsg(hwndFrame, WM_UPDATEFRAME, MPNULL, MPNULL); if (pData->flStyleFrame & WS_VISIBLE) WinSetWindowPos(hwndFrame, HWND_TOP, 0, 0, 0, 0, SWP_SHOW | SWP_ZORDER | SWP_ACTIVATE); } else { free(pFrameData); WinDestroyWindow(hwndFrame); hwndFrame = NULLHANDLE; } } } return hwndFrame; }