home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
tolkit45.zip
/
os2tk45
/
samples
/
pm
/
clipbrd
/
clipbrd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-11
|
51KB
|
1,591 lines
/**************************************************************************
* File name : clipbrd.c
*
* Description: This program displays a standard window containing a
* picture. The action bar contains the choices Edit and
* Help. The Edit pull-down contains choices that let the
* user perform clipboard operations on the picture.
*
* This source file contains the following functions:
*
* main( VOID );
* ClipbrdHelp ( HWND, USHORT );
* ClearRoutine( VOID );
* CopyRoutine( VOID );
* CutRoutine( VOID );
* DrawRect( VOID );
* EraseRect( VOID );
* ExitRoutine( HWND );
* Finalize( VOID );
* GetBitmap( VOID );
* Initialize( VOID );
* MenuInitialization( MPARAM, MPARAM);
* MouseButtonDown( HWND, MPARAM);
* PaintRoutine( HWND );
* PasteRoutine( VOID );
* RemoveRect( VOID );
* Report_Error( HAB );
* WindowDestroy( VOID );
* WindowInitialization( HWND );
* ReportAPIError( PSZ );
* ProductInfoDlgProc( HWND, ULONG, MPARAM, MPARAM );
* HelpProductInfo( HWND );
* SetSysMenu( HWND );
*
* Concepts : clipboard
*
* API's : DevOpenDC
* DevCloseDC
*
* DosExit
*
* GpiAssociate
* GpiBox
* GpiBitBlt
* GpiCreateBitmap
* GpiCreatePS
* GpiDestroyPS
* GpiDeleteBitmap
* GpiLoadBitmap
* GpiQueryBitmapParameters
* GpiQueryColor
* GpiQueryLineType
* GpiSetCurrentPosition
* GpiSetColor
* GpiSetLineType
* GpiSetBitmap
*
* WinCreateStdWindow
* WinCreateMsgQueue
* WinCloseClipbrd
* WinDispatchMsg
* WinDefDlgProc
* WinDefWindowProc
* WinDestroyWindow
* WinDestroyMsgQueue
* WinDlgBox
* WinFillRect
* WinFreeErrorInfo
* WinGetMsg
* WinGetErrorInfo
* WinIsRectEmpty
* WinInitialize
* WinLoadString
* WinMessageBox
* WinOpenClipbrd
* WinOpenWindowDC
* WinPostMsg
* WinQuerySysValue
* WinQueryClipbrdData
* WinQuerySysPointer
* WinQueryWindowText
* WinQueryWindowRect
* WinQueryUpdateRect
* WinRegisterClass
* WinSendMsg
* WinSetFocus
* WinSetPointer
* WinSetClipbrdData
* WinSetRect
* WinSetWindowText
* WinTerminate
* WinTrackRect
* WinValidateRect
* WinWindowFromID
*
* Required
* Files : OS2.H, STRING.H, CLIPBRD.H
*
* Copyright (C) 1991 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. *
*************************************************************************/
#define INCL_DEV
#define INCL_WINWINDOWMGR
#define INCL_WINDIALOGS
#define INCL_WININPUT
#define INCL_WINRECTANGLES
#define INCL_WINACCELERATORS
#define INCL_WINPOINTERS
#define INCL_WINSETERRORINFO
#define INCL_WINMESSAGEMGR
#define INCL_WINBUTTONS
#define INCL_WINEDITCTLS
#define INCL_WINLISTBOXES
#define INCL_WINMENUS
#define INCL_WINSCROLLBARS
#define INCL_WINFRAMEMGR
#define INCL_WINFRAMECTLS
#define INCL_WINSYS
#define INCL_WINTRACKRECT
#define INCL_WINCLIPBOARD
#define INCL_GPICONTROL
#define INCL_GPITRANSFORMS
#define INCL_GPIPRIMITIVES
#define INCL_GPIREGIONS
#define INCL_GPICORRELATION
#define INCL_GPILCIDS
#define INCL_GPIBITMAPS
#define INCL_ERRORS
#define INCL_DOSPROCESS
#include <os2.h>
#include <string.h>
#include "clipbrd.h"
/*----------------- various window-dependent globals -------------------------*/
HAB habMain; /* Anchor block handle */
HMQ hmqMain; /* Application queue handle */
HWND hwndFrame=0L; /* Frame control handle */
HWND hwndClient; /* Client area handle */
HPS hpsClient=0L; /* Client area gpi ps handle */
HDC hdcClient; /* Window dc handle */
HACCEL haccelMain; /* Accelerator table handle */
HACCEL haccelTrack; /* Tracking rect accelerator table */
/*-------------------------- memory bit map globals --------------------------*/
HDC hdcMemory;
HBITMAP bmapMemory;
HPS hpsMemory;
DRIVDATA drvdata = {44L, 0L, "DISPLAY", 0L};
struct {
PSZ address;
PSZ driver_name;
PSZ driver_data;
PSZ data_type;
PSZ comment;
PSZ proc_name;
PSZ proc_params;
PSZ spl_params;
PSZ network_params;
}
dcdatablk = {0L, "DISPLAY", 0L, 0L, 0L, 0L, 0L, 0L, 0L};
BITMAPINFOHEADER2 bmpMemory; /* bitmap information header for
create bitmap API */
POINTL aptlCorners[4]; /* rectangle corners for BitBlting */
/*---------------------- tracking rectangle info structure -------------------*/
TRACKINFO tiStruct;
/*----------------- only process WM_PAINT when we are ready ------------------*/
BOOL fPaintable = FALSE;
/*----------------------- Line attribute bundle ------------------------------*/
LINEBUNDLE lbndLineAttr = {(LONG)0, /* lColor; */
(LONG)0, /* lBackColor; */
FM_XOR, /* usMixMode; */
(USHORT)0, /* usBackMixMode */
(FIXED)0, /* fxWidth; */
(LONG)0, /* lGeomWidth; */
(USHORT)0, /* usType; */
(USHORT)0, /* usEnd; */
(USHORT)0}; /* usJoin; */
/*---------------------------- loaded strings --------------------------------*/
char szTitleBar[CCHMAXSTRING];
char szTerminate[CCHMAXSTRING];
char szHelp[CCHMAXSTRING];
char szDefErrMesg[] = "No further infomation"; /* message when no other */
char szApiErrTitle[] = "API Error Return"; /* title for error message */
LONG Status = SUCCESSX;
BOOL fErrMem=FALSE;
/*
* Function prototypes
*/
MRESULT EXPENTRY ClientWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
/**************************************************************************
*
* Name : main()
*
* Description: Initializes the PM environment and processes
* the application message queue until a WM_QUIT
* message is received. It then destroys all OS/2
* PM services and terminates.
*
* Concepts : - obtains anchor block handle and creates message
* queue
* - calls the initialization routine
* - creates the main frame window which creates the
* main client window
* - polls the message queue via Get/Dispatch Msg loop
* - upon exiting the loop, exits
*
* API's : WinInitialize
* WinCreateMsgQueue
* WinGetMsg
* WinDispatchMsg
* WinTerminate
*
* Parameters : [none]
*
* Return : 1 - if successful execution completed
* 0 - if error
*
*************************************************************************/
int main()
{
QMSG qmsgMain; /* application queue structure */
habMain = WinInitialize(0L);
hmqMain = WinCreateMsgQueue(habMain,0);
/*
* Test to see if the queue handle is 0L. If it is, it probably
* means that the program has been installed in Desktop Manager as
* VIO or Full Screen. In this case, the WinInitialize works,
* but creating the message queue will fail and if you continue
* with anything else you will get invalid selectors.
* You can't even put up a message box so the program will
* not start and the user will not know why!
*/
if (hmqMain != (HMQ)0L)
{
if (!Initialize())
{
Report_Error(habMain);
Finalize();
}
while (WinGetMsg(habMain, &qmsgMain, 0L, 0,0))
WinDispatchMsg(habMain, &qmsgMain);
Finalize();
}
else
{
WinTerminate(habMain);
}
return SUCCESSX;
} /* end of main */
/**************************************************************************
*
* Name : ClientWndProc
*
* Description: This is the window procedure associated with the client
* area in the standard frame window. It processes all
* messages either sent or posted to the client area,
* depending on the message command and parameters.
*
* Concepts : messaging
*
* API's : WinMessageBox
* WinDefWindowProc
*
* Parameters : hwnd = window handle
* msg = message i.d.
* mp1 - first message parameter
* mp2 - second message parameter
*
* Return : depends on type of message processed
*
*************************************************************************/
MRESULT EXPENTRY ClientWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
switch (msg)
{
case WM_CREATE:
WindowInitialization(hwnd);
break;
case WM_DESTROY:
WindowDestroy();
break;
case WM_HELP:
WinMessageBox(HWND_DESKTOP,
hwnd,
(PSZ)szHelp,
(PSZ)szTitleBar,
0,
MB_MOVEABLE | MB_CUANOTIFICATION | MB_OK
);
break;
case WM_PAINT:
PaintRoutine(hwnd);
break;
case WM_CLOSE:
ExitRoutine(hwnd);
break;
case WM_INITMENU:
MenuInitialization(mp1,mp2);
break;
/*
* process menu item commands
*/
case WM_COMMAND:
switch (LOUSHORT(mp1))
{
case MENU_EXTHELP:
ClipbrdHelp( hwnd, EXTHELP );
break;
case MENU_HELPINDEX:
ClipbrdHelp( hwnd, HELPINDEX );
break;
case MENU_KEYSHELP:
ClipbrdHelp( hwnd, KEYSHELP );
break;
case MENU_HELPUSING:
ClipbrdHelp( hwnd, GENHELP );
break;
case MENU_PRODINFO:
HelpProductInfo( hwnd );
break;
case MENU_COPY:
CopyRoutine();
break;
case MENU_PASTE:
PasteRoutine();
break;
case MENU_CUT:
CutRoutine();
break;
case MENU_CLEAR:
ClearRoutine();
break;
/*
* Unrecognized WM_COMMAND IDs are processed in a default manner.
*/
default:
return(WinDefWindowProc(hwnd, msg, mp1, mp2));
}
break;
/*
* Clear an existing rectangle from the screen, and set the process into
* track rectangle mode loop, after setting up the required parameters
*/
case WM_BUTTON1DOWN:
MouseButtonDown(hwnd,mp1);
break;
default:
return(WinDefWindowProc(hwnd, msg, mp1, mp2));
}
return (MRESULT)0;
} /* end of ClientWndProc */
/**************************************************************************
*
* Name : ClearRoutine
*
* Description: erases a bounding rectangle from the screen
*
* Concepts :
*
* API's : WinIsRectEmpty
* WinSetRect
*
* Parameters : [none]
*
* Return : [none]
*
*************************************************************************/
VOID ClearRoutine()
{
/*
* If a bounding rectangle has been defined, erase that part of the
* picture from the screen and the memory bit map.
*/
if(!WinIsRectEmpty(habMain, &tiStruct.rclTrack))
{
EraseRect();
WinSetRect(habMain, &tiStruct.rclTrack, 0, 0, 0, 0);
} /* endif */
return;
} /* end of ClearRoutine */
/**************************************************************************
*
* Name : ClipbrdHelp
*
* Description: displays the appropriate help string
*
* Concepts : help
*
* API's : WinLoadString
* WinMessageBox
*
* Parameters : hwnd = window handle
* HelpId = help string i.d.
*
* Return : [none]
*
*************************************************************************/
VOID ClipbrdHelp(HWND hwnd, USHORT HelpId)
{
CHAR szTemp[CCHMAXSTRING];
/*
* Get the appropriate help string.
*/
if (!WinLoadString(habMain, (HMODULE)0L, HelpId, (SHORT)CCHMAXSTRING,
(PSZ)szTemp))
ReportAPIError("Error loading Help String");
/*
* Display the help string.
*/
WinMessageBox(HWND_DESKTOP,
hwnd,
(PSZ)szTemp,
(PSZ)szTitleBar,
0,
MB_MOVEABLE | MB_CUANOTIFICATION | MB_OK );
return;
} /* end of ClipbrdHelp */
/**************************************************************************
*
* Name : CopyRoutine
*
* Description: copies a rectangle into a fresh bitmap
*
* Concepts :
*
* API's : WinOpenClipbrd
* WinSetClipbrdData
* WinCloseClipbrd
*
* Parameters : [none]
*
* Return : [none]
*
*************************************************************************/
VOID CopyRoutine()
{
HBITMAP bmapTempMem;
/*
* If a bounding rectangle has been defined, copy that part of the
* memory bit map into a newly-created bitmap.
* Give the new bit map to the clipboard. Finally, clear the
* bounding rectangle.
*/
bmapTempMem = GetBitmap();
if(bmapTempMem != (HBITMAP)0L)
{
WinOpenClipbrd(habMain);
WinSetClipbrdData(habMain, (ULONG)bmapTempMem, CF_BITMAP, 0L);
WinCloseClipbrd(habMain);
RemoveRect();
} /* endif */
return;
} /* end of CopyRoutine */
/**************************************************************************
*
* Name : CutRoutine
*
* Description: cuts a rectangle to the clipboard and removes it from the
* window
*
* Concepts : clipboard
*
* API's : WinOpenClipbrd
* WinSetClipbrdData
* WinCloseClipbrd
* WinSetRect
*
* Parameters : [none]
*
* Return : [none]
*
*************************************************************************/
VOID CutRoutine()
{
HBITMAP bmapTempMem;
/*
* If a bounding rectangle has been defined, copy that part of the
* memory bit map into a newly created bitmap.
* Give the new bitmap to the clipboard. Finally clear the
* bounding rectangle and erase that part of the picture from the
* screen and the memory bit map.
*/
bmapTempMem = GetBitmap();
if (bmapTempMem != (HBITMAP)0L)
{
WinOpenClipbrd(habMain);
WinSetClipbrdData(habMain, (ULONG)bmapTempMem, CF_BITMAP, 0L);
WinCloseClipbrd(habMain);
EraseRect();
WinSetRect(habMain, &tiStruct.rclTrack, 0, 0, 0, 0);
} /* endif */
return;
} /* end of CutRoutine */
/**************************************************************************
*
* Name : DrawRect
*
* Description: Draw a rectangle on the screen, using the last position
* and size of the tracking rectangle.
*
* Concepts :
*
* API's : GpiQueryLineType
* GpiSetLineType
* GpiQueryColor
* GpiSetColor
* GpiSetCurrentPosition
* GpiBox
*
* Parameters : [none]
*
* Return : [none]
*
*************************************************************************/
VOID DrawRect()
{
POINTL ptlWork;
LONG lSaveType;
LONG lSaveColor;
lSaveType = GpiQueryLineType(hpsClient);
GpiSetLineType(hpsClient, LINETYPE_DOT);
lSaveColor = GpiQueryColor(hpsClient);
GpiSetColor(hpsClient,CLR_RED);
ptlWork.x = tiStruct.rclTrack.xLeft;
ptlWork.y = tiStruct.rclTrack.yBottom;
GpiSetCurrentPosition(hpsClient, &ptlWork);
ptlWork.x = tiStruct.rclTrack.xRight;
ptlWork.y = tiStruct.rclTrack.yTop;
GpiBox(hpsClient, DRO_OUTLINE, &ptlWork, 0L, 0L);
GpiSetLineType(hpsClient, lSaveType);
GpiSetColor(hpsClient,lSaveColor);
return;
} /* end of DrawRect */
/**************************************************************************
*
* Name : EraseRect
*
* Description: Erase a rectangle from the screen and from the memory
* bit map
*
* Concepts :
*
* API's : WinFillRect
*
* Parameters : [none]
*
* Return : [none]
*
*************************************************************************/
VOID EraseRect()
{
RECTL rclErase;
rclErase = tiStruct.rclTrack;
WinFillRect(hpsMemory, &rclErase, CLR_WHITE);
RemoveRect();
return;
} /* end of EraseRect */
/**************************************************************************
*
* Name : ExitRoutine
*
* Description: called when PF3 is pushed, when Close is selected from
* the System Menu, or when Exit is selected
*
* Concepts :
*
* API's : WinFillRect
*
* Parameters : hwnd = window handle
*
* Return : [none]
*
*************************************************************************/
VOID ExitRoutine(HWND hwnd)
{
WinPostMsg(hwnd, WM_QUIT, (MPARAM)0, (MPARAM)0);
return;
} /* end of ExitRoutine */
/**************************************************************************
*
* Name : Finalize
*
* Description: destroy all Presentation Manager resources and end the
* process
*
* Concepts : termination
*
* API's : WinDestroyWindow
* WinDestroyMsgQueue
* WinTerminate
* DosExit
*
* Parameters : [none]
*
* Return : [none]
*
*************************************************************************/
VOID Finalize( VOID )
{
WinDestroyWindow(hwndFrame);
WinDestroyMsgQueue(hmqMain);
WinTerminate(habMain);
DosExit( Status, 0);
return;
} /* end of Finalize */
/**************************************************************************
*
* Name : GetBitmap
*
* Description: If a bounding rectangle has been defined, create a screen
* compatible device context and a screen compatible bit map.
* Select the bit map into the DC, create a
* suitably sized GPI PS and associate it with the DC.
* BitBlt that part of the
* screen defined by the rectangle into the new bit map.
* Destroy all other resources but return the bit map handle
* (to be passed to the clipboard)
*
* Concepts :
*
* API's : WinIsRectEmpty
* WinQuerySysPointer
* WinSetPointer
* DevOpenDC
* GpiCreatePS
* GpiCreateBitmap
* GpiSetBitmap
* GpiBitBlt
* GpiAssociate
* GpiDestroyPS
* DevCloseDC
*
* Parameters : [none]
*
* Return : bitmap handle
*
*************************************************************************/
HBITMAP GetBitmap()
{
HDC hdc;
HPS hps;
HBITMAP bmap;
register HPOINTER tptr;
SIZEL sizlWork;
if(WinIsRectEmpty(habMain, &tiStruct.rclTrack))
{
return((HBITMAP)0L);
} /* endif */
if ( (tptr = WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE)) == 0 )
ReportAPIError("Failed to get System pointer handle");
WinSetPointer(HWND_DESKTOP, tptr);
/*
* It is a bounding rectangle, so we only want what is inside.
*/
sizlWork.cx = tiStruct.rclTrack.xRight - tiStruct.rclTrack.xLeft - 1;
sizlWork.cy = tiStruct.rclTrack.yTop - tiStruct.rclTrack.yBottom - 1;
hdc = DevOpenDC(habMain,
OD_MEMORY,
(PSZ)"*",
8L,
(PDEVOPENDATA)&dcdatablk,
(HDC)0L
);
if (hdc == 0) ReportAPIError("DevOpenDC Failure");
bmpMemory.cbFix = sizeof(bmpMemory);
bmpMemory.cx = (USHORT)sizlWork.cx;
bmpMemory.cy = (USHORT)sizlWork.cy;
bmpMemory.cPlanes = 1L;
bmpMemory.cBitCount = 24L;
bmpMemory.ulCompression = BCA_UNCOMP;
bmpMemory.cxResolution = 0;
bmpMemory.cyResolution = 0;
bmpMemory.cclrUsed = 0;
bmpMemory.cclrImportant = 0;
bmpMemory.usUnits = BRU_METRIC;
bmpMemory.usRecording = BRA_BOTTOMUP;
bmpMemory.usRendering = BRH_NOTHALFTONED;
bmpMemory.cSize1 = 0;
bmpMemory.cSize2 = 0;
bmpMemory.ulColorEncoding = 0;
bmpMemory.ulIdentifier = 0;
hps = GpiCreatePS(habMain, hdc, &sizlWork, GPIA_ASSOC | PU_PELS);
if (hps == 0)
{
ReportAPIError("GpiCreatePS Failure");
}
bmap = GpiCreateBitmap(hps,
(PBITMAPINFOHEADER2)&bmpMemory,
0L,
(PBYTE)NULL,
(PBITMAPINFO2)NULL
);
if (bmap ==0)
{
ReportAPIError("GpiCreateBitmap Failure");
}
GpiSetBitmap(hps, bmap);
/*
* No adjustments to the top and right top (using lengths) since the
* rectangles used for the BitBlt are non-inclusive (the bottom and
* left are included, but not the top and right)
*/
aptlCorners[0].x = 0;
aptlCorners[0].y = 0;
aptlCorners[1].x = sizlWork.cx;
aptlCorners[1].y = sizlWork.cy;
/*
* Want to copy from inside the bounding rect. Increase the left & bottom
* by one but leave the top & right since the rectangles used for the BitBlt
* are non-inclusive (the bottom and left are included, but not the
* top and right).
*/
aptlCorners[2].x = tiStruct.rclTrack.xLeft + 1;
aptlCorners[2].y = tiStruct.rclTrack.yBottom + 1;
aptlCorners[3].x = tiStruct.rclTrack.xRight;
aptlCorners[3].y = tiStruct.rclTrack.yTop;
GpiBitBlt(hps, hpsMemory, 4L, aptlCorners, ROP_SRCCOPY, BBO_IGNORE);
GpiSetBitmap(hps, (HBITMAP)0L);
GpiAssociate(hps, (HDC)0L);
GpiDestroyPS(hps);
DevCloseDC(hdc);
WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP,
SPTR_ARROW,
FALSE)
);
return(bmap);
} /* end of GetBitmap */
/**************************************************************************
*
* Name : Initialize
*
* Description: initialize the PM interface,
* create an application message queue and a
* standard frame window
*
* Concepts :
*
* API's : WinLoadString
* WinRegisterClass
* WinSetPointer
* WinQuerySysPointer
* WinCreateStdWindow
* WinQueryWIndowText
* WinSetWindowText
*
* Parameters : [none]
*
* Return : TRUE = successful initialization
* FALSE = error occurred
*
*************************************************************************/
BOOL Initialize()
{
ULONG flCreate;
BOOL fErrTmp=FALSE;
fErrMem = (BOOL)!WinLoadString(habMain,
(HMODULE)0L,
(USHORT)TERMINATE,
(SHORT)CCHMAXSTRING,
(PSZ)szTerminate
);
fErrTmp = (BOOL)!WinLoadString(habMain,
(HMODULE)0L,
(USHORT)HELPPANEL,
(SHORT)CCHMAXSTRING,
(PSZ)szHelp
);
if (fErrMem || fErrTmp)
return(FALSE);
if (!WinRegisterClass(habMain,
(PSZ)"My Class",
(PFNWP)ClientWndProc,
CS_SIZEREDRAW,
0))
return(FALSE);
WinSetPointer(HWND_DESKTOP,
WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE));
flCreate = FCF_STANDARD;
hwndFrame = WinCreateStdWindow(HWND_DESKTOP,
WS_VISIBLE,
&flCreate,
(PSZ)"My Class",
(PSZ)NULL,
WS_VISIBLE,
(HMODULE)0L,
AMENU,
&hwndClient
);
WinSetWindowText(hwndFrame, "CLIPBOARD SAMPLE");
WinSetPointer(HWND_DESKTOP,
WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
if (hwndFrame == (HWND)0L)
{
return(FALSE);
} /* endif */
/*
* Get the window title given to the window by the system
*/
WinQueryWindowText(hwndFrame, CCHMAXSTRING, (PSZ)szTitleBar);
return(TRUE);
} /* end of Initialize */
/**************************************************************************
*
* Name : MenuInitialization
*
* Description: set beginning attributes (enabled or not) of menu items
*
* Concepts : menu
*
* API's : WinIsRectEmpty
* WinSendMsg
* WinOpenClipbrd
* WinQueryClipbrdData
* WinCloseClipbrd
*
* Parameters : mp1 = first message parameter
* mp2 = second message parameter
*
* Return : [none]
*
*************************************************************************/
VOID MenuInitialization(MPARAM mp1, MPARAM mp2)
{
BOOL fEmptyRect;
/*
* Menu items in the Edit pull-down may need to be grayed, depending on
* the presence of a rectangle and the contents of the clipboard.
*/
if (LOUSHORT(mp1) == SM_CLIPBRD)
{
fEmptyRect = WinIsRectEmpty(habMain, &tiStruct.rclTrack);
WinSendMsg((HWND)mp2,
MM_SETITEMATTR,
MPFROM2SHORT(MENU_COPY, TRUE),
MPFROM2SHORT(MIA_DISABLED,
fEmptyRect ? MIA_DISABLED : ~MIA_DISABLED)
);
WinSendMsg((HWND)mp2,
MM_SETITEMATTR,
MPFROM2SHORT(MENU_CUT, TRUE),
MPFROM2SHORT(MIA_DISABLED,
fEmptyRect ? MIA_DISABLED : ~MIA_DISABLED)
);
WinSendMsg((HWND)mp2,
MM_SETITEMATTR,
MPFROM2SHORT(MENU_CLEAR, TRUE),
MPFROM2SHORT(MIA_DISABLED,
fEmptyRect ? MIA_DISABLED : ~MIA_DISABLED)
);
WinOpenClipbrd(habMain);
if ((HBITMAP)WinQueryClipbrdData(habMain, CF_BITMAP) != (HBITMAP)0L &&
!fEmptyRect)
{
fEmptyRect = TRUE;
}
else
{
fEmptyRect = FALSE;
}
WinSendMsg((HWND)mp2,
MM_SETITEMATTR,
MPFROM2SHORT(MENU_PASTE, TRUE),
MPFROM2SHORT(MIA_DISABLED,
fEmptyRect ? ~MIA_DISABLED : MIA_DISABLED)
);
WinCloseClipbrd(habMain);
}
} /* end of MenuInitialization */
/**************************************************************************
*
* Name : MouseButtonDown
*
* Description: process the mouse button interface
*
* Concepts : rectangle tracking
*
* API's : WinSetFocus
* WinIsRectEmpty
* WinSetRect
* WinQueryWindowRect
* WinTrackRect
*
* Parameters : hwnd = window handle
* mp1 = message parameter
*
* Return : [none]
*
*************************************************************************/
VOID MouseButtonDown(HWND hwnd, MPARAM mp1)
{
/*
* As the application is handling the button message, set the focus
* to the frame window.
*/
WinSetFocus(HWND_DESKTOP,hwndClient);
/*
* Clear an existing rectangle from the screen, and set the process into
* track rectangle mode loop, after setting up the required parameters.
*/
if(!WinIsRectEmpty(habMain, &tiStruct.rclTrack))
{
RemoveRect();
WinSetRect(habMain, &tiStruct.rclTrack, 0, 0, 0, 0);
} /* endif */
tiStruct.cxBorder = 1;
tiStruct.cyBorder = 1;
tiStruct.cxGrid = 0;
tiStruct.cyGrid = 0;
WinSetRect(habMain, &tiStruct.rclTrack,
LOUSHORT(mp1),
HIUSHORT(mp1),
LOUSHORT(mp1),
HIUSHORT(mp1));
WinQueryWindowRect(hwnd, &tiStruct.rclBoundary);
tiStruct.ptlMinTrackSize.x = 1;
tiStruct.ptlMinTrackSize.y = 1;
tiStruct.ptlMaxTrackSize.x = ++tiStruct.rclBoundary.xRight;
tiStruct.ptlMaxTrackSize.y = ++tiStruct.rclBoundary.yTop;
tiStruct.fs = TF_STANDARD | TF_ALLINBOUNDARY | TF_RIGHT | TF_BOTTOM;
WinTrackRect(hwnd, (HPS)0L, &tiStruct);
if((tiStruct.rclTrack.xRight - tiStruct.rclTrack.xLeft) > 2 &&
(tiStruct.rclTrack.yTop - tiStruct.rclTrack.yBottom) > 2)
{
DrawRect();
}
else
{
WinSetRect(habMain, &tiStruct.rclTrack, 0, 0, 0, 0);
} /* endif */
} /* end of MouseButtonDown */
/**************************************************************************
*
* Name : PaintRoutine
*
* Description: display bits in the window
*
* Concepts :
*
* API's : WinQueryUpdateRect
* GpiBitBlt
* WinInvalidateRect
* WinIsRectEmpty
*
*
* Parameters : hwnd = window handle
*
* Return : [none]
*
*************************************************************************/
VOID PaintRoutine(HWND hwnd)
{
RECTL rclUpdt;
BOOL RC;
/*
* If we are in a position to update the window, get the invalidated
* rectangle and use this to copy from the memory bit map to the screen,
* using a BitBlt. Finally, validate the updated rectangle.
*/
if (fPaintable)
{
WinQueryUpdateRect(hwnd, &rclUpdt);
/*
* Want the top & right-hand side, so increase by one, since the
* rectangles used for the BitBlt are non-inclusive (the bottom
* and left are included, but not the top and right).
*/
aptlCorners[0].x = rclUpdt.xLeft;
aptlCorners[0].y = rclUpdt.yBottom;
aptlCorners[1].x = rclUpdt.xRight+1;
aptlCorners[1].y = rclUpdt.yTop+1;
/*
* Want the top & right-hand side as well, so increase by one, since the
* rectangles used for the BitBlt are non-inclusive (the bottom
* and left are included, but not the top and right).
*/
aptlCorners[2].x = rclUpdt.xLeft;
aptlCorners[2].y = rclUpdt.yBottom;
aptlCorners[3].x = rclUpdt.xRight+1;
aptlCorners[3].y = rclUpdt.yTop+1;
GpiBitBlt(hpsClient,
hpsMemory,
4L,
aptlCorners,
ROP_SRCCOPY,
BBO_IGNORE
);
RC = WinValidateRect(hwnd, &rclUpdt, FALSE);
if (!WinIsRectEmpty(habMain, &tiStruct.rclTrack))
DrawRect();
}
} /* end of PaintRoutine */
/**************************************************************************
*
* Name : PasteRoutine
*
* Description: display a rectangle from the clipboard
*
* Concepts :
*
* API's : WinIsRectEmpty
* WinOpenClipbrd
* WinQueryClipbrdData
* GpiQueryBitmapParameters
* DevOpenDC
* GpiCreatePS
* GpiSetBitmap
* WinSetPointer
* GpiBitBlt
* GpiAssociate
* GpiDestroyPS
* DevCloseDC
* WinCloseClipbrd
* WinSetRect
*
* Parameters : [none]
*
* Return : [none]
*
*************************************************************************/
VOID PasteRoutine()
{
HDC hdcTempMem;
HBITMAP bmapTempMem;
HPS hpsTempMem;
BITMAPINFOHEADER bmpTemp;
SIZEL sizlWork;
/*
* If a bounding rectangle has been defined, open the clipboard and
* see if it contains a bit map. If one exists, create temporary DCs
* and GPI PSs to enable the clipboard bit map to be BitBlted into
* the memory bit map and from there onto the screen. Destroy all the
* temporary resources, close the clipboard and clear the
* bounding rectangle.
*/
if (!WinIsRectEmpty(habMain, &tiStruct.rclTrack))
{
WinOpenClipbrd(habMain);
bmapTempMem = (HBITMAP)WinQueryClipbrdData(habMain, CF_BITMAP);
if(bmapTempMem != (HBITMAP)0L)
{
GpiQueryBitmapParameters(bmapTempMem,
&bmpTemp
);
/*
* Want to paste inside the bounding rect. So increase the
* left & bottom by one but leave the top & right since the
* rectangles used for the BitBlt are non-inclusive (the
* bottom and left are included, but not the top and right).
*/
aptlCorners[0].x = tiStruct.rclTrack.xLeft+1;
aptlCorners[0].y = tiStruct.rclTrack.yBottom+1;
aptlCorners[1].x = tiStruct.rclTrack.xRight;
aptlCorners[1].y = tiStruct.rclTrack.yTop;
/*
* No adjustments to the top & right top (using lengths)
* since the rectangles used for the BitBlt are
* non-inclusive (the bottom and left are included,
* but not the top and right).
*/
aptlCorners[2].x = 0;
aptlCorners[2].y = 0;
aptlCorners[3].x = bmpTemp.cx;
aptlCorners[3].y = bmpTemp.cy;
hdcTempMem = DevOpenDC(habMain,
OD_MEMORY,
(PSZ)"*",
8L,
(PDEVOPENDATA)&dcdatablk,
(HDC)0L
);
sizlWork.cx = bmpTemp.cx;
sizlWork.cy = bmpTemp.cy;
hpsTempMem = GpiCreatePS(habMain,
hdcTempMem,
&sizlWork,
GPIA_ASSOC | PU_PELS
);
GpiSetBitmap(hpsTempMem, bmapTempMem);
WinSetPointer(HWND_DESKTOP,
WinQuerySysPointer(HWND_DESKTOP,
SPTR_WAIT,
FALSE)
);
GpiBitBlt(hpsMemory,
hpsTempMem,
4L,
aptlCorners,
ROP_SRCCOPY,
BBO_IGNORE
);
/*
* Want a slightly bigger rectangle for the screen because
* we need to remove the bounding rectangle as well as do
* the paste.
*/
aptlCorners[2].x = (--aptlCorners[0].x);
aptlCorners[2].y = (--aptlCorners[0].y);
aptlCorners[3].x = (++aptlCorners[1].x);
aptlCorners[3].y = (++aptlCorners[1].y);
GpiBitBlt(hpsClient,
hpsMemory,
4L,
aptlCorners,
ROP_SRCCOPY,
BBO_IGNORE
);
WinSetPointer(HWND_DESKTOP,
WinQuerySysPointer(HWND_DESKTOP,
SPTR_ARROW,
FALSE)
);
GpiSetBitmap(hpsTempMem, (HBITMAP)0L);
GpiAssociate(hpsTempMem, (HDC)0L);
GpiDestroyPS(hpsTempMem);
DevCloseDC(hdcTempMem);
} /* endif */
WinCloseClipbrd(habMain);
WinSetRect(habMain, &tiStruct.rclTrack, 0, 0, 0, 0);
} /* endif */
} /* end of PasteRoutine */
/**************************************************************************
*
* Name : RemoveRect
*
* Description: Update the screen from the memory bitmap, thus erasing
* the rectangle
*
* Concepts : bitblt
*
* API's : GpiBitBlt
* WinSetRect
*
* Parameters : [none]
*
* Return : [none]
*
*************************************************************************/
VOID RemoveRect()
{
/*
* Want the top & right-hand side as well, so increase by one since the
* rectangles used for the BitBlt are non-inclusive (the
* bottom and left are included, but not the top and right).
*/
aptlCorners[0].x = tiStruct.rclTrack.xLeft;
aptlCorners[0].y = tiStruct.rclTrack.yBottom;
aptlCorners[1].x = tiStruct.rclTrack.xRight+1;
aptlCorners[1].y = tiStruct.rclTrack.yTop+1;
/*
* Want the top & right-hand side as well, so increase by one since the
* rectangles used for the BitBlt are non-inclusive (the
* bottom and left are included, but not the top and right).
*/
aptlCorners[2].x = tiStruct.rclTrack.xLeft;
aptlCorners[2].y = tiStruct.rclTrack.yBottom;
aptlCorners[3].x = tiStruct.rclTrack.xRight+1;
aptlCorners[3].y = tiStruct.rclTrack.yTop+1;
GpiBitBlt(hpsClient,
hpsMemory,
4L,
aptlCorners,
ROP_SRCCOPY,
BBO_IGNORE
);
WinSetRect(habMain, &tiStruct.rclTrack, 0, 0, 0, 0);
} /* end of RemoveRect */
/**************************************************************************
*
* Name : Report_Error
*
* Description: Display a particular system error message, the latest one
* for the required thread. No resources can be loaded in
* case of memory error.
*
* Concepts :
*
* API's : WinGetErrorInfo
* WinMessageBox
* WinFreeErrorInfo
*
* Parameters : hab = anchor block handle
*
* Return : [none]
*
*************************************************************************/
VOID Report_Error(HAB hab)
{
PERRINFO perriBlk;
PSZ pszErrMsg;
PSZ pszOffSet;
if (!fErrMem)
{
if((perriBlk = WinGetErrorInfo(hab)) != (PERRINFO)NULL)
{
pszOffSet = ((PSZ)perriBlk) + perriBlk->offaoffszMsg;
pszErrMsg = ((PSZ)perriBlk) + *((PUSHORT)pszOffSet);
WinMessageBox(HWND_DESKTOP,
hwndFrame,
(PSZ)(pszErrMsg),
(PSZ)szTitleBar,
0,
MB_MOVEABLE | MB_CUACRITICAL | MB_CANCEL );
WinFreeErrorInfo(perriBlk);
return;
}
} /* endif */
WinMessageBox(HWND_DESKTOP,
hwndFrame,
(PSZ)"ERROR - Out Of Memory",
(PSZ)szTitleBar,
0,
MB_MOVEABLE | MB_CUACRITICAL | MB_CANCEL);
} /* end of Report_Error */
/**************************************************************************
*
* Name : WindowDestroy
*
* Description: destroy particular window data
*
* Concepts :
*
* API's : GpiSetBitmap
* GpiDeleteBitmap
* GpiAssociate
* GpiDestroyPS
* DevCloseDC
*
* Parameters : [none]
*
* Return : [none]
*
*************************************************************************/
VOID WindowDestroy()
{
/*
* Deselect the bit map from the screen-compatible device context, and
* delete the bit map. Disassociate the two GPI PSs from their respective
* DCs and destroy the PSs. Finally destroy the memory DC.
*/
GpiSetBitmap(hpsMemory, (HBITMAP)0L);
GpiDeleteBitmap(bmapMemory);
GpiAssociate(hpsClient, (HDC)0L);
GpiDestroyPS(hpsClient);
GpiAssociate(hpsMemory, (HDC)0L);
GpiDestroyPS(hpsMemory);
DevCloseDC(hdcMemory);
return;
} /* end of WindowDestroy */
/**************************************************************************
*
* Name : WindowInitialization
*
* Description: create window information
*
* Concepts :
*
* API's : WinQuerySysValue
* WinOpenWindowDC
* GpiCreatePS
* DevOpenDC
* GpiSetBitmap
* GpiLoadBitmap
* GpiSetRect
*
* Parameters : [none]
*
* Return : [none]
*
*************************************************************************/
VOID WindowInitialization(HWND hwnd)
{
SIZEL sizlWork;
/*
* Get the maximum client area size. Create a window DC for the client
* area and a normal GPI Presentation Space and associate the two. The
* GPI PS will be the maximum client area size in pels. Create a
* memory DC compatible with the screen, create a GPI PS and associate it
* with the screen compatible DC. Load a bit map from the resource
* file, and select the bit map into the screen-compatible DC.
* Initialize the rectangle tracking and set a flag to enable window
* painting.
*/
sizlWork.cx = WinQuerySysValue(HWND_DESKTOP, SV_CXFULLSCREEN);
sizlWork.cy = WinQuerySysValue(HWND_DESKTOP, SV_CYFULLSCREEN);
hdcClient = WinOpenWindowDC(hwnd);
hpsClient = GpiCreatePS(habMain,
hdcClient,
&sizlWork,
GPIA_ASSOC | PU_PELS
);
dcdatablk.driver_data = (PSZ)&drvdata;
hdcMemory = DevOpenDC(habMain,
OD_MEMORY,
(PSZ)"*",
8L,
(PDEVOPENDATA)&dcdatablk,
(HDC)0L
);
hpsMemory = GpiCreatePS(habMain,
hdcMemory,
&sizlWork,
GPIA_ASSOC | PU_PELS
);
bmapMemory = GpiLoadBitmap( hpsMemory
, (HMODULE)0L
, (USHORT)ID_BITMAP
, sizlWork.cx
, sizlWork.cy
);
GpiSetBitmap(hpsMemory, bmapMemory);
WinSetRect(habMain, &tiStruct.rclTrack, 0, 0, 0, 0);
fPaintable = TRUE;
return;
} /* end of WindowInitialization */
/**************************************************************************
*
* Name : ReportAPIError
*
* Description: display an error message returned from an API call
*
* Concepts :
*
* API's : WinGetErrorInfo
* WinMessageBox
* WinPostMsg
*
* Parameters : what = message string
*
* Return : [none]
*
*************************************************************************/
VOID ReportAPIError(PSZ what)
{
PERRINFO pErrInfoBlk;
PSZ pszErrMsg;
PSZ pszOffSet;
char ErrorMsg[CCHMAXSTRING]; /* error text buffer */
pszErrMsg = &szDefErrMesg[0]; /* set default in case no err */
strcpy(ErrorMsg, what); /* init message string */
strcat(ErrorMsg, "\n\n"); /* double space for neatness */
if ((pErrInfoBlk = WinGetErrorInfo(habMain)) != (PERRINFO)NULL)
{
pszOffSet = ((PSZ)pErrInfoBlk) + pErrInfoBlk->offaoffszMsg;
pszErrMsg = ((PSZ)pErrInfoBlk) + *((PUSHORT)pszOffSet);
WinFreeErrorInfo(pErrInfoBlk);
} /* if ((pErrInfoBlk = WinGetErrorInfo(hab)) != (PCH)NULL) */
strcat(ErrorMsg, pszErrMsg); /* combine specific text */
WinMessageBox(HWND_DESKTOP, /* parent window is desk top */
hwndFrame, /* owner window is our frame */
(PSZ)&ErrorMsg[0], /* text for message */
(PSZ)szApiErrTitle, /* title is API error */
0, /* null window id */
MB_MOVEABLE | MB_CUACRITICAL | MB_CANCEL ); /* flags */
Status = ERRORX;
WinPostMsg(hwndClient, WM_QUIT, (ULONG)0, (ULONG)0);
return;
} /* end of ReportAPIError */
/**************************************************************************
*
* Name : ProductInfoDlgProc(hwnd, msg, mp1, mp2)
*
* Description: Processes all messages sent to the Product
* information dialog
*
* Concepts : Called for each message sent to the Product information
* dialog box.
*
* the Product information dialog has only a button control, so this
* routine processes only WM_COMMAND messages. Any
* WM_COMMAND posted must have come from the OK
* button, so we dismiss the dialog upon receiving it.
*
* API's : WinDefDlgProc
*
* Parameters : [none]
*
* Return : dependent on message sent
*
*************************************************************************/
MRESULT EXPENTRY ProductInfoDlgProc(HWND hwnd,ULONG msg, MPARAM mp1, MPARAM mp2)
{
switch (msg)
{
case WM_INITDLG:
SetSysMenu(hwnd); /* system menu for this dialog */
return (MRESULT)NULL;
default:
return WinDefDlgProc(hwnd, msg, mp1, mp2);
}
return (MRESULT)NULL;
} /* End of ProductInfoDlgProc */
/**************************************************************************
*
* Name : HelpProductInfo(hwndMain)
*
* Description: Processes the Product information choice from the Help
* pulldown
*
* Concepts : Processes the WM_COMMAND message posted by the
* Product information item of the Help menu
* Called from MainCommand when the Product information
* menu item is selected
* Calls WinDlgBox to display the Product information
* dialog.
*
* API's : WinDlgBox
*
* Parameters : hwndMain = main window handle
*
* Return : [none]
*
*************************************************************************/
VOID HelpProductInfo(HWND hwndMain)
{
/* display the Product Information dialog. */
if(DID_ERROR == WinDlgBox(HWND_DESKTOP,
hwndMain,
(PFNWP)ProductInfoDlgProc,
0,
IDD_PRODUCTINFO,
(PVOID)NULL))
ReportAPIError("Can't start dialog");
return;
} /* End of HelpProductInfo */
/**************************************************************************
*
* Name : SetSysMenu(hDlg)
*
* Description: Enables only the Move and Close items in the
* system menu pulldown for any dialog
*
* Concepts :
*
* API's : WinWindowFromID
* WinSendMsg
*
* Parameters : hDlg = dialog handle
*
* Return : [none]
*
*************************************************************************/
VOID SetSysMenu(HWND hDlg)
{
HWND hSysMenu;
MENUITEM Mi;
SHORT Pos;
SHORT Id;
SHORT cItems;
/*
* We only want Move and Close in the system menu.
*/
hSysMenu = WinWindowFromID(hDlg, FID_SYSMENU);
WinSendMsg( hSysMenu, MM_QUERYITEM
, MPFROM2SHORT(SC_SYSMENU, FALSE), MPFROMP((PCH) & Mi));
Pos = 0;
cItems = (SHORT)WinSendMsg( Mi.hwndSubMenu, MM_QUERYITEMCOUNT,
(MPARAM)NULL, (MPARAM)NULL);
while (cItems--)
{
Id = SHORT1FROMMR(WinSendMsg( Mi.hwndSubMenu, MM_ITEMIDFROMPOSITION
, MPFROM2SHORT(Pos, TRUE), (MPARAM)NULL));
switch (Id)
{
case SC_MOVE:
case SC_CLOSE:
Pos++; /* Don't delete that one. */
break;
default:
WinSendMsg( Mi.hwndSubMenu, MM_DELETEITEM
, MPFROM2SHORT(Id, TRUE), (MPARAM)NULL);
}
}
} /* End of SetSysMenu */
/*************************** End of clipbrd.c **************************/