home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
xwphescr.zip
/
XWPH0208.ZIP
/
src
/
helpers
/
shapewin.c
< prev
next >
Wrap
Text File
|
2002-07-05
|
55KB
|
1,723 lines
/*
*@@sourcefile shapewin.c:
* contains helper functions for "shaped" PM windows which
* can be non-rectangular in shape and have transparency.
*
* This file is new with V0.85.
*
* Usage: All PM programs.
*
* Function prefixes:
* -- shp* shape window functions
*
* This file consists of two parts:
*
* *** Part 1 ***
*
* The code in Part 1 implements the "Shape" window. This is used
* to display a bitmap on the screen with transparency.
*
* Really, it is not the "Shape" window which displays the bitmap.
* Since PM can only handle rectangular windows, as many subwindows
* as required are created, which are only managed by the (invisible)
* "Shape" window.
*
* See shp_fnwpShapeMgr for a window hierarchy.
*
* If you are not using the frame window functions in Part 2, the
* shape window class must be registered like this (the declarations
* are in shapewin.h):
*
+ WinRegisterClass(
+ hab, // anchor block handle
+ SHAPE_WINDOW_CLASS, // class name (shapewin.h)
+ shp_fnwpShapeMgr, // window procedure (in this file)
+ 0L, // default window style
+ sizeof(PVOID)) ; // class data size
*
* You can then create shape windows using WinCreateWindow():
+ hwndShape = WinCreateWindow(
+ hwndParent, // see remark (2)
+ SHAPE_WINDOW_CLASS, // class name (shapewin.h)
+ pszName, // doesn't matter
+ flStyle, // can be 0
+ x, y, cx, cy, // can all be 0; shape window
+ // size depends on bitmap
+ hwndOwner, // see remark (2)
+ hwndInsertBehind, // should be HWND_TOP
+ id,
+ pCtlData, // *SHPCTLDATA, see remark (1)
+ pPresParams); // NULL
*
* Remarks:
*
* 1) Shape windows _require_ a SHPCTLDATA structure for input with
* the pCtlData parameter of WinCreateWindow. This structure
* must contain the following:
+ SHORT cx, cy ; // bitmap size
+ HPS hpsMask; // HPS with bitmap selected into
+ HPS hpsDraw; // HPS used for drawing the bitmap
*
* Note that the bitmap in hpsMask determines the drawing mask
* of the bitmap, while the bitmap in hpsDraw determines the
* bitmap to be drawn. You can use the same HPS (and thus
* the same bitmap) for both, but you can also use different
* ones.
*
* You _must_ select the bitmap(s) to be displayed into the HPS's,
* using GpiSetBitmap, or nothing will work. shpLoadBitmap
* in Part 2 of this file offers you a one-shot function for
* loading a bitmap either from resources or a PM 1.3 *.BMP
* file.
*
* Transparency is determined according to the most lower-left
* pixel of the bitmap in hpsMask. That is, all hpsDraw bitmap
* pixels which have the same color as hpsMask pixel (0, 0)
* will be made transparent.
*
* During window creation, the shape window analyzes the bitmap
* which was selected into hpsMask and creates lots of rectangular
* PM windows as neccessary. This is dependent of the
* "transparency" pixels of the bitmap.
*
* There is no limit for the size of the bitmap (in the HPS's).
* But you should be very careful with large bitmaps, because
* this can block the system forever. Shape windows are real
* CPU hogs. The number of PM subwindows created depends on the
* size of the bitmap and on the transparency. The calculations
* are line-based:
* -- each line is examined, and a PM window is created for
* each line of the input bitmap;
* -- if this line contains "transparency" pixels, more PM
* windows are created accordingly for that line.
* -- However, if several vertically adjacent subwindows have
* the same left and right coordinates, they are combined
* into one window.
*
* As a result, the more single transparent pixels you have,
* the more windows need to be created. The more rectangular
* transparent areas you have, the less windows need to be
* created.
*
* 2) The "Shape" window requires both a parent and an owner window.
* As always, the parent window determines the visibility, while
* the owner window requires a more abstract relationship. With
* shape windows, the owner window is important because all the
* input messages (for mouse and keyboard input) are forwarded
* to the owner.
*
* So it's best to set the parent to HWND_DESKTOP and specify
* a frame window for the owner. If you don't already have a
* frame window in your application, you can create an invisible
* frame window just for message handling. That's what the shp*
* functions in Part 2 of this file do (Akira Hatakeyama calls
* this the "Voodoo" feature).
*
* Never use the shape window itself as a top-level window,
* but one of your own windows instead, which own the shape
* window.
*
* Note that the keyboard and mouse input messages which are
* forwarded to the owner contain mouse coordinates relative
* to the rectangular shape subwindow which actually received
* the message, not relative to the frame window. So you better
* determine the real mouse position using WinQueryPointerPos().
*
* Note that the size of the shape window is defined once upon
* creation and cannot be changed later because this would conflict
* with all the subwindows which were created. For the same reason,
* you cannot alter the bitmap of the shape window after creation.
* You must create a second shape bitmap for that.
* Thus all the size parameters in WinSetWindowPos are swallowed and
* ignored.
*
* *** Part 2 ***
*
* This implements a proper invisible frame window for displaying
* shaped bitmap windows directly on the desktop.
* See shpCreateWindows for a working example.
*
* Note: Version numbering in this file relates to XWorkplace version
* numbering.
*
*@@header "helpers\shapewin.h"
*/
/*
* Credits:
* 1) Functions for shaped windows.
* This is based on the ShapeWin library 1.01 (SHAPEWIN.ZIP at
* Hobbes), (C) 1998, 1999 Software Research Associates, Inc.
* This has been written by Akira Hatakeyama (akira@sra.co.jp).
* Updated by Takayuki Suwa (jjsuwa@ibm.net).
* The original was placed under the GPL.
*
* Changes made by Ulrich Möller (February 1999):
* -- some speedup (marked with *UM)
* -- renamed and commented out almost all of the functions
* and structures to make their use more lucid.
*
* 2) Functions for easily creating shape frame windows from a
* given HBITMAP. This has been written by me, after getting
* some inspiration from the sample programs in SHAPEWIN.ZIP.
*
* Copyright (C) 1998-2000
* Ulrich Möller,
* Akira Hatakeyama,
* Takayuki Suwa.
* This file is part of the "XWorkplace helpers" source package.
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, in version 2 as it comes in the
* "COPYING" file of the XWorkplace main distribution.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#define OS2EMX_PLAIN_CHAR
// this is needed for "os2emx.h"; if this is defined,
// emx will define PSZ as _signed_ char, otherwise
// as unsigned char
#define INCL_DOSERRORS
#define INCL_WINWINDOWMGR
#define INCL_WINFRAMEMGR
#define INCL_WINDIALOGS
#define INCL_WININPUT
#define INCL_WINPOINTERS
#define INCL_WINSYS
#define INCL_WINRECTANGLES
#define INCL_WINTRACKRECT
#define INCL_GPILOGCOLORTABLE
#define INCL_GPIPRIMITIVES
#define INCL_GPIBITMAPS
#include <os2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "setup.h" // code generation and debugging options
#include "helpers\gpih.h"
#include "helpers\shapewin.h"
#pragma hdrstop
/*
*@@category: Helpers\PM helpers\Window classes\Shaped windows (transparency)
* see shapewin.c.
*/
/* ******************************************************************
*
* Global variables
*
********************************************************************/
BOOL G_ShapeRegisteredRegion = FALSE;
/* ******************************************************************
*
* Part 1: Shape window functions
*
********************************************************************/
// forward declarations for structures, because
// the structures are referenced from each other
typedef struct _SHPWINCTLDATA *PSHPWINCTLDATA;
typedef struct _SHPREGION *PSHPREGION;
/*
* SHPWINCTLDATA:
* internal shape window control data.
* This is the shape-window-internal structure
* to allow the shape window to manage itself.
* This is created in WM_CREATE with the data
* passed in the mp1 and mp2 parameters
* (CREATESTRUCT and SHPCTLDATA).
* This is stored in a shape window's window words.
*/
typedef struct _SHPWINCTLDATA
{
// common window parameters
// (copied from CREATESTRUCT in WM_CREATE)
HWND hwndShape ; // main shape window handle
HWND hwndParent; // shape window's parent (should be HWND_DESKTOP)
HWND hwndOwner ; // shape window's owner, to whom we'll forward all
// all the input messages
USHORT id ; // window ID
SHORT x ; // x - horz. position
SHORT y ; // y - vert. position
SHORT cx ; // horz. size
SHORT cy ; // vert. size
PSZ pszText ; // window text
// additional window parameters
HPS hpsDraw; // the input HPS with the bitmap
ULONG nRegion; // number of "regions"
PSHPREGION aRegion; // array of "regions"
} SHPWINCTLDATA;
/*
* SHPREGION:
* this is the structure for shape window
* "regions". Note that has nothing to do
* with GPI regions, but is simply a structure
* for each rectangular area in the shape
* window's bitmap which can be displayed
* as a rectangular PM window.
*/
typedef struct _SHPREGION
{
PSHPWINCTLDATA pCtrl; // link to parent
HWND hwnd ; // drawing window
RECTL rect ; // rectangle of sub-bitmap
} SHPREGION;
/*
* SHPSPAN:
* this is a temporary structure used during
* the creation of SHPREGION's from the
* input bitmap.
*/
typedef struct _SHPSPAN {
ULONG nSize ;
ULONG nUsed ;
RECTL aSpan[1];
} SHPSPAN, *PSHPSPAN;
// the following defines how many SHPSPAN structures
// will be initially created and afterwards for span
// expansions by spanExpand
#define SPAN_ALLOC_STEP 1024
/*
* spanFree:
*
*/
static void spanFree(PSHPSPAN pSpan)
{
if (pSpan != NULL)
free(pSpan);
}
/*
* spanCreate:
* this creates SPAN_ALLOC_STEP SHPSPAN structures.
*/
static PSHPSPAN spanCreate(void)
{
PSHPSPAN pSpan;
int len ;
len = sizeof(SHPSPAN) + sizeof(RECTL) * SPAN_ALLOC_STEP;
if ((pSpan = (PSHPSPAN)malloc(len)) == NULL)
return NULL;
memset(pSpan, 0, len);
pSpan->nSize = SPAN_ALLOC_STEP;
pSpan->nUsed = 0 ;
return pSpan;
}
/*
* spanExpand:
* this expands the memory used for the SHPSPAN
* structures if more spans need to be appended.
* Another SPAN_ALLOC_STEP SHPSPAN structures are created.
*/
static PSHPSPAN spanExpand(PSHPSPAN pOld)
{
PSHPSPAN pNew;
int len ;
// TRACE("spanExpand\n");
len = sizeof(SHPSPAN) + sizeof(RECTL) * (pOld->nSize + SPAN_ALLOC_STEP);
if ((pNew = (PSHPSPAN)malloc(len)) == NULL)
return NULL;
memset(pNew, 0, len);
pNew->nSize = pOld->nSize + SPAN_ALLOC_STEP;
pNew->nUsed = pOld->nUsed;
memcpy(pNew->aSpan, pOld->aSpan, sizeof(RECTL) * pOld->nUsed);
spanFree(pOld);
return pNew;
}
/*
* spanAppend:
* this adds a new SHPSPAN to the list of spans.
*
*/
static PSHPSPAN spanAppend(PSHPSPAN pSpan,
int y, // bottom y; top y = y+1
int x1, // left x
int x2) // right x
{
int i;
PRECTL p;
PSHPSPAN pNew;
// TRACE("spanAppend %d (%d %d)\n", y, x1, x2);
/*
* check if continuous one
*/
for (i = 0; i < pSpan->nUsed; i++) {
p = &pSpan->aSpan[i];
if (p->yTop == y && p->xLeft == x1 && p->xRight == x2)
{
p->yTop += 1;
return pSpan; // merged
}
}
/*
* if not enough space, expand
*/
if ((pSpan->nUsed + 1) >= pSpan->nSize)
{
if ((pNew = spanExpand(pSpan)) == NULL)
return NULL;
pSpan = pNew;
}
/*
* append a rectangle
*/
pSpan->aSpan[pSpan->nUsed].yTop = y + 1;
pSpan->aSpan[pSpan->nUsed].yBottom = y ;
pSpan->aSpan[pSpan->nUsed].xLeft = x1;
pSpan->aSpan[pSpan->nUsed].xRight = x2;
pSpan->nUsed += 1;
return pSpan;
}
#ifdef SHPDEBUG
/*
* ptisin:
*
*/
static BOOL ptisin(PSHPSPAN pSpan, int x, int y)
{
int i;
for (i = 0; i < pSpan->nUsed; i++)
{
if (y >= pSpan->aSpan[i].yTop) {
continue;
}
if (y < pSpan->aSpan[i].yBottom) {
continue;
}
if (x < pSpan->aSpan[i].xLeft) {
continue;
}
if (x >= pSpan->aSpan[i].xRight) {
continue;
}
return TRUE;
}
return FALSE;
}
/*
* dumpSpan:
*
*/
static void dumpSpan(PSHPSPAN pSpan)
{
int i, maxx, maxy, x, y;
TRACE("dumpSpan %d\n", pSpan->nUsed);
maxx = maxy = 0;
for (i = 0; i < pSpan->nUsed; i++)
{
if (pSpan->aSpan[i].yTop > maxy)
{
maxy = pSpan->aSpan[i].yTop;
}
if (pSpan->aSpan[i].xRight > maxx)
{
maxx = pSpan->aSpan[i].xRight;
}
}
for (y = maxy - 1; y >= 0; y--)
{
printf("%03d : ", y);
for (x = 0; x < maxx; x++)
{
if (ptisin(pSpan, x, y))
printf("#");
else
printf("_");
}
printf("\n");
}
}
#endif // SHPDEBUG
/*
* shprgnDraw:
* this gets called upon receiving WM_PAINT in
* shp_fnwpShapeRegion. We simply draw the
* subrectangle from the shape window's bitmap
* which corresponds to our region rectangle.
*/
static void shprgnDraw(HPS hps, PSHPREGION pRgn)
{
POINTL apt[3];
apt[0].x = 0;
apt[0].y = 0;
apt[1].x = (pRgn->rect.xRight - pRgn->rect.xLeft);
apt[1].y = (pRgn->rect.yTop - pRgn->rect.yBottom);
apt[2].x = pRgn->rect.xLeft ;
apt[2].y = pRgn->rect.yBottom;
GpiBitBlt(hps, pRgn->pCtrl->hpsDraw, 3, apt, ROP_SRCCOPY, 0);
}
/*
*@@ shp_fnwpShapeRegion:
* this is the window procedure for each of the
* shape window's rectangular subwindows.
*
* See shp_fnwpShapeMgr for a window hierarchy.
*/
static MRESULT EXPENTRY shp_fnwpShapeRegion(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
PSHPREGION pRgn;
HPS hps ;
pRgn = (PSHPREGION)WinQueryWindowPtr(hwnd, 0);
switch (msg)
{
/*
* WM_CREATE:
* store the SHPREGION pointer in our
* window words.
*/
case WM_CREATE:
// TRACE("WM_CREATE\n");
pRgn = (PSHPREGION)PVOIDFROMMP(mp1);
WinSetWindowPtr(hwnd, 0, (PVOID) pRgn);
return (MRESULT) FALSE;
/*
* WM_PAINT:
* draw our subrectangle of the main bitmap.
*/
case WM_PAINT:
// TRACE("WM_PAINT (%d %d) (%d %d)\n", pRgn->rect.yBottom, pRgn->rect.xLeft, pRgn->rect.yTop, pRgn->rect.xRight);
hps = WinBeginPaint(hwnd, NULLHANDLE, NULL);
shprgnDraw(hps, pRgn);
WinEndPaint(hps) ;
return (MRESULT) 0;
case WM_MOUSEMOVE :
case WM_BUTTON1DOWN :
case WM_BUTTON1UP :
case WM_BUTTON1CLICK :
case WM_BUTTON1DBLCLK:
case WM_BUTTON2DOWN :
case WM_BUTTON2UP :
case WM_BUTTON2CLICK :
case WM_BUTTON2DBLCLK:
case WM_BUTTON3DOWN :
case WM_BUTTON3UP :
case WM_BUTTON3CLICK :
case WM_BUTTON3DBLCLK:
case WM_CHAR :
case WM_VIOCHAR :
case WM_BEGINDRAG :
case WM_ENDDRAG :
case WM_SINGLESELECT :
case WM_OPEN :
case WM_CONTEXTMENU :
case WM_CONTEXTHELP :
case WM_TEXTEDIT :
case WM_BEGINSELECT :
case WM_ENDSELECT :
// forward all these to the shape window
return WinSendMsg(pRgn->pCtrl->hwndShape, msg, mp1, mp2);
}
return WinDefWindowProc(hwnd, msg, mp1, mp2);
}
/*
* shpmgrWMAdjustWindowPos:
* adjust the region windows' positions, visibility etc.
* by going thru the whole region windows list and
* repositioning all the windows.
* This gets called upon receiving WM_ADJUSTWINDOWPOS
* in shp_fnwpShapeMgr.
*/
static int shpmgrWMAdjustWindowPos(PSHPWINCTLDATA pCtrl, PSWP pSwp)
{
int i ;
PSHPREGION pRgn;
ULONG fl ;
// HPS hps ;
PSWP pswpArray;
// TRACE("shpmgrWMAdjustWindowPos - %d, %08x\n", pCtrl->nRegion, pSwp->fl);
if (pCtrl->nRegion == 0 || pCtrl->aRegion == NULL)
{
// TRACE("ShpDrawRegion - no region to open\n");
return -1;
}
if ((fl = pSwp->fl) & SWP_MOVE)
{
pCtrl->x = pSwp->x;
pCtrl->y = pSwp->y;
}
pswpArray = (PSWP) malloc(sizeof(SWP) * pCtrl->nRegion);
// go thru all the "regions" and adjust their sizes
for (i = 0, pRgn = pCtrl->aRegion;
i < pCtrl->nRegion;
i++, pRgn++)
{
pswpArray[i].fl = fl;
pswpArray[i].cy = (pRgn->rect.yTop - pRgn->rect.yBottom);
pswpArray[i].cx = (pRgn->rect.xRight - pRgn->rect.xLeft);
pswpArray[i].y = (pCtrl->y + pRgn->rect.yBottom);
pswpArray[i].x = (pCtrl->x + pRgn->rect.xLeft);
pswpArray[i].hwndInsertBehind = pSwp->hwndInsertBehind;
pswpArray[i].hwnd = pRgn->hwnd;
}
// set all window positions at once
WinSetMultWindowPos(WinQueryAnchorBlock(pCtrl->hwndShape),
&pswpArray[0],
pCtrl->nRegion);
free((void*) pswpArray);
// calling WinInvalidateRect is not neccessary,
// because the windows' update regions are already
// properly set by WinSetMultWindowPos (*UM)
/* for (i = 0, pRgn = pCtrl->aRegion;
i < pCtrl->nRegion;
i++, pRgn++)
{
if (fl & (SWP_MOVE | SWP_ZORDER)) {
WinInvalidateRect(pRgn->hwnd, NULL, FALSE);
}
} */
return 0;
}
/*
* shpmgrUpdateRegions:
* this gets called by shp_fnwpShapeMgr upon receiving
* SHAPEWIN_MSG_UPDATE.
*/
static int shpmgrUpdateRegions(PSHPWINCTLDATA pCtrl, PRECTL pRect)
{
RECTL rect, intern;
int i ;
PSHPREGION pRgn;
HAB hab ;
// HPS hps ;
// TRACE("shpmgrUpdateRegions\n");
hab = WinQueryAnchorBlock(pCtrl->hwndShape);
if (pRect == NULL) {
rect.xLeft = 0 ;
rect.yBottom = 0 ;
rect.xRight = pCtrl->cx;
rect.yTop = pCtrl->cy;
pRect = ▭
}
for (i = 0, pRgn = pCtrl->aRegion; i < pCtrl->nRegion; i++, pRgn++)
{
if (WinIntersectRect(hab, &intern, pRect, &pRgn->rect) == FALSE) {
continue;
} else {
WinInvalidateRect(pRgn->hwnd, NULL, FALSE);
}
}
return 0;
}
/*
* shpmgrParseBitmap:
* this gets called from shpmgrWMCreate_Bitmap2Regions when the
* shape region windows need to be created.
* This function does the actual bitmap analysis and
* creates a large number of SHPSPAN structures according
* to the bitmaps, which can later be turned into
* PM windows.
* This happens during the processing of WM_CREATE in
* shp_fnwpShapeMgr.
* CPU usage: relatively low. Maybe 5% of the whole creation
* procedure.
*
*@@changed V0.9.1 (99-12-03): fixed memory leak
*/
static PSHPSPAN shpmgrParseBitmap(HPS hps, PBITMAPINFOHEADER2 bmih2)
{
int blen, hlen;
PUCHAR buf;
PBITMAPINFO2 pbmi;
PSHPSPAN pSpan, pNew;
int x, y, k;
LONG first, color;
BOOL inspan;
int left;
// TRACE("shpmgrParseBitmap\n");
hlen = sizeof(BITMAPINFO2) + sizeof(RGB) * 256;
blen = ((bmih2->cBitCount * bmih2->cx + 31) / 32) * bmih2->cPlanes * 4;
pbmi = (PBITMAPINFO2)malloc(hlen);
buf = (PUCHAR)malloc(blen);
if (pbmi == NULL || buf == NULL)
{
// TRACE("shpmgrParseBitmap - failed to alloc %d %d\n", hlen, blen);
if (pbmi)
free(pbmi);
if (buf)
free(buf);
return NULL;
}
memcpy(pbmi, bmih2, sizeof(BITMAPINFOHEADER2));
if ((pSpan = spanCreate()) == NULL)
{
// TRACE("shpmgrParseBitmap - failed to make\n");
free(pbmi);
free(buf);
return NULL;
}
first = -1;
for (y = 0; y < bmih2->cy; y++)
{
// TRACE("shpmgrParseBitmap - scan line %d\n", y); fflush(stdout);
GpiQueryBitmapBits(hps, y, 1, (PBYTE)buf, pbmi);
for (x = 0, inspan = FALSE; x < bmih2->cx; x++)
{
k = x * 3;
color = ((buf[k] << 16) | (buf[k+1] << 8) | buf[k+2]);
if (first < 0)
{
// first iteration: get the very first color (that
// is the pixel at (0, 0)), with which we will
// compare the others to determine the mask
first = color;
}
if (inspan == FALSE && color != first)
{
inspan = TRUE;
left = x;
}
else if (inspan == TRUE && color == first)
{
// transparent color found:
// create new span
inspan = FALSE;
if ((pNew = spanAppend(pSpan, y, left, x)) != NULL)
{
pSpan = pNew;
}
else
{
// TRACE("shpmgrParseBitmap - failed to extend\n");
break;
}
}
}
if (inspan == TRUE)
{
if ((pNew = spanAppend(pSpan, y, left, x)) != NULL)
pSpan = pNew;
else
// TRACE("shpmgrParseBitmap - failed to extend\n");
break;
}
}
#ifdef SHPDEBUG
dumpSpan(pSpan);
#endif
// fixed these memory leaks V0.9.1 (99-12-03)
if (pbmi)
free(pbmi);
if (buf)
free(buf);
return pSpan;
}
/*
* shpmgrWMCreate_Bitmap2Regions:
* this gets called from shpmgrWMCreate (WM_CREATE) to have a
* drawing region created from the bitmap which has been
* selected into the given HPS.
*
* First step in WM_CREATE.
*/
static int shpmgrWMCreate_Bitmap2Regions(PSHPWINCTLDATA pCtrl, // in: shape control data
HPS hpsMask) // in: HPS with selected bitmap
{
HAB hab;
HDC hdc;
HPS hps;
SIZEL siz;
HBITMAP hbm,
hbmPrevious;
BITMAPINFOHEADER2 bmi;
POINTL apt[3];
PSHPSPAN pSpan;
PSHPREGION pRegn;
int i;
// TRACE("shpmgrWMCreate_Bitmap2Regions\n");
hab = WinQueryAnchorBlock(pCtrl->hwndShape);
/*
* Create Memory DC & HPS
*/
hdc = DevOpenDC(hab, OD_MEMORY, "*", 0, NULL, NULLHANDLE);
siz.cx = siz.cy = 0;
hps = GpiCreatePS(hab, hdc, &siz,
PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC);
/*
* Create Bitmap and relate to memory PS
*/
memset(&bmi, 0, sizeof(bmi));
bmi.cbFix = sizeof(BITMAPINFOHEADER2);
bmi.cx = pCtrl->cx;
bmi.cy = pCtrl->cy;
bmi.cPlanes = 1 ;
bmi.cBitCount = 24;
bmi.ulCompression = 0 ;
bmi.cclrUsed = 0 ;
bmi.cclrImportant = 0 ;
hbm = GpiCreateBitmap(hps, &bmi, 0, NULL, NULL);
hbmPrevious = GpiSetBitmap(hps, hbm);
/*
* Copy in Mask Pattern
*/
// TRACE("shpmgrWMCreate_Bitmap2Regions - copyin %d x %d mask pattern\n", bmi.cx, bmi.cy);
apt[0].x = 0; // Target
apt[0].y = 0;
apt[1].x = bmi.cx;
apt[1].y = bmi.cy;
apt[2].x = 0; // Source
apt[2].y = 0;
if (GpiBitBlt(hps, pCtrl->hpsDraw, 3, apt, ROP_SRCCOPY, 0) == GPI_ERROR) {
// TRACE("MakeRect - BitBlt Failed %08x, hdc %08x, hps %08x, hbm %08x\n",
// WinGetLastError(hab), hdc, hps, hbm);
}
/*
* Parse Mask Pattern
*/
// call shpmgrParseBitmap; this does the actual creation of the
// "spans" by comparing all bitmap pixels to the (0, 0)
// pixel
if ((pSpan = shpmgrParseBitmap(hps, &bmi)) != NULL)
{
if ((pRegn = (PSHPREGION) malloc(sizeof(SHPREGION) * pSpan->nUsed)) == NULL)
{
// TRACE("shpmgrWMCreate_Bitmap2Regions - failed to alloc\n");
}
else
{
// mask created successfully:
pCtrl->nRegion = pSpan->nUsed;
pCtrl->aRegion = pRegn;
for (i = 0; i < pSpan->nUsed; i++)
{
pRegn[i].pCtrl = pCtrl;
pRegn[i].hwnd = NULLHANDLE;
pRegn[i].rect.xLeft = pSpan->aSpan[i].xLeft ;
pRegn[i].rect.xRight = pSpan->aSpan[i].xRight ;
pRegn[i].rect.yTop = pSpan->aSpan[i].yTop ;
pRegn[i].rect.yBottom = pSpan->aSpan[i].yBottom;
}
}
spanFree(pSpan);
}
/*
* dispose local resources
*/
GpiSetBitmap(hps, hbmPrevious); // (*UM)
GpiDeleteBitmap(hbm);
GpiDestroyPS(hps);
DevCloseDC(hdc);
return 0;
}
/*
* shpmgrWMCreate_Regions2Windows:
* this gets called from shpmgrWMCreate (WM_CREATE) to convert
* all the "regions" that have been created by shpmgrWMCreate_Bitmap2Regions
* in pCtrl to individual rectangular PM windows.
*
* CPU usage: extremely high, because all the dull PM functions
* take so damn long. Calculating the "regions" isn't really
* difficult, but it's the PM windows which cause the CPU hog.
*
* Second step in WM_CREATE.
*/
static int shpmgrWMCreate_Regions2Windows(PSHPWINCTLDATA pCtrl)
{
int i ;
PSHPREGION pRgn;
ULONG flStyle;
// TRACE("shpmgrWMCreate_Regions2Windows %d regions\n", pCtrl->nRegion);
// check if any "regions" exist at all
if (pCtrl->nRegion == 0 || pCtrl->aRegion == NULL)
{
// TRACE("shpmgrWMCreate_Regions2Windows - no region to open\n");
return -1;
}
if (G_ShapeRegisteredRegion == FALSE)
{
// first call: register "shape region" class
WinRegisterClass(WinQueryAnchorBlock(pCtrl->hwndShape),
WC_SHAPE_REGION,
shp_fnwpShapeRegion,
CS_PARENTCLIP
// use parent's clipping region instead
// of the one of the region window
| CS_CLIPSIBLINGS
// don't allow the subwindows to paint
// over siblings (ie. windows with the
// same parent); this is neccessary if
// HWND_DESKTOP is the parent
| CS_SYNCPAINT,
// paint immediately
sizeof(PVOID));
G_ShapeRegisteredRegion = TRUE;
}
flStyle = 0;
// now go thru the "regions" list
for (i = 0, pRgn = pCtrl->aRegion;
i < pCtrl->nRegion;
i++, pRgn++)
{
// and create a window for each "region"
pRgn->hwnd = WinCreateWindow(
pCtrl->hwndParent, // copy parent window from shape window
// changed (*UM)
// HWND_DESKTOP, // Parent Window
WC_SHAPE_REGION, // window class
NULL, // window text
flStyle, // window style
(pCtrl->x + pRgn->rect.xLeft), // x
(pCtrl->y + pRgn->rect.yBottom), // y
(pRgn->rect.xRight - pRgn->rect.xLeft), // cx
(pRgn->rect.yTop - pRgn->rect.yBottom), // cy
pCtrl->hwndOwner, // Owner Window
HWND_TOP, // Z-Order
i, // Window ID
pRgn, // Control Data
NULL); // Pres. Param.
}
return 0;
}
/*
* shpmgrFreeRegion:
* cleanup during WM_DESTROY.
*/
static int shpmgrFreeRegion(PSHPWINCTLDATA pCtrl)
{
int i ;
PSHPREGION pRgn;
for (i = 0, pRgn = pCtrl->aRegion;
i < pCtrl->nRegion;
i++, pRgn++)
WinDestroyWindow(pRgn->hwnd);
free(pCtrl->aRegion);
return 0;
}
/*
* shpmgrWMCreate:
* this initializes the "shape window".
* This gets called upon receiving WM_CREATE in shp_fnwpShapeMgr.
* The procedure is as follows:
* 1) the bitmap in pData->hpsDraw is analyzed pixel by
* pixel to create a number of "regions" from it
* (which are not GPI regions, but an array of SHPREGION
* structures. At least one of these structures is
* created for each line. This is done by calling
* shpmgrWMCreate_Bitmap2Regions.
* 2) We then call shpmgrWMCreate_Regions2Windows to actually create
* PM windows from all these structures.
*/
static PSHPWINCTLDATA shpmgrWMCreate(HWND hwnd, // in: shape window
PCREATESTRUCT pWin, // in: create struct of WM_CREATE
PSHPCTLDATA pData) // in: SHPCTLDATA struct (WM_CREATE mp1)
{
PSHPWINCTLDATA pCtrl;
if (pData->hpsDraw == NULLHANDLE || pData->hpsMask == NULLHANDLE) {
return NULL;
}
// create new PSHPWINCTLDATA structure
if ((pCtrl = (PSHPWINCTLDATA) malloc(sizeof(SHPWINCTLDATA))) == NULL) {
return NULL;
}
/*
* Setup Common Window Parameters
*/
pCtrl->hwndShape = hwnd;
pCtrl->hwndParent = pWin->hwndParent;
pCtrl->hwndOwner = pWin->hwndOwner ;
pCtrl->id = pWin->id;
pCtrl->x = pWin->x ;
pCtrl->y = pWin->y ;
pCtrl->cx = pWin->cx;
pCtrl->cy = pWin->cy;
/*
* Setup Image Window's Control Data
*/
pCtrl->cx = pData->cx;
pCtrl->cy = pData->cy;
pCtrl->hpsDraw = pData->hpsDraw;
// now create "regions" from bitmap;
// this will store the "regions" in pCtrl
shpmgrWMCreate_Bitmap2Regions(pCtrl, pData->hpsMask);
// now create as many rectangular PM
// windows as we have "regions" in pCtrl
shpmgrWMCreate_Regions2Windows(pCtrl);
return pCtrl;
}
/*
* shpmgrWMDestroy:
* this cleans up the shape's resources.
* Gets called upon receiving WM_DESTROY in
* shp_fnwpShapeMgr.
*/
static void shpmgrWMDestroy(PSHPWINCTLDATA pCtrl)
{
if (pCtrl == NULL)
return;
shpmgrFreeRegion(pCtrl);
free(pCtrl);
}
/*
*@@ shp_fnwpShapeMgr:
* this is the window procedure for the "shape window manager".
* Register this procedure with WinRegisterWindowClass.
*
* This does the transformation of the bitmap into many
* rectangular subwindows upon WM_CREATE, each of which
* will use shp_fnwpShapeRegion as its window proc.
*
* There should be the following window hierarchy (the
* lines signify ownership):
*
+ Your owner window
+ |
+ +-- owns "shape manager" window (this window proc)
+ |
+ +-- lots of "region" windows (shp_fnwpShapeRegion)
+ +-- ...
*
* The "region" windows are owned by the "shape manager" window,
* but have the same parent as the "shape manager" window.
* Normally, this should be set to HWND_DESKTOP when creating the
* "shape" window.
*
* This window procedure forwards the following messages
* to its owner:
* -- WM_MOUSEMOVE
* -- all WM_BUTTONxxx messages
* -- WM_CHAR
* -- WM_VIOCHAR
* -- WM_BEGINDRAG
* -- WM_ENDDRAG
* -- WM_SINGLESELECT
* -- WM_OPEN
* -- WM_CONTEXTMENU
* -- WM_CONTEXTHELP
* -- WM_TEXTEDIT
* -- WM_BEGINSELECT
* -- WM_ENDSELECT
*/
static MRESULT EXPENTRY shp_fnwpShapeMgr(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
PSHPWINCTLDATA pCtrl;
PSWP pswp ;
// SHORT sx; // , sy;
pCtrl = (PSHPWINCTLDATA) WinQueryWindowPtr(hwnd, 0);
switch (msg)
{
/*
* WM_CREATE:
* shape window is being created.
* Parameters:
* PSHPCTLDATA mp1
* PCREATESTRUCT mp2
* Shaped windows must have a SHPCTLDATA
* structure in mp1.
*/
case WM_CREATE:
// TRACE("WM_CREATE\n");
pCtrl = shpmgrWMCreate(hwnd,
(PCREATESTRUCT)PVOIDFROMMP(mp2),
(PSHPCTLDATA)PVOIDFROMMP(mp1));
if (pCtrl == NULL)
return (MRESULT) TRUE;
// store control data in window words
WinSetWindowPtr(hwnd, 0, (PVOID) pCtrl);
return (MRESULT) FALSE;
/*
* WM_DESTROY:
* clean up.
*/
case WM_DESTROY:
// TRACE("WM_DESTORY\n");
shpmgrWMDestroy(pCtrl);
return (MRESULT) 0;
/*
* WM_ADJUSTWINDOWPOS:
* this needs to be manipulated to
* adjust the positions of all the
* subwindows instead.
*/
case WM_ADJUSTWINDOWPOS:
// TRACE("WM_ADJUSTWINDOWPOS\n");
pswp = (PSWP) PVOIDFROMMP(mp1);
// DUMPSWP(pswp);
// enforce the size which we were given
// in the beginning, because we cannot
// change the size later
pswp->cx = pCtrl->cx;
pswp->cy = pCtrl->cy;
// adjust the sub-windows
shpmgrWMAdjustWindowPos(pCtrl, pswp);
// never show ourselves
pswp->fl &= ~SWP_SHOW;
return (MRESULT) 0;
/*
* SHAPEWIN_MSG_UPDATE:
*
*/
case SHAPEWIN_MSG_UPDATE:
shpmgrUpdateRegions(pCtrl, (PRECTL) PVOIDFROMMP(mp1));
return (MRESULT) 0;
/*
* WM_QUERYDLGCODE:
*
*/
case WM_QUERYDLGCODE:
// TRACE("WM_QUERYDLGCODE\n");
return (MRESULT)DLGC_STATIC;
/*
* WM_PAINT:
* we just swallow this message because
* there's no "shape window" to be painted;
* instead, all the region windows get
* their own WM_PAINT message
*/
case WM_PAINT:
{
// TRACE("WM_PAINT\n");
/* HPS hps = WinBeginPaint(hwnd, NULLHANDLE, NULL);
POINTL apt[3];
RECTL rclWin;
WinQueryWindowRect(hwnd, &rclWin);
// lower left of target
apt[0].x = 0;
apt[0].y = 0;
// upper right of target
apt[1].x = rclWin.xRight;
apt[1].y = rclWin.yTop;
// lower left of source
apt[2].x = 0;
apt[2].y = 0;
GpiBitBlt(hps,
pCtrl->hpsDraw,
3,
apt,
ROP_SRCCOPY,
0); */
// delete update region to stop further
// WM_PAINTs for this window;
// this is faster than WiNBeginPaint
WinValidateRect(hwnd, NULL, FALSE);
// WinEndPaint(hps);
return (MRESULT) 0;
}
/*
* all input-related messages:
* forward these to the owner
*/
case WM_MOUSEMOVE :
case WM_BUTTON1DOWN :
case WM_BUTTON1UP :
case WM_BUTTON1CLICK :
case WM_BUTTON1DBLCLK:
case WM_BUTTON2DOWN :
case WM_BUTTON2UP :
case WM_BUTTON2CLICK :
case WM_BUTTON2DBLCLK:
case WM_BUTTON3DOWN :
case WM_BUTTON3UP :
case WM_BUTTON3CLICK :
case WM_BUTTON3DBLCLK:
case WM_CHAR :
case WM_VIOCHAR :
case WM_BEGINDRAG :
case WM_ENDDRAG :
case WM_SINGLESELECT :
case WM_OPEN :
case WM_CONTEXTMENU :
case WM_CONTEXTHELP :
case WM_TEXTEDIT :
case WM_BEGINSELECT :
case WM_ENDSELECT :
return WinSendMsg(pCtrl->hwndOwner, msg, mp1, mp2);
} // end switch (msg)
return WinDefWindowProc(hwnd, msg, mp1, mp2);
}
/* ******************************************************************
*
* Part 2: Shape frame functions
*
********************************************************************/
MRESULT EXPENTRY fnwpShapeFrame(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
/*
*@@ shpLoadBitmap:
* this creates a memory device context/presentation space
* and loads and selects a bitmap into it.
*
* If pszBitmap == NULL, the bitmap is loaded from the
* specified resources, otherwise we attempt to load the
* bitmap file specified in pszBitmap (using gpihLoadBitmapFile).
*
* Output in the given SHAPEFRAME structure:
* -- hab: as passed to this func
* -- hdc: device context handle
* -- hps: presentation space handle
* -- hbm: bitmap handle
* -- bmi: BITMAPINFOHEADER of hbmp
* -- ptlLowerLeft: lower left corner is set so that
* bitmap is centered on screen
*
* All other fields are neither read nor written to.
* Returns TRUE if everything went OK.
*
* You can call this function directly before calling
* shpCreateWindows.
*
* Pass the SHAPEFRAME structure to shpFreeBitmap to clean up.
*
*@@changed V0.9.0 [umoeller]: added default window positioning
*@@changed V0.9.0 [umoeller]: removed GpiSetBitmap here
*@@changed V0.9.9 (2001-03-18) [lafaix]: brc was not set
*/
BOOL shpLoadBitmap(HAB hab, // in: anchor block
PSZ pszBitmapFile, // in: OS/2 1.3 bmp file or NULL
HMODULE hmodResource, // in: module handle from where the
// resources should be loaded if
// pszBitmapFile == NULL. This can be 0 for
// the current EXE
ULONG idResource, // in: bitmap resource ID in that module
PSHAPEFRAME psb) // out: bitmap info
{
SIZEL siz;
BOOL brc = FALSE;
psb->hab = hab;
if (psb->hdc = DevOpenDC(hab, OD_MEMORY, "*", 0, NULL, NULLHANDLE))
{
siz.cx = siz.cy = 0;
if (psb->hps = GpiCreatePS(hab,
psb->hdc,
&siz,
PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC))
{
if (pszBitmapFile)
{
// load bitmap file
if (gpihLoadBitmapFile(&psb->hbm,
psb->hps,
pszBitmapFile))
psb->hbm = NULLHANDLE;
}
else
// load resource bitmap
psb->hbm = GpiLoadBitmap(psb->hps,
hmodResource,
idResource,
0, 0);
if (psb->hbm)
{
SWP swpScreen;
// store bitmap info in structure
psb->bmi.cbFix = sizeof(psb->bmi);
GpiQueryBitmapInfoHeader(psb->hbm, &psb->bmi);
// set ptlLowerLeft so that the bitmap
// is centered on the screen
WinQueryWindowPos(HWND_DESKTOP, &swpScreen);
psb->ptlLowerLeft.x = (swpScreen.cx - psb->bmi.cx) / 2;
psb->ptlLowerLeft.y = (swpScreen.cy - psb->bmi.cy) / 2;
brc = TRUE;
}
}
}
return brc;
}
/*
*@@ shpFreeBitmap:
* this cleans up resources allocated by shpLoadBitmap:
* delete the bitmap, destroy the HPS and HDC.
*
*@@changed V0.9.3 (2000-04-11) [umoeller]: fixed major resource leak; the bitmap was never freed
*/
VOID shpFreeBitmap(PSHAPEFRAME psb)
{
if (psb->hbm != NULLHANDLE)
{
// unset bitmap in HPS; it cannot be deleted otherwise...
GpiSetBitmap(psb->hps, NULLHANDLE); // V0.9.3 (2000-04-11) [umoeller]
GpiDeleteBitmap(psb->hbm);
psb->hbm = NULLHANDLE;
}
if (psb->hps != NULLHANDLE)
{
GpiDestroyPS(psb->hps);
psb->hps = NULLHANDLE;
}
if (psb->hdc != NULLHANDLE)
{
DevCloseDC(psb->hdc);
psb->hdc = NULLHANDLE;
}
}
/*
*@@ shpCreateWindows:
* this is a one-shot function for creating a
* shaped window from a bitmap.
*
* Required fields in SHAPEFRAME for input (those
* are all properly set by shpLoadBitmap):
* -- hab: anchor block
* -- hps: presentation space handle
* -- hbm: bitmap handle
* -- bmi: BITMAPINFOHEADER of hbmp
* -- ptlLowerLeft: lower left corner of where
* to position the shape window (new with V0.9.0).
*
* All other fields are ignored for input and only
* set for output (and for the shape window later).
*
* You can use shpLoadBitmap to have all the fields
* initialized, which will also set ptlLowerLeft
* so that the shape window gets centered on the
* Desktop.
*
* Otherwise you must initialize the above fields for
* yourself.
*
* Obviously, this function uses the same HPS (and
* thus bitmap) for both transparency and drawing.
* If you wish to use two different bitmaps (one for
* transparency, one for drawing), you cannot use
* this function.
*
* Note that the windows are now (V0.9.0) also positioned
* on the screen.
*
* Output in that structure:
* -- hwndShapeFrame: invisible rectangular frame
* window for the shape window
* (fnwpShapeFrame, created here)
* -- hwndShape: "shape" window
* (shp_fnwpShapeMgr, created here)
* -- pfnFrame: original window procedure of
* WC_FRAME (hwndShapeFrame),
* which is subclassed here
* using fnwpShapeFrame
* -- shpctrl: control data for hwndShape
*
* Returns TRUE if everything went OK.
*
* <B>Example</B> for creating a shaped window and
* centering it on the screen:
+ SHAPEFRAME sb;
+ if (shpLoadBitmap(hab...,
+ szBitmapFile...,
+ 0, 0,
+ &sb))
+ {
+ // create shape (transparent) windows
+ if (shpCreateWindows(habQuickThread, &sb))
+ {
* ...
+ }
+ }
+ ...
+ // cleanup
+ shpFreeBitmap(&sb);
+ WinDestroyWindow(sb.hwndShapeFrame) ;
+ WinDestroyWindow(sb.hwndShape);
*
*@@changed V0.9.0 [umoeller]: removed hab from function prototype
*@@changed V0.9.0 [umoeller]: added window positioning
*@@changed V0.9.0 [umoeller]: added GpiSetBitmap here (always forget that)
*/
BOOL shpCreateWindows(PSHAPEFRAME psb)
{
BOOL brc = FALSE;
if (psb->hbm)
{
// bitmap seems to be valid:
FRAMECDATA fcd;
GpiSetBitmap(psb->hps, psb->hbm);
memset(&fcd, 0, sizeof(fcd));
fcd.cb = sizeof(fcd);
// create invisible frame
psb->hwndShapeFrame = WinCreateWindow(
HWND_DESKTOP, // Parent window handle
WC_FRAME, // Frame Window Class
"XWorkplaceLogoShape", // title
0, // Window Style
0, 0, 0, 0, // Position & size
NULLHANDLE, // Owner Window
HWND_TOP, // Z-Order
0, // Window ID
&fcd, // Control Data
NULL); // Presentation Parameter
if (psb->hwndShapeFrame)
{
// store the SHAPEFRAME structure in the frame's window words
// so that the subclassed frame can access the data
WinSetWindowULong(psb->hwndShapeFrame, QWL_USER, (ULONG)psb);
// subclass the frame window; store the original wnd proc in
// the SHAPEFRAME structure
psb->pfnFrame = WinSubclassWindow(psb->hwndShapeFrame, fnwpShapeFrame);
if ((psb->hwndShapeFrame) && (psb->hps))
{
// OK, no errors so far
// register shape window class; if this is already
// registered, this won't hurt
WinRegisterClass(psb->hab,
WC_SHAPE_WINDOW,
shp_fnwpShapeMgr,
0L, // class style flags
sizeof(PVOID));
// create shape manager window
psb->shpctrl.cx = psb->bmi.cx;
psb->shpctrl.cy = psb->bmi.cy;
psb->shpctrl.hpsDraw = psb->hps;
psb->shpctrl.hpsMask = psb->hps;
// create the "shape" window
psb->hwndShape = WinCreateWindow(
HWND_DESKTOP, // Parent Window
WC_SHAPE_WINDOW, // Window Class
NULL, // Window Text
0, // Window Style;
// no clip siblings!
0, 0, 0, 0, // Pos & Size
psb->hwndShapeFrame, // Owner Window
HWND_TOP, // Z-Order
0, // Window ID
&psb->shpctrl, // Control Data
NULL); // Pres. Param.
if (psb->hwndShape)
{
// no error: only then return TRUE
brc = TRUE;
// and position the windows
WinSetWindowPos(psb->hwndShapeFrame, NULLHANDLE,
psb->ptlLowerLeft.x, psb->ptlLowerLeft.y,
psb->bmi.cx, psb->bmi.cy,
(SWP_MOVE | SWP_SIZE | SWP_HIDE));
WinSetWindowPos(psb->hwndShape, NULLHANDLE,
psb->ptlLowerLeft.x, psb->ptlLowerLeft.y,
psb->bmi.cx, psb->bmi.cy,
(SWP_MOVE | SWP_SIZE | SWP_SHOW));
}
}
}
}
return brc;
}
/*
*@@ fnwpShapeFrame:
* this is the window proc for subclassing the shape frame window
* (shpCreateWindows above).
* The shaped window proc (shp_fnwpShapeMgr) keeps forwarding messages
* to its owner (which is the frame here), so we better handle
* those messages.
*/
MRESULT EXPENTRY fnwpShapeFrame(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
MRESULT mrc;
// get the SHAPEFRAME structure from the window words,
// which has been stored there by shpCreateWindows
PSHAPEFRAME psb = (PSHAPEFRAME)WinQueryWindowULong(hwnd, QWL_USER);
// _Pmpf(("frame %08x %08x %08x", msg, mp1, mp2));
switch (msg)
{
/*
* WM_ADJUSTWINDOWPOS:
* forward the data we get here to the shape
* window (which will in turn reposition all
* the region windows);
* afterwards, always delete SHOW and set HIDE
* for ourselves
*/
case WM_ADJUSTWINDOWPOS: {
PSWP pswp = (PSWP) PVOIDFROMMP(mp1);
POINTL ptl;
WinQueryPointerPos(HWND_DESKTOP, &ptl);
WinSetWindowPos(psb->hwndShape,
pswp->hwndInsertBehind,
// use current mouse position instead
// of the original ones
ptl.x,
ptl.y,
// pswp->x,
// pswp->y,
pswp->cx,
pswp->cy,
pswp->fl);
pswp->fl &= ~SWP_SHOW;
pswp->fl |= SWP_HIDE;
mrc = (*psb->pfnFrame)(hwnd, msg, mp1, mp2);
break; }
/* the shape window forwards these messages to us:
WM_MOUSEMOVE
WM_BUTTON1DOWN
WM_BUTTON1UP
WM_BUTTON1CLICK
WM_BUTTON1DBLCLK
WM_BUTTON2DOWN
WM_BUTTON2UP
WM_BUTTON2CLICK
WM_BUTTON2DBLCLK
WM_BUTTON3DOWN
WM_BUTTON3UP
WM_BUTTON3CLICK
WM_BUTTON3DBLCLK
WM_CHAR
WM_VIOCHAR
WM_BEGINDRAG
WM_ENDDRAG
WM_SINGLESELECT
WM_OPEN
WM_CONTEXTMENU
WM_CONTEXTHELP
WM_TEXTEDIT
WM_BEGINSELECT
WM_ENDSELECT */
/*
* WM_SINGLESELECT:
* if we are being clicked upon, bring the
* shape window to top instead
*/
case WM_SINGLESELECT:
WinSetWindowPos(psb->hwndShape, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER);
mrc = 0;
break;
/*
* WM_BEGINDRAG:
* if we are being dragged with MB2, forward
* this to the shape window
*/
case WM_BEGINDRAG:
WinSendMsg(psb->hwndShapeFrame, WM_TRACKFRAME,
MPFROMSHORT(TF_MOVE /* | TF_SETPOINTERPOS*/ ), NULL);
mrc = 0;
break;
default:
mrc = (*psb->pfnFrame)(hwnd, msg, mp1, mp2);
}
return mrc;
}
/*
*@@ shp2RegisterClasses:
*
*@@added V0.9.3 (2000-05-03) [umoeller]
*/
BOOL shp2RegisterClasses(HAB hab)
{
// register shape window class; if this is already
// registered, this won't hurt
return(WinRegisterClass(hab,
WC_SHAPE_WINDOW,
shp_fnwpShapeMgr,
0L, // class style flags
sizeof(PVOID)));
}