home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
cset21v1.zip
/
IBMCPP
/
SAMPLES
/
COMPILER
/
SAMPLE1A
/
PMLINES.C
< prev
next >
Wrap
Text File
|
1993-03-15
|
27KB
|
608 lines
#pragma strings( readonly )
/*+--------------------------------------------------------------------------+*/
/*| |*/
/*| PROGRAM NAME: PMLINES |*/
/*| ------------- |*/
/*| A Simple OS/2 Presentation Manager Graphics Demonstration Program |*/
/*| |*/
/*| COPYRIGHT: |*/
/*| ---------- |*/
/*| Copyright (C) International Business Machines Corp., 1991,1992. |*/
/*| |*/
/*| DISCLAIMER OF WARRANTIES: |*/
/*| ------------------------- |*/
/*| The following [enclosed] code is sample code created by IBM Corporation.|*/
/*| This sample code is not part of any standard 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. |*/
/*| |*/
/*| REVISION LEVEL: 1.0 |*/
/*| --------------- |*/
/*| |*/
/*| WHAT THIS PROGRAM DOES: |*/
/*| ----------------------- |*/
/*| This program displays a standard window and then draws lines in the |*/
/*| window. Both the line and background colours change. |*/
/*| |*/
/*| WHAT THIS PROGRAM DEMONSTRATES: |*/
/*| ------------------------------- |*/
/*| This program demonstrates how to create and display a standard window, |*/
/*| use simple menus and dialog boxes, use a second thread for drawing, |*/
/*| and displaying graphics using some basic GPI calls. |*/
/*| |*/
/*| WHAT YOU NEED TO COMPILE THIS PROGRAM: |*/
/*| -------------------------------------- |*/
/*| |*/
/*| REQUIRED FILES: |*/
/*| --------------- |*/
/*| |*/
/*| PMLINES.C - Source code |*/
/*| PMLINES.DEF - Module definition file |*/
/*| PMLINES.H - Application header file |*/
/*| PMLINES.ICO - Icon file |*/
/*| SAMPLE1A.RC - Resource file |*/
/*| PMLINES.DLG - Dialog file |*/
/*| |*/
/*| OS2.H - Presentation Manager include file |*/
/*| STDLIB.H - Standard library function declarations |*/
/*| STRING.H - String handling function declarations |*/
/*| |*/
/*| REQUIRED LIBRARIES: |*/
/*| ------------------- |*/
/*| |*/
/*| OS2386.LIB - Presentation Manager/OS2 library |*/
/*| DDE4NBS.LIB - Subsystem Development Library |*/
/*| |*/
/*| REQUIRED PROGRAMS: |*/
/*| ------------------ |*/
/*| |*/
/*| IBM C Set/2 Compiler |*/
/*| IBM Linker |*/
/*| Resource Compiler |*/
/*| |*/
/*| EXPECTED INPUT: |*/
/*| --------------- |*/
/*| |*/
/*| EXPECTED OUTPUT: |*/
/*| ---------------- |*/
/*| |*/
/*+--------------------------------------------------------------------------+*/
/*+--------------------------------------------------------------------------+*/
/*| System and library header files. |*/
/*+--------------------------------------------------------------------------+*/
#define INCL_NOCOMMON
#define INCL_DOSPROCESS
#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS
#define INCL_WINWINDOWMGR
#define INCL_WINMESSAGEMGR
#define INCL_WINFRAMEMGR
#define INCL_WINDIALOGS
#define INCL_WININPUT
#define INCL_WINSWITCHLIST
#define INCL_WINPROGRAMLIST
#define INCL_GPICONTROL
#define INCL_GPIPRIMITIVES
#include <os2.h>
#include <stdlib.h>
#include <string.h>
/*+--------------------------------------------------------------------------+*/
/*| Application header files. |*/
/*+--------------------------------------------------------------------------+*/
#include "pmlines.h"
/*+--------------------------------------------------------------------------+*/
/*| Internal function prototypes. |*/
/*+--------------------------------------------------------------------------+*/
static void InitTitle( HAB, HWND, char * );
static MRESULT EXPENTRY ClientWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
static MRESULT EXPENTRY HelpDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 );
static FNTHREAD DrawingThread;
static void DisplayMessage( HAB, ULONG );
/*+--------------------------------------------------------------------------+*/
/*| Static global variables and local constants. |*/
/*+--------------------------------------------------------------------------+*/
#define WINDOW_CLASS "My_Window" /* window class name */
#define COLOUR_TBL_LEN 16 /* number of colour table entries */
#define MSG_BOX_ID 256 /* error message box id */
#define STRING_LENGTH 128 /* size of buffer used for strings*/
#define STACK_SIZE 8192UL /* stack size for second thread */
static HWND hwndClient = NULLHANDLE; /* client window handle */
static HMQ hmqThread2 = NULLHANDLE; /* message queue handle for thread*/
static POINTL ptl1; /* line start point */
static POINTL ptl2; /* line end point */
static LONG lFcolour = CLR_BLUE; /* foreground (line) colour */
static LONG lBcolour = CLR_DARKGRAY; /* background colour */
static LONG cxClient, cyClient; /* client window X and Y size */
static LONG fcolourcounter = 1L; /* wait time to change line colour*/
static TID tidDrawing = 0UL; /* drawing thread identifier */
static char szAppName[ MAXNAMEL + 1 ]; /* application name string */
/*+--------------------------------------------------------------------------+*/
/*| Main control procedure. |*/
/*+--------------------------------------------------------------------------+*/
int main( void )
{
HAB hab = NULLHANDLE; /* PM anchor block handle */
HMQ hmq = NULLHANDLE; /* message queue handle */
HWND hwndFrame = NULLHANDLE; /* frame window handle */
ULONG flCreate = 0UL; /* window creation control flags */
QMSG qmsg; /* message from message queue */
int rc = 1;
do
{
/* Initialize PM and create a message queue of default size. */
if ( ( hab = WinInitialize( 0UL ) ) == NULLHANDLE )
break;
if ( ( hmq = WinCreateMsgQueue( hab, 0UL ) ) == NULLHANDLE )
break;
/* Register client window class. */
if ( !WinRegisterClass( hab, /* PM anchor block handle */
WINDOW_CLASS, /* window class name */
ClientWindowProc, /* address of window procedure */
CS_SIZEREDRAW,/* size changes cause redrawing */
0UL ) ) /* window data */
{
DisplayMessage( hab, IDS_NOREGISTER );
break;
}
/* Create the standard windows but do not add the application to the */
/* task manager list. */
flCreate = FCF_STANDARD & ~FCF_TASKLIST;
hwndFrame =
WinCreateStdWindow( HWND_DESKTOP, /* make desktop window the parent */
WS_VISIBLE, /* frame window class style */
&flCreate, /* frame control flags */
WINDOW_CLASS, /* client window class name */
"", /* title bar text */
CS_SIZEREDRAW, /* client window class style */
0UL, /* resource file handle - in EXE */
ID_WINDOW, /* resources identifier */
&hwndClient ); /* client window handle */
if ( hwndFrame == NULLHANDLE )
{
DisplayMessage( hab, IDS_NOSTDWINDOWS );
break;
}
/* Initialize the window title and task switch list. */
InitTitle( hab, hwndFrame, szAppName );
/* Create the thread that will draw the lines. */
/* NOTE: _beginthread MUST be used if the thread contains CRT calls */
if ( DosCreateThread( &tidDrawing, DrawingThread, 0UL, 0UL, STACK_SIZE ) )
{
DisplayMessage( hab, IDS_NOTHREAD );
break;
}
/* While the WM_QUIT message is not received, dispatch the message. */
/* When the WM_QUIT message is received, WinGetMsg will return FALSE. */
while( WinGetMsg( hab, &qmsg, 0UL, 0UL, 0UL ) )
WinDispatchMsg( hab, /* PM anchor block handle */
&qmsg ); /* pointer to message */
rc = 0;
} while ( FALSE );
/* Destroy the standard windows if they were created. */
if ( hwndFrame != NULLHANDLE )
WinDestroyWindow( hwndFrame ); /* frame window handle */
/* Destroy the message queue and release the anchor block. */
if ( hmq != NULLHANDLE )
WinDestroyMsgQueue( hmq );
if ( hab != NULLHANDLE )
WinTerminate( hab );
return rc;
}
/*+--------------------------------------------------------------------------+*/
/*| InitTitle - Initializes window title and task switch list. |*/
/*+--------------------------------------------------------------------------+*/
static void InitTitle( HAB hab, HWND hwnd, char *szTitle )
{
SWCNTRL tSwcntrl; /* task switch structure */
/* Load the application name from the resources in the EXE. Set the title */
/* bar text to this name. Then add this application to the task manager */
/* list with the loaded application name. */
WinLoadString( hab, 0UL, IDS_APPNAME, MAXNAMEL, szTitle );
WinSetWindowText( hwnd, szTitle );
tSwcntrl.hwnd = hwnd;
tSwcntrl.hwndIcon = NULLHANDLE;
tSwcntrl.hprog = NULLHANDLE;
tSwcntrl.idProcess = 0;
tSwcntrl.idSession = 0;
tSwcntrl.uchVisibility = SWL_VISIBLE;
tSwcntrl.fbJump = SWL_JUMPABLE;
strcpy( tSwcntrl.szSwtitle, szTitle );
tSwcntrl.bProgType = PROG_PM;
WinAddSwitchEntry( &tSwcntrl );
return;
}
/*+--------------------------------------------------------------------------+*/
/*| ClientWindowProc - Client window procedure. |*/
/*+--------------------------------------------------------------------------+*/
static MRESULT EXPENTRY ClientWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
HPS hps = NULLHANDLE; /* presentation space handle */
/* Process the message. */
switch( msg )
{
case WM_CREATE:
/* The client window has been created but is not visible yet. */
/* Initialize the window here. */
break;
case WM_CLOSE:
/* Tell the main procedure to terminate the message loop. */
WinPostMsg( hwnd, WM_QUIT, NULL, NULL );
break;
case WM_PAINT:
/* Post a message to the second thread to make it repaint the */
/* background. */
hps = WinBeginPaint( hwnd, NULLHANDLE, NULL );
WinPostQueueMsg( hmqThread2, WM_USER_REPAINT, 0UL, 0UL );
WinEndPaint( hps );
break;
case WM_COMMAND:
/* The user has chosen a menu item. Process the selection */
/* accordingly. */
switch ( SHORT1FROMMP( mp1 ) )
{
case IDM_EXITPROG:
/* Post a close message. */
WinPostMsg( hwnd, WM_CLOSE, NULL, NULL );
break;
case IDM_RESUME:
break;
case IDM_HELPINSTRUCTIONS:
/* Display the help dialog box. */
WinMessageBox( HWND_DESKTOP, /* desktop is the parent */
hwnd, /* owned by client window */
INSTRUCTIONS, /* pointer to message text */
szAppName, /* pointer to title text */
1UL, /* message box identifier */
MB_OK | MB_INFORMATION | /* message box style */
MB_APPLMODAL | MB_MOVEABLE );
/* Force a repaint. */
WinInvalidateRegion( hwnd, NULLHANDLE, FALSE );
break;
case IDM_HELPABOUT:
/* Display the help dialog box. */
WinDlgBox( HWND_DESKTOP, /* make the desktop the parent */
hwnd, /* owned by client window */
HelpDlgProc, /* address of dialog procedure */
0UL, /* module handle */
IDD_HELP, /* dialog identifier in resource */
NULL ); /* initialization data */
/* Force a repaint. */
WinInvalidateRegion( hwnd, NULLHANDLE, FALSE );
break;
}
break;
case WM_SIZE:
/* Window is being resized so get new client window size and */
/* recompute the end points for the lines. */
cxClient = SHORT1FROMMP( mp2 ); /* Get new client window size */
cyClient = SHORT2FROMMP( mp2 );
ptl1.x = cxClient / 2; /* Set new points for lines based */
ptl1.y = cyClient / 2; /* on the size of client window */
ptl2.x = ptl1.x / 2;
ptl2.y = ptl1.y / 2;
break;
case WM_BUTTON1DOWN:
/* The user has pushed mouse button 1 which means change the */
/* foreground colour. */
/* Make sure that this window has the focus. */
WinSetFocus( HWND_DESKTOP, hwnd );
/* Reset foreground colour counter and increment foreground colour. */
fcolourcounter = 1;
lFcolour++;
/* Make sure foreground and background colours are different. */
if ( lFcolour == lBcolour )
lFcolour++;
/* Make sure the foregound colour does not exceed CLR_PALEGRAY. */
if ( lFcolour >= CLR_PALEGRAY )
lFcolour = CLR_BLUE;
return ( MRESULT )TRUE;
case WM_BUTTON1DBLCLK:
/* The user has double clicked mouse button 1 which means change */
/* the background colour. */
/* Make sure that this window has the focus. */
WinSetFocus( HWND_DESKTOP, hwnd );
/* Increment the backgound colour but make sure the background */
/* does not exceed CLR_PALEGRAY. */
if ( lBcolour == CLR_PALEGRAY )
lBcolour = CLR_BLUE;
else
++lBcolour;
/* Make sure foreground and background colours are different. */
if ( lFcolour == lBcolour )
lFcolour++;
/* Make sure the foregound colour does not exceed CLR_PALEGRAY. */
if ( lFcolour >= CLR_PALEGRAY )
lFcolour = CLR_BLUE;
/* Force the client window to repaint so that the background colour */
/* is updated. */
WinInvalidateRegion( hwnd, NULLHANDLE, FALSE );
return ( MRESULT )TRUE;
case WM_BUTTON2DOWN:
/* Make sure that this window has the focus. */
WinSetFocus( HWND_DESKTOP, hwnd );
/* Force the client window to repaint to clear the window. */
WinInvalidateRegion( hwnd, NULLHANDLE, FALSE );
return ( MRESULT )TRUE;
case WM_DESTROY:
/* The client window is being destroyed so tell the second thread to */
/* stop running. */
WinPostQueueMsg( hmqThread2, WM_USER_END_THREAD, 0UL, 0UL );
/* Wait for the drawing thread to terminate before returning. */
DosWaitThread( &tidDrawing, DCWW_WAIT );
break;
default:
/* For all other messages, let the default window procedure */
/* process them. */
return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
}
return NULL;
}
/*+--------------------------------------------------------------------------+*/
/*| HelpDlgProc - Help Dialog Procedure |*/
/*+--------------------------------------------------------------------------+*/
static MRESULT EXPENTRY HelpDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
switch( msg )
{
case WM_COMMAND:
switch( SHORT1FROMMP( mp1 ) ) /* Extract the command value */
{
case DID_OK: /* The Enter pushbutton or key */
WinDismissDlg( hwndDlg, TRUE );
break;
default:
break;
}
break;
default:
return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
}
return NULL;
}
/*+--------------------------------------------------------------------------+*/
/*| DrawingThread - Procedure that draws the lines in the client window. |*/
/*+--------------------------------------------------------------------------+*/
static void DrawingThread( ULONG ulThreadArg )
{
/* Declare local variables. */
HAB habThread2 = NULLHANDLE; /* anchor block handle for thread */
HPS hps = NULLHANDLE; /* presentation Space handle */
LONG delta1x = START_DELTA_X; /* start point delta values */
LONG delta1y = START_DELTA_Y;
LONG delta2x = END_DELTA_X; /* end point delta values */
LONG delta2y = END_DELTA_Y;
RECTL rclClient; /* rectangle for client window */
QMSG qmsgThread2; /* message queue structure */
/* Change the priority class of this thread to idle class. */
DosSetPriority( PRTYS_THREAD, PRTYC_IDLETIME, 0L, 0UL );
/* Initialize thread to PM. */
habThread2 = WinInitialize( 0UL );
hmqThread2 = WinCreateMsgQueue( habThread2, 0UL );
/* Get a presentation space. */
hps = WinGetPS( hwndClient );
/* Run drawing thread. */
qmsgThread2.msg = WM_USER_REPAINT;
while ( qmsgThread2.msg != WM_USER_END_THREAD )
{
if ( qmsgThread2.msg == WM_USER_REPAINT )
{
WinQueryWindowRect( hwndClient, &rclClient );
WinFillRect( hps, &rclClient, lBcolour );
}
else
{
/* Increment the foreground colour if necessary. */
if ( ++fcolourcounter > ( ( cxClient + cyClient ) >> 1 ) )
{
fcolourcounter = 1; /* Reset fcolourcounter and */
lFcolour++; /* increment foreground colour.*/
/* Make sure foreground and background colours are different. */
if ( lFcolour == lBcolour )
lFcolour++;
/* Make sure the foregound colour does not exceed CLR_PALEGRAY. */
if ( lFcolour >= CLR_PALEGRAY )
lFcolour = CLR_BLUE;
}
/* Add deltas to the start and end points for a line. */
/* If the start point would be invalid then negate the delta. */
if ( ( ptl1.x + delta1x ) > cxClient )
delta1x = -delta1x;
if ( ( ptl1.x + delta1x ) < 1 )
delta1x = -delta1x;
if ( ( ptl1.y + delta1y ) > cyClient )
delta1y = -delta1y;
if ( ( ptl1.y + delta1y ) < 1 )
delta1y = -delta1y;
/* Add delta to start point. */
ptl1.x += delta1x;
ptl1.y += delta1y;
/* If the end point would be invalid then negate the delta. */
if ( ( ptl2.x + delta2x ) > cxClient )
delta2x = -delta2x;
if ( ( ptl2.x + delta2x ) < 1 )
delta2x = -delta2x;
if ( ( ptl2.y + delta2y ) > cyClient )
delta2y = -delta2y;
if ( ( ptl2.y + delta2y ) < 1 )
delta2y = -delta2y;
/* Add delta to end point. */
ptl2.x += delta2x;
ptl2.y += delta2y;
/* Now draw the line. */
GpiSetColor( hps, lFcolour );
GpiMove( hps, &ptl1 ); /* Move to start point */
GpiLine( hps, &ptl2 ); /* Draw new line */
}
/* Peek in the message queue to see if the main thread has posted a msg.*/
WinPeekMsg( habThread2, &qmsgThread2, NULLHANDLE, 0UL, 0UL, PM_REMOVE );
}
/* Clean up and terminate drawing thread. */
WinReleasePS( hps );
WinDestroyMsgQueue( hmqThread2 );
WinTerminate( habThread2 );
DosExit( EXIT_THREAD, 0UL );
}
/*+--------------------------------------------------------------------------+*/
/*| DisplayMessage - display an error message in a message box. |*/
/*+--------------------------------------------------------------------------+*/
static void DisplayMessage( HAB hab, ULONG ulStringNum )
{
char szTemp[ STRING_LENGTH ];
WinLoadString( hab, 0UL, ulStringNum, STRING_LENGTH, szTemp );
WinAlarm( HWND_DESKTOP, /* desktop window handle */
WA_ERROR ); /* type of alarm */
WinMessageBox( HWND_DESKTOP, /* parent window handle */
HWND_DESKTOP, /* owner window handle */
szTemp, /* pointer to message text */
szAppName, /* pointer to title text */
MSG_BOX_ID, /* message box identifier */
MB_OK | MB_ERROR | /* message box style */
MB_SYSTEMMODAL );
return;
}