source: trunk/src/helpers/cctl_xframe.c@ 233

Last change on this file since 233 was 233, checked in by umoeller, 23 years ago

Minor changes.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 20.1 KB
Line 
1
2/*
3 *@@sourcefile cctl_xframe.c:
4 * implementation for the "extended frame" common control.
5 * This is a drop-in replacement for WinCreateStdWindow;
6 * see ctlCreateStdWindow for an introduction.
7 *
8 * See comctl.c for an overview of the common controls.
9 *
10 * This is new with V1.0.1 (2002-11-30) [umoeller].
11 *
12 * Note: Version numbering in this file relates to XWorkplace version
13 * numbering.
14 *
15 *@@header "helpers\comctl.h"
16 *@@added V1.0.1 (2002-11-30) [umoeller]
17 */
18
19/*
20 * Copyright (C) 1997-2002 Ulrich M”ller.
21 * This file is part of the "XWorkplace helpers" source package.
22 * This is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published
24 * by the Free Software Foundation, in version 2 as it comes in the
25 * "COPYING" file of the XWorkplace main distribution.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 */
31
32#define OS2EMX_PLAIN_CHAR
33 // this is needed for "os2emx.h"; if this is defined,
34 // emx will define PSZ as _signed_ char, otherwise
35 // as unsigned char
36
37#define INCL_WINWINDOWMGR
38#define INCL_WINFRAMEMGR
39#define INCL_WINSYS
40#define INCL_WINSTATICS
41#define INCL_WINSHELLDATA
42#include <os2.h>
43
44#include <stdlib.h>
45#include <stdio.h>
46#include <string.h>
47#include <setjmp.h> // needed for except.h
48#include <assert.h> // needed for except.h
49
50#include "setup.h" // code generation and debugging options
51
52#include "helpers\gpih.h"
53#include "helpers\linklist.h"
54#include "helpers\standards.h"
55#include "helpers\winh.h"
56
57#include "helpers\comctl.h"
58
59#pragma hdrstop
60
61/*
62 *@@category: Helpers\PM helpers\Window classes\Extended frame windows
63 * See comctl.c and ctlMakeMenuButton.
64 */
65
66/* ******************************************************************
67 *
68 * Extended frame
69 *
70 ********************************************************************/
71
72/*
73 *@@ ctlFormatFrame:
74 * implementation for WM_FORMATFRAME in fnwpSubclExtFrame.
75 *
76 * This can also be called externally if you have a frame
77 * window proc that implements tool or status bars.
78 * (XWorkplace status bars).
79 *
80 *@@changed V1.0.1 (2002-12-08) [umoeller]: didn't work if frame had no menu, fixed
81 */
82
83MRESULT ctlFormatExtFrame(HWND hwndFrame,
84 PXFRAMECONTROLS pxfc,
85 MPARAM mp1,
86 MPARAM mp2)
87{
88 // query the number of standard frame controls
89 ULONG c = (ULONG)pxfc->pfnwpOrig(hwndFrame, WM_FORMATFRAME, mp1, mp2),
90 cOrig = c;
91
92 // increment the number of frame controls
93 // to include our tool and status bar
94 if (pxfc->hwndToolBar)
95 ++c;
96 if (pxfc->hwndStatusBar)
97 ++c;
98
99 if (c != cOrig)
100 {
101 // we have something:
102 // format client, status, and tool bar
103 ULONG ul;
104 PSWP paswp = (PSWP)mp1,
105 pswpClient = NULL,
106 pswpMenu = NULL,
107 pswpTitleBar = NULL,
108 pswpToolBar = NULL,
109 pswpStatusBar = NULL,
110 // first of the new SWP entries:
111 pswpLast = paswp + cOrig;
112
113 // PMREF says mp2 has a PRECTL to the client rectangle,
114 // but we cannot rely on that since from my testing
115 // that pointer is NULL if the frame has no client...
116 // so calculate this manually
117 POINTL ptlBorderSizes;
118 RECTL rclFrame;
119 WinSendMsg(hwndFrame,
120 WM_QUERYBORDERSIZE,
121 (MPARAM)&ptlBorderSizes,
122 0);
123 WinQueryWindowRect(hwndFrame, &rclFrame);
124
125 // find the client in the SWP array
126 for (ul = 0; ul < cOrig; ul++)
127 {
128 switch (WinQueryWindowUShort(paswp[ul].hwnd, QWS_ID))
129 {
130 case FID_CLIENT:
131 pswpClient = &paswp[ul];
132 break;
133
134 case FID_MENU:
135 pswpMenu = &paswp[ul];
136 break;
137
138 case FID_TITLEBAR:
139 pswpTitleBar = &paswp[ul];
140 break;
141 }
142 }
143
144 // position tool bar, if present
145 if (pxfc->hwndToolBar)
146 {
147 pswpToolBar = pswpLast++;
148
149 pswpToolBar->fl = SWP_MOVE | SWP_SIZE; // | SWP_NOADJUST;
150 pswpToolBar->x = ptlBorderSizes.x;
151
152 if (pswpMenu)
153 pswpToolBar->y = pswpMenu->y - pxfc->lToolBarHeight;
154 // if we don't have a menu, we need to use the title bar instead
155 // or the toolbar will overlap it V1.0.1 (2002-12-08) [umoeller]
156 else if (pswpTitleBar)
157 pswpToolBar->y = pswpTitleBar->y - pxfc->lToolBarHeight;
158 else
159 pswpToolBar->y = rclFrame.yTop - ptlBorderSizes.y - pxfc->lToolBarHeight;
160
161 pswpToolBar->cx = rclFrame.xRight - 2 * ptlBorderSizes.x;
162 pswpToolBar->cy = pxfc->lToolBarHeight;
163 pswpToolBar->hwndInsertBehind = HWND_TOP;
164 pswpToolBar->hwnd = pxfc->hwndToolBar;
165 }
166
167 // position status bar, if present
168 if (pxfc->hwndStatusBar)
169 {
170 pswpStatusBar = pswpLast++;
171
172 pswpStatusBar->fl = SWP_MOVE | SWP_SIZE | SWP_NOADJUST;
173 pswpStatusBar->x = ptlBorderSizes.x;
174 pswpStatusBar->y = ptlBorderSizes.y;
175 pswpStatusBar->cx = rclFrame.xRight - 2 * ptlBorderSizes.x;
176 pswpStatusBar->cy = pxfc->lStatusBarHeight;
177 pswpStatusBar->hwndInsertBehind = HWND_TOP;
178 pswpStatusBar->hwnd = pxfc->hwndStatusBar;
179 }
180
181 // finally, reduce client
182 if (pswpClient)
183 {
184 if (pswpStatusBar)
185 {
186 pswpClient->y += pswpStatusBar->cy;
187 pswpClient->cy -= pswpStatusBar->cy;
188 }
189 if (pswpToolBar)
190 {
191 pswpClient->cy -= pswpToolBar->cy;
192 }
193 }
194 }
195
196 return (MRESULT)c;
197}
198
199/*
200 *@@ ctlCalcExtFrameRect:
201 * implementation for WM_CALCFRAMERECT in fnwpSubclExtFrame.
202 *
203 * This can also be called externally if you have a frame
204 * window proc that implements tool or status bars
205 * (XWorkplace status bars).
206 *
207 *@@added V1.0.0 (2002-08-28) [umoeller]
208 *@@changed V1.0.1 (2002-11-30) [umoeller]: moved here from winh.c, renamed
209 */
210
211VOID ctlCalcExtFrameRect(MPARAM mp1,
212 MPARAM mp2,
213 LONG lStatusBarHeight)
214{
215 PRECTL prclPassed = (PRECTL)mp1;
216
217 if (mp2)
218 {
219 // mp2 == TRUE: frame rectangle provided, calculate client
220 // call default window procedure to subtract child frame
221 // controls from the rectangle's height
222 LONG lClientHeight;
223
224 // position the static text frame extension below the client
225 lClientHeight = prclPassed->yTop - prclPassed->yBottom;
226 if (lStatusBarHeight > lClientHeight)
227 // extension is taller than client, so set client height to 0
228 prclPassed->yTop = prclPassed->yBottom;
229 else
230 {
231 // set the origin of the client and shrink it based upon the
232 // static text control's height
233 prclPassed->yBottom += lStatusBarHeight;
234 prclPassed->yTop -= lStatusBarHeight;
235 }
236 }
237 else
238 {
239 // mp2 == FALSE: client area rectangle provided, calculate frame
240 // call default window procedure to subtract child frame
241 // controls from the rectangle's height;
242 // set the origin of the frame and increase it based upon the
243 // static text control's height
244 prclPassed->yBottom -= lStatusBarHeight;
245 prclPassed->yTop += lStatusBarHeight;
246 }
247}
248
249#define STATUS_BAR_HEIGHT 20
250
251/*
252 *@@ fnwpSubclExtFrame:
253 * subclassed frame window proc for the extended frame
254 * window (see ctlCreateStdWindow).
255 *
256 *@@added V0.9.16 (2001-09-29) [umoeller]
257 *@@changed V1.0.1 (2002-11-30) [umoeller]: moved here from winh.c
258 */
259
260STATIC MRESULT EXPENTRY fnwpSubclExtFrame(HWND hwndFrame, ULONG msg, MPARAM mp1, MPARAM mp2)
261{
262 MRESULT mrc = 0;
263
264 PEXTFRAMEDATA pData = (PEXTFRAMEDATA)WinQueryWindowPtr(hwndFrame, QWL_USER);
265 ULONG c;
266
267 switch (msg)
268 {
269 case WM_QUERYFRAMECTLCOUNT:
270 // query the standard frame controls count
271 c = (ULONG)pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2);
272
273 // increment the number of frame controls
274 // to include our tool and status bar
275 if (pData->xfc.hwndToolBar)
276 ++c;
277 if (pData->xfc.hwndStatusBar)
278 ++c;
279
280 mrc = (MPARAM)c;
281 break;
282
283 case WM_FORMATFRAME:
284 mrc = ctlFormatExtFrame(hwndFrame,
285 &pData->xfc,
286 mp1,
287 mp2);
288 break;
289
290 case WM_CALCFRAMERECT:
291 mrc = pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2);
292
293 // we have a status bar: calculate its rectangle
294 ctlCalcExtFrameRect(mp1,
295 mp2,
296 STATUS_BAR_HEIGHT);
297 break;
298
299 case WM_SYSCOMMAND:
300 if ( (SHORT1FROMMP(mp1) == SC_CLOSE)
301 && (pData->CData.hiniSaveWinPos)
302 )
303 {
304 SWP swp;
305 WinQueryWindowPos(hwndFrame, &swp);
306 PrfWriteProfileData(pData->CData.hiniSaveWinPos,
307 (PSZ)pData->CData.pcszIniApp,
308 (PSZ)pData->CData.pcszIniKey,
309 &swp,
310 sizeof(swp));
311 }
312
313 mrc = pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2);
314 break;
315
316 case WM_DESTROY:
317 WinSetWindowPtr(hwndFrame, QWL_USER, NULL);
318 WinSubclassWindow(hwndFrame, pData->xfc.pfnwpOrig);
319 free(pData);
320
321 mrc = pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2);
322 break;
323
324 default:
325 mrc = pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2);
326 }
327
328 return mrc;
329}
330
331/*
332 *@@ ctlCreateStatusBar:
333 * creates a status bar for a frame window.
334 *
335 * Normally there's no need to call this manually,
336 * this gets called by ctlCreateStdWindow
337 * automatically.
338 *
339 *@@added V0.9.16 (2001-09-29) [umoeller]
340 *@@changed V1.0.1 (2002-11-30) [umoeller]: moved here from winh.c, renamed
341 */
342
343HWND ctlCreateStatusBar(HWND hwndFrame,
344 HWND hwndOwner,
345 const char *pcszText, // in: initial status bar text
346 const char *pcszFont, // in: font to use for status bar
347 LONG lColor) // in: foreground color for status bar
348{
349 // create status bar
350 HWND hwndReturn = NULLHANDLE;
351
352 PPRESPARAMS ppp = winhCreateDefaultPresparams();
353
354 hwndReturn = WinCreateWindow(hwndFrame,
355 WC_STATIC,
356 (PSZ)pcszText,
357 SS_TEXT | DT_VCENTER | WS_VISIBLE,
358 0, 0, 0, 0,
359 hwndOwner,
360 HWND_TOP,
361 FID_STATUSBAR,
362 NULL,
363 ppp);
364 free(ppp);
365
366 return hwndReturn;
367}
368
369/*
370 *@@ ctlCreateStdWindow:
371 * creates an extended frame window. Use this
372 * instead of WinCreateStdWindow if you want a
373 * quick way to add an enhanced frame window with
374 * status or tool bars.
375 *
376 * pData must point to an EXTFRAMECDATA structure
377 * which contains a copy of the parameters to be
378 * passed to winhCreateStdWindow. In addition,
379 * this contains the flExtFlags field, which allows
380 * you to automatically create a status and tool bar
381 * for the frame.
382 *
383 * Note that we subclass the frame here and require
384 * QWL_USER for that. The frame's QWL_USER points
385 * to an EXTFRAMEDATA structure whose pUser parameter
386 * you may use for additional data, if you want to
387 * do further subclassing.
388 *
389 * For tool bars to work, you must call ctlRegisterToolbar
390 * beforehand.
391 *
392 * This has the following extra features:
393 *
394 * -- To have a status bar created automatically,
395 * pass in XFCF_STATUSBAR with EXTFRAMECDATA.flExtFrame.
396 * The status bar is a frame control and can be
397 * queried with WinWindowFromID(hwndFrame, FID_STATUSBAR).
398 * It is a subclassed static and thus supports plain
399 * WinSetWindowText and the like.
400 *
401 * -- To have a tool bar created automatically,
402 * pass in XFCF_TOOLBAR with EXTFRAMECDATA.flExtFrame
403 * and an array of TOOLBARCONTROL structures for the
404 * list of controls to be created in the tool bar.
405 * See cctl_toolbar.c for details. The tool bar can be
406 * queried with WinWindowFromID(hwndFrame, FID_TOOLBAR).
407 *
408 * -- You can specify pswpFrame for the initial window
409 * position. If it is NULL, the extended frame will
410 * resize itself to fill most of the screen with about
411 * 20 pixels border around it.
412 *
413 * -- If you specify hiniSaveWinPos, pcszIniApp, and
414 * pcszIniKey with EXTFRAMECDATA, the frame supports
415 * saving its window position automatically. Only if
416 * no window position is found in that key, pswpFrame
417 * is respected.
418 *
419 * -- The frame will only be visible and activated when this
420 * function returns if you specify WS_VISIBLE with flStyleFrame.
421 * The SWP_SHOW, SWP_HIDE, and SWP_ACTIVATE flags are
422 * always filtered out from the given pswpFrame. If
423 * WS_VISIBLE is set, the frame will be activated also.
424 *
425 *@@added V0.9.16 (2001-09-29) [umoeller]
426 *@@changed V1.0.1 (2002-11-30) [umoeller]: moved here from winh.c, renamed
427 *@@changed V1.0.1 (2002-11-30) [umoeller]: added support for saving window pos automatically
428 */
429
430HWND ctlCreateStdWindow(PEXTFRAMECDATA pData, // in: extended frame data
431 PHWND phwndClient) // out: created client wnd
432{
433 HWND hwndFrame;
434
435 SWP swpFrame;
436 ULONG cb = sizeof(swpFrame);
437
438 if ( (!pData->hiniSaveWinPos)
439 || (!PrfQueryProfileData(pData->hiniSaveWinPos,
440 (PSZ)pData->pcszIniApp,
441 (PSZ)pData->pcszIniKey,
442 &swpFrame,
443 &cb))
444 || (cb != sizeof(swpFrame))
445 )
446 {
447 // window pos not loaded:
448 // try to use the specified one
449 if (pData->pswpFrame)
450 memcpy(&swpFrame, pData->pswpFrame, sizeof(SWP));
451 else
452 {
453 swpFrame.hwndInsertBehind = HWND_TOP;
454 swpFrame.x = 20;
455 swpFrame.y = 20;
456 swpFrame.cx = G_cxScreen - 2 * 20;
457 swpFrame.cy = G_cyScreen - 2 * 20;
458 swpFrame.fl = SWP_MOVE | SWP_SIZE;
459 }
460 }
461
462 swpFrame.fl &= ~ SWP_SHOW | SWP_HIDE | SWP_ACTIVATE;
463
464 if (hwndFrame = winhCreateStdWindow(HWND_DESKTOP,
465 &swpFrame,
466 pData->flFrame | WS_CLIPCHILDREN,
467 pData->flStyleFrame & ~ WS_VISIBLE,
468 // do not show before we have formatted
469 // the frame correctly
470 pData->pcszFrameTitle,
471 pData->ulResourcesID,
472 pData->pcszClassClient,
473 pData->flStyleClient,
474 pData->ulID,
475 pData->pClientCtlData,
476 phwndClient))
477 {
478 PEXTFRAMEDATA pFrameData;
479
480 // subclass frame for supporting status bar and msgs
481 if (pFrameData = NEW(EXTFRAMEDATA))
482 {
483 ZERO(pFrameData),
484 memcpy(&pFrameData->CData, pData, sizeof(pFrameData->CData));
485
486 if (pFrameData->xfc.pfnwpOrig = WinSubclassWindow(hwndFrame,
487 fnwpSubclExtFrame))
488 {
489 WinSetWindowPtr(hwndFrame, QWL_USER, pFrameData);
490
491 if (pData->flExtFrame & XFCF_TOOLBAR)
492 {
493 HWND hwndControlsOwner;
494
495 // determine owner for the tool bar controls:
496 // client, if present and XFCF_FORCETBOWNER is
497 // not set
498 if ( (!(hwndControlsOwner = *phwndClient))
499 || (pData->flExtFrame & XFCF_FORCETBOWNER)
500 )
501 hwndControlsOwner = hwndFrame;
502
503 // create tool bar as frame control
504 if (pFrameData->xfc.hwndToolBar = ctlCreateToolBar(hwndFrame,
505 hwndFrame,
506 WS_VISIBLE
507 | TBS_TOOLTIPS
508 | TBS_AUTORESIZE,
509 // owner for controls:
510 // client, if it exists
511 hwndControlsOwner,
512 pData->cTBControls,
513 pData->paTBControls))
514 {
515 WinQueryWindowPos(pFrameData->xfc.hwndToolBar,
516 &swpFrame);
517 pFrameData->xfc.lToolBarHeight = swpFrame.cy;
518 }
519 }
520
521 if (pData->flExtFrame & XFCF_STATUSBAR)
522 {
523 // create status bar as frame control
524 pFrameData->xfc.hwndStatusBar = ctlCreateStatusBar(hwndFrame,
525 hwndFrame,
526 "",
527 "9.WarpSans",
528 CLR_BLACK);
529
530 pFrameData->xfc.lStatusBarHeight = STATUS_BAR_HEIGHT;
531 }
532
533 WinSendMsg(hwndFrame, WM_UPDATEFRAME, MPNULL, MPNULL);
534
535 if (pData->flStyleFrame & WS_VISIBLE)
536 WinSetWindowPos(hwndFrame,
537 HWND_TOP,
538 0,
539 0,
540 0,
541 0,
542 SWP_SHOW | SWP_ZORDER | SWP_ACTIVATE);
543 }
544 else
545 {
546 free(pFrameData);
547 WinDestroyWindow(hwndFrame);
548 hwndFrame = NULLHANDLE;
549 }
550 }
551 }
552
553 return hwndFrame;
554}
555
Note: See TracBrowser for help on using the repository browser.