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

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

First attempt at new container contol.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 20.0 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 const XFRAMECONTROLS *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
211MRESULT ctlCalcExtFrameRect(HWND hwndFrame,
212 const XFRAMECONTROLS *pxfc,
213 MPARAM mp1,
214 MPARAM mp2)
215{
216 PRECTL prclPassed = (PRECTL)mp1;
217
218 MRESULT mrc = pxfc->pfnwpOrig(hwndFrame, WM_CALCFRAMERECT, mp1, mp2);
219
220 if (mp2)
221 {
222 // mp2 == TRUE: frame rectangle provided, calculate client
223 // call default window procedure to subtract child frame
224 // controls from the rectangle's height
225
226 if (pxfc->hwndToolBar)
227 prclPassed->yTop -= pxfc->lToolBarHeight;
228
229 if (pxfc->hwndStatusBar)
230 prclPassed->yBottom += pxfc->lStatusBarHeight;
231 }
232 else
233 {
234 // mp2 == FALSE: client area rectangle provided, calculate frame
235 // call default window procedure to subtract child frame
236 // controls from the rectangle's height;
237 // set the origin of the frame and increase it based upon the
238 // static text control's height
239
240 if (pxfc->hwndToolBar)
241 prclPassed->yTop += pxfc->lToolBarHeight;
242
243 if (pxfc->hwndStatusBar)
244 prclPassed->yBottom -= pxfc->lStatusBarHeight;
245 }
246
247 return mrc;
248}
249
250#define STATUS_BAR_HEIGHT 20
251
252/*
253 *@@ fnwpSubclExtFrame:
254 * subclassed frame window proc for the extended frame
255 * window (see ctlCreateStdWindow).
256 *
257 *@@added V0.9.16 (2001-09-29) [umoeller]
258 *@@changed V1.0.1 (2002-11-30) [umoeller]: moved here from winh.c
259 */
260
261STATIC MRESULT EXPENTRY fnwpSubclExtFrame(HWND hwndFrame, ULONG msg, MPARAM mp1, MPARAM mp2)
262{
263 MRESULT mrc = 0;
264
265 PEXTFRAMEDATA pData = (PEXTFRAMEDATA)WinQueryWindowPtr(hwndFrame, QWL_USER);
266 ULONG c;
267
268 switch (msg)
269 {
270 case WM_QUERYFRAMECTLCOUNT:
271 // query the standard frame controls count
272 c = (ULONG)pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2);
273
274 // increment the number of frame controls
275 // to include our tool and status bar
276 if (pData->xfc.hwndToolBar)
277 ++c;
278 if (pData->xfc.hwndStatusBar)
279 ++c;
280
281 mrc = (MPARAM)c;
282 break;
283
284 case WM_FORMATFRAME:
285 mrc = ctlFormatExtFrame(hwndFrame,
286 &pData->xfc,
287 mp1,
288 mp2);
289 break;
290
291 case WM_CALCFRAMERECT:
292 // we have a status bar: calculate its rectangle
293 mrc = ctlCalcExtFrameRect(hwndFrame,
294 &pData->xfc,
295 mp1,
296 mp2);
297 break;
298
299 /*
300 case WM_WINDOWPOSCHANGED:
301 WinSendMsg(hwndFrame, WM_UPDATEFRAME, 0, 0);
302 break; */
303
304 case WM_SYSCOMMAND:
305 if ( (SHORT1FROMMP(mp1) == SC_CLOSE)
306 && (pData->CData.hiniSaveWinPos)
307 )
308 {
309 SWP swp;
310 WinQueryWindowPos(hwndFrame, &swp);
311 PrfWriteProfileData(pData->CData.hiniSaveWinPos,
312 (PSZ)pData->CData.pcszIniApp,
313 (PSZ)pData->CData.pcszIniKey,
314 &swp,
315 sizeof(swp));
316 }
317
318 mrc = pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2);
319 break;
320
321 case WM_DESTROY:
322 WinSetWindowPtr(hwndFrame, QWL_USER, NULL);
323 WinSubclassWindow(hwndFrame, pData->xfc.pfnwpOrig);
324 free(pData);
325
326 mrc = pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2);
327 break;
328
329 default:
330 mrc = pData->xfc.pfnwpOrig(hwndFrame, msg, mp1, mp2);
331 }
332
333 return mrc;
334}
335
336/*
337 *@@ ctlCreateStatusBar:
338 * creates a status bar for a frame window.
339 *
340 * Normally there's no need to call this manually,
341 * this gets called by ctlCreateStdWindow
342 * automatically.
343 *
344 *@@added V0.9.16 (2001-09-29) [umoeller]
345 *@@changed V1.0.1 (2002-11-30) [umoeller]: moved here from winh.c, renamed
346 */
347
348HWND ctlCreateStatusBar(HWND hwndFrame,
349 HWND hwndOwner,
350 const char *pcszText, // in: initial status bar text
351 const char *pcszFont, // in: font to use for status bar
352 LONG lColor) // in: foreground color for status bar
353{
354 // create status bar
355 HWND hwndReturn = NULLHANDLE;
356
357 PPRESPARAMS ppp = winhCreateDefaultPresparams();
358
359 hwndReturn = WinCreateWindow(hwndFrame,
360 WC_STATIC,
361 (PSZ)pcszText,
362 SS_TEXT | DT_VCENTER | WS_VISIBLE,
363 0, 0, 0, 0,
364 hwndOwner,
365 HWND_TOP,
366 FID_STATUSBAR,
367 NULL,
368 ppp);
369 free(ppp);
370
371 return hwndReturn;
372}
373
374/*
375 *@@ ctlCreateStdWindow:
376 * creates an extended frame window. Use this
377 * instead of WinCreateStdWindow if you want a
378 * quick way to add an enhanced frame window with
379 * status or tool bars.
380 *
381 * pData must point to an EXTFRAMECDATA structure
382 * which contains a copy of the parameters to be
383 * passed to winhCreateStdWindow. In addition,
384 * this contains the flExtFlags field, which allows
385 * you to automatically create a status and tool bar
386 * for the frame.
387 *
388 * Note that we subclass the frame here and require
389 * QWL_USER for that. The frame's QWL_USER points
390 * to an EXTFRAMEDATA structure whose pUser parameter
391 * you may use for additional data, if you want to
392 * do further subclassing.
393 *
394 * For tool bars to work, you must call ctlRegisterToolbar
395 * beforehand.
396 *
397 * This has the following extra features:
398 *
399 * -- To have a status bar created automatically,
400 * pass in XFCF_STATUSBAR with EXTFRAMECDATA.flExtFrame.
401 * The status bar is a frame control and can be
402 * queried with WinWindowFromID(hwndFrame, FID_STATUSBAR).
403 * It is a subclassed static and thus supports plain
404 * WinSetWindowText and the like.
405 *
406 * -- To have a tool bar created automatically,
407 * pass in XFCF_TOOLBAR with EXTFRAMECDATA.flExtFrame
408 * and an array of TOOLBARCONTROL structures for the
409 * list of controls to be created in the tool bar.
410 * See cctl_toolbar.c for details. The tool bar can be
411 * queried with WinWindowFromID(hwndFrame, FID_TOOLBAR).
412 *
413 * -- You can specify pswpFrame for the initial window
414 * position. If it is NULL, the extended frame will
415 * resize itself to fill most of the screen with about
416 * 20 pixels border around it.
417 *
418 * -- If you specify hiniSaveWinPos, pcszIniApp, and
419 * pcszIniKey with EXTFRAMECDATA, the frame supports
420 * saving its window position automatically. Only if
421 * no window position is found in that key, pswpFrame
422 * is respected.
423 *
424 * -- The frame will only be visible and activated when this
425 * function returns if you specify WS_VISIBLE with flStyleFrame.
426 * The SWP_SHOW, SWP_HIDE, and SWP_ACTIVATE flags are
427 * always filtered out from the given pswpFrame. If
428 * WS_VISIBLE is set, the frame will be activated also.
429 *
430 *@@added V0.9.16 (2001-09-29) [umoeller]
431 *@@changed V1.0.1 (2002-11-30) [umoeller]: moved here from winh.c, renamed
432 *@@changed V1.0.1 (2002-11-30) [umoeller]: added support for saving window pos automatically
433 */
434
435HWND ctlCreateStdWindow(PEXTFRAMECDATA pData, // in: extended frame data
436 PHWND phwndClient) // out: created client wnd
437{
438 HWND hwndFrame;
439
440 SWP swpFrame;
441 ULONG cb = sizeof(swpFrame);
442
443 if ( (!pData->hiniSaveWinPos)
444 || (!PrfQueryProfileData(pData->hiniSaveWinPos,
445 (PSZ)pData->pcszIniApp,
446 (PSZ)pData->pcszIniKey,
447 &swpFrame,
448 &cb))
449 || (cb != sizeof(swpFrame))
450 )
451 {
452 // window pos not loaded:
453 // try to use the specified one
454 if (pData->pswpFrame)
455 memcpy(&swpFrame, pData->pswpFrame, sizeof(SWP));
456 else
457 {
458 swpFrame.hwndInsertBehind = HWND_TOP;
459 swpFrame.x = 20;
460 swpFrame.y = 20;
461 swpFrame.cx = G_cxScreen - 2 * 20;
462 swpFrame.cy = G_cyScreen - 2 * 20;
463 swpFrame.fl = SWP_MOVE | SWP_SIZE;
464 }
465 }
466
467 swpFrame.fl &= ~ SWP_SHOW | SWP_HIDE | SWP_ACTIVATE;
468
469 if (hwndFrame = winhCreateStdWindow(HWND_DESKTOP,
470 &swpFrame,
471 pData->flFrame | WS_CLIPCHILDREN,
472 pData->flStyleFrame & ~ WS_VISIBLE,
473 // do not show before we have formatted
474 // the frame correctly
475 pData->pcszFrameTitle,
476 pData->ulResourcesID,
477 pData->pcszClassClient,
478 pData->flStyleClient,
479 pData->ulID,
480 pData->pClientCtlData,
481 phwndClient))
482 {
483 PEXTFRAMEDATA pFrameData;
484
485 // subclass frame for supporting status bar and msgs
486 if (pFrameData = NEW(EXTFRAMEDATA))
487 {
488 ZERO(pFrameData),
489 memcpy(&pFrameData->CData, pData, sizeof(pFrameData->CData));
490
491 if (pFrameData->xfc.pfnwpOrig = WinSubclassWindow(hwndFrame,
492 fnwpSubclExtFrame))
493 {
494 WinSetWindowPtr(hwndFrame, QWL_USER, pFrameData);
495
496 if (pData->flExtFrame & XFCF_TOOLBAR)
497 {
498 HWND hwndControlsOwner;
499
500 // determine owner for the tool bar controls:
501 // client, if present and XFCF_FORCETBOWNER is
502 // not set
503 if ( (!(hwndControlsOwner = *phwndClient))
504 || (pData->flExtFrame & XFCF_FORCETBOWNER)
505 )
506 hwndControlsOwner = hwndFrame;
507
508 // create tool bar as frame control
509 if (pFrameData->xfc.hwndToolBar = ctlCreateToolBar(hwndFrame,
510 hwndFrame,
511 WS_VISIBLE
512 | TBS_TOOLTIPS
513 | TBS_AUTORESIZE,
514 // owner for controls:
515 // client, if it exists
516 hwndControlsOwner,
517 pData->cTBControls,
518 pData->paTBControls))
519 {
520 WinQueryWindowPos(pFrameData->xfc.hwndToolBar,
521 &swpFrame);
522 pFrameData->xfc.lToolBarHeight = swpFrame.cy;
523 }
524 }
525
526 if (pData->flExtFrame & XFCF_STATUSBAR)
527 {
528 // create status bar as frame control
529 pFrameData->xfc.hwndStatusBar = ctlCreateStatusBar(hwndFrame,
530 hwndFrame,
531 "",
532 "9.WarpSans",
533 CLR_BLACK);
534
535 pFrameData->xfc.lStatusBarHeight = STATUS_BAR_HEIGHT;
536 }
537
538 WinSendMsg(hwndFrame, WM_UPDATEFRAME, MPNULL, MPNULL);
539
540 if (pData->flStyleFrame & WS_VISIBLE)
541 WinSetWindowPos(hwndFrame,
542 HWND_TOP,
543 0,
544 0,
545 0,
546 0,
547 SWP_SHOW | SWP_ZORDER | SWP_ACTIVATE);
548 }
549 else
550 {
551 free(pFrameData);
552 WinDestroyWindow(hwndFrame);
553 hwndFrame = NULLHANDLE;
554 }
555 }
556 }
557
558 return hwndFrame;
559}
560
Note: See TracBrowser for help on using the repository browser.