-
Notifications
You must be signed in to change notification settings - Fork 0
/
TOOLBAR.C
510 lines (443 loc) · 20.9 KB
/
TOOLBAR.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
/* ********************************************************************** */
/* */
/* ToolBar Main Module */
/* */
/* This sample program implements two menu bars: a standard action bar */
/* and a "toolbar". The toolbar consists of "buttons" that can be */
/* pressed. The toolbar is actually a regular class menu whose items */
/* have the style MIS_BITMAP. The toolbar is positioned in between */
/* the standard titlebar and the standard action or menu bar. */
/* */
/* The purpose of this sample is to demonstrate subclassing the frame */
/* window to add frame controls. */
/* */
/* This code was written quickly for demonstration of a technique, not */
/* as an example of production level coding. Error checking was left */
/* out in many areas to make the code less "cluttered". The code was */
/* also written for readability, not for optimal use of resources. */
/* In other words, please don't judge it too harshly :-) */
/* */
/* DISCLAIMER OF WARRANTIES. The following [enclosed] code is */
/* sample code created by IBM Corporation. This sample code is not */
/* part of any standard or IBM product and is provided to you solely */
/* for the purpose of assisting you in the development of your */
/* applications. The code is provided "AS IS", without */
/* warranty of any kind. IBM shall not be liable for any damages */
/* arising out of your use of the sample code, even if they have been */
/* advised of the possibility of such damages. */
/* */
/* Copyright 1992, IBM Corp */
/* */
/* John D. Webb */
/* AUSVM1( V$IJOHNW ) */
/* CIS: 71075,1117 */
/* johnw@vnet.ibm.com */
/* */
/* ********************************************************************** */
#define INCL_WIN
#define INCL_GPI
#define INCL_DOS
#define INCL_DOSMISC
#define INCL_DOSERRORS
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "toolbar.h"
HAB hab;
HMQ hmq;
HWND hwndClient;
HWND hwndFrame;
HWND hwndToolBar ;
HWND hwndMenuBar ;
QMSG qmsg;
PSZ pszClassName = (PSZ) "ToolBarClass" ;
PSZ pszMainTitle = (PSZ) "ToolBar" ;
PSZ pszErrorTitle = (PSZ) "ToolBar Error" ;
/* ---------------- Prototypes ------------------------ */
MRESULT EXPENTRY MainWindowProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY NewFrameProc( HWND, ULONG, MPARAM, MPARAM );
VOID ShowErrorWindow( PSZ, BOOL );
/* ********************************************************************** */
/* */
/* Main */
/* */
/* ********************************************************************** */
int main(void)
{
if ( (hab = WinInitialize( 0L )) == (HAB) NULL ){
DosBeep( 60, 250 );
DosBeep( 120, 250 );
}
else {
if ( (hmq = WinCreateMsgQueue( hab, 0 )) == (HMQ) NULL ){
DosBeep( 60, 250 );
DosBeep( 120, 250 );
DosBeep( 60, 250 );
}
else {
ULONG fulCreate= FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER |
FCF_MINMAX | FCF_SHELLPOSITION | FCF_ICON ;
/*
* Note: no menu was specificed in create flags
*/
WinSetPointer( HWND_DESKTOP,
WinQuerySysPointer(HWND_DESKTOP,SPTR_WAIT,TRUE));
WinRegisterClass(hab, pszClassName, (PFNWP)MainWindowProc, CS_SIZEREDRAW, 0);
hwndFrame = WinCreateStdWindow(HWND_DESKTOP,
0L,
(PULONG)&fulCreate,
pszClassName ,
pszMainTitle,
0L,
(HMODULE)NULL,
ID_MAIN_WIN,
&hwndClient);
if ( hwndFrame == NULLHANDLE ) {
ShowErrorWindow( (PSZ) "Error creating Main window !", TRUE );
}
else {
PFNWP pfnwpOldFrameProc ;
/* --------- subclass frame proc ------------------ */
pfnwpOldFrameProc = WinSubclassWindow( hwndFrame,
(PFNWP) NewFrameProc );
if ( pfnwpOldFrameProc == (PFNWP)0L ){
ShowErrorWindow( (PSZ) "Error subclassing frame window !", TRUE );
}
else {
PID pid ;
SWCNTRL swCntrl;
HSWITCH hSwitch ;
/* ------- store old frame proc with handle ------- */
WinSetWindowULong( hwndFrame,
QWL_USER,
(ULONG) pfnwpOldFrameProc );
/* ------------------ load menus ------------------- */
hwndMenuBar = WinLoadMenu( hwndFrame,
(HMODULE)NULL,
MID_MENUBAR );
hwndToolBar = WinLoadMenu( hwndFrame,
(HMODULE)NULL,
MID_TOOLBAR );
/*
* Note that the last menu loaded, the toolbar, is the
* one that is associated with the frame as "the" menu.
* this means that hwndMenuBar is the only link to the
* regular action bar, so hang onto it tightly
*/
/* --------- set window size and pos -------------- */
WinSetWindowPos( hwndFrame,
HWND_TOP,
0, 0, 370, 300,
SWP_SIZE | SWP_SHOW | SWP_ACTIVATE );
/* ----------- add program to tasklist --------------- */
WinQueryWindowProcess( hwndFrame, &pid, NULL );
swCntrl.hwnd = hwndFrame ;
swCntrl.hwndIcon = (HWND) NULL ;
swCntrl.hprog = (HPROGRAM) NULL ;
swCntrl.idProcess = pid ;
swCntrl.idSession = (LONG) NULL ;
swCntrl.uchVisibility = SWL_VISIBLE ;
swCntrl.fbJump = SWL_JUMPABLE ;
strcpy( swCntrl.szSwtitle, (const char * restrict) pszMainTitle );
hSwitch = WinAddSwitchEntry((PSWCNTRL)&swCntrl);
WinSetPointer(HWND_DESKTOP,
WinQuerySysPointer(HWND_DESKTOP,SPTR_ARROW,TRUE));
/* ---------- start the main processing loop ----------- */
while (WinGetMsg(hab, &qmsg,NULLHANDLE,0,0)){
WinDispatchMsg(hab, &qmsg);
}
WinRemoveSwitchEntry( hSwitch );
} /* end of else ( pfnwpOldFrameProc ) */
WinSetPointer(HWND_DESKTOP,
WinQuerySysPointer(HWND_DESKTOP,SPTR_ARROW,TRUE));
WinDestroyWindow(hwndFrame);
} /* end of else (hwndFrame == NULLHANDLE) */
WinSetPointer(HWND_DESKTOP,
WinQuerySysPointer(HWND_DESKTOP,SPTR_ARROW,TRUE));
WinDestroyMsgQueue(hmq);
} /* end of else ( ...WinCreateMsgQueue() */
WinTerminate(hab);
} /* end of else (...WinInitialize(NULL) */
} /* end of main() */
/* ********************************************************************** */
/* */
/* MainWindowProc */
/* */
/* ********************************************************************** */
MRESULT EXPENTRY
MainWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
switch (msg) {
case WM_PAINT:
{
RECTL rectl ;
HPS hps;
hps = WinBeginPaint( hwnd, (HPS) NULL, &rectl );
WinFillRect( hps, (PRECTL)&rectl, SYSCLR_WINDOW);
WinEndPaint( hps );
}
break;
/* -------- Handle commands from *both* menus ---------- */
case WM_COMMAND :
{
switch ( SHORT1FROMMP( mp1 )){
/* ----- Toolbar items -------- */
case MID_TB_1 :
DosBeep( 440,250 ) ;
break;
case MID_TB_2 :
DosBeep( 466,250 ) ;
break;
case MID_TB_3 :
DosBeep( 494,250 ) ;
break;
case MID_TB_4 :
DosBeep( 524,250 ) ;
break;
case MID_TB_5 :
DosBeep( 550,250 ) ;
break;
case MID_TB_6 :
DosBeep( 588,250 ) ;
break;
case MID_TB_7 :
DosBeep( 624,250 ) ;
break;
case MID_TB_8 :
DosBeep( 662,250 ) ;
break;
case MID_TB_9 :
DosBeep( 701,250 ) ;
break;
case MID_TB_10:
DosBeep( 743,250 ) ;
break;
/* -------- Menu Bar items ----------- */
case MID_SUB11 :
WinMessageBox( HWND_DESKTOP,
HWND_DESKTOP,
(PCSZ) "Menu 1, Item 1 Selected",
pszMainTitle ,
0,
MB_ICONASTERISK | MB_OK );
break;
case MID_SUB21 :
WinMessageBox( HWND_DESKTOP,
HWND_DESKTOP,
(PCSZ) "Menu 2, Item 1 Selected",
pszMainTitle ,
0,
MB_ICONASTERISK | MB_OK );
break;
case MID_SUB22 :
WinMessageBox( HWND_DESKTOP,
HWND_DESKTOP,
(PCSZ) "Menu 2, Item 2 Selected",
pszMainTitle ,
0,
MB_ICONASTERISK | MB_OK );
break;
case MID_SUB31 :
WinMessageBox( HWND_DESKTOP,
HWND_DESKTOP,
(PCSZ) "Menu 3, Item 1 Selected",
pszMainTitle ,
0,
MB_ICONASTERISK | MB_OK );
break;
case MID_SUB32 :
WinMessageBox( HWND_DESKTOP,
HWND_DESKTOP,
(PCSZ) "Menu 3, Item 2 Selected",
pszMainTitle ,
0,
MB_ICONASTERISK | MB_OK );
break;
case MID_SUB33 :
WinMessageBox( HWND_DESKTOP,
HWND_DESKTOP,
(PCSZ) "Menu 3, Item 3 Selected",
pszMainTitle ,
0,
MB_ICONASTERISK | MB_OK );
break;
default:
break;
} /* end of switch */
}
break;
default:
return WinDefWindowProc(hwnd,msg,mp1,mp2);
} /* end of switch () */
return( FALSE );
} /* end of MainWindowProc */
/* ********************************************************************** */
/* */
/* NewFrameProc */
/* */
/* This frame proc subclasses the original frame proc. The two */
/* messages of interest are WM_QUERYFRAMECTLCOUNT and WM_FORMATFRAME. */
/* By catching WM_QUERYFRAMECTLCOUNT, we can return the count of the */
/* total number of frame controls, both original and new. This count */
/* is used to allocate SWP structures for the array during frame */
/* formating. When we process WM_FORMATFRAME, we first call the */
/* the original frame proc to setup the SWP array for the original */
/* frame controls. Note that among these "original" frame controls is */
/* the toolbar. We will add the regular action bar as a second menu */
/* below the toolbar. The original processing of WM_FORMATFRAME will */
/* return the count of original frame controls (note that because we */
/* modified WM_QUERYFRAMECTLCOUNT the SWP array will actually contain */
/* an extra SWP for our second menu). We will setup the SWP for our */
/* second menu based upon setting for the first menu. We will also have */
/* to adjust the client window size to make room for the additional */
/* menu. Likewise, we will need to check if there is a vertical scroll */
/* bar and adjust it. We will us a simple technique of comparing the */
/* hwnd field from the SWP array with our global variable hwnds to */
/* determine which SWP structures in the array we are interested in. */
/* */
/* ********************************************************************** */
MRESULT EXPENTRY
NewFrameProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
PFNWP pfnwpOldFrameProc ;
/* ------- get original frame procedure --------- */
pfnwpOldFrameProc = (PFNWP) WinQueryWindowULong( hwnd, QWL_USER );
switch (msg) {
case WM_QUERYFRAMECTLCOUNT :
{
ULONG usItemCount ;
/* ---- get count of original frame controls --- */
usItemCount = SHORT1FROMMR( pfnwpOldFrameProc( hwnd,
msg,
mp1, mp2 ));
/* ------- add 1 for new toolbar control ------ */
return ( (MRESULT) ++usItemCount );
}
case WM_FORMATFRAME :
{
PSWP pSWP ; // pointer to array of frame ctl SWPs
ULONG usItemCount ; // count of original frame controls
ULONG usNewMenuIndex ; // index of new menu SWP
ULONG usToolBarIndex ; // index of Tool Bar menu SWP
ULONG usClientIndex ; // index of client window SWP
ULONG usVertScrollIndex ; // index of vertical scrollbar SWP
HWND hwndVertScroll ; // hwnd of vertical scrollbar
/* ------- get a pointer to the SWP array ---------- */
pSWP = PVOIDFROMMP( mp1 );
/* ---- run regular processing for original controls --- */
/*
* Note that the original frame proc will setup all
* the SWP sturctures for the standard frame window
* controls starting at the beginning of the array.
* A count of how many SWP structures were initialized
* is returned.
* All SWP structures for new controls that are to be
* added ( in our case, 1 ) will be uninitialized and
* at the end of the array. The start of the uninitialied
* SWP structure start at an index equal to the returned
* count.
*/
usItemCount = SHORT1FROMMR( pfnwpOldFrameProc( hwnd,
msg,
mp1, mp2 ));
/* ------------- locate SWP for 1st menu ---------- */
/*
* We will use the settings of the 1st menu to help initialize
* the SWP for the second menu. We look for the proper SWP
* by scanning the array for the matching hwnd.
*/
for ( usToolBarIndex = 0;
usToolBarIndex < usItemCount;
usToolBarIndex++) {
if (pSWP[usToolBarIndex].hwnd == hwndToolBar){
break;
}
} // end of for( usToolBarIndex...
/* ------------- locate SWP for client window ---------- */
/*
* We will need to adjust the vertical height of the client
* window to make room for the second menu. We look for the
* proper SWP by scanning the array for a matching hwnd.
*/
for ( usClientIndex = 0;
usClientIndex < usItemCount;
usClientIndex++){
if (pSWP[usClientIndex].hwnd == hwndClient ){
break;
}
} // end of for ( usClientIndex...
/* --- locate SWP for vert scroll (if exists) --- */
/*
* First we will check if this window has a vert. scroll bar.
* We will need to adjust the vertical height of the scroll
* bar to make room for the second menu. We look for the
* proper SWP by scanning the array for a matching hwnd.
*/
if ( ( hwndVertScroll =
WinWindowFromID( hwnd, FID_VERTSCROLL)) != NULLHANDLE ){
for ( usVertScrollIndex = 0;
usVertScrollIndex < usItemCount;
usVertScrollIndex++){
if (pSWP[usVertScrollIndex].hwnd == hwndVertScroll ){
break;
}
} // end of for ( usClientIndex...
} // end of if (( hwndVertScroll...
/* ------ the new SWP starts after standard control SWPs ----- */
usNewMenuIndex = usItemCount ;
/* ---- get size values for 2nd menu bar -------- */
pSWP[ usNewMenuIndex ].fl = SWP_SIZE;
pSWP[ usNewMenuIndex ].cx = pSWP[usToolBarIndex].cx ; // set some
pSWP[ usNewMenuIndex ].cy = pSWP[usToolBarIndex].cy ; // defaults
pSWP[ usNewMenuIndex ].hwndInsertBehind = HWND_TOP ;
pSWP[ usNewMenuIndex ].hwnd = hwndMenuBar ;
/* -- get the menu code to make the actual size adjustments -- */
WinSendMsg( hwndMenuBar,
WM_ADJUSTWINDOWPOS,
MPFROMP( pSWP+usNewMenuIndex ),
(MPARAM) 0L );
/* ------ position menu directly below other menu ------- */
pSWP[usNewMenuIndex].x = pSWP[usToolBarIndex].x ;
pSWP[usNewMenuIndex].y = pSWP[usToolBarIndex].y -
pSWP[usNewMenuIndex].cy ;
pSWP[usNewMenuIndex].fl = pSWP[usToolBarIndex].fl ;
/* -------- adjust client window size for 2nd menu ------- */
pSWP[usClientIndex].cy -= pSWP[usNewMenuIndex].cy ;
/* -------- adjust vertical scroll size for 2nd menu ----- */
if ( hwndVertScroll != NULLHANDLE ){
pSWP[usVertScrollIndex].cy -= pSWP[usNewMenuIndex].cy ;
}
/* --- return total count of controls ( +1 for 2nd menu ) --- */
return( MRFROMSHORT( ++usItemCount ) );
}
break;
default:
return( pfnwpOldFrameProc(hwnd,msg,mp1,mp2) );
} /* end of switch () */
return( FALSE );
} /* end of NewFrameProc */
/* ********************************************************************** */
/* */
/* ShowErrorWindow */
/* */
/* ********************************************************************** */
VOID
ShowErrorWindow( PSZ pszErrorMsg, BOOL bUseLastError )
{
CHAR acErrorBuffer[256] ;
if ( bUseLastError ) {
ERRORID errorID = WinGetLastError( hab );
sprintf( acErrorBuffer,
"%s \n(code = 0x%lX)",
pszErrorMsg,
(ULONG) errorID );
pszErrorMsg = (PSZ) acErrorBuffer ;
} /* end of if ( bUseLastError ) */
WinMessageBox( HWND_DESKTOP,
HWND_DESKTOP,
pszErrorMsg ,
pszErrorTitle ,
0,
MB_CUACRITICAL | MB_OK );
}