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