1 |
|
---|
2 | /*
|
---|
3 | *@@sourcefile shapewin.c:
|
---|
4 | * contains helper functions for "shaped" PM windows which
|
---|
5 | * can be non-rectangular in shape and have transparency.
|
---|
6 | *
|
---|
7 | * This file is new with V0.85.
|
---|
8 | *
|
---|
9 | * Usage: All PM programs.
|
---|
10 | *
|
---|
11 | * Function prefixes:
|
---|
12 | * -- shp* shape window functions
|
---|
13 | *
|
---|
14 | * This file consists of two parts:
|
---|
15 | *
|
---|
16 | * *** Part 1 ***
|
---|
17 | *
|
---|
18 | * The code in Part 1 implements the "Shape" window. This is used
|
---|
19 | * to display a bitmap on the screen with transparency.
|
---|
20 | *
|
---|
21 | * Really, it is not the "Shape" window which displays the bitmap.
|
---|
22 | * Since PM can only handle rectangular windows, as many subwindows
|
---|
23 | * as required are created, which are only managed by the (invisible)
|
---|
24 | * "Shape" window.
|
---|
25 | *
|
---|
26 | * See shp_fnwpShapeMgr for a window hierarchy.
|
---|
27 | *
|
---|
28 | * If you are not using the frame window functions in Part 2, the
|
---|
29 | * shape window class must be registered like this (the declarations
|
---|
30 | * are in shapewin.h):
|
---|
31 | *
|
---|
32 | + WinRegisterClass(
|
---|
33 | + hab, // anchor block handle
|
---|
34 | + SHAPE_WINDOW_CLASS, // class name (shapewin.h)
|
---|
35 | + shp_fnwpShapeMgr, // window procedure (in this file)
|
---|
36 | + 0L, // default window style
|
---|
37 | + sizeof(PVOID)) ; // class data size
|
---|
38 | *
|
---|
39 | * You can then create shape windows using WinCreateWindow():
|
---|
40 | + hwndShape = WinCreateWindow(
|
---|
41 | + hwndParent, // see remark (2)
|
---|
42 | + SHAPE_WINDOW_CLASS, // class name (shapewin.h)
|
---|
43 | + pszName, // doesn't matter
|
---|
44 | + flStyle, // can be 0
|
---|
45 | + x, y, cx, cy, // can all be 0; shape window
|
---|
46 | + // size depends on bitmap
|
---|
47 | + hwndOwner, // see remark (2)
|
---|
48 | + hwndInsertBehind, // should be HWND_TOP
|
---|
49 | + id,
|
---|
50 | + pCtlData, // *SHPCTLDATA, see remark (1)
|
---|
51 | + pPresParams); // NULL
|
---|
52 | *
|
---|
53 | * Remarks:
|
---|
54 | *
|
---|
55 | * 1) Shape windows _require_ a SHPCTLDATA structure for input with
|
---|
56 | * the pCtlData parameter of WinCreateWindow. This structure
|
---|
57 | * must contain the following:
|
---|
58 | + SHORT cx, cy ; // bitmap size
|
---|
59 | + HPS hpsMask; // HPS with bitmap selected into
|
---|
60 | + HPS hpsDraw; // HPS used for drawing the bitmap
|
---|
61 | *
|
---|
62 | * Note that the bitmap in hpsMask determines the drawing mask
|
---|
63 | * of the bitmap, while the bitmap in hpsDraw determines the
|
---|
64 | * bitmap to be drawn. You can use the same HPS (and thus
|
---|
65 | * the same bitmap) for both, but you can also use different
|
---|
66 | * ones.
|
---|
67 | *
|
---|
68 | * You _must_ select the bitmap(s) to be displayed into the HPS's,
|
---|
69 | * using GpiSetBitmap, or nothing will work. shpLoadBitmap
|
---|
70 | * in Part 2 of this file offers you a one-shot function for
|
---|
71 | * loading a bitmap either from resources or a PM 1.3 *.BMP
|
---|
72 | * file.
|
---|
73 | *
|
---|
74 | * Transparency is determined according to the most lower-left
|
---|
75 | * pixel of the bitmap in hpsMask. That is, all hpsDraw bitmap
|
---|
76 | * pixels which have the same color as hpsMask pixel (0, 0)
|
---|
77 | * will be made transparent.
|
---|
78 | *
|
---|
79 | * During window creation, the shape window analyzes the bitmap
|
---|
80 | * which was selected into hpsMask and creates lots of rectangular
|
---|
81 | * PM windows as neccessary. This is dependent of the
|
---|
82 | * "transparency" pixels of the bitmap.
|
---|
83 | *
|
---|
84 | * There is no limit for the size of the bitmap (in the HPS's).
|
---|
85 | * But you should be very careful with large bitmaps, because
|
---|
86 | * this can block the system forever. Shape windows are real
|
---|
87 | * CPU hogs. The number of PM subwindows created depends on the
|
---|
88 | * size of the bitmap and on the transparency. The calculations
|
---|
89 | * are line-based:
|
---|
90 | * -- each line is examined, and a PM window is created for
|
---|
91 | * each line of the input bitmap;
|
---|
92 | * -- if this line contains "transparency" pixels, more PM
|
---|
93 | * windows are created accordingly for that line.
|
---|
94 | * -- However, if several vertically adjacent subwindows have
|
---|
95 | * the same left and right coordinates, they are combined
|
---|
96 | * into one window.
|
---|
97 | *
|
---|
98 | * As a result, the more single transparent pixels you have,
|
---|
99 | * the more windows need to be created. The more rectangular
|
---|
100 | * transparent areas you have, the less windows need to be
|
---|
101 | * created.
|
---|
102 | *
|
---|
103 | * 2) The "Shape" window requires both a parent and an owner window.
|
---|
104 | * As always, the parent window determines the visibility, while
|
---|
105 | * the owner window requires a more abstract relationship. With
|
---|
106 | * shape windows, the owner window is important because all the
|
---|
107 | * input messages (for mouse and keyboard input) are forwarded
|
---|
108 | * to the owner.
|
---|
109 | *
|
---|
110 | * So it's best to set the parent to HWND_DESKTOP and specify
|
---|
111 | * a frame window for the owner. If you don't already have a
|
---|
112 | * frame window in your application, you can create an invisible
|
---|
113 | * frame window just for message handling. That's what the shp*
|
---|
114 | * functions in Part 2 of this file do (Akira Hatakeyama calls
|
---|
115 | * this the "Voodoo" feature).
|
---|
116 | *
|
---|
117 | * Never use the shape window itself as a top-level window,
|
---|
118 | * but one of your own windows instead, which own the shape
|
---|
119 | * window.
|
---|
120 | *
|
---|
121 | * Note that the keyboard and mouse input messages which are
|
---|
122 | * forwarded to the owner contain mouse coordinates relative
|
---|
123 | * to the rectangular shape subwindow which actually received
|
---|
124 | * the message, not relative to the frame window. So you better
|
---|
125 | * determine the real mouse position using WinQueryPointerPos().
|
---|
126 | *
|
---|
127 | * Note that the size of the shape window is defined once upon
|
---|
128 | * creation and cannot be changed later because this would conflict
|
---|
129 | * with all the subwindows which were created. For the same reason,
|
---|
130 | * you cannot alter the bitmap of the shape window after creation.
|
---|
131 | * You must create a second shape bitmap for that.
|
---|
132 | * Thus all the size parameters in WinSetWindowPos are swallowed and
|
---|
133 | * ignored.
|
---|
134 | *
|
---|
135 | * *** Part 2 ***
|
---|
136 | *
|
---|
137 | * This implements a proper invisible frame window for displaying
|
---|
138 | * shaped bitmap windows directly on the desktop.
|
---|
139 | * See shpCreateWindows for a working example.
|
---|
140 | *
|
---|
141 | * Note: Version numbering in this file relates to XWorkplace version
|
---|
142 | * numbering.
|
---|
143 | *
|
---|
144 | *@@header "helpers\shapewin.h"
|
---|
145 | */
|
---|
146 |
|
---|
147 | /*
|
---|
148 | * Credits:
|
---|
149 | * 1) Functions for shaped windows.
|
---|
150 | * This is based on the ShapeWin library 1.01 (SHAPEWIN.ZIP at
|
---|
151 | * Hobbes), (C) 1998, 1999 Software Research Associates, Inc.
|
---|
152 | * This has been written by Akira Hatakeyama (akira@sra.co.jp).
|
---|
153 | * Updated by Takayuki Suwa (jjsuwa@ibm.net).
|
---|
154 | * The original was placed under the GPL.
|
---|
155 | *
|
---|
156 | * Changes made by Ulrich Mller (February 1999):
|
---|
157 | * -- some speedup (marked with *UM)
|
---|
158 | * -- renamed and commented out almost all of the functions
|
---|
159 | * and structures to make their use more lucid.
|
---|
160 | *
|
---|
161 | * 2) Functions for easily creating shape frame windows from a
|
---|
162 | * given HBITMAP. This has been written by me, after getting
|
---|
163 | * some inspiration from the sample programs in SHAPEWIN.ZIP.
|
---|
164 | *
|
---|
165 | * Copyright (C) 1998-2000
|
---|
166 | * Ulrich Mller,
|
---|
167 | * Akira Hatakeyama,
|
---|
168 | * Takayuki Suwa.
|
---|
169 | * This file is part of the XWorkplace source package.
|
---|
170 | * XWorkplace is free software; you can redistribute it and/or modify
|
---|
171 | * it under the terms of the GNU General Public License as published
|
---|
172 | * by the Free Software Foundation, in version 2 as it comes in the
|
---|
173 | * "COPYING" file of the XWorkplace main distribution.
|
---|
174 | * This program is distributed in the hope that it will be useful,
|
---|
175 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
176 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
177 | * GNU General Public License for more details.
|
---|
178 | *
|
---|
179 | */
|
---|
180 |
|
---|
181 | #define OS2EMX_PLAIN_CHAR
|
---|
182 | // this is needed for "os2emx.h"; if this is defined,
|
---|
183 | // emx will define PSZ as _signed_ char, otherwise
|
---|
184 | // as unsigned char
|
---|
185 |
|
---|
186 | #define INCL_DOS
|
---|
187 | #define INCL_DOSERRORS
|
---|
188 | #define INCL_WIN
|
---|
189 | #define INCL_WINSYS
|
---|
190 | #define INCL_GPILOGCOLORTABLE
|
---|
191 | #define INCL_GPIPRIMITIVES
|
---|
192 | #define INCL_GPIBITMAPS
|
---|
193 | #include <os2.h>
|
---|
194 |
|
---|
195 | #include <stdlib.h>
|
---|
196 | #include <stdio.h>
|
---|
197 | #include <string.h>
|
---|
198 |
|
---|
199 | #include "setup.h" // code generation and debugging options
|
---|
200 |
|
---|
201 | #include "helpers\gpih.h"
|
---|
202 | #include "helpers\shapewin.h"
|
---|
203 |
|
---|
204 | #pragma hdrstop
|
---|
205 |
|
---|
206 | /*
|
---|
207 | *@@category: Helpers\PM helpers\Window classes\Shaped windows (transparency)
|
---|
208 | */
|
---|
209 |
|
---|
210 | /* ******************************************************************
|
---|
211 | * *
|
---|
212 | * Global variables *
|
---|
213 | * *
|
---|
214 | ********************************************************************/
|
---|
215 |
|
---|
216 | BOOL G_ShapeRegisteredRegion = FALSE;
|
---|
217 |
|
---|
218 | /* ******************************************************************
|
---|
219 | * *
|
---|
220 | * Part 1: Shape window functions *
|
---|
221 | * *
|
---|
222 | ********************************************************************/
|
---|
223 |
|
---|
224 | // forward declarations for structures, because
|
---|
225 | // the structures are referenced from each other
|
---|
226 | typedef struct _SHPWINCTLDATA *PSHPWINCTLDATA;
|
---|
227 | typedef struct _SHPREGION *PSHPREGION;
|
---|
228 |
|
---|
229 | /*
|
---|
230 | * SHPWINCTLDATA:
|
---|
231 | * internal shape window control data.
|
---|
232 | * This is the shape-window-internal structure
|
---|
233 | * to allow the shape window to manage itself.
|
---|
234 | * This is created in WM_CREATE with the data
|
---|
235 | * passed in the mp1 and mp2 parameters
|
---|
236 | * (CREATESTRUCT and SHPCTLDATA).
|
---|
237 | * This is stored in a shape window's window words.
|
---|
238 | */
|
---|
239 |
|
---|
240 | typedef struct _SHPWINCTLDATA
|
---|
241 | {
|
---|
242 | // common window parameters
|
---|
243 | // (copied from CREATESTRUCT in WM_CREATE)
|
---|
244 | HWND hwndShape ; // main shape window handle
|
---|
245 | HWND hwndParent; // shape window's parent (should be HWND_DESKTOP)
|
---|
246 | HWND hwndOwner ; // shape window's owner, to whom we'll forward all
|
---|
247 | // all the input messages
|
---|
248 | USHORT id ; // window ID
|
---|
249 | SHORT x ; // x - horz. position
|
---|
250 | SHORT y ; // y - vert. position
|
---|
251 | SHORT cx ; // horz. size
|
---|
252 | SHORT cy ; // vert. size
|
---|
253 | PSZ pszText ; // window text
|
---|
254 |
|
---|
255 | // additional window parameters
|
---|
256 | HPS hpsDraw; // the input HPS with the bitmap
|
---|
257 | ULONG nRegion; // number of "regions"
|
---|
258 | PSHPREGION aRegion; // array of "regions"
|
---|
259 |
|
---|
260 | } SHPWINCTLDATA;
|
---|
261 |
|
---|
262 | /*
|
---|
263 | * SHPREGION:
|
---|
264 | * this is the structure for shape window
|
---|
265 | * "regions". Note that has nothing to do
|
---|
266 | * with GPI regions, but is simply a structure
|
---|
267 | * for each rectangular area in the shape
|
---|
268 | * window's bitmap which can be displayed
|
---|
269 | * as a rectangular PM window.
|
---|
270 | */
|
---|
271 |
|
---|
272 | typedef struct _SHPREGION
|
---|
273 | {
|
---|
274 | PSHPWINCTLDATA pCtrl; // link to parent
|
---|
275 | HWND hwnd ; // drawing window
|
---|
276 | RECTL rect ; // rectangle of sub-bitmap
|
---|
277 | } SHPREGION;
|
---|
278 |
|
---|
279 | /*
|
---|
280 | * SHPSPAN:
|
---|
281 | * this is a temporary structure used during
|
---|
282 | * the creation of SHPREGION's from the
|
---|
283 | * input bitmap.
|
---|
284 | */
|
---|
285 |
|
---|
286 | typedef struct _SHPSPAN {
|
---|
287 | ULONG nSize ;
|
---|
288 | ULONG nUsed ;
|
---|
289 | RECTL aSpan[1];
|
---|
290 | } SHPSPAN, *PSHPSPAN;
|
---|
291 |
|
---|
292 | // the following defines how many SHPSPAN structures
|
---|
293 | // will be initially created and afterwards for span
|
---|
294 | // expansions by spanExpand
|
---|
295 | #define SPAN_ALLOC_STEP 1024
|
---|
296 |
|
---|
297 | /*
|
---|
298 | * spanFree:
|
---|
299 | *
|
---|
300 | */
|
---|
301 |
|
---|
302 | void spanFree(PSHPSPAN pSpan)
|
---|
303 | {
|
---|
304 | if (pSpan != NULL)
|
---|
305 | free(pSpan);
|
---|
306 | }
|
---|
307 |
|
---|
308 | /*
|
---|
309 | * spanCreate:
|
---|
310 | * this creates SPAN_ALLOC_STEP SHPSPAN structures.
|
---|
311 | */
|
---|
312 |
|
---|
313 | PSHPSPAN spanCreate(void)
|
---|
314 | {
|
---|
315 | PSHPSPAN pSpan;
|
---|
316 | int len ;
|
---|
317 |
|
---|
318 | len = sizeof(SHPSPAN) + sizeof(RECTL) * SPAN_ALLOC_STEP;
|
---|
319 |
|
---|
320 | if ((pSpan = (PSHPSPAN)malloc(len)) == NULL)
|
---|
321 | return NULL;
|
---|
322 |
|
---|
323 | memset(pSpan, 0, len);
|
---|
324 | pSpan->nSize = SPAN_ALLOC_STEP;
|
---|
325 | pSpan->nUsed = 0 ;
|
---|
326 | return pSpan;
|
---|
327 | }
|
---|
328 |
|
---|
329 | /*
|
---|
330 | * spanExpand:
|
---|
331 | * this expands the memory used for the SHPSPAN
|
---|
332 | * structures if more spans need to be appended.
|
---|
333 | * Another SPAN_ALLOC_STEP SHPSPAN structures are created.
|
---|
334 | */
|
---|
335 |
|
---|
336 | PSHPSPAN spanExpand(PSHPSPAN pOld)
|
---|
337 | {
|
---|
338 | PSHPSPAN pNew;
|
---|
339 | int len ;
|
---|
340 |
|
---|
341 | // TRACE("spanExpand\n");
|
---|
342 |
|
---|
343 | len = sizeof(SHPSPAN) + sizeof(RECTL) * (pOld->nSize + SPAN_ALLOC_STEP);
|
---|
344 |
|
---|
345 | if ((pNew = (PSHPSPAN)malloc(len)) == NULL)
|
---|
346 | return NULL;
|
---|
347 |
|
---|
348 | memset(pNew, 0, len);
|
---|
349 | pNew->nSize = pOld->nSize + SPAN_ALLOC_STEP;
|
---|
350 | pNew->nUsed = pOld->nUsed;
|
---|
351 | memcpy(pNew->aSpan, pOld->aSpan, sizeof(RECTL) * pOld->nUsed);
|
---|
352 | spanFree(pOld);
|
---|
353 |
|
---|
354 | return pNew;
|
---|
355 | }
|
---|
356 |
|
---|
357 | /*
|
---|
358 | * spanAppend:
|
---|
359 | * this adds a new SHPSPAN to the list of spans.
|
---|
360 | *
|
---|
361 | */
|
---|
362 |
|
---|
363 | PSHPSPAN spanAppend(PSHPSPAN pSpan,
|
---|
364 | int y, // bottom y; top y = y+1
|
---|
365 | int x1, // left x
|
---|
366 | int x2) // right x
|
---|
367 | {
|
---|
368 | int i;
|
---|
369 | PRECTL p;
|
---|
370 | PSHPSPAN pNew;
|
---|
371 |
|
---|
372 | // TRACE("spanAppend %d (%d %d)\n", y, x1, x2);
|
---|
373 |
|
---|
374 | /*
|
---|
375 | * check if continuous one
|
---|
376 | */
|
---|
377 |
|
---|
378 | for (i = 0; i < pSpan->nUsed; i++) {
|
---|
379 | p = &pSpan->aSpan[i];
|
---|
380 | if (p->yTop == y && p->xLeft == x1 && p->xRight == x2)
|
---|
381 | {
|
---|
382 | p->yTop += 1;
|
---|
383 | return pSpan; // merged
|
---|
384 | }
|
---|
385 | }
|
---|
386 |
|
---|
387 | /*
|
---|
388 | * if not enough space, expand
|
---|
389 | */
|
---|
390 |
|
---|
391 | if ((pSpan->nUsed + 1) >= pSpan->nSize)
|
---|
392 | {
|
---|
393 | if ((pNew = spanExpand(pSpan)) == NULL)
|
---|
394 | return NULL;
|
---|
395 |
|
---|
396 | pSpan = pNew;
|
---|
397 | }
|
---|
398 |
|
---|
399 | /*
|
---|
400 | * append a rectangle
|
---|
401 | */
|
---|
402 |
|
---|
403 | pSpan->aSpan[pSpan->nUsed].yTop = y + 1;
|
---|
404 | pSpan->aSpan[pSpan->nUsed].yBottom = y ;
|
---|
405 | pSpan->aSpan[pSpan->nUsed].xLeft = x1;
|
---|
406 | pSpan->aSpan[pSpan->nUsed].xRight = x2;
|
---|
407 | pSpan->nUsed += 1;
|
---|
408 |
|
---|
409 | return pSpan;
|
---|
410 | }
|
---|
411 |
|
---|
412 | #ifdef SHPDEBUG
|
---|
413 |
|
---|
414 | /*
|
---|
415 | * ptisin:
|
---|
416 | *
|
---|
417 | */
|
---|
418 |
|
---|
419 | BOOL ptisin(PSHPSPAN pSpan, int x, int y)
|
---|
420 | {
|
---|
421 | int i;
|
---|
422 |
|
---|
423 | for (i = 0; i < pSpan->nUsed; i++)
|
---|
424 | {
|
---|
425 | if (y >= pSpan->aSpan[i].yTop) {
|
---|
426 | continue;
|
---|
427 | }
|
---|
428 | if (y < pSpan->aSpan[i].yBottom) {
|
---|
429 | continue;
|
---|
430 | }
|
---|
431 | if (x < pSpan->aSpan[i].xLeft) {
|
---|
432 | continue;
|
---|
433 | }
|
---|
434 | if (x >= pSpan->aSpan[i].xRight) {
|
---|
435 | continue;
|
---|
436 | }
|
---|
437 | return TRUE;
|
---|
438 | }
|
---|
439 | return FALSE;
|
---|
440 | }
|
---|
441 |
|
---|
442 | /*
|
---|
443 | * dumpSpan:
|
---|
444 | *
|
---|
445 | */
|
---|
446 |
|
---|
447 | void dumpSpan(PSHPSPAN pSpan)
|
---|
448 | {
|
---|
449 | int i, maxx, maxy, x, y;
|
---|
450 |
|
---|
451 | TRACE("dumpSpan %d\n", pSpan->nUsed);
|
---|
452 |
|
---|
453 | maxx = maxy = 0;
|
---|
454 |
|
---|
455 | for (i = 0; i < pSpan->nUsed; i++)
|
---|
456 | {
|
---|
457 | if (pSpan->aSpan[i].yTop > maxy)
|
---|
458 | {
|
---|
459 | maxy = pSpan->aSpan[i].yTop;
|
---|
460 | }
|
---|
461 | if (pSpan->aSpan[i].xRight > maxx)
|
---|
462 | {
|
---|
463 | maxx = pSpan->aSpan[i].xRight;
|
---|
464 | }
|
---|
465 | }
|
---|
466 |
|
---|
467 | for (y = maxy - 1; y >= 0; y--)
|
---|
468 | {
|
---|
469 | printf("%03d : ", y);
|
---|
470 | for (x = 0; x < maxx; x++)
|
---|
471 | {
|
---|
472 | if (ptisin(pSpan, x, y))
|
---|
473 | printf("#");
|
---|
474 | else
|
---|
475 | printf("_");
|
---|
476 | }
|
---|
477 | printf("\n");
|
---|
478 | }
|
---|
479 | }
|
---|
480 |
|
---|
481 | #endif // SHPDEBUG
|
---|
482 |
|
---|
483 | /*
|
---|
484 | * shprgnDraw:
|
---|
485 | * this gets called upon receiving WM_PAINT in
|
---|
486 | * shp_fnwpShapeRegion. We simply draw the
|
---|
487 | * subrectangle from the shape window's bitmap
|
---|
488 | * which corresponds to our region rectangle.
|
---|
489 | */
|
---|
490 |
|
---|
491 | void shprgnDraw(HPS hps, PSHPREGION pRgn)
|
---|
492 | {
|
---|
493 | POINTL apt[3];
|
---|
494 |
|
---|
495 | apt[0].x = 0;
|
---|
496 | apt[0].y = 0;
|
---|
497 | apt[1].x = (pRgn->rect.xRight - pRgn->rect.xLeft);
|
---|
498 | apt[1].y = (pRgn->rect.yTop - pRgn->rect.yBottom);
|
---|
499 | apt[2].x = pRgn->rect.xLeft ;
|
---|
500 | apt[2].y = pRgn->rect.yBottom;
|
---|
501 | GpiBitBlt(hps, pRgn->pCtrl->hpsDraw, 3, apt, ROP_SRCCOPY, 0);
|
---|
502 | }
|
---|
503 |
|
---|
504 | /*
|
---|
505 | *@@ shp_fnwpShapeRegion:
|
---|
506 | * this is the window procedure for each of the
|
---|
507 | * shape window's rectangular subwindows.
|
---|
508 | *
|
---|
509 | * See shp_fnwpShapeMgr for a window hierarchy.
|
---|
510 | */
|
---|
511 |
|
---|
512 | MRESULT EXPENTRY shp_fnwpShapeRegion(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
|
---|
513 | {
|
---|
514 | PSHPREGION pRgn;
|
---|
515 | HPS hps ;
|
---|
516 |
|
---|
517 | pRgn = (PSHPREGION) WinQueryWindowPtr(hwnd, 0);
|
---|
518 |
|
---|
519 | switch (msg)
|
---|
520 | {
|
---|
521 | /*
|
---|
522 | * WM_CREATE:
|
---|
523 | * store the SHPREGION pointer in our
|
---|
524 | * window words.
|
---|
525 | */
|
---|
526 |
|
---|
527 | case WM_CREATE:
|
---|
528 | // TRACE("WM_CREATE\n");
|
---|
529 | pRgn = (PSHPREGION)PVOIDFROMMP(mp1);
|
---|
530 | WinSetWindowPtr(hwnd, 0, (PVOID) pRgn);
|
---|
531 | return (MRESULT) FALSE;
|
---|
532 |
|
---|
533 | /*
|
---|
534 | * WM_PAINT:
|
---|
535 | * draw our subrectangle of the main bitmap.
|
---|
536 | */
|
---|
537 |
|
---|
538 | case WM_PAINT:
|
---|
539 | // TRACE("WM_PAINT (%d %d) (%d %d)\n", pRgn->rect.yBottom, pRgn->rect.xLeft, pRgn->rect.yTop, pRgn->rect.xRight);
|
---|
540 | hps = WinBeginPaint(hwnd, NULLHANDLE, NULL);
|
---|
541 | shprgnDraw(hps, pRgn);
|
---|
542 | WinEndPaint(hps) ;
|
---|
543 | return (MRESULT) 0;
|
---|
544 |
|
---|
545 | case WM_MOUSEMOVE :
|
---|
546 | case WM_BUTTON1DOWN :
|
---|
547 | case WM_BUTTON1UP :
|
---|
548 | case WM_BUTTON1CLICK :
|
---|
549 | case WM_BUTTON1DBLCLK:
|
---|
550 | case WM_BUTTON2DOWN :
|
---|
551 | case WM_BUTTON2UP :
|
---|
552 | case WM_BUTTON2CLICK :
|
---|
553 | case WM_BUTTON2DBLCLK:
|
---|
554 | case WM_BUTTON3DOWN :
|
---|
555 | case WM_BUTTON3UP :
|
---|
556 | case WM_BUTTON3CLICK :
|
---|
557 | case WM_BUTTON3DBLCLK:
|
---|
558 | case WM_CHAR :
|
---|
559 | case WM_VIOCHAR :
|
---|
560 | case WM_BEGINDRAG :
|
---|
561 | case WM_ENDDRAG :
|
---|
562 | case WM_SINGLESELECT :
|
---|
563 | case WM_OPEN :
|
---|
564 | case WM_CONTEXTMENU :
|
---|
565 | case WM_CONTEXTHELP :
|
---|
566 | case WM_TEXTEDIT :
|
---|
567 | case WM_BEGINSELECT :
|
---|
568 | case WM_ENDSELECT :
|
---|
569 | // forward all these to the shape window
|
---|
570 | return WinSendMsg(pRgn->pCtrl->hwndShape, msg, mp1, mp2);
|
---|
571 | }
|
---|
572 | return WinDefWindowProc(hwnd, msg, mp1, mp2);
|
---|
573 | }
|
---|
574 |
|
---|
575 | /*
|
---|
576 | * shpmgrWMAdjustWindowPos:
|
---|
577 | * adjust the region windows' positions, visibility etc.
|
---|
578 | * by going thru the whole region windows list and
|
---|
579 | * repositioning all the windows.
|
---|
580 | * This gets called upon receiving WM_ADJUSTWINDOWPOS
|
---|
581 | * in shp_fnwpShapeMgr.
|
---|
582 | */
|
---|
583 |
|
---|
584 | int shpmgrWMAdjustWindowPos(PSHPWINCTLDATA pCtrl, PSWP pSwp)
|
---|
585 | {
|
---|
586 | int i ;
|
---|
587 | PSHPREGION pRgn;
|
---|
588 | ULONG fl ;
|
---|
589 | // HPS hps ;
|
---|
590 |
|
---|
591 | PSWP pswpArray;
|
---|
592 |
|
---|
593 | // TRACE("shpmgrWMAdjustWindowPos - %d, %08x\n", pCtrl->nRegion, pSwp->fl);
|
---|
594 |
|
---|
595 | if (pCtrl->nRegion == 0 || pCtrl->aRegion == NULL)
|
---|
596 | {
|
---|
597 | // TRACE("ShpDrawRegion - no region to open\n");
|
---|
598 | return -1;
|
---|
599 | }
|
---|
600 |
|
---|
601 | if ((fl = pSwp->fl) & SWP_MOVE)
|
---|
602 | {
|
---|
603 | pCtrl->x = pSwp->x;
|
---|
604 | pCtrl->y = pSwp->y;
|
---|
605 | }
|
---|
606 |
|
---|
607 | pswpArray = (PSWP) malloc(sizeof(SWP) * pCtrl->nRegion);
|
---|
608 |
|
---|
609 | // go thru all the "regions" and adjust their sizes
|
---|
610 | for (i = 0, pRgn = pCtrl->aRegion;
|
---|
611 | i < pCtrl->nRegion;
|
---|
612 | i++, pRgn++)
|
---|
613 | {
|
---|
614 | pswpArray[i].fl = fl;
|
---|
615 | pswpArray[i].cy = (pRgn->rect.yTop - pRgn->rect.yBottom);
|
---|
616 | pswpArray[i].cx = (pRgn->rect.xRight - pRgn->rect.xLeft);
|
---|
617 | pswpArray[i].y = (pCtrl->y + pRgn->rect.yBottom);
|
---|
618 | pswpArray[i].x = (pCtrl->x + pRgn->rect.xLeft);
|
---|
619 | pswpArray[i].hwndInsertBehind = pSwp->hwndInsertBehind;
|
---|
620 | pswpArray[i].hwnd = pRgn->hwnd;
|
---|
621 | }
|
---|
622 |
|
---|
623 | // set all window positions at once
|
---|
624 | WinSetMultWindowPos(WinQueryAnchorBlock(pCtrl->hwndShape),
|
---|
625 | &pswpArray[0],
|
---|
626 | pCtrl->nRegion);
|
---|
627 | free((void*) pswpArray);
|
---|
628 |
|
---|
629 | // calling WinInvalidateRect is not neccessary,
|
---|
630 | // because the windows' update regions are already
|
---|
631 | // properly set by WinSetMultWindowPos (*UM)
|
---|
632 |
|
---|
633 | /* for (i = 0, pRgn = pCtrl->aRegion;
|
---|
634 | i < pCtrl->nRegion;
|
---|
635 | i++, pRgn++)
|
---|
636 | {
|
---|
637 | if (fl & (SWP_MOVE | SWP_ZORDER)) {
|
---|
638 | WinInvalidateRect(pRgn->hwnd, NULL, FALSE);
|
---|
639 | }
|
---|
640 | } */
|
---|
641 | return 0;
|
---|
642 | }
|
---|
643 |
|
---|
644 | /*
|
---|
645 | * shpmgrUpdateRegions:
|
---|
646 | * this gets called by shp_fnwpShapeMgr upon receiving
|
---|
647 | * SHAPEWIN_MSG_UPDATE.
|
---|
648 | */
|
---|
649 |
|
---|
650 | int shpmgrUpdateRegions(PSHPWINCTLDATA pCtrl, PRECTL pRect)
|
---|
651 | {
|
---|
652 | RECTL rect, intern;
|
---|
653 | int i ;
|
---|
654 | PSHPREGION pRgn;
|
---|
655 | HAB hab ;
|
---|
656 | // HPS hps ;
|
---|
657 |
|
---|
658 | // TRACE("shpmgrUpdateRegions\n");
|
---|
659 |
|
---|
660 | hab = WinQueryAnchorBlock(pCtrl->hwndShape);
|
---|
661 |
|
---|
662 | if (pRect == NULL) {
|
---|
663 | rect.xLeft = 0 ;
|
---|
664 | rect.yBottom = 0 ;
|
---|
665 | rect.xRight = pCtrl->cx;
|
---|
666 | rect.yTop = pCtrl->cy;
|
---|
667 | pRect = ▭
|
---|
668 | }
|
---|
669 | for (i = 0, pRgn = pCtrl->aRegion; i < pCtrl->nRegion; i++, pRgn++)
|
---|
670 | {
|
---|
671 | if (WinIntersectRect(hab, &intern, pRect, &pRgn->rect) == FALSE) {
|
---|
672 | continue;
|
---|
673 | } else {
|
---|
674 | WinInvalidateRect(pRgn->hwnd, NULL, FALSE);
|
---|
675 | }
|
---|
676 | }
|
---|
677 | return 0;
|
---|
678 | }
|
---|
679 |
|
---|
680 | /*
|
---|
681 | * shpmgrParseBitmap:
|
---|
682 | * this gets called from shpmgrWMCreate_Bitmap2Regions when the
|
---|
683 | * shape region windows need to be created.
|
---|
684 | * This function does the actual bitmap analysis and
|
---|
685 | * creates a large number of SHPSPAN structures according
|
---|
686 | * to the bitmaps, which can later be turned into
|
---|
687 | * PM windows.
|
---|
688 | * This happens during the processing of WM_CREATE in
|
---|
689 | * shp_fnwpShapeMgr.
|
---|
690 | * CPU usage: relatively low. Maybe 5% of the whole creation
|
---|
691 | * procedure.
|
---|
692 | *
|
---|
693 | *@@changed V0.9.1 (99-12-03): fixed memory leak
|
---|
694 | */
|
---|
695 |
|
---|
696 | PSHPSPAN shpmgrParseBitmap(HPS hps, PBITMAPINFOHEADER2 bmih2)
|
---|
697 | {
|
---|
698 | int blen, hlen;
|
---|
699 | PUCHAR buf;
|
---|
700 | PBITMAPINFO2 pbmi;
|
---|
701 | PSHPSPAN pSpan, pNew;
|
---|
702 | int x, y, k;
|
---|
703 | LONG first, color;
|
---|
704 | BOOL inspan;
|
---|
705 | int left;
|
---|
706 |
|
---|
707 | // TRACE("shpmgrParseBitmap\n");
|
---|
708 |
|
---|
709 | hlen = sizeof(BITMAPINFO2) + sizeof(RGB) * 256;
|
---|
710 | blen = ((bmih2->cBitCount * bmih2->cx + 31) / 32) * bmih2->cPlanes * 4;
|
---|
711 |
|
---|
712 | pbmi = (PBITMAPINFO2)malloc(hlen);
|
---|
713 | buf = (PUCHAR)malloc(blen);
|
---|
714 |
|
---|
715 | if (pbmi == NULL || buf == NULL)
|
---|
716 | {
|
---|
717 | // TRACE("shpmgrParseBitmap - failed to alloc %d %d\n", hlen, blen);
|
---|
718 | if (pbmi)
|
---|
719 | free(pbmi);
|
---|
720 | if (buf)
|
---|
721 | free(buf);
|
---|
722 | return NULL;
|
---|
723 | }
|
---|
724 | memcpy(pbmi, bmih2, sizeof(BITMAPINFOHEADER2));
|
---|
725 |
|
---|
726 | if ((pSpan = spanCreate()) == NULL)
|
---|
727 | {
|
---|
728 | // TRACE("shpmgrParseBitmap - failed to make\n");
|
---|
729 | free(pbmi);
|
---|
730 | free(buf);
|
---|
731 | return NULL;
|
---|
732 | }
|
---|
733 |
|
---|
734 | first = -1;
|
---|
735 |
|
---|
736 | for (y = 0; y < bmih2->cy; y++)
|
---|
737 | {
|
---|
738 |
|
---|
739 | // TRACE("shpmgrParseBitmap - scan line %d\n", y); fflush(stdout);
|
---|
740 |
|
---|
741 | GpiQueryBitmapBits(hps, y, 1, (PBYTE)buf, pbmi);
|
---|
742 |
|
---|
743 | for (x = 0, inspan = FALSE; x < bmih2->cx; x++)
|
---|
744 | {
|
---|
745 | k = x * 3;
|
---|
746 | color = ((buf[k] << 16) | (buf[k+1] << 8) | buf[k+2]);
|
---|
747 |
|
---|
748 | if (first < 0)
|
---|
749 | {
|
---|
750 | // first iteration: get the very first color (that
|
---|
751 | // is the pixel at (0, 0)), with which we will
|
---|
752 | // compare the others to determine the mask
|
---|
753 | first = color;
|
---|
754 | }
|
---|
755 |
|
---|
756 | if (inspan == FALSE && color != first)
|
---|
757 | {
|
---|
758 | inspan = TRUE;
|
---|
759 | left = x;
|
---|
760 | }
|
---|
761 | else if (inspan == TRUE && color == first)
|
---|
762 | {
|
---|
763 | // transparent color found:
|
---|
764 | // create new span
|
---|
765 | inspan = FALSE;
|
---|
766 | if ((pNew = spanAppend(pSpan, y, left, x)) != NULL)
|
---|
767 | {
|
---|
768 | pSpan = pNew;
|
---|
769 | }
|
---|
770 | else
|
---|
771 | {
|
---|
772 | // TRACE("shpmgrParseBitmap - failed to extend\n");
|
---|
773 | break;
|
---|
774 | }
|
---|
775 | }
|
---|
776 | }
|
---|
777 | if (inspan == TRUE)
|
---|
778 | {
|
---|
779 | if ((pNew = spanAppend(pSpan, y, left, x)) != NULL)
|
---|
780 | pSpan = pNew;
|
---|
781 | else
|
---|
782 | // TRACE("shpmgrParseBitmap - failed to extend\n");
|
---|
783 | break;
|
---|
784 | }
|
---|
785 | }
|
---|
786 |
|
---|
787 | #ifdef SHPDEBUG
|
---|
788 | dumpSpan(pSpan);
|
---|
789 | #endif
|
---|
790 |
|
---|
791 | // fixed these memory leaks V0.9.1 (99-12-03)
|
---|
792 | if (pbmi)
|
---|
793 | free(pbmi);
|
---|
794 | if (buf)
|
---|
795 | free(buf);
|
---|
796 |
|
---|
797 | return pSpan;
|
---|
798 | }
|
---|
799 |
|
---|
800 | /*
|
---|
801 | * shpmgrWMCreate_Bitmap2Regions:
|
---|
802 | * this gets called from shpmgrWMCreate (WM_CREATE) to have a
|
---|
803 | * drawing region created from the bitmap which has been
|
---|
804 | * selected into the given HPS.
|
---|
805 | *
|
---|
806 | * First step in WM_CREATE.
|
---|
807 | */
|
---|
808 |
|
---|
809 | int shpmgrWMCreate_Bitmap2Regions(PSHPWINCTLDATA pCtrl, // in: shape control data
|
---|
810 | HPS hpsMask) // in: HPS with selected bitmap
|
---|
811 | {
|
---|
812 | HAB hab;
|
---|
813 | HDC hdc;
|
---|
814 | HPS hps;
|
---|
815 | SIZEL siz;
|
---|
816 | HBITMAP hbm,
|
---|
817 | hbmPrevious;
|
---|
818 | BITMAPINFOHEADER2 bmi;
|
---|
819 | POINTL apt[3];
|
---|
820 | PSHPSPAN pSpan;
|
---|
821 | PSHPREGION pRegn;
|
---|
822 | int i;
|
---|
823 |
|
---|
824 | // TRACE("shpmgrWMCreate_Bitmap2Regions\n");
|
---|
825 |
|
---|
826 | hab = WinQueryAnchorBlock(pCtrl->hwndShape);
|
---|
827 |
|
---|
828 | /*
|
---|
829 | * Create Memory DC & HPS
|
---|
830 | */
|
---|
831 |
|
---|
832 | hdc = DevOpenDC(hab, OD_MEMORY, "*", 0, NULL, NULLHANDLE);
|
---|
833 | siz.cx = siz.cy = 0;
|
---|
834 | hps = GpiCreatePS(hab, hdc, &siz,
|
---|
835 | PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC);
|
---|
836 |
|
---|
837 | /*
|
---|
838 | * Create Bitmap and relate to memory PS
|
---|
839 | */
|
---|
840 |
|
---|
841 | memset(&bmi, 0, sizeof(bmi));
|
---|
842 |
|
---|
843 | bmi.cbFix = sizeof(BITMAPINFOHEADER2);
|
---|
844 | bmi.cx = pCtrl->cx;
|
---|
845 | bmi.cy = pCtrl->cy;
|
---|
846 | bmi.cPlanes = 1 ;
|
---|
847 | bmi.cBitCount = 24;
|
---|
848 | bmi.ulCompression = 0 ;
|
---|
849 | bmi.cclrUsed = 0 ;
|
---|
850 | bmi.cclrImportant = 0 ;
|
---|
851 |
|
---|
852 | hbm = GpiCreateBitmap(hps, &bmi, 0, NULL, NULL);
|
---|
853 |
|
---|
854 | hbmPrevious = GpiSetBitmap(hps, hbm);
|
---|
855 |
|
---|
856 | /*
|
---|
857 | * Copy in Mask Pattern
|
---|
858 | */
|
---|
859 |
|
---|
860 | // TRACE("shpmgrWMCreate_Bitmap2Regions - copyin %d x %d mask pattern\n", bmi.cx, bmi.cy);
|
---|
861 |
|
---|
862 | apt[0].x = 0; // Target
|
---|
863 | apt[0].y = 0;
|
---|
864 | apt[1].x = bmi.cx;
|
---|
865 | apt[1].y = bmi.cy;
|
---|
866 | apt[2].x = 0; // Source
|
---|
867 | apt[2].y = 0;
|
---|
868 |
|
---|
869 | if (GpiBitBlt(hps, pCtrl->hpsDraw, 3, apt, ROP_SRCCOPY, 0) == GPI_ERROR) {
|
---|
870 | // TRACE("MakeRect - BitBlt Failed %08x, hdc %08x, hps %08x, hbm %08x\n",
|
---|
871 | // WinGetLastError(hab), hdc, hps, hbm);
|
---|
872 | }
|
---|
873 |
|
---|
874 | /*
|
---|
875 | * Parse Mask Pattern
|
---|
876 | */
|
---|
877 |
|
---|
878 | // call shpmgrParseBitmap; this does the actual creation of the
|
---|
879 | // "spans" by comparing all bitmap pixels to the (0, 0)
|
---|
880 | // pixel
|
---|
881 | if ((pSpan = shpmgrParseBitmap(hps, &bmi)) != NULL)
|
---|
882 | {
|
---|
883 | if ((pRegn = (PSHPREGION) malloc(sizeof(SHPREGION) * pSpan->nUsed)) == NULL)
|
---|
884 | {
|
---|
885 | // TRACE("shpmgrWMCreate_Bitmap2Regions - failed to alloc\n");
|
---|
886 | }
|
---|
887 | else
|
---|
888 | {
|
---|
889 | // mask created successfully:
|
---|
890 | pCtrl->nRegion = pSpan->nUsed;
|
---|
891 | pCtrl->aRegion = pRegn;
|
---|
892 |
|
---|
893 | for (i = 0; i < pSpan->nUsed; i++)
|
---|
894 | {
|
---|
895 | pRegn[i].pCtrl = pCtrl;
|
---|
896 | pRegn[i].hwnd = NULLHANDLE;
|
---|
897 | pRegn[i].rect.xLeft = pSpan->aSpan[i].xLeft ;
|
---|
898 | pRegn[i].rect.xRight = pSpan->aSpan[i].xRight ;
|
---|
899 | pRegn[i].rect.yTop = pSpan->aSpan[i].yTop ;
|
---|
900 | pRegn[i].rect.yBottom = pSpan->aSpan[i].yBottom;
|
---|
901 | }
|
---|
902 | }
|
---|
903 | spanFree(pSpan);
|
---|
904 | }
|
---|
905 |
|
---|
906 | /*
|
---|
907 | * dispose local resources
|
---|
908 | */
|
---|
909 |
|
---|
910 | GpiSetBitmap(hps, hbmPrevious); // (*UM)
|
---|
911 | GpiDeleteBitmap(hbm);
|
---|
912 | GpiDestroyPS(hps);
|
---|
913 | DevCloseDC(hdc);
|
---|
914 |
|
---|
915 | return 0;
|
---|
916 | }
|
---|
917 |
|
---|
918 | /*
|
---|
919 | * shpmgrWMCreate_Regions2Windows:
|
---|
920 | * this gets called from shpmgrWMCreate (WM_CREATE) to convert
|
---|
921 | * all the "regions" that have been created by shpmgrWMCreate_Bitmap2Regions
|
---|
922 | * in pCtrl to individual rectangular PM windows.
|
---|
923 | *
|
---|
924 | * CPU usage: extremely high, because all the dull PM functions
|
---|
925 | * take so damn long. Calculating the "regions" isn't really
|
---|
926 | * difficult, but it's the PM windows which cause the CPU hog.
|
---|
927 | *
|
---|
928 | * Second step in WM_CREATE.
|
---|
929 | */
|
---|
930 |
|
---|
931 | int shpmgrWMCreate_Regions2Windows(PSHPWINCTLDATA pCtrl)
|
---|
932 | {
|
---|
933 | int i ;
|
---|
934 | PSHPREGION pRgn;
|
---|
935 | ULONG flStyle;
|
---|
936 |
|
---|
937 | // TRACE("shpmgrWMCreate_Regions2Windows %d regions\n", pCtrl->nRegion);
|
---|
938 |
|
---|
939 | // check if any "regions" exist at all
|
---|
940 | if (pCtrl->nRegion == 0 || pCtrl->aRegion == NULL)
|
---|
941 | {
|
---|
942 | // TRACE("shpmgrWMCreate_Regions2Windows - no region to open\n");
|
---|
943 | return -1;
|
---|
944 | }
|
---|
945 |
|
---|
946 | if (G_ShapeRegisteredRegion == FALSE)
|
---|
947 | {
|
---|
948 | // first call: register "shape region" class
|
---|
949 | WinRegisterClass(WinQueryAnchorBlock(pCtrl->hwndShape),
|
---|
950 | WC_SHAPE_REGION,
|
---|
951 | shp_fnwpShapeRegion,
|
---|
952 | CS_PARENTCLIP
|
---|
953 | // use parent's clipping region instead
|
---|
954 | // of the one of the region window
|
---|
955 | | CS_CLIPSIBLINGS
|
---|
956 | // don't allow the subwindows to paint
|
---|
957 | // over siblings (ie. windows with the
|
---|
958 | // same parent); this is neccessary if
|
---|
959 | // HWND_DESKTOP is the parent
|
---|
960 | | CS_SYNCPAINT,
|
---|
961 | // paint immediately
|
---|
962 | sizeof(PVOID));
|
---|
963 | G_ShapeRegisteredRegion = TRUE;
|
---|
964 | }
|
---|
965 |
|
---|
966 | flStyle = 0;
|
---|
967 |
|
---|
968 | // now go thru the "regions" list
|
---|
969 | for (i = 0, pRgn = pCtrl->aRegion;
|
---|
970 | i < pCtrl->nRegion;
|
---|
971 | i++, pRgn++)
|
---|
972 | {
|
---|
973 | // and create a window for each "region"
|
---|
974 | pRgn->hwnd = WinCreateWindow(
|
---|
975 | pCtrl->hwndParent, // copy parent window from shape window
|
---|
976 | // changed (*UM)
|
---|
977 | // HWND_DESKTOP, // Parent Window
|
---|
978 | WC_SHAPE_REGION, // window class
|
---|
979 | NULL, // window text
|
---|
980 | flStyle, // window style
|
---|
981 | (pCtrl->x + pRgn->rect.xLeft), // x
|
---|
982 | (pCtrl->y + pRgn->rect.yBottom), // y
|
---|
983 | (pRgn->rect.xRight - pRgn->rect.xLeft), // cx
|
---|
984 | (pRgn->rect.yTop - pRgn->rect.yBottom), // cy
|
---|
985 | pCtrl->hwndOwner, // Owner Window
|
---|
986 | HWND_TOP, // Z-Order
|
---|
987 | i, // Window ID
|
---|
988 | pRgn, // Control Data
|
---|
989 | NULL); // Pres. Param.
|
---|
990 | }
|
---|
991 | return 0;
|
---|
992 | }
|
---|
993 |
|
---|
994 | /*
|
---|
995 | * shpmgrFreeRegion:
|
---|
996 | * cleanup during WM_DESTROY.
|
---|
997 | */
|
---|
998 |
|
---|
999 | int shpmgrFreeRegion(PSHPWINCTLDATA pCtrl)
|
---|
1000 | {
|
---|
1001 | int i ;
|
---|
1002 | PSHPREGION pRgn;
|
---|
1003 |
|
---|
1004 | for (i = 0, pRgn = pCtrl->aRegion;
|
---|
1005 | i < pCtrl->nRegion;
|
---|
1006 | i++, pRgn++)
|
---|
1007 | WinDestroyWindow(pRgn->hwnd);
|
---|
1008 |
|
---|
1009 | free(pCtrl->aRegion);
|
---|
1010 |
|
---|
1011 | return 0;
|
---|
1012 | }
|
---|
1013 |
|
---|
1014 | /*
|
---|
1015 | * shpmgrWMCreate:
|
---|
1016 | * this initializes the "shape window".
|
---|
1017 | * This gets called upon receiving WM_CREATE in shp_fnwpShapeMgr.
|
---|
1018 | * The procedure is as follows:
|
---|
1019 | * 1) the bitmap in pData->hpsDraw is analyzed pixel by
|
---|
1020 | * pixel to create a number of "regions" from it
|
---|
1021 | * (which are not GPI regions, but an array of SHPREGION
|
---|
1022 | * structures. At least one of these structures is
|
---|
1023 | * created for each line. This is done by calling
|
---|
1024 | * shpmgrWMCreate_Bitmap2Regions.
|
---|
1025 | * 2) We then call shpmgrWMCreate_Regions2Windows to actually create
|
---|
1026 | * PM windows from all these structures.
|
---|
1027 | */
|
---|
1028 |
|
---|
1029 | PSHPWINCTLDATA shpmgrWMCreate(HWND hwnd, // in: shape window
|
---|
1030 | PCREATESTRUCT pWin, // in: create struct of WM_CREATE
|
---|
1031 | PSHPCTLDATA pData) // in: SHPCTLDATA struct (WM_CREATE mp1)
|
---|
1032 | {
|
---|
1033 | PSHPWINCTLDATA pCtrl;
|
---|
1034 |
|
---|
1035 | if (pData->hpsDraw == NULLHANDLE || pData->hpsMask == NULLHANDLE) {
|
---|
1036 | return NULL;
|
---|
1037 | }
|
---|
1038 |
|
---|
1039 | // create new PSHPWINCTLDATA structure
|
---|
1040 | if ((pCtrl = (PSHPWINCTLDATA) malloc(sizeof(SHPWINCTLDATA))) == NULL) {
|
---|
1041 | return NULL;
|
---|
1042 | }
|
---|
1043 |
|
---|
1044 | /*
|
---|
1045 | * Setup Common Window Parameters
|
---|
1046 | */
|
---|
1047 |
|
---|
1048 | pCtrl->hwndShape = hwnd;
|
---|
1049 | pCtrl->hwndParent = pWin->hwndParent;
|
---|
1050 | pCtrl->hwndOwner = pWin->hwndOwner ;
|
---|
1051 | pCtrl->id = pWin->id;
|
---|
1052 | pCtrl->x = pWin->x ;
|
---|
1053 | pCtrl->y = pWin->y ;
|
---|
1054 | pCtrl->cx = pWin->cx;
|
---|
1055 | pCtrl->cy = pWin->cy;
|
---|
1056 |
|
---|
1057 | /*
|
---|
1058 | * Setup Image Window's Control Data
|
---|
1059 | */
|
---|
1060 |
|
---|
1061 | pCtrl->cx = pData->cx;
|
---|
1062 | pCtrl->cy = pData->cy;
|
---|
1063 | pCtrl->hpsDraw = pData->hpsDraw;
|
---|
1064 |
|
---|
1065 | // now create "regions" from bitmap;
|
---|
1066 | // this will store the "regions" in pCtrl
|
---|
1067 | shpmgrWMCreate_Bitmap2Regions(pCtrl, pData->hpsMask);
|
---|
1068 |
|
---|
1069 | // now create as many rectangular PM
|
---|
1070 | // windows as we have "regions" in pCtrl
|
---|
1071 | shpmgrWMCreate_Regions2Windows(pCtrl);
|
---|
1072 |
|
---|
1073 | return pCtrl;
|
---|
1074 | }
|
---|
1075 |
|
---|
1076 | /*
|
---|
1077 | * shpmgrWMDestroy:
|
---|
1078 | * this cleans up the shape's resources.
|
---|
1079 | * Gets called upon receiving WM_DESTROY in
|
---|
1080 | * shp_fnwpShapeMgr.
|
---|
1081 | */
|
---|
1082 |
|
---|
1083 | void shpmgrWMDestroy(PSHPWINCTLDATA pCtrl)
|
---|
1084 | {
|
---|
1085 | if (pCtrl == NULL)
|
---|
1086 | return;
|
---|
1087 |
|
---|
1088 | shpmgrFreeRegion(pCtrl);
|
---|
1089 | free(pCtrl);
|
---|
1090 | }
|
---|
1091 |
|
---|
1092 | /*
|
---|
1093 | *@@ shp_fnwpShapeMgr:
|
---|
1094 | * this is the window procedure for the "shape window manager".
|
---|
1095 | * Register this procedure with WinRegisterWindowClass.
|
---|
1096 | *
|
---|
1097 | * This does the transformation of the bitmap into many
|
---|
1098 | * rectangular subwindows upon WM_CREATE, each of which
|
---|
1099 | * will use shp_fnwpShapeRegion as its window proc.
|
---|
1100 | *
|
---|
1101 | * There should be the following window hierarchy (the
|
---|
1102 | * lines signify ownership):
|
---|
1103 | *
|
---|
1104 | + Your owner window
|
---|
1105 | + |
|
---|
1106 | + +-- owns "shape manager" window (this window proc)
|
---|
1107 | + |
|
---|
1108 | + +-- lots of "region" windows (shp_fnwpShapeRegion)
|
---|
1109 | + +-- ...
|
---|
1110 | *
|
---|
1111 | * The "region" windows are owned by the "shape manager" window,
|
---|
1112 | * but have the same parent as the "shape manager" window.
|
---|
1113 | * Normally, this should be set to HWND_DESKTOP when creating the
|
---|
1114 | * "shape" window.
|
---|
1115 | *
|
---|
1116 | * This window procedure forwards the following messages
|
---|
1117 | * to its owner:
|
---|
1118 | * -- WM_MOUSEMOVE
|
---|
1119 | * -- all WM_BUTTONxxx messages
|
---|
1120 | * -- WM_CHAR
|
---|
1121 | * -- WM_VIOCHAR
|
---|
1122 | * -- WM_BEGINDRAG
|
---|
1123 | * -- WM_ENDDRAG
|
---|
1124 | * -- WM_SINGLESELECT
|
---|
1125 | * -- WM_OPEN
|
---|
1126 | * -- WM_CONTEXTMENU
|
---|
1127 | * -- WM_CONTEXTHELP
|
---|
1128 | * -- WM_TEXTEDIT
|
---|
1129 | * -- WM_BEGINSELECT
|
---|
1130 | * -- WM_ENDSELECT
|
---|
1131 | */
|
---|
1132 |
|
---|
1133 | MRESULT EXPENTRY shp_fnwpShapeMgr(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
|
---|
1134 | {
|
---|
1135 | PSHPWINCTLDATA pCtrl;
|
---|
1136 | PSWP pswp ;
|
---|
1137 | // SHORT sx; // , sy;
|
---|
1138 |
|
---|
1139 | pCtrl = (PSHPWINCTLDATA) WinQueryWindowPtr(hwnd, 0);
|
---|
1140 |
|
---|
1141 | switch (msg)
|
---|
1142 | {
|
---|
1143 |
|
---|
1144 | /*
|
---|
1145 | * WM_CREATE:
|
---|
1146 | * shape window is being created.
|
---|
1147 | * Parameters:
|
---|
1148 | * PSHPCTLDATA mp1
|
---|
1149 | * PCREATESTRUCT mp2
|
---|
1150 | * Shaped windows must have a SHPCTLDATA
|
---|
1151 | * structure in mp1.
|
---|
1152 | */
|
---|
1153 |
|
---|
1154 | case WM_CREATE:
|
---|
1155 | // TRACE("WM_CREATE\n");
|
---|
1156 | pCtrl = shpmgrWMCreate(hwnd,
|
---|
1157 | (PCREATESTRUCT)PVOIDFROMMP(mp2),
|
---|
1158 | (PSHPCTLDATA)PVOIDFROMMP(mp1));
|
---|
1159 |
|
---|
1160 | if (pCtrl == NULL)
|
---|
1161 | return (MRESULT) TRUE;
|
---|
1162 |
|
---|
1163 | // store control data in window words
|
---|
1164 | WinSetWindowPtr(hwnd, 0, (PVOID) pCtrl);
|
---|
1165 | return (MRESULT) FALSE;
|
---|
1166 |
|
---|
1167 | /*
|
---|
1168 | * WM_DESTROY:
|
---|
1169 | * clean up.
|
---|
1170 | */
|
---|
1171 |
|
---|
1172 | case WM_DESTROY:
|
---|
1173 | // TRACE("WM_DESTORY\n");
|
---|
1174 | shpmgrWMDestroy(pCtrl);
|
---|
1175 | return (MRESULT) 0;
|
---|
1176 |
|
---|
1177 | /*
|
---|
1178 | * WM_ADJUSTWINDOWPOS:
|
---|
1179 | * this needs to be manipulated to
|
---|
1180 | * adjust the positions of all the
|
---|
1181 | * subwindows instead.
|
---|
1182 | */
|
---|
1183 |
|
---|
1184 | case WM_ADJUSTWINDOWPOS:
|
---|
1185 | // TRACE("WM_ADJUSTWINDOWPOS\n");
|
---|
1186 | pswp = (PSWP) PVOIDFROMMP(mp1);
|
---|
1187 | // DUMPSWP(pswp);
|
---|
1188 |
|
---|
1189 | // enforce the size which we were given
|
---|
1190 | // in the beginning, because we cannot
|
---|
1191 | // change the size later
|
---|
1192 | pswp->cx = pCtrl->cx;
|
---|
1193 | pswp->cy = pCtrl->cy;
|
---|
1194 |
|
---|
1195 | // adjust the sub-windows
|
---|
1196 | shpmgrWMAdjustWindowPos(pCtrl, pswp);
|
---|
1197 |
|
---|
1198 | // never show ourselves
|
---|
1199 | pswp->fl &= ~SWP_SHOW;
|
---|
1200 | return (MRESULT) 0;
|
---|
1201 |
|
---|
1202 | /*
|
---|
1203 | * SHAPEWIN_MSG_UPDATE:
|
---|
1204 | *
|
---|
1205 | */
|
---|
1206 |
|
---|
1207 | case SHAPEWIN_MSG_UPDATE:
|
---|
1208 | shpmgrUpdateRegions(pCtrl, (PRECTL) PVOIDFROMMP(mp1));
|
---|
1209 | return (MRESULT) 0;
|
---|
1210 |
|
---|
1211 | /*
|
---|
1212 | * WM_QUERYDLGCODE:
|
---|
1213 | *
|
---|
1214 | */
|
---|
1215 |
|
---|
1216 | case WM_QUERYDLGCODE:
|
---|
1217 | // TRACE("WM_QUERYDLGCODE\n");
|
---|
1218 | return (MRESULT) DLGC_STATIC;
|
---|
1219 |
|
---|
1220 | /*
|
---|
1221 | * WM_PAINT:
|
---|
1222 | * we just swallow this message because
|
---|
1223 | * there's no "shape window" to be painted;
|
---|
1224 | * instead, all the region windows get
|
---|
1225 | * their own WM_PAINT message
|
---|
1226 | */
|
---|
1227 |
|
---|
1228 | case WM_PAINT:
|
---|
1229 | {
|
---|
1230 | // TRACE("WM_PAINT\n");
|
---|
1231 | /* HPS hps = WinBeginPaint(hwnd, NULLHANDLE, NULL);
|
---|
1232 |
|
---|
1233 | POINTL apt[3];
|
---|
1234 | RECTL rclWin;
|
---|
1235 | WinQueryWindowRect(hwnd, &rclWin);
|
---|
1236 |
|
---|
1237 | // lower left of target
|
---|
1238 | apt[0].x = 0;
|
---|
1239 | apt[0].y = 0;
|
---|
1240 | // upper right of target
|
---|
1241 | apt[1].x = rclWin.xRight;
|
---|
1242 | apt[1].y = rclWin.yTop;
|
---|
1243 | // lower left of source
|
---|
1244 | apt[2].x = 0;
|
---|
1245 | apt[2].y = 0;
|
---|
1246 | GpiBitBlt(hps,
|
---|
1247 | pCtrl->hpsDraw,
|
---|
1248 | 3,
|
---|
1249 | apt,
|
---|
1250 | ROP_SRCCOPY,
|
---|
1251 | 0); */
|
---|
1252 |
|
---|
1253 | // delete update region to stop further
|
---|
1254 | // WM_PAINTs for this window;
|
---|
1255 | // this is faster than WiNBeginPaint
|
---|
1256 | WinValidateRect(hwnd, NULL, FALSE);
|
---|
1257 | // WinEndPaint(hps);
|
---|
1258 | return (MRESULT) 0;
|
---|
1259 | }
|
---|
1260 |
|
---|
1261 | /*
|
---|
1262 | * all input-related messages:
|
---|
1263 | * forward these to the owner
|
---|
1264 | */
|
---|
1265 |
|
---|
1266 | case WM_MOUSEMOVE :
|
---|
1267 | case WM_BUTTON1DOWN :
|
---|
1268 | case WM_BUTTON1UP :
|
---|
1269 | case WM_BUTTON1CLICK :
|
---|
1270 | case WM_BUTTON1DBLCLK:
|
---|
1271 | case WM_BUTTON2DOWN :
|
---|
1272 | case WM_BUTTON2UP :
|
---|
1273 | case WM_BUTTON2CLICK :
|
---|
1274 | case WM_BUTTON2DBLCLK:
|
---|
1275 | case WM_BUTTON3DOWN :
|
---|
1276 | case WM_BUTTON3UP :
|
---|
1277 | case WM_BUTTON3CLICK :
|
---|
1278 | case WM_BUTTON3DBLCLK:
|
---|
1279 | case WM_CHAR :
|
---|
1280 | case WM_VIOCHAR :
|
---|
1281 | case WM_BEGINDRAG :
|
---|
1282 | case WM_ENDDRAG :
|
---|
1283 | case WM_SINGLESELECT :
|
---|
1284 | case WM_OPEN :
|
---|
1285 | case WM_CONTEXTMENU :
|
---|
1286 | case WM_CONTEXTHELP :
|
---|
1287 | case WM_TEXTEDIT :
|
---|
1288 | case WM_BEGINSELECT :
|
---|
1289 | case WM_ENDSELECT :
|
---|
1290 | return WinSendMsg(pCtrl->hwndOwner, msg, mp1, mp2);
|
---|
1291 |
|
---|
1292 | } // end switch (msg)
|
---|
1293 | return WinDefWindowProc(hwnd, msg, mp1, mp2);
|
---|
1294 | }
|
---|
1295 |
|
---|
1296 | /* ******************************************************************
|
---|
1297 | * *
|
---|
1298 | * Part 2: Shape frame functions *
|
---|
1299 | * *
|
---|
1300 | ********************************************************************/
|
---|
1301 |
|
---|
1302 | MRESULT EXPENTRY fnwpShapeFrame(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
|
---|
1303 |
|
---|
1304 | /*
|
---|
1305 | *@@ shpLoadBitmap:
|
---|
1306 | * this creates a memory device context/presentation space
|
---|
1307 | * and loads and selects a bitmap into it.
|
---|
1308 | *
|
---|
1309 | * If pszBitmap == NULL, the bitmap is loaded from the
|
---|
1310 | * specified resources, otherwise we attempt to load the
|
---|
1311 | * bitmap file specified in pszBitmap (using gpihLoadBitmapFile).
|
---|
1312 | *
|
---|
1313 | * Output in the given SHAPEFRAME structure:
|
---|
1314 | * -- hab: as passed to this func
|
---|
1315 | * -- hdc: device context handle
|
---|
1316 | * -- hps: presentation space handle
|
---|
1317 | * -- hbm: bitmap handle
|
---|
1318 | * -- bmi: BITMAPINFOHEADER of hbmp
|
---|
1319 | * -- ptlLowerLeft: lower left corner is set so that
|
---|
1320 | * bitmap is centered on screen
|
---|
1321 | *
|
---|
1322 | * All other fields are neither read nor written to.
|
---|
1323 | * Returns TRUE if everything went OK.
|
---|
1324 | *
|
---|
1325 | * You can call this function directly before calling
|
---|
1326 | * shpCreateWindows.
|
---|
1327 | *
|
---|
1328 | * Pass the SHAPEFRAME structure to shpFreeBitmap to clean up.
|
---|
1329 | *
|
---|
1330 | *@@changed V0.9.0 [umoeller]: added default window positioning
|
---|
1331 | *@@changed V0.9.0 [umoeller]: removed GpiSetBitmap here
|
---|
1332 | */
|
---|
1333 |
|
---|
1334 | BOOL shpLoadBitmap(HAB hab, // in: anchor block
|
---|
1335 | PSZ pszBitmapFile, // in: OS/2 1.3 bmp file or NULL
|
---|
1336 | HMODULE hmodResource, // in: module handle from where the
|
---|
1337 | // resources should be loaded if
|
---|
1338 | // pszBitmapFile == NULL. This can be 0 for
|
---|
1339 | // the current EXE
|
---|
1340 | ULONG idResource, // in: bitmap resource ID in that module
|
---|
1341 | PSHAPEFRAME psb) // out: bitmap info
|
---|
1342 | {
|
---|
1343 | SIZEL siz;
|
---|
1344 | BOOL brc;
|
---|
1345 |
|
---|
1346 | psb->hab = hab;
|
---|
1347 |
|
---|
1348 | psb->hdc = DevOpenDC(hab, OD_MEMORY, "*", 0, NULL, NULLHANDLE);
|
---|
1349 | if (psb->hdc)
|
---|
1350 | {
|
---|
1351 | siz.cx = siz.cy = 0;
|
---|
1352 | psb->hps = GpiCreatePS(hab, psb->hdc, &siz,
|
---|
1353 | PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC);
|
---|
1354 |
|
---|
1355 | if (psb->hps)
|
---|
1356 | {
|
---|
1357 | if (pszBitmapFile)
|
---|
1358 | {
|
---|
1359 | // load bitmap file
|
---|
1360 | ULONG ulError;
|
---|
1361 | psb->hbm = gpihLoadBitmapFile(psb->hps,
|
---|
1362 | pszBitmapFile,
|
---|
1363 | &ulError);
|
---|
1364 | } else
|
---|
1365 | // load resource bitmap
|
---|
1366 | psb->hbm = GpiLoadBitmap(psb->hps,
|
---|
1367 | hmodResource,
|
---|
1368 | idResource,
|
---|
1369 | 0, 0);
|
---|
1370 | if (psb->hbm)
|
---|
1371 | {
|
---|
1372 | SWP swpScreen;
|
---|
1373 | // store bitmap info in structure
|
---|
1374 | psb->bmi.cbFix = sizeof(psb->bmi);
|
---|
1375 | GpiQueryBitmapInfoHeader(psb->hbm, &psb->bmi);
|
---|
1376 |
|
---|
1377 | // set ptlLowerLeft so that the bitmap
|
---|
1378 | // is centered on the screen
|
---|
1379 | WinQueryWindowPos(HWND_DESKTOP, &swpScreen);
|
---|
1380 | psb->ptlLowerLeft.x = (swpScreen.cx - psb->bmi.cx) / 2;
|
---|
1381 | psb->ptlLowerLeft.y = (swpScreen.cy - psb->bmi.cy) / 2;
|
---|
1382 |
|
---|
1383 | brc = TRUE;
|
---|
1384 | }
|
---|
1385 | }
|
---|
1386 | }
|
---|
1387 | return (brc);
|
---|
1388 | }
|
---|
1389 |
|
---|
1390 | /*
|
---|
1391 | *@@ shpFreeBitmap:
|
---|
1392 | * this cleans up resources allocated by shpLoadBitmap:
|
---|
1393 | * delete the bitmap, destroy the HPS and HDC.
|
---|
1394 | *
|
---|
1395 | *@@changed V0.9.3 (2000-04-11) [umoeller]: fixed major resource leak; the bitmap was never freed
|
---|
1396 | */
|
---|
1397 |
|
---|
1398 | VOID shpFreeBitmap(PSHAPEFRAME psb)
|
---|
1399 | {
|
---|
1400 | if (psb->hbm != NULLHANDLE)
|
---|
1401 | {
|
---|
1402 | // unset bitmap in HPS; it cannot be deleted otherwise...
|
---|
1403 | GpiSetBitmap(psb->hps, NULLHANDLE); // V0.9.3 (2000-04-11) [umoeller]
|
---|
1404 | GpiDeleteBitmap(psb->hbm);
|
---|
1405 | psb->hbm = NULLHANDLE;
|
---|
1406 | }
|
---|
1407 | if (psb->hps != NULLHANDLE)
|
---|
1408 | {
|
---|
1409 | GpiDestroyPS(psb->hps);
|
---|
1410 | psb->hps = NULLHANDLE;
|
---|
1411 | }
|
---|
1412 | if (psb->hdc != NULLHANDLE)
|
---|
1413 | {
|
---|
1414 | DevCloseDC(psb->hdc);
|
---|
1415 | psb->hdc = NULLHANDLE;
|
---|
1416 | }
|
---|
1417 | }
|
---|
1418 |
|
---|
1419 | /*
|
---|
1420 | *@@ shpCreateWindows:
|
---|
1421 | * this is a one-shot function for creating a
|
---|
1422 | * shaped window from a bitmap.
|
---|
1423 | *
|
---|
1424 | * Required fields in SHAPEFRAME for input (those
|
---|
1425 | * are all properly set by shpLoadBitmap):
|
---|
1426 | * -- hab: anchor block
|
---|
1427 | * -- hps: presentation space handle
|
---|
1428 | * -- hbm: bitmap handle
|
---|
1429 | * -- bmi: BITMAPINFOHEADER of hbmp
|
---|
1430 | * -- ptlLowerLeft: lower left corner of where
|
---|
1431 | * to position the shape window (new with V0.9.0).
|
---|
1432 | *
|
---|
1433 | * All other fields are ignored for input and only
|
---|
1434 | * set for output (and for the shape window later).
|
---|
1435 | *
|
---|
1436 | * You can use shpLoadBitmap to have all the fields
|
---|
1437 | * initialized, which will also set ptlLowerLeft
|
---|
1438 | * so that the shape window gets centered on the
|
---|
1439 | * Desktop.
|
---|
1440 | *
|
---|
1441 | * Otherwise you must initialize the above fields for
|
---|
1442 | * yourself.
|
---|
1443 | *
|
---|
1444 | * Obviously, this function uses the same HPS (and
|
---|
1445 | * thus bitmap) for both transparency and drawing.
|
---|
1446 | * If you wish to use two different bitmaps (one for
|
---|
1447 | * transparency, one for drawing), you cannot use
|
---|
1448 | * this function.
|
---|
1449 | *
|
---|
1450 | * Note that the windows are now (V0.9.0) also positioned
|
---|
1451 | * on the screen.
|
---|
1452 | *
|
---|
1453 | * Output in that structure:
|
---|
1454 | * -- hwndShapeFrame: invisible rectangular frame
|
---|
1455 | * window for the shape window
|
---|
1456 | * (fnwpShapeFrame, created here)
|
---|
1457 | * -- hwndShape: "shape" window
|
---|
1458 | * (shp_fnwpShapeMgr, created here)
|
---|
1459 | * -- pfnFrame: original window procedure of
|
---|
1460 | * WC_FRAME (hwndShapeFrame),
|
---|
1461 | * which is subclassed here
|
---|
1462 | * using fnwpShapeFrame
|
---|
1463 | * -- shpctrl: control data for hwndShape
|
---|
1464 | *
|
---|
1465 | * Returns TRUE if everything went OK.
|
---|
1466 | *
|
---|
1467 | * <B>Example</B> for creating a shaped window and
|
---|
1468 | * centering it on the screen:
|
---|
1469 | + SHAPEFRAME sb;
|
---|
1470 | + if (shpLoadBitmap(hab...,
|
---|
1471 | + szBitmapFile...,
|
---|
1472 | + 0, 0,
|
---|
1473 | + &sb))
|
---|
1474 | + {
|
---|
1475 | + // create shape (transparent) windows
|
---|
1476 | + if (shpCreateWindows(habQuickThread, &sb))
|
---|
1477 | + {
|
---|
1478 | * ...
|
---|
1479 | + }
|
---|
1480 | + }
|
---|
1481 | + ...
|
---|
1482 | + // cleanup
|
---|
1483 | + shpFreeBitmap(&sb);
|
---|
1484 | + WinDestroyWindow(sb.hwndShapeFrame) ;
|
---|
1485 | + WinDestroyWindow(sb.hwndShape);
|
---|
1486 | *
|
---|
1487 | *@@changed V0.9.0 [umoeller]: removed hab from function prototype
|
---|
1488 | *@@changed V0.9.0 [umoeller]: added window positioning
|
---|
1489 | *@@changed V0.9.0 [umoeller]: added GpiSetBitmap here (always forget that)
|
---|
1490 | */
|
---|
1491 |
|
---|
1492 | BOOL shpCreateWindows(PSHAPEFRAME psb)
|
---|
1493 | {
|
---|
1494 | BOOL brc = FALSE;
|
---|
1495 |
|
---|
1496 | if (psb->hbm)
|
---|
1497 | {
|
---|
1498 | // bitmap seems to be valid:
|
---|
1499 | FRAMECDATA fcd;
|
---|
1500 |
|
---|
1501 | GpiSetBitmap(psb->hps, psb->hbm);
|
---|
1502 |
|
---|
1503 | memset(&fcd, 0, sizeof(fcd));
|
---|
1504 | fcd.cb = sizeof(fcd);
|
---|
1505 |
|
---|
1506 | // create invisible frame
|
---|
1507 | psb->hwndShapeFrame = WinCreateWindow(
|
---|
1508 | HWND_DESKTOP, // Parent window handle
|
---|
1509 | WC_FRAME, // Frame Window Class
|
---|
1510 | "XWorkplaceLogoShape", // title
|
---|
1511 | 0, // Window Style
|
---|
1512 | 0, 0, 0, 0, // Position & size
|
---|
1513 | NULLHANDLE, // Owner Window
|
---|
1514 | HWND_TOP, // Z-Order
|
---|
1515 | 0, // Window ID
|
---|
1516 | &fcd, // Control Data
|
---|
1517 | NULL); // Presentation Parameter
|
---|
1518 |
|
---|
1519 | if (psb->hwndShapeFrame)
|
---|
1520 | {
|
---|
1521 | // store the SHAPEFRAME structure in the frame's window words
|
---|
1522 | // so that the subclassed frame can access the data
|
---|
1523 | WinSetWindowULong(psb->hwndShapeFrame, QWL_USER, (ULONG)psb);
|
---|
1524 |
|
---|
1525 | // subclass the frame window; store the original wnd proc in
|
---|
1526 | // the SHAPEFRAME structure
|
---|
1527 | psb->pfnFrame = WinSubclassWindow(psb->hwndShapeFrame, fnwpShapeFrame);
|
---|
1528 |
|
---|
1529 | if ((psb->hwndShapeFrame) && (psb->hps))
|
---|
1530 | {
|
---|
1531 | // OK, no errors so far
|
---|
1532 |
|
---|
1533 | // register shape window class; if this is already
|
---|
1534 | // registered, this won't hurt
|
---|
1535 | WinRegisterClass(psb->hab,
|
---|
1536 | WC_SHAPE_WINDOW,
|
---|
1537 | shp_fnwpShapeMgr,
|
---|
1538 | 0L, // class style flags
|
---|
1539 | sizeof(PVOID));
|
---|
1540 |
|
---|
1541 | // create shape manager window
|
---|
1542 | psb->shpctrl.cx = psb->bmi.cx;
|
---|
1543 | psb->shpctrl.cy = psb->bmi.cy;
|
---|
1544 | psb->shpctrl.hpsDraw = psb->hps;
|
---|
1545 | psb->shpctrl.hpsMask = psb->hps;
|
---|
1546 |
|
---|
1547 | // create the "shape" window
|
---|
1548 | psb->hwndShape = WinCreateWindow(
|
---|
1549 | HWND_DESKTOP, // Parent Window
|
---|
1550 | WC_SHAPE_WINDOW, // Window Class
|
---|
1551 | NULL, // Window Text
|
---|
1552 | 0, // Window Style;
|
---|
1553 | // no clip siblings!
|
---|
1554 | 0, 0, 0, 0, // Pos & Size
|
---|
1555 | psb->hwndShapeFrame, // Owner Window
|
---|
1556 | HWND_TOP, // Z-Order
|
---|
1557 | 0, // Window ID
|
---|
1558 | &psb->shpctrl, // Control Data
|
---|
1559 | NULL); // Pres. Param.
|
---|
1560 |
|
---|
1561 | if (psb->hwndShape)
|
---|
1562 | {
|
---|
1563 | // no error: only then return TRUE
|
---|
1564 | brc = TRUE;
|
---|
1565 |
|
---|
1566 | // and position the windows
|
---|
1567 | WinSetWindowPos(psb->hwndShapeFrame, NULLHANDLE,
|
---|
1568 | psb->ptlLowerLeft.x, psb->ptlLowerLeft.y,
|
---|
1569 | psb->bmi.cx, psb->bmi.cy,
|
---|
1570 | (SWP_MOVE | SWP_SIZE | SWP_HIDE));
|
---|
1571 | WinSetWindowPos(psb->hwndShape, NULLHANDLE,
|
---|
1572 | psb->ptlLowerLeft.x, psb->ptlLowerLeft.y,
|
---|
1573 | psb->bmi.cx, psb->bmi.cy,
|
---|
1574 | (SWP_MOVE | SWP_SIZE | SWP_SHOW));
|
---|
1575 | }
|
---|
1576 | }
|
---|
1577 | }
|
---|
1578 | }
|
---|
1579 |
|
---|
1580 | return (brc);
|
---|
1581 | }
|
---|
1582 |
|
---|
1583 | /*
|
---|
1584 | *@@ fnwpShapeFrame:
|
---|
1585 | * this is the window proc for subclassing the shape frame window
|
---|
1586 | * (shpCreateWindows above).
|
---|
1587 | * The shaped window proc (shp_fnwpShapeMgr) keeps forwarding messages
|
---|
1588 | * to its owner (which is the frame here), so we better handle
|
---|
1589 | * those messages.
|
---|
1590 | */
|
---|
1591 |
|
---|
1592 | MRESULT EXPENTRY fnwpShapeFrame(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
|
---|
1593 | {
|
---|
1594 | MRESULT mrc;
|
---|
1595 |
|
---|
1596 | // get the SHAPEFRAME structure from the window words,
|
---|
1597 | // which has been stored there by shpCreateWindows
|
---|
1598 | PSHAPEFRAME psb = (PSHAPEFRAME)WinQueryWindowULong(hwnd, QWL_USER);
|
---|
1599 |
|
---|
1600 | // _Pmpf(("frame %08x %08x %08x", msg, mp1, mp2));
|
---|
1601 |
|
---|
1602 | switch (msg)
|
---|
1603 | {
|
---|
1604 |
|
---|
1605 | /*
|
---|
1606 | * WM_ADJUSTWINDOWPOS:
|
---|
1607 | * forward the data we get here to the shape
|
---|
1608 | * window (which will in turn reposition all
|
---|
1609 | * the region windows);
|
---|
1610 | * afterwards, always delete SHOW and set HIDE
|
---|
1611 | * for ourselves
|
---|
1612 | */
|
---|
1613 |
|
---|
1614 | case WM_ADJUSTWINDOWPOS: {
|
---|
1615 | PSWP pswp = (PSWP) PVOIDFROMMP(mp1);
|
---|
1616 | POINTL ptl;
|
---|
1617 | WinQueryPointerPos(HWND_DESKTOP, &ptl);
|
---|
1618 | WinSetWindowPos(psb->hwndShape,
|
---|
1619 | pswp->hwndInsertBehind,
|
---|
1620 | // use current mouse position instead
|
---|
1621 | // of the original ones
|
---|
1622 | ptl.x,
|
---|
1623 | ptl.y,
|
---|
1624 | // pswp->x,
|
---|
1625 | // pswp->y,
|
---|
1626 | pswp->cx,
|
---|
1627 | pswp->cy,
|
---|
1628 | pswp->fl);
|
---|
1629 | pswp->fl &= ~SWP_SHOW;
|
---|
1630 | pswp->fl |= SWP_HIDE;
|
---|
1631 | mrc = (*psb->pfnFrame)(hwnd, msg, mp1, mp2);
|
---|
1632 | break; }
|
---|
1633 |
|
---|
1634 | /* the shape window forwards these messages to us:
|
---|
1635 | WM_MOUSEMOVE
|
---|
1636 | WM_BUTTON1DOWN
|
---|
1637 | WM_BUTTON1UP
|
---|
1638 | WM_BUTTON1CLICK
|
---|
1639 | WM_BUTTON1DBLCLK
|
---|
1640 | WM_BUTTON2DOWN
|
---|
1641 | WM_BUTTON2UP
|
---|
1642 | WM_BUTTON2CLICK
|
---|
1643 | WM_BUTTON2DBLCLK
|
---|
1644 | WM_BUTTON3DOWN
|
---|
1645 | WM_BUTTON3UP
|
---|
1646 | WM_BUTTON3CLICK
|
---|
1647 | WM_BUTTON3DBLCLK
|
---|
1648 | WM_CHAR
|
---|
1649 | WM_VIOCHAR
|
---|
1650 | WM_BEGINDRAG
|
---|
1651 | WM_ENDDRAG
|
---|
1652 | WM_SINGLESELECT
|
---|
1653 | WM_OPEN
|
---|
1654 | WM_CONTEXTMENU
|
---|
1655 | WM_CONTEXTHELP
|
---|
1656 | WM_TEXTEDIT
|
---|
1657 | WM_BEGINSELECT
|
---|
1658 | WM_ENDSELECT */
|
---|
1659 |
|
---|
1660 | /*
|
---|
1661 | * WM_SINGLESELECT:
|
---|
1662 | * if we are being clicked upon, bring the
|
---|
1663 | * shape window to top instead
|
---|
1664 | */
|
---|
1665 |
|
---|
1666 | case WM_SINGLESELECT:
|
---|
1667 | WinSetWindowPos(psb->hwndShape, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER);
|
---|
1668 | mrc = 0;
|
---|
1669 | break;
|
---|
1670 |
|
---|
1671 | /*
|
---|
1672 | * WM_BEGINDRAG:
|
---|
1673 | * if we are being dragged with MB2, forward
|
---|
1674 | * this to the shape window
|
---|
1675 | */
|
---|
1676 |
|
---|
1677 | case WM_BEGINDRAG:
|
---|
1678 | WinSendMsg(psb->hwndShapeFrame, WM_TRACKFRAME,
|
---|
1679 | MPFROMSHORT(TF_MOVE /* | TF_SETPOINTERPOS*/ ), NULL);
|
---|
1680 | mrc = 0;
|
---|
1681 | break;
|
---|
1682 |
|
---|
1683 | default:
|
---|
1684 | mrc = (*psb->pfnFrame)(hwnd, msg, mp1, mp2);
|
---|
1685 | }
|
---|
1686 |
|
---|
1687 | return (mrc);
|
---|
1688 | }
|
---|
1689 |
|
---|
1690 | /*
|
---|
1691 | *@@ shp2RegisterClasses:
|
---|
1692 | *
|
---|
1693 | *@@added V0.9.3 (2000-05-03) [umoeller]
|
---|
1694 | */
|
---|
1695 |
|
---|
1696 | BOOL shp2RegisterClasses(HAB hab)
|
---|
1697 | {
|
---|
1698 | // register shape window class; if this is already
|
---|
1699 | // registered, this won't hurt
|
---|
1700 | return(WinRegisterClass(hab,
|
---|
1701 | WC_SHAPE_WINDOW,
|
---|
1702 | shp_fnwpShapeMgr,
|
---|
1703 | 0L, // class style flags
|
---|
1704 | sizeof(PVOID)));
|
---|
1705 | }
|
---|
1706 |
|
---|
1707 |
|
---|