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

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

New toolbar control.

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