home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
wpentk.zip
/
WBPENTK2.DSK
/
ISMPROCS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-06
|
98KB
|
2,138 lines
/*****************************************************************************
* *
* File Name : ISMPROCS.C *
* *
* Description : Window Procedures for the ISM_SAMP.EXE *
* *
* Function: This file has all the window procedures for the ISM_SAMP.EXE. *
* *
* Copyright (C) 1993 IBM Corporation *
* *
* DISCLAIMER OF WARRANTIES. The following [enclosed] code is *
* sample code created by IBM Corporation. This sample code is not *
* part of any standard or IBM product and is provided to you solely *
* for the purpose of assisting you in the development of your *
* applications. The code is provided "AS IS", without *
* warranty of any kind. IBM shall not be liable for any damages *
* arising out of your use of the sample code, even if they have been *
* advised of the possibility of such damages. *
* *
*****************************************************************************/
/*****************************************************************************
* Defines *
*****************************************************************************/
#define INCL_PM
#define INCL_GPIPRIMATIVES
/*****************************************************************************
* Includes *
*****************************************************************************/
#include <os2.h>
#include <penpm.h>
#include "ism_samp.h"
BOOL ChangeColor ( PMYWINDOWDATA pMyWindowData, LONG NewColor );
HRGN CreateClipRect ( PMYWINDOWDATA pMyWindowData, SHORT NumSegments );
HWND CreateInkControls ( HWND hWnd );
MRESULT APIENTRY InkEditHelp ( HWND hWnd, ULONG ulMsg, MPARAM mp1, MPARAM mp2 );
/*****************************************************************************
* Debug Messages *
*****************************************************************************/
VOID DebugMessage ( char dmessage[50] )
{
WinMessageBox ( HWND_DESKTOP,
HWND_DESKTOP,
dmessage,
"Debug Message",
0,
MB_OK |
MB_ERROR |
MB_SYSTEMMODAL |
MB_MOVEABLE );
}
/*****************************************************************************
* Update the status window *
*****************************************************************************/
VOID StatusLine ( PMYWINDOWDATA pMyWindowData, CHAR *StatusText )
{
WinSetWindowText ( pMyWindowData->StatusWindow, StatusText );
return;
}
/*****************************************************************************
* COMMON WINDOWPROC MESSAGE HANDLING *
* *
* All of the window procedures will call this module if they do not handle *
* any given message. This routine will in turn call the default window *
* procedure ( WinDefWindowProc ) if the message isn't handled here. *
*****************************************************************************/
MRESULT EXPENTRY ISMCOMMON ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
PMYWINDOWDATA pMyWindowData;
RECTL rcl;
HPS hps;
HWND hFrame;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_INITMYWINDOW:
DosAllocMem ( (VOID *) &pMyWindowData,
sizeof(MYWINDOWDATA),
PAG_COMMIT |
PAG_READ |
PAG_WRITE );
WinSetWindowPtr ( hWnd, 0, (PVOID) pMyWindowData );
pMyWindowData->StatusWindow = (HWND) mp1;
pMyWindowData->MyWindow = hWnd;
return ( (MRESULT) TRUE );
break;
case WM_CLOSE:
StatusLine ( pMyWindowData, "" );
hFrame = WinQueryWindow ( hWnd, QW_PARENT );
WinDestroyWindow ( hFrame );
return ( (MRESULT) 0 );
break;
case WM_COMMAND:
switch ( LONGFROMMP(mp1) )
{
case ID_QUIT:
WinPostMsg ( hWnd, WM_CLOSE, 0, 0 );
break;
default:
break;
}
break;
case WM_SETFOCUS:
if ( pMyWindowData != NULL )
StatusLine ( pMyWindowData, "" );
break;
case WM_PAINT:
hps = WinBeginPaint ( hWnd, NULLHANDLE, (PRECTL)NULL );
WinQueryWindowRect ( hWnd, &rcl );
WinFillRect ( hps, &rcl, SYSCLR_MENU );
WinEndPaint ( hps );
return ( (MRESULT) TRUE );
break;
default:
break;
}
return( (MRESULT) WinDefWindowProc ( hWnd, ulMsg, mp1, mp2 ) );
}
/*****************************************************************************
* WM_TOUCHDOWN: RETURN CODE: TDN_DEFAULT_DELAY *
* *
* Use the default delay between WM_TOUCHDOWN and WM_BUTTONxDOWN. The result *
* of this is that if the user touches the sensor and pauses for a duration *
* equal to the default delay, mouse emulation is performed. However, if the *
* user touches the sensor and begins a stroke, then gesture recognition is *
* attempted. *
*****************************************************************************/
MRESULT APIENTRY tdn_default_delay ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
pMyWindowData->td = TRUE;
StatusLine ( pMyWindowData, "Returning TDN_DEFAULT_DELAY." );
return ( (MRESULT) TDN_DEFAULT_DELAY );
break;
case WM_BUTTON1DOWN:
if ( pMyWindowData->td )
{
pMyWindowData->td = FALSE;
StatusLine ( pMyWindowData, "Mouse Emulation Mode" );
};
return ( (MRESULT) TRUE );
break;
case WM_STROKE:
pMyWindowData->td = FALSE;
StatusLine ( pMyWindowData, "Gesture Mode" );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TOUCHDOWN: RETURN CODE: TDN_IMMEDIATE *
* *
* No delay. The program will recieve a WM_BUTTONxDOWN message immediately. *
* Note that a stroke buffer is not built when using this return code. *
*****************************************************************************/
MRESULT APIENTRY tdn_immediate ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
StatusLine ( pMyWindowData, "Returning TDN_IMMEDIATE" );
return ( (MRESULT) TDN_IMMEDIATE );
break;
case WM_BUTTON1DOWN:
StatusLine ( pMyWindowData, "WM_BUTTON1DOWN has been received" );
return ( (MRESULT) TRUE );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TOUCHDOWN: RETURN CODE: TDN_INFINITE *
* *
* The program will not recieve a WM_BUTTONxDOWN message as a result of *
* touchdown. *
*****************************************************************************/
MRESULT APIENTRY tdn_infinite ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
pMyWindowData->td = TRUE;
StatusLine ( pMyWindowData, "Returning TDN_INFINITE." );
return ( (MRESULT) TDN_INFINITE );
break;
case WM_BUTTON1DOWN:
if ( pMyWindowData->td )
{
StatusLine ( pMyWindowData, "Error: WM_TOUCHDOWN generated WM_BUTTON1DOWN" );
};
return ( (MRESULT) TRUE );
break;
case WM_LIFTOFF:
pMyWindowData->td = FALSE;
break;
case WM_EXIT_PROXIMITY:
pMyWindowData->td = FALSE;
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TOUCHDOWN: RETURN CODE: TDN_INK_STROKE *
* *
* Let PenPM do the inking of the stroke for you. The ink is not actually *
* placed in your window. It is draw in a transparent window that covers the *
* screen. *
*****************************************************************************/
MRESULT APIENTRY tdn_ink_stroke ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
StatusLine ( pMyWindowData, "Returning TDN_INK_STROKE." );
return ( (MRESULT) TDN_INK_STROKE );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TOUCHDOWN: RETURN CODE: TDN_NO_INK_STROKE *
* *
* PenPM will not ink the stroke. This is usually used when the program *
* intends to do the inking itself. *
*****************************************************************************/
MRESULT APIENTRY tdn_no_ink_stroke ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
StatusLine ( pMyWindowData, "Returning TDN_NO_INK_STROKE." );
return ( (MRESULT) TDN_NO_INK_STROKE );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TOUCHDOWN: RETURN CODE: TDN_LEAVE_INK *
* *
* Inform PenPM to ink the stroke and leave it on the screen if the stroke *
* does not leave the window that received WM_TOUCHDOWN. However, if the *
* stroke extends outside the window then the ink is removed. When your *
* window repaints, the ink left by PenPM will not be repainted. If you wish *
* to retain the ink, you must capture the point and/or stroke data and paint *
* the ink yourself. *
*****************************************************************************/
MRESULT APIENTRY tdn_leave_ink ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
StatusLine ( pMyWindowData, "Returning TDN_LEAVE_INK." );
return ( (MRESULT) TDN_LEAVE_INK );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TOUCHDOWN: RETURN CODE: TDN_HIFREQ_MOUSEMOVE *
* *
* Inform PenPM to report all pointing device movements as WM_MOUSEMOVE's at *
* full bandwidth. The points are reported in window coordinates. This is *
* primarily used when all you are doing is inking to the window or display. *
* If you are inking to a higher resolution bitmap or if you intend to do *
* some type of recoginition on the strokes then use WM_SENSOR_MOVE since the *
* sensors generally have a higher resolution. *
*****************************************************************************/
MRESULT APIENTRY tdn_hifreq_mousemove ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
pMyWindowData->td = TRUE;
StatusLine ( pMyWindowData, "Returning TDN_HIFREQ_MOUSEMOVE." );
return ( (MRESULT) TDN_HIFREQ_MOUSEMOVE );
break;
case WM_MOUSEMOVE:
if ( pMyWindowData->td )
{
StatusLine ( pMyWindowData, "WM_MOUSMOVE" );
return ( (MRESULT) TRUE );
}
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TOUCHDOWN: RETURN CODE: TDN_SENSOR_MOVE *
* *
* Inform PenPM to report all pointing device movements as WM_SENSOR_MOVE's *
* at sensor resolution. This is usually used when you are inking to a high *
* resolution bitmap or when you are using the strokes and or points for some *
* type of recoginition. If you are only inking to the display use the *
* WM_HIGHFREQ_MOUSEMOVE message, since it does not require any scaling of *
* the point data. *
*****************************************************************************/
MRESULT APIENTRY tdn_sensor_move ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
static HPS hpsClient;
static POINTL points = { 0, 0 } ;
static BOOL FirstTime = TRUE;
static WRTLOCATORDEVINFO WrtLocatorDevInfo;
WRTEVENTDATA WrtEventData;
static SHORT changecolor = 0;
static SHORT numpoints = 26;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
if ( FirstTime )
{
WrtEventData = *( (PWRTEVENTDATA) PVOIDFROMMP ( mp2 ) );
WrtLocatorDevInfo.cbStructSize = sizeof ( WRTLOCATORDEVINFO );
WrtQueryLocatorCaps ( &WrtEventData.ulLocatorID, &WrtLocatorDevInfo );
FirstTime=FALSE;
};
WinSetCapture ( HWND_DESKTOP, hWnd );
hpsClient = WinGetPS ( hWnd );
points.x = SHORT1FROMMP ( mp1 );
points.y = SHORT2FROMMP ( mp1 );
GpiMove ( hpsClient, &points );
GpiSetColor ( hpsClient, CLR_BLUE );
numpoints = 25;
StatusLine ( pMyWindowData, "Returning TDN_INFINITE | TDN_SENSOR_MOVE | TDN_NO_INK_STROKE." );
return ( (MRESULT) ( TDN_INFINITE | TDN_SENSOR_MOVE | TDN_NO_INK_STROKE ) );
break;
case WM_SENSOR_MOVE:
points.x = SHORT1FROMMP ( mp1 );
points.y = SHORT2FROMMP ( mp1 );
WrtMapPointLong ( hWnd,
&points,
MP_SCALE,
WrtLocatorDevInfo.ulSensorXpts,
WrtLocatorDevInfo.ulSensorYpts,
0L,
0L,
1 );
GpiLine ( hpsClient, &points );
numpoints--;
if ( numpoints == 0 )
{
if ( changecolor )
{
changecolor = 0;
GpiSetColor ( hpsClient, CLR_BLUE );
}
else
{
changecolor = 1;
GpiSetColor ( hpsClient, CLR_RED );
};
numpoints=25;
};
GpiMove ( hpsClient, &points );
return ( (MRESULT) 0 );
break;
case WM_LIFTOFF:
WinSetCapture ( HWND_DESKTOP, NULLHANDLE );
points.x = SHORT1FROMMP ( mp1 );
points.y = SHORT2FROMMP ( mp1 );
GpiLine ( hpsClient, &points );
WinReleasePS ( hpsClient );
return ( (MRESULT) LO_STROKE_PROCESSED );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TOUCHDOWN: RETURN CODE: TDN_IMMEDIATE | *
* TDN_HEFREQ_MOUSEMOVE | *
* TDN_NO_INK_STROKE *
* *
* This is an example of how to use ink without a stroke buffer. *
*****************************************************************************/
MRESULT APIENTRY ink_without_stroke_buffer ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
HPS hps;
static HPS hpsClient;
static POINTL points = { 0, 0 } ;
static RECTL rcl;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
pMyWindowData->td = TRUE;
hpsClient = WinGetPS ( hWnd );
WinSetCapture ( HWND_DESKTOP, hWnd );
points.x = SHORT1FROMMP ( mp1 );
points.y = SHORT2FROMMP ( mp1 );
GpiMove ( hpsClient, &points );
WinQueryWindowRect ( hWnd, &rcl );
StatusLine ( pMyWindowData, "Returning TDN_IMMEDIATE | TDN_HIFREQ_MOUSEMOVE | TDN_NO_INK_STROKE." );
return ( (MRESULT) ( TDN_IMMEDIATE |
TDN_HIFREQ_MOUSEMOVE |
TDN_NO_INK_STROKE ));
break;
case WM_MOUSEMOVE:
if ( pMyWindowData->td )
{
/**********************************************************
* Make sure that the sign is preserved by casting it to a *
**********************************************************/
points.x = (SHORT) SHORT1FROMMP ( mp1 );
points.y = (SHORT) SHORT2FROMMP ( mp1 );
GpiLine ( hpsClient, &points );
GpiMove ( hpsClient, &points );
};
break;
case WM_LIFTOFF:
WinSetCapture ( HWND_DESKTOP, NULLHANDLE );
pMyWindowData->td = FALSE;
GpiMove ( hpsClient, &points );
points.x = SHORT1FROMMP ( mp1 );
points.y = SHORT2FROMMP ( mp1 );
GpiLine ( hpsClient, &points );
WinReleasePS ( hpsClient );
return ( (MRESULT) LO_DEFAULT );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TOUCHDOWN: RETURN CODE: TDN_INFINITE | *
* TDN_SENSOR_MOVE | *
* TDN_LEAVE_INK *
* *
* This is an example of how to use ink with a stroke buffer. *
*****************************************************************************/
MRESULT APIENTRY ink_with_stroke_buffer ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
ULONG ulBufLen;
PSTROKEDATA pStrokeData;
ULONG ulConversionOptions;
ULONG ulXOutput;
ULONG ulYOutput;
ULONG ulAuxData;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
StatusLine ( pMyWindowData, "Returning TDN_INFINITE | TDN_SENSOR_MOVE | TDN_LEAVE_INK" );
WinSetCapture ( HWND_DESKTOP, hWnd );
return ( (MRESULT) ( TDN_INFINITE |
TDN_SENSOR_MOVE |
TDN_LEAVE_INK ));
break;
case WM_LIFTOFF:
WinSetCapture ( HWND_DESKTOP, NULLHANDLE );
/***************************************************************
* Get the stroke data size *
***************************************************************/
pStrokeData = NULL;
ulBufLen = 0;
ulConversionOptions = QSD_SCALE;
ulXOutput = 0;
ulYOutput = 0;
ulAuxData = 0;
if ( !WrtQueryStrokeData ( (PBYTE) pStrokeData,
&ulBufLen,
hWnd,
ulConversionOptions,
ulXOutput,
ulYOutput,
ulAuxData ) )
{
/************************************************************
* Check to verify that buffer length is net set to zero *
************************************************************/
if ( !ulBufLen )
{
StatusLine ( pMyWindowData,"Zero Buffer Length");
return((MPARAM)FALSE);
};
/************************************************************
* Allocate the memory for the stroke data *
************************************************************/
DosAllocMem ( (VOID *) &pStrokeData,
ulBufLen,
PAG_COMMIT |
PAG_READ |
PAG_WRITE );
if ( pStrokeData == NULL )
{
StatusLine ( pMyWindowData,"DosAllocMem Failed");
return((MPARAM)FALSE);
};
/************************************************************
* Initialize the structure *
************************************************************/
pStrokeData->cbStructSize = sizeof ( STROKEDATA );
if ( !WrtQueryStrokeData ( (PBYTE) pStrokeData,
&ulBufLen,
hWnd,
ulConversionOptions,
ulXOutput,
ulYOutput,
ulAuxData ) )
{
hps = WinGetPS ( hWnd );
GpiSetColor ( hps, CLR_BLUE );
GpiMove ( hps,
pStrokeData->pXY );
GpiPolyLine( hps,
pStrokeData->ulNumPoints - 1L,
pStrokeData->pXY++ );
WinReleasePS ( hps );
};
DosFreeMem ( (VOID *) pStrokeData );
};
return ( (MRESULT) LO_STROKE_PROCESSED );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TOUCHDOWN: RETURN CODE: TDN_DEFAULT_DELAY | *
* TDN_INK_STROKE *
* *
* This is default ink processing. *
*****************************************************************************/
MRESULT APIENTRY default_inking ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
static HPS hps;
static HPOINTER hptrOld;
HPOINTER hptrNew;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
StatusLine ( pMyWindowData, "Returning TDN_DEFAULT_DELAY | TDN_INK_STROKE" );
WinSetCapture ( HWND_DESKTOP, hWnd );
return ( (MRESULT) ( TDN_DEFAULT_DELAY |
TDN_INK_STROKE ) );
break;
case WM_PAUSE_TIMEOUT:
hptrNew = WinQuerySysPointer ( HWND_DESKTOP,
SPTR_ILLEGAL,
FALSE );
hptrOld = WinQueryPointer ( HWND_DESKTOP );
WinSetPointer ( HWND_DESKTOP, hptrNew );
break;
case WM_LIFTOFF:
WinSetPointer ( HWND_DESKTOP, hptrOld );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_LIFTOFF: RETURN CODE: LO_DEFAULT *
* *
* The default behavior is to continue with gesture recognition and send a *
* WM_STROKE and WM_RECO messages. *
*****************************************************************************/
MRESULT APIENTRY lo_default ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_LIFTOFF:
StatusLine ( pMyWindowData, "Returning LO_DEFAULT" );
return ( (MRESULT) LO_DEFAULT );
break;
case WM_STROKE:
StatusLine ( pMyWindowData, "WM_STROKE received");
return ( (MRESULT) TRUE );
break;
case WM_RECO:
StatusLine ( pMyWindowData, "WM_RECO received");
return ( (MRESULT) TRUE );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_LIFTOFF: RETURN CODE: LO_STROKE_PROCESSED *
* *
* Inform PenPM that the stroke has been processed and to not perform any *
* furthur processing on the stroke.
*****************************************************************************/
MRESULT APIENTRY lo_stroke_processed ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_LIFTOFF:
StatusLine ( pMyWindowData, "Returning LO_STROKE_PROCESSED" );
return ( (MRESULT) LO_STROKE_PROCESSED );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_LIFTOFF: RETURN CODE: LO_EMULATE_MOUSE *
* *
* Inform PenPM to send the mouse button down and up messages. *
*****************************************************************************/
MRESULT APIENTRY lo_emulate_mouse ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
int b1d;
int b1u;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_LIFTOFF:
StatusLine ( pMyWindowData, "Returning LO_EMULATE_MOUSE" );
return ( (MRESULT) LO_EMULATE_MOUSE );
break;
case WM_BUTTON1DOWN:
StatusLine ( pMyWindowData, "WM_BUTTON1DOWN" );
b1d++;
break;
case WM_BUTTON1UP:
b1u++;
StatusLine ( pMyWindowData, "WM_BUTTON1UP" );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_STROKE: RETURN CODE: STK_DEFAULT *
* *
* Application does not process stroke. Informs PenPM to do gesture *
* recognition processing. *
*****************************************************************************/
MRESULT APIENTRY stk_default ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_STROKE:
StatusLine ( pMyWindowData, "Returning STK_DEFAULT" );
return ( (MRESULT) STK_DEFAULT );
break;
case WM_RECO:
StatusLine ( pMyWindowData, "WM_RECO received");
return ( (MRESULT) TRUE );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_STROKE: RETURN CODE: STK_STROKE_PROCESSED *
* *
* Inform PenPM that the application has already processed the stroke and *
* thus do not continue with gesture recognition processing. *
*****************************************************************************/
MRESULT APIENTRY stk_stroke_processed ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_STROKE:
StatusLine ( pMyWindowData, "Returning STK_STROKE_PROCESSED" );
return ( (MRESULT) STK_STROKE_PROCESSED );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_SENSOR_MOVE: RETURN: VOID *
* *
* Inform PenPM at WM_TOUCHDOWN to send us all points as WM_SENSOR_MOVE's *
* with sensor resolution. Note that this does not mean that WM_MOUSEMOVE's *
* will not be sent. WM_MOUSEMOVE's are always being sent around PM to move *
* mouse pointer. WM_SENSOR_MOVE's at sensor resolution are usually much *
* better for things like gesture and handwriting recognition processing. *
*****************************************************************************/
MRESULT APIENTRY wm_sensor_move ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
static HPS hpsClient;
static POINTL points = { 0, 0 } ;
static BOOL FirstTime = TRUE;
static WRTLOCATORDEVINFO WrtLocatorDevInfo;
WRTEVENTDATA WrtEventData;
static SHORT changecolor = 0;
static SHORT numpoints = 26;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TOUCHDOWN:
if ( FirstTime )
{
WrtEventData = *( (PWRTEVENTDATA) PVOIDFROMMP ( mp2 ) );
WrtLocatorDevInfo.cbStructSize = sizeof ( WRTLOCATORDEVINFO );
WrtQueryLocatorCaps ( &WrtEventData.ulLocatorID, &WrtLocatorDevInfo );
FirstTime=FALSE;
};
WinSetCapture ( HWND_DESKTOP, hWnd );
hpsClient = WinGetPS ( hWnd );
points.x = SHORT1FROMMP ( mp1 );
points.y = SHORT2FROMMP ( mp1 );
GpiMove ( hpsClient, &points );
GpiSetColor ( hpsClient, CLR_BLUE );
numpoints = 25;
StatusLine ( pMyWindowData, "Returning TDN_INFINITE | TDN_SENSOR_MOVE | TDN_NO_INK_STROKE." );
return ( (MRESULT) ( TDN_INFINITE | TDN_SENSOR_MOVE | TDN_NO_INK_STROKE ) );
break;
case WM_SENSOR_MOVE:
points.x = SHORT1FROMMP ( mp1 );
points.y = SHORT2FROMMP ( mp1 );
WrtMapPointLong ( hWnd,
&points,
MP_SCALE,
WrtLocatorDevInfo.ulSensorXpts,
WrtLocatorDevInfo.ulSensorYpts,
0L,
0L,
1 );
GpiLine ( hpsClient, &points );
numpoints--;
if ( numpoints == 0 )
{
if ( changecolor )
{
changecolor = 0;
GpiSetColor ( hpsClient, CLR_BLUE );
}
else
{
changecolor = 1;
GpiSetColor ( hpsClient, CLR_RED );
};
numpoints=25;
};
GpiMove ( hpsClient, &points );
return ( (MRESULT) 0 );
break;
case WM_LIFTOFF:
WinSetCapture ( HWND_DESKTOP, NULLHANDLE );
points.x = SHORT1FROMMP ( mp1 );
points.y = SHORT2FROMMP ( mp1 );
GpiLine ( hpsClient, &points );
WinReleasePS ( hpsClient );
return ( (MRESULT) LO_STROKE_PROCESSED );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TAP: RETURN: TP_DEFAULT *
* *
* Tell PenPM to perform mouse emulation, ie send WM_BUTTON1DOWN and *
* WM_BUTTON1UP messages. However, if you return TDN_INFINITE at WM_TOUCHDOWN *
* the button events will not be sent. *
*****************************************************************************/
MRESULT APIENTRY tap_tp_default ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
static int tap = FALSE;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TAP:
tap = TRUE;
StatusLine ( pMyWindowData, "Returning TP_DEFAULT. ");
return ( (MRESULT) TP_DEFAULT );
break;
case WM_BUTTON1DOWN:
if ( tap )
{
StatusLine ( pMyWindowData, "Mouse emulation" );
tap = FALSE;
};
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_TAP: RETURN: TP_TAP_PROCESSED *
* *
* Inform PenPM that the application has processed the WM_TAP message and *
* take no furthur action in processing the event. *
*****************************************************************************/
MRESULT APIENTRY tap_tp_tap_processed ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
static int tap = FALSE;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_TAP:
tap = TRUE;
StatusLine ( pMyWindowData, "Returning TP_TAP_PROCESSED. ");
return ( (MRESULT) TP_TAP_PROCESSED );
break;
case WM_BUTTON1DOWN:
if ( tap )
{
StatusLine ( pMyWindowData, "Mouse emulation" );
tap = FALSE;
};
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_DBL_TAP: RETURN: TP_DEFAULT *
* *
* Tell PenPM to perform mouse emulation, ie send WM_BUTTON1DOWN and *
* WM_BUTTON1UP messages. However, if you return TDN_INFINITE at WM_TOUCHDOWN *
* the button events will not be sent. *
*****************************************************************************/
MRESULT APIENTRY dbl_tap_tp_default ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
static int tap = FALSE;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_DBL_TAP:
tap = TRUE;
StatusLine ( pMyWindowData, "Returning TP_DEFAULT. ");
return ( (MRESULT) TP_DEFAULT );
break;
case WM_BUTTON1DOWN:
if ( tap )
{
StatusLine ( pMyWindowData, "Mouse emulation." );
tap = FALSE;
};
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_DBL_TAP: RETURN: TP_TAP_PROCESSED *
* *
* Inform PenPM that the application has processed the WM_TAP message and *
* take no furthur action in processing the event. *
*****************************************************************************/
MRESULT APIENTRY dbl_tap_tp_tap_processed ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
static int tap = FALSE;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_DBL_TAP:
tap = TRUE;
StatusLine ( pMyWindowData, "Returning TP_TAP_PROCESSED. ");
return ( (MRESULT) TP_TAP_PROCESSED );
break;
case WM_BUTTON1DOWN:
if ( tap )
{
tap = FALSE;
StatusLine ( pMyWindowData, "Mouse emulation." );
};
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_PAUSE_TIMEOUT: RETURN: PTO_DEFAULT *
* *
* This message is generated by PenPM when the user has touched the sensor *
* and remained motionless for a period of time. PTO_DEFAULT tells PenPM to *
* allow mouse emulation. *
*****************************************************************************/
MRESULT APIENTRY pto_default ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
static BOOL pto = FALSE;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_PAUSE_TIMEOUT:
pto = TRUE;
StatusLine ( pMyWindowData, "Returning PTO_DEFAULT. ");
return ( (MRESULT) PTO_DEFAULT );
break;
case WM_BUTTON1DOWN:
if ( pto )
{
StatusLine ( pMyWindowData, "Mouse emulation" );
pto = FALSE;
};
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_PAUSE_TIMEOUT: RETURN: PTO_CONTINUE *
* *
* This message is generated by PenPM when the user has touched the sensor *
* and remained motionless for a period of time. PTO_CONTINUE tells PenPM to *
* remain in a gesture mode and not perform mouse emulation. *
*****************************************************************************/
MRESULT APIENTRY pto_continue ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_PAUSE_TIMEOUT:
StatusLine ( pMyWindowData, "Returning PTO_CONTINUE. ");
return ( (MRESULT) PTO_CONTINUE );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_EXIT_PROXIMITY: RETURN: VOID *
* *
* This indicates that the pointing device has left proximity to the sensor. *
* Note that not all devices provide proximity data. *
*****************************************************************************/
MRESULT APIENTRY wm_exit_proximity ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_EXIT_PROXIMITY:
StatusLine ( pMyWindowData, "Exiting Proximity" );
return ( (MRESULT) 0 );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_WRT_DEV_CAPS_CHANGE: RETURN: VOID *
* *
* This message indicates a change to the device capabilities has been *
* reported to PenPM. *
*****************************************************************************/
MRESULT APIENTRY wm_wrt_dev_caps_change ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_WRT_DEV_CAPS_CHANGE:
StatusLine ( pMyWindowData, "Device capabilities changed" );
return ( (MRESULT) 0 );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* WM_WRT_SYSVALUECHANGED: RETURN: VOID *
* *
* This message indicates that a change to the PenPM system variables has *
* occurred. Note that it is the responsibility of the program changing the *
* value to broadcaset this message to the rest of the system. *
*****************************************************************************/
MRESULT APIENTRY wm_wrt_sysvaluechanged ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
HPS hps;
PMYWINDOWDATA pMyWindowData;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_WRT_SYSVALUECHANGED:
StatusLine ( pMyWindowData, "System value changed" );
return ( (MRESULT) 0 );
break;
default:
break;
};
return( (MRESULT) ISMCOMMON ( hWnd, ulMsg, mp1, mp2 ) );
};
/*****************************************************************************
* This is an example of inking and editing of ink using the capabilities of *
* the graphics engine, provided with OS/2 2.1. You enter ink while in a *
* freehand mode. The ink is grouped into sets of strokes from the moment of *
* touchdown until the sensor leaves proximity. You can change the color of *
* an entire group with a C-tap gesture. You can delete an entire group with *
* an X gesture. You can delete any individual stroke with a pigtail gesture. *
*****************************************************************************/
MRESULT APIENTRY InkEditing ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
RECTL rcl;
SIZEL PickSize;
SHORT NumHits;
SIZEL PageSize;
HWND hMenu;
MENUITEM menuitem;
PMYWINDOWDATA pMyWindowData;
HRGN hrgn;
HRGN hrgnold;
HPS hpspaint;
LINEWIDTHORDER LineWidthOrder;
SHORT i;
PickSize.cx = 10;
PickSize.cy = 10;
pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
switch ( ulMsg )
{
case WM_INITMYWINDOW:
/**************************************************************
* Add Pen input mode menu item *
**************************************************************/
hMenu = WinWindowFromID ( WinQueryWindow ( hWnd, QW_PARENT ),
FID_MENU );
menuitem.iPosition = MIT_END;
menuitem.afStyle = MIS_TEXT;
menuitem.afAttribute = 0;
menuitem.id = ID_MENUITEM;
menuitem.hItem = 0;
menuitem.hwndSubMenu = 0;
WinSendMsg ( hMenu,
MM_INSERTITEM,
(MPARAM) &menuitem,
(MPARAM) "GestureMode" );
/**************************************************************
* Initialize window instance data *
**************************************************************/
DosAllocMem ( (VOID *) &pMyWindowData,
sizeof(MYWINDOWDATA),
PAG_COMMIT |
PAG_READ |
PAG_WRITE );
pMyWindowData->MyWindow = hWnd;
pMyWindowData->StatusWindow = (HWND) mp1;
pMyWindowData->freehand = TRUE;
pMyWindowData->NewSegment = TRUE;
pMyWindowData->SegmentName = 1;
pMyWindowData->ElementName = 0;
if ( !WinSetWindowPtr ( hWnd, 0, (PVOID) pMyWindowData ) )
return ( (MPARAM) FALSE );
/**************************************************************
* Create the presentation space for the window *
**************************************************************/
pMyWindowData->hab = WinQueryAnchorBlock ( hWnd );
pMyWindowData->hdc = WinOpenWindowDC ( hWnd );
DevQueryCaps ( pMyWindowData->hdc, CAPS_WIDTH, 1L, &PageSize.cx );
DevQueryCaps ( pMyWindowData->hdc, CAPS_WIDTH, 1L, &PageSize.cy );
pMyWindowData->hps = GpiCreatePS ( pMyWindowData->hab,
pMyWindowData->hdc,
&PageSize,
( PU_PELS |
GPIT_NORMAL |
GPIF_LONG |
GPIA_ASSOC ) );
if ( pMyWindowData->hps == GPI_ERROR )
{
StatusLine ( pMyWindowData, "Could not create PS" );
WinPostMsg ( hWnd, WM_CLOSE, (MPARAM) 0, (MPARAM) 0 );
};
/**************************************************************
* Prepare the presentation space for drawing and retaining *
* the graphic primatives *
**************************************************************/
GpiSetDrawingMode ( pMyWindowData->hps,
DM_DRAWANDRETAIN );
GpiSetInitialSegmentAttrs ( pMyWindowData->hps,
ATTR_FASTCHAIN,
ATTR_OFF );
GpiSetDrawControl ( pMyWindowData->hps,
DCTL_ERASE,
DCTL_OFF );
GpiSetDrawControl ( pMyWindowData->hps,
DCTL_CORRELATE,
DCTL_ON );
GpiSetDrawControl ( pMyWindowData->hps,
DCTL_BOUNDARY,
DCTL_OFF );
GpiSetInitialSegmentAttrs ( pMyWindowData->hps,
ATTR_DETECTABLE,
ATTR_OFF );
pMyWindowData->points.x = 0;
pMyWindowData->points.y = 0;
GpiMove ( pMyWindowData->hps, &pMyWindowData->points );
pMyWindowData->points.x = PageSize.cx;
pMyWindowData->points.y = PageSize.cy;
GpiOpenSegment ( pMyWindowData->hps,
pMyWindowData->SegmentName );
GpiSetColor ( pMyWindowData->hps, CLR_PALEGRAY );
GpiBox ( pMyWindowData->hps, DRO_FILL, &pMyWindowData->points, 0L, 0L );
GpiCloseSegment ( pMyWindowData->hps );
pMyWindowData->CurrentColor = InkColor[0];
GpiSetColor ( pMyWindowData->hps, pMyWindowData->CurrentColor );
GpiSetInitialSegmentAttrs ( pMyWindowData->hps,
ATTR_DETECTABLE,
ATTR_ON );
WinShowWindow ( hWnd, TRUE );
pMyWindowData->InkColors = CreateInkControls ( hWnd );
GpiSetPickApertureSize ( pMyWindowData->hps, PICKAP_REC, &PickSize );
WinSetFocus ( HWND_DESKTOP, hWnd );
StatusLine ( pMyWindowData, "Freehand Mode" );
return((MRESULT) TRUE);
break;
/***********************************************************************
* Process the help request *
***********************************************************************/
case WM_PROCESSDIALOG:
WinDlgBox ( HWND_DESKTOP,
hWnd,
InkEditHelp,
NULLHANDLE,
ID_INKEDITGESTUREHELP,
NULL );
return((MRESULT) TRUE);
break;
/***********************************************************************
* Process the menu selections *
***********************************************************************/
case WM_COMMAND:
switch ( SHORT1FROMMP (mp1) )
{
case ID_QUIT:
WinPostMsg ( hWnd, WM_CLOSE, 0, 0 );
break;
case ID_MENUITEM:
pMyWindowData->freehand = FALSE;
StatusLine ( pMyWindowData, "Gesture Mode - ? for Help" );
break;
default:
break;
};
break;
/***********************************************************************
* When we get focus, update the status line to indicate the mode this *
* window is in. *
***********************************************************************/
case WM_SETFOCUS:
if ( pMyWindowData != NULL )
{
if ( pMyWindowData->freehand )
{
StatusLine ( pMyWindowData, "Freehand Mode" );
}
else
{
StatusLine ( pMyWindowData, "Gesture Mode - ? for Help" );
};
};
break;
/***********************************************************************
* Set the current color to the value selected in the ink colors *
* value set control. *
***********************************************************************/
case WM_CONTROL:
switch ( SHORT2FROMMP(mp1) )
{
case VN_SELECT:
switch ( SHORT1FROMMP(mp1) )
{
case ID_VALUE_SET_INK:
pMyWindowData->CurrentColor = InkColor[SHORT1FROMMP ( mp2 )-1];
break;
default:
break;
};
return( (MPARAM)TRUE );
break;
default:
break;
};
break;
/***********************************************************************
* The use has touched the sensor. If this is to be a new segment, then *
* setup the segment attributes for color, width, lineend, and linejoin.*
* Then begin a new stroke. The importent thing to do here is set the *
* tag for the element and set a label with the same value for later *
* locating this point. *
***********************************************************************/
case WM_TOUCHDOWN:
if ( pMyWindowData->freehand )
{
pMyWindowData->SegmentName++;
if ( pMyWindowData->NewSegment )
{
pMyWindowData->ElementName = 0;
pMyWindowData->NewSegment = FALSE;
GpiOpenSegment ( pMyWindowData->hps,
pMyWindowData->SegmentName );
GpiLabel ( pMyWindowData->hps,
LABEL_BEGIN_SEGMENT );
GpiLabel ( pMyWindowData->hps,
LABEL_BEGIN_COLOR );
GpiSetColor ( pMyWindowData->hps,
pMyWindowData->CurrentColor );
GpiLabel ( pMyWindowData->hps,
LABEL_END_COLOR );
GpiLabel ( pMyWindowData->hps,
LABEL_BEGIN_WIDTH );
GpiSetLineWidthGeom ( pMyWindowData->hps, 1L );
GpiLabel ( pMyWindowData->hps,
LABEL_END_WIDTH );
GpiSetLineEnd ( pMyWindowData->hps, LINEEND_ROUND );
GpiSetLinejOIN ( pMyWindowData->hps, LINEJOIN_ROUND );
};
pMyWindowData->ElementName++;
GpiSetTag ( pMyWindowData->hps,
pMyWindowData->ElementName );
GpiLabel ( pMyWindowData->hps,
pMyWindowData->ElementName );
GpiLabel ( pMyWindowData->hps,
LABEL_BEGIN_STROKE );
GpiLabel ( pMyWindowData->hps,
LABEL_BEGIN_BEGIN_PATH );
GpiLabel ( pMyWindowData->hps,
LABEL_END_BEGIN_PATH );
pMyWindowData->td = TRUE;
WinSetCapture ( HWND_DESKTOP, hWnd );
pMyWindowData->points.x = SHORT1FROMMP ( mp1 );
pMyWindowData->points.y = SHORT2FROMMP ( mp1 );
GpiMove ( pMyWindowData->hps, &pMyWindowData->points );
return ( (MRESULT) ( TDN_IMMEDIATE |
TDN_HIFREQ_MOUSEMOVE |
TDN_NO_INK_STROKE ));
}
else
{
return((MRESULT) ( TDN_DEFAULT_DELAY | TDN_INK_STROKE ));
};
break;
/***********************************************************************
* In this case we are using the hifrequency mouse moves to do the *
* inking. We could have just as easily used sensor moves if we desired *
* a higher resolution. *
***********************************************************************/
case WM_MOUSEMOVE:
if ( pMyWindowData->td )
{
/**********************************************************
* Make sure that the sign is preserved by casting it to a *
* short *
**********************************************************/
pMyWindowData->points.x = (SHORT) SHORT1FROMMP ( mp1 );
pMyWindowData->points.y = (SHORT) SHORT2FROMMP ( mp1 );
GpiLine ( pMyWindowData->hps, &pMyWindowData->points );
};
break;
/***********************************************************************
* When the user lifts the pointing device off of the sensor, we will *
* finish the stroke and set the labels for later editing. *
***********************************************************************/
case WM_LIFTOFF:
if ( pMyWindowData->td )
{
WinSetCapture ( HWND_DESKTOP, NULLHANDLE );
pMyWindowData->td = FALSE;
pMyWindowData->points.x = SHORT1FROMMP ( mp1 );
pMyWindowData->points.y = SHORT2FROMMP ( mp1 );
GpiLine ( pMyWindowData->hps, &pMyWindowData->points );
GpiLabel ( pMyWindowData->hps, LABEL_BEGIN_END_PATH );
GpiLabel ( pMyWindowData->hps, LABEL_END_END_PATH );
GpiLabel ( pMyWindowData->hps, LABEL_END_STROKE );
return ( (MRESULT) LO_STROKE_PROCESSED );
}
else
{
return ( (MRESULT) LO_DEFAULT );
};
break;
/***********************************************************************
* Close the segment when the pointer device leaves proximity. *
***********************************************************************/
case WM_EXIT_PROXIMITY:
pMyWindowData->NewSegment = TRUE;
pMyWindowData->ElementName = 0;
GpiLabel ( pMyWindowData->hps, LABEL_END_SEGMENT );
GpiCloseSegment ( pMyWindowData->hps );
break;
/***********************************************************************
* When in a gesture mode, the reco engine will inform us of any reco *
* event. mp1 contains the hotspot of the gesture. mp2 has a pointer to *
* the reco event data. *
***********************************************************************/
case WM_RECO:
pMyWindowData->HotSpot.x = (SHORT) SHORT1FROMMP ( mp1 );
pMyWindowData->HotSpot.y = (SHORT) SHORT2FROMMP ( mp1 );
pMyWindowData->RecoData = *((PRECODATA) PVOIDFROMMP ( mp2 ));
switch ( pMyWindowData->RecoData.virtual_id )
{
/***********************************************************
* By default a ? gesture is mapped to the virtual id for *
* help. Pop up a dialog box with the help information. *
***********************************************************/
case VE_HELP:
WinPostMsg ( hWnd, WM_PROCESSDIALOG, (MPARAM)0, (MPARAM)0 );
return( (MRESULT) RECO_PROCESSED );
break;
/***********************************************************
* This event is mapped to the scratchout gesture. We will *
* use this to delete all segments contained within the *
* bounding box for the gesture. *
***********************************************************/
case VE_SCRATCHOUT:
PickSize.cx = pMyWindowData->RecoData.bound_box.xRight - pMyWindowData->RecoData.bound_box.xLeft;
PickSize.cy = pMyWindowData->RecoData.bound_box.yTop - pMyWindowData->RecoData.bound_box.yBottom;
GpiSetPickApertureSize ( pMyWindowData->hps, PICKAP_REC, &PickSize );
NumHits = GpiCorrelateChain ( pMyWindowData->hps,
PICKSEL_VISIBLE,
&pMyWindowData->HotSpot,
10L,
1L,
&pMyWindowData->SegmentHits[0].Segment );
if ( NumHits )
{
hrgn = CreateClipRect ( pMyWindowData, NumHits );
for ( i=0; i<NumHits; i++ )
{
GpiDeleteSegment ( pMyWindowData->hps,
pMyWindowData->SegmentHits[i].Segment );
};
GpiSetClipRegion ( pMyWindowData->hps, hrgn, &hrgnold );
GpiDrawChain ( pMyWindowData->hps );
GpiSetClipRegion ( pMyWindowData->hps, hrgnold, NULL );
GpiDestroyRegion ( pMyWindowData->hps, hrgn );
WinValidateRect ( hWnd, (PRECTL) NULL, TRUE );
}
else
{
DosBeep ( 200, 200 );
};
return( (MRESULT) RECO_PROCESSED );
break;
/***********************************************************
* This event is mapped to the X-out gesture. We will use *
* this to delete the entire segment under the hotspot. *
***********************************************************/
case VE_DELETE:
NumHits = GpiCorrelateChain ( pMyWindowData->hps,
PICKSEL_VISIBLE,
&pMyWindowData->HotSpot,
1L,
1L,
&pMyWindowData->SegmentHits[0].Segment );
if ( NumHits )
{
hrgn = CreateClipRect ( pMyWindowData, NumHits );
GpiDeleteSegment ( pMyWindowData->hps,
pMyWindowData->SegmentHits[0].Segment );
GpiSetClipRegion ( pMyWindowData->hps, hrgn, &hrgnold );
GpiDrawChain ( pMyWindowData->hps );
GpiSetClipRegion ( pMyWindowData->hps, hrgnold, NULL );
GpiDestroyRegion ( pMyWindowData->hps, hrgn );
WinValidateRect ( hWnd, (PRECTL) NULL, TRUE );
}
else
{
DosBeep ( 200, 200 );
};
return( (MRESULT) RECO_PROCESSED );
break;
/***********************************************************
* By default the system maps a pigtail gesture to the *
* virtual event for deleting a character. We will use this *
* to delete the stroke under the hot spot from the segment *
* under the hotspot. *
***********************************************************/
case VE_DELETECHAR:
NumHits = GpiCorrelateChain ( pMyWindowData->hps,
PICKSEL_VISIBLE,
&pMyWindowData->HotSpot,
1L,
1L,
&pMyWindowData->SegmentHits[0].Segment );
if ( NumHits )
{
hrgn = CreateClipRect ( pMyWindowData, NumHits );
GpiSetDrawingMode ( pMyWindowData->hps, DM_RETAIN );
GpiSetEditMode ( pMyWindowData->hps, SEGEM_INSERT );
GpiOpenSegment ( pMyWindowData->hps, pMyWindowData->SegmentHits[0].Segment );
GpiSetElementPointerAtLabel ( pMyWindowData->hps,
pMyWindowData->SegmentHits[0].Element );
GpiDeleteElementsBetweenLabels ( pMyWindowData->hps,
LABEL_BEGIN_STROKE,
LABEL_END_STROKE );
GpiCloseSegment ( pMyWindowData->hps );
GpiSetDrawingMode ( pMyWindowData->hps,
DM_DRAWANDRETAIN );
GpiSetClipRegion ( pMyWindowData->hps, hrgn, &hrgnold );
GpiDrawChain ( pMyWindowData->hps );
GpiSetClipRegion ( pMyWindowData->hps, hrgnold, NULL );
GpiDestroyRegion ( pMyWindowData->hps, hrgn );
WinValidateRect ( hWnd, (PRECTL) NULL, TRUE );
}
else
{
DosBeep ( 200, 200 );
};
return( (MRESULT) RECO_PROCESSED );
break;
/***********************************************************
* User has entered a letter gesture *
***********************************************************/
case VE_LETTERGESTURE:
switch ( pMyWindowData->RecoData.char_code )
{
/**************************************************
* Change the color to the currently selected *
* color. *
**************************************************/
case 'C':
NumHits = GpiCorrelateChain ( pMyWindowData->hps,
PICKSEL_VISIBLE,
&pMyWindowData->HotSpot,
1L,
1L,
&pMyWindowData->SegmentHits[0].Segment );
if ( NumHits )
{
ChangeColor ( pMyWindowData, pMyWindowData->CurrentColor );
}
else
{
DosBeep ( 200, 200 );
};
return( (MRESULT) RECO_PROCESSED );
break;
/**************************************************
* Decrease the ink width *
**************************************************/
case 'D':
NumHits = GpiCorrelateChain ( pMyWindowData->hps,
PICKSEL_VISIBLE,
&pMyWindowData->HotSpot,
1L,
1L,
&pMyWindowData->SegmentHits[0].Segment );
if ( NumHits )
{
hrgn = CreateClipRect ( pMyWindowData, NumHits );
GpiSetDrawingMode ( pMyWindowData->hps, DM_RETAIN );
GpiSetEditMode ( pMyWindowData->hps, SEGEM_INSERT );
GpiOpenSegment ( pMyWindowData->hps, pMyWindowData->SegmentHits[0].Segment );
GpiSetElementPointerAtLabel ( pMyWindowData->hps,
LABEL_BEGIN_WIDTH );
GpiOffsetElementPointer ( pMyWindowData->hps, 1L );
GpiQueryElement ( pMyWindowData->hps, 0L, sizeof(LWO), (PBYTE) &LineWidthOrder );
if ( LineWidthOrder.width > 1 )
{
GpiSetElementPointer ( pMyWindowData->hps, 1L );
GpiDeleteElementsBetweenLabels ( pMyWindowData->hps,
LABEL_BEGIN_WIDTH,
LABEL_END_WIDTH );
GpiSetLineWidthGeom ( pMyWindowData->hps, LineWidthOrder.width/2 );
};
GpiCloseSegment ( pMyWindowData->hps );
GpiSetDrawingMode ( pMyWindowData->hps,
DM_DRAWANDRETAIN );
GpiSetClipRegion ( pMyWindowData->hps, hrgn, &hrgnold );
GpiDrawChain ( pMyWindowData->hps );
GpiSetClipRegion ( pMyWindowData->hps, hrgnold, NULL );
GpiDestroyRegion ( pMyWindowData->hps, hrgn );
}
else
{
DosBeep ( 200, 200 );
};
return( (MRESULT) RECO_PROCESSED );
break;
/**************************************************
* Erase the presentation space, except for the *
* background palegray box. *
**************************************************/
case 'E':
GpiDeleteSegments ( pMyWindowData->hps, 2, pMyWindowData->SegmentName );
pMyWindowData->SegmentName=1;
GpiDrawChain ( pMyWindowData->hps );
return( (MRESULT) RECO_PROCESSED );
break;
/**************************************************
* Return to freehand drawing mode *
**************************************************/
case 'F':
pMyWindowData->freehand = TRUE;
StatusLine ( pMyWindowData, "Freehand Mode" );
return( (MRESULT) RECO_PROCESSED );
break;
/**************************************************
* Increase the ink width *
**************************************************/
case 'I':
NumHits = GpiCorrelateChain ( pMyWindowData->hps,
PICKSEL_VISIBLE,
&pMyWindowData->HotSpot,
1L,
1L,
&pMyWindowData->SegmentHits[0].Segment );
if ( NumHits )
{
GpiSetDrawingMode ( pMyWindowData->hps, DM_RETAIN );
GpiSetEditMode ( pMyWindowData->hps, SEGEM_INSERT );
GpiOpenSegment ( pMyWindowData->hps, pMyWindowData->SegmentHits[0].Segment );
GpiSetElementPointerAtLabel ( pMyWindowData->hps,
LABEL_BEGIN_WIDTH );
GpiOffsetElementPointer ( pMyWindowData->hps, 1L );
GpiQueryElement ( pMyWindowData->hps, 0L, sizeof(LWO), (PBYTE) &LineWidthOrder );
GpiSetElementPointer ( pMyWindowData->hps, 1L );
GpiDeleteElementsBetweenLabels ( pMyWindowData->hps,
LABEL_BEGIN_WIDTH,
LABEL_END_WIDTH );
GpiSetLineWidthGeom ( pMyWindowData->hps, LineWidthOrder.width*2 );
if ( LineWidthOrder.width == 1 )
{
while ( GpiSetElementPointerAtLabel ( pMyWindowData->hps,
LABEL_BEGIN_BEGIN_PATH ) )
{
GpiBeginPath ( pMyWindowData->hps, 1L );
GpiSetElementPointerAtLabel ( pMyWindowData->hps,
LABEL_BEGIN_END_PATH );
GpiEndPath ( pMyWindowData->hps );
GpiStrokePath ( pMyWindowData->hps, 1L, 0L );
};
};
GpiCloseSegment ( pMyWindowData->hps );
hrgn = CreateClipRect ( pMyWindowData, NumHits );
GpiSetDrawingMode ( pMyWindowData->hps,
DM_DRAWANDRETAIN );
GpiSetClipRegion ( pMyWindowData->hps, hrgn, &hrgnold );
GpiDrawChain ( pMyWindowData->hps );
GpiSetClipRegion ( pMyWindowData->hps, hrgnold, NULL );
GpiDestroyRegion ( pMyWindowData->hps, hrgn );
}
else
{
DosBeep ( 200, 200 );
};
return( (MRESULT) RECO_PROCESSED );
break;
default:
break;
};
break;
default:
break;
}
return ( (MRESULT) RECO_MAP );
break;
/***********************************************************************
* Make sure we resize the ink control when the window is resized *
***********************************************************************/
case WM_SIZE:
WinQueryWindowRect ( hWnd, &rcl );
if ( pMyWindowData != NULL )
{
WinSetWindowPos ( pMyWindowData->InkColors,
HWND_TOP,
0,
0,
25,
rcl.yTop,
SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW );
};
break;
/***********************************************************************
* Repaint the window *
***********************************************************************/
case WM_PAINT:
hpspaint = WinBeginPaint ( hWnd, pMyWindowData->hps, &rcl );
GpiDrawChain ( hpspaint );
WinUpdateWindow ( pMyWindowData->InkColors );
WinEndPaint ( hpspaint );
return ( (MRESULT) TRUE );
break;
/***********************************************************************
* Clean up before we close the window *
***********************************************************************/
case WM_CLOSE:
GpiDestroyPS ( pMyWindowData->hps );
StatusLine ( pMyWindowData, "" );
WinDestroyWindow ( WinQueryWindow ( hWnd, QW_PARENT ) );
DosFreeMem ( (PVOID) pMyWindowData );
return ( (MRESULT) 0 );
break;
default:
break;
};
return( (MRESULT) WinDefWindowProc ( hWnd, ulMsg, mp1, mp2 ) );
}
/*****************************************************************************
* Change the color of the selected segment. *
* *
* 1 Set the drawing mode to retain *
* 2 Get the clipping region for the segment *
* 3 Set the edit mode to replace *
* 4 Open the segment for editing *
* 5 Position element pointer at the label for setting color *
* 6 Increment the element pointer to the actual element that sets color *
* 7 Replace element with new color *
* 8 Close the segment *
* 9 Reset the drawing mode to draw and retain *
* 10 Set the clipping region and save old clipping region *
* 11 Draw the entire chain since other segments may cross the clipping *
* region *
* 12 Reset the clipping region *
* 13 Destroy the clipping regaion *
* 14 Validate the window since the screen is now valid *
* *
*****************************************************************************/
BOOL ChangeColor ( PMYWINDOWDATA pMyWindowData, LONG NewColor )
{
HRGN hrgn;
HRGN hrgnold;
GpiSetDrawingMode ( pMyWindowData->hps, DM_RETAIN );
hrgn = CreateClipRect ( pMyWindowData, 1 );
GpiSetEditMode ( pMyWindowData->hps, SEGEM_REPLACE );
GpiOpenSegment ( pMyWindowData->hps, pMyWindowData->SegmentHits[0].Segment );
GpiSetElementPointerAtLabel ( pMyWindowData->hps, LABEL_BEGIN_COLOR );
GpiOffsetElementPointer ( pMyWindowData->hps, 1L );
GpiSetColor ( pMyWindowData->hps, NewColor );
GpiCloseSegment ( pMyWindowData->hps );
GpiSetDrawingMode ( pMyWindowData->hps, DM_DRAWANDRETAIN );
GpiSetClipRegion ( pMyWindowData->hps, hrgn, &hrgnold );
GpiDrawChain ( pMyWindowData->hps );
GpiSetClipRegion ( pMyWindowData->hps, hrgnold, NULL );
GpiDestroyRegion ( pMyWindowData->hps, hrgn );
WinValidateRect ( pMyWindowData->MyWindow, (PRECTL) NULL, TRUE );
return ( TRUE );
}
/*****************************************************************************
* Calculate the clipping region for updating the window. *
* *
* 1 Turn on the colletion of boundary data *
* 2 Turn off the displaying of the updates while we collect the boundary *
* data *
* 3 Draw each of the selected segments, with display off, to get the *
* boundary data for the segment *
* 4 Add the boundary for this segment to the boundary data for all of the *
* segments being updated *
* 5 Increment the size of the bounding rectangle since the clipping region *
* is an inclusive/exclusive rectangle *
* 6 create and return the calculated clipping region *
* *
*****************************************************************************/
HRGN CreateClipRect ( PMYWINDOWDATA pMyWindowData, SHORT NumSegments )
{
SHORT i;
RECTL TmpBoundary1;
RECTL TmpBoundary2;
TmpBoundary2.xLeft = 0;
TmpBoundary2.xRight = 0;
TmpBoundary2.yTop = 0;
TmpBoundary2.yBottom = 0;
GpiSetDrawControl ( pMyWindowData->hps, DCTL_BOUNDARY, DCTL_ON );
GpiSetDrawControl ( pMyWindowData->hps, DCTL_DISPLAY, DCTL_OFF );
for ( i=0; i<NumSegments; i++)
{
GpiDrawSegment ( pMyWindowData->hps, pMyWindowData->SegmentHits[i].Segment );
GpiQueryBoundaryData ( pMyWindowData->hps, &TmpBoundary1 );
WinUnionRect ( pMyWindowData->hab, &pMyWindowData->Boundary, &TmpBoundary1, &TmpBoundary2 );
TmpBoundary2 = pMyWindowData->Boundary;
};
pMyWindowData->Boundary.xRight++;
pMyWindowData->Boundary.yTop++;
GpiSetDrawControl ( pMyWindowData->hps, DCTL_DISPLAY, DCTL_ON );
GpiSetDrawControl ( pMyWindowData->hps, DCTL_BOUNDARY, DCTL_OFF );
GpiConvert ( pMyWindowData->hps, CVTC_MODEL, CVTC_DEVICE, 2L, (PPOINTL) &pMyWindowData->Boundary );
pMyWindowData->Boundary.xRight++;
pMyWindowData->Boundary.yTop++;
return ( GpiCreateRegion ( pMyWindowData->hps, 1L, &pMyWindowData->Boundary ) );
}
/*****************************************************************************
* Create the ink color value set control on left side of the window *
*****************************************************************************/
HWND CreateInkControls ( HWND hWnd )
{
int i;
HWND hValueSet;
ULONG ulValueSetStyles;
VSCDATA vscdata;
RECTL rcl;
WinQueryWindowRect ( hWnd, &rcl );
vscdata.cbSize = sizeof (VSCDATA);
vscdata.usRowCount = 16;
vscdata.usColumnCount = 1;
ulValueSetStyles = VS_COLORINDEX |
VS_ITEMBORDER |
VS_BORDER;
hValueSet = WinCreateWindow ( hWnd,
WC_VALUESET,
"",
ulValueSetStyles,
0, 0,
25, rcl.yTop,
hWnd,
HWND_TOP,
ID_VALUE_SET_INK,
&vscdata,
NULL );
for (i=0; i<16; i++)
{
WinSendMsg ( hValueSet,
VM_SETITEM,
MPFROM2SHORT ( i+1, 1 ),
MPFROMLONG ( InkColor[i] ) );
};
WinSendMsg ( hValueSet,
VM_SELECTITEM,
MPFROM2SHORT ( 1, 1 ),
NULL );
WinShowWindow ( hValueSet, TRUE );
return ( hValueSet );
}
/*****************************************************************************
* Dialog procedure for displaying help *
*****************************************************************************/
MRESULT APIENTRY InkEditHelp ( HWND hWnd,
ULONG ulMsg,
MPARAM mp1,
MPARAM mp2 )
{
switch ( ulMsg )
{
case WM_COMMAND:
switch ( SHORT1FROMMP(mp1) )
{
case DID_CANCEL:
WinDismissDlg ( hWnd, FALSE );
return( (MRESULT) TRUE);
break;
default:
break;
};
return((MRESULT) TRUE);
break;
default:
break;
};
return( (MRESULT) WinDefDlgProc ( hWnd, ulMsg, mp1, mp2 ) );
}