[8] | 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.
|
---|
[14] | 169 | * This file is part of the "XWorkplace helpers" source package.
|
---|
| 170 | * This is free software; you can redistribute it and/or modify
|
---|
[8] | 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
|
---|
[14] | 187 |
|
---|
| 188 | #define INCL_WINWINDOWMGR
|
---|
| 189 | #define INCL_WINFRAMEMGR
|
---|
| 190 | #define INCL_WINDIALOGS
|
---|
| 191 | #define INCL_WININPUT
|
---|
| 192 | #define INCL_WINPOINTERS
|
---|
[8] | 193 | #define INCL_WINSYS
|
---|
[14] | 194 | #define INCL_WINRECTANGLES
|
---|
| 195 | #define INCL_WINTRACKRECT
|
---|
| 196 |
|
---|
[8] | 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)
|
---|
[21] | 215 | * see shapewin.c.
|
---|
[8] | 216 | */
|
---|
| 217 |
|
---|
| 218 | /* ******************************************************************
|
---|
[14] | 219 | *
|
---|
| 220 | * Global variables
|
---|
| 221 | *
|
---|
[8] | 222 | ********************************************************************/
|
---|
| 223 |
|
---|
| 224 | BOOL G_ShapeRegisteredRegion = FALSE;
|
---|
| 225 |
|
---|
| 226 | /* ******************************************************************
|
---|
[14] | 227 | *
|
---|
| 228 | * Part 1: Shape window functions
|
---|
| 229 | *
|
---|
[8] | 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 |
|
---|
[222] | 310 | STATIC void spanFree(PSHPSPAN pSpan)
|
---|
[8] | 311 | {
|
---|
| 312 | if (pSpan != NULL)
|
---|
| 313 | free(pSpan);
|
---|
| 314 | }
|
---|
| 315 |
|
---|
| 316 | /*
|
---|
| 317 | * spanCreate:
|
---|
| 318 | * this creates SPAN_ALLOC_STEP SHPSPAN structures.
|
---|
| 319 | */
|
---|
| 320 |
|
---|
[222] | 321 | STATIC PSHPSPAN spanCreate(void)
|
---|
[8] | 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 |
|
---|
[222] | 344 | STATIC PSHPSPAN spanExpand(PSHPSPAN pOld)
|
---|
[8] | 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 |
|
---|
[222] | 371 | STATIC PSHPSPAN spanAppend(PSHPSPAN pSpan,
|
---|
[142] | 372 | int y, // bottom y; top y = y+1
|
---|
| 373 | int x1, // left x
|
---|
| 374 | int x2) // right x
|
---|
[8] | 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 |
|
---|
[142] | 427 | static BOOL ptisin(PSHPSPAN pSpan, int x, int y)
|
---|
[8] | 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 |
|
---|
[142] | 455 | static void dumpSpan(PSHPSPAN pSpan)
|
---|
[8] | 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 |
|
---|
[222] | 499 | STATIC void shprgnDraw(HPS hps, PSHPREGION pRgn)
|
---|
[8] | 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 |
|
---|
[222] | 520 | STATIC MRESULT EXPENTRY shp_fnwpShapeRegion(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
|
---|
[8] | 521 | {
|
---|
| 522 | PSHPREGION pRgn;
|
---|
| 523 | HPS hps ;
|
---|
| 524 |
|
---|
[14] | 525 | pRgn = (PSHPREGION)WinQueryWindowPtr(hwnd, 0);
|
---|
[8] | 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);
|
---|
[238] | 539 | return (MRESULT)FALSE;
|
---|
[8] | 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) ;
|
---|
[238] | 551 | return (MRESULT)0;
|
---|
[8] | 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 | }
|
---|
[184] | 580 |
|
---|
[8] | 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 |
|
---|
[222] | 593 | STATIC int shpmgrWMAdjustWindowPos(PSHPWINCTLDATA pCtrl, PSWP pSwp)
|
---|
[8] | 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 | } */
|
---|
[184] | 650 |
|
---|
[8] | 651 | return 0;
|
---|
| 652 | }
|
---|
| 653 |
|
---|
| 654 | /*
|
---|
| 655 | * shpmgrUpdateRegions:
|
---|
| 656 | * this gets called by shp_fnwpShapeMgr upon receiving
|
---|
| 657 | * SHAPEWIN_MSG_UPDATE.
|
---|
| 658 | */
|
---|
| 659 |
|
---|
[222] | 660 | STATIC int shpmgrUpdateRegions(PSHPWINCTLDATA pCtrl, PRECTL pRect)
|
---|
[8] | 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 | }
|
---|
[184] | 679 |
|
---|
[8] | 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 | }
|
---|
[184] | 688 |
|
---|
[8] | 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 |
|
---|
[222] | 708 | STATIC PSHPSPAN shpmgrParseBitmap(HPS hps, PBITMAPINFOHEADER2 bmih2)
|
---|
[8] | 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 | }
|
---|
[184] | 789 |
|
---|
[8] | 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 |
|
---|
[222] | 822 | STATIC int shpmgrWMCreate_Bitmap2Regions(PSHPWINCTLDATA pCtrl, // in: shape control data
|
---|
[142] | 823 | HPS hpsMask) // in: HPS with selected bitmap
|
---|
[8] | 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 |
|
---|
[222] | 944 | STATIC int shpmgrWMCreate_Regions2Windows(PSHPWINCTLDATA pCtrl)
|
---|
[8] | 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 | }
|
---|
[184] | 1004 |
|
---|
[8] | 1005 | return 0;
|
---|
| 1006 | }
|
---|
| 1007 |
|
---|
| 1008 | /*
|
---|
| 1009 | * shpmgrFreeRegion:
|
---|
| 1010 | * cleanup during WM_DESTROY.
|
---|
| 1011 | */
|
---|
| 1012 |
|
---|
[222] | 1013 | STATIC int shpmgrFreeRegion(PSHPWINCTLDATA pCtrl)
|
---|
[8] | 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 |
|
---|
[222] | 1043 | STATIC PSHPWINCTLDATA shpmgrWMCreate(HWND hwnd, // in: shape window
|
---|
[142] | 1044 | PCREATESTRUCT pWin, // in: create struct of WM_CREATE
|
---|
| 1045 | PSHPCTLDATA pData) // in: SHPCTLDATA struct (WM_CREATE mp1)
|
---|
[8] | 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 |
|
---|
[222] | 1097 | STATIC void shpmgrWMDestroy(PSHPWINCTLDATA pCtrl)
|
---|
[8] | 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 |
|
---|
[222] | 1147 | STATIC MRESULT EXPENTRY shp_fnwpShapeMgr(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
|
---|
[8] | 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)
|
---|
[238] | 1175 | return (MRESULT)TRUE;
|
---|
[8] | 1176 |
|
---|
| 1177 | // store control data in window words
|
---|
| 1178 | WinSetWindowPtr(hwnd, 0, (PVOID) pCtrl);
|
---|
[238] | 1179 | return (MRESULT)FALSE;
|
---|
[8] | 1180 |
|
---|
| 1181 | /*
|
---|
| 1182 | * WM_DESTROY:
|
---|
| 1183 | * clean up.
|
---|
| 1184 | */
|
---|
| 1185 |
|
---|
| 1186 | case WM_DESTROY:
|
---|
| 1187 | // TRACE("WM_DESTORY\n");
|
---|
| 1188 | shpmgrWMDestroy(pCtrl);
|
---|
[238] | 1189 | return (MRESULT)0;
|
---|
[8] | 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;
|
---|
[238] | 1214 | return (MRESULT)0;
|
---|
[8] | 1215 |
|
---|
| 1216 | /*
|
---|
| 1217 | * SHAPEWIN_MSG_UPDATE:
|
---|
| 1218 | *
|
---|
| 1219 | */
|
---|
| 1220 |
|
---|
| 1221 | case SHAPEWIN_MSG_UPDATE:
|
---|
| 1222 | shpmgrUpdateRegions(pCtrl, (PRECTL) PVOIDFROMMP(mp1));
|
---|
[238] | 1223 | return (MRESULT)0;
|
---|
[8] | 1224 |
|
---|
| 1225 | /*
|
---|
| 1226 | * WM_QUERYDLGCODE:
|
---|
| 1227 | *
|
---|
| 1228 | */
|
---|
| 1229 |
|
---|
| 1230 | case WM_QUERYDLGCODE:
|
---|
| 1231 | // TRACE("WM_QUERYDLGCODE\n");
|
---|
[14] | 1232 | return (MRESULT)DLGC_STATIC;
|
---|
[8] | 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);
|
---|
[238] | 1272 | return (MRESULT)0;
|
---|
[8] | 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 | /* ******************************************************************
|
---|
[14] | 1311 | *
|
---|
| 1312 | * Part 2: Shape frame functions
|
---|
| 1313 | *
|
---|
[8] | 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
|
---|
[51] | 1346 | *@@changed V0.9.9 (2001-03-18) [lafaix]: brc was not set
|
---|
[8] | 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;
|
---|
[51] | 1359 | BOOL brc = FALSE;
|
---|
[8] | 1360 |
|
---|
| 1361 | psb->hab = hab;
|
---|
| 1362 |
|
---|
[154] | 1363 | if (psb->hdc = DevOpenDC(hab, OD_MEMORY, "*", 0, NULL, NULLHANDLE))
|
---|
[8] | 1364 | {
|
---|
| 1365 | siz.cx = siz.cy = 0;
|
---|
[154] | 1366 | if (psb->hps = GpiCreatePS(hab,
|
---|
| 1367 | psb->hdc,
|
---|
| 1368 | &siz,
|
---|
| 1369 | PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC))
|
---|
[8] | 1370 | {
|
---|
| 1371 | if (pszBitmapFile)
|
---|
| 1372 | {
|
---|
| 1373 | // load bitmap file
|
---|
[154] | 1374 | if (gpihLoadBitmapFile(&psb->hbm,
|
---|
| 1375 | psb->hps,
|
---|
| 1376 | pszBitmapFile))
|
---|
| 1377 | psb->hbm = NULLHANDLE;
|
---|
| 1378 | }
|
---|
| 1379 | else
|
---|
[8] | 1380 | // load resource bitmap
|
---|
| 1381 | psb->hbm = GpiLoadBitmap(psb->hps,
|
---|
[110] | 1382 | hmodResource,
|
---|
| 1383 | idResource,
|
---|
| 1384 | 0, 0);
|
---|
[8] | 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 | }
|
---|
[167] | 1402 | return brc;
|
---|
[8] | 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 |
|
---|
[167] | 1595 | return brc;
|
---|
[8] | 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 |
|
---|
[167] | 1702 | return mrc;
|
---|
[8] | 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 |
|
---|