home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
drgthr.zip
/
srcrendr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-18
|
21KB
|
456 lines
/*********************************************************************
* *
* MODULE NAME : srcrendr.c AUTHOR: Rick Fishman *
* DATE WRITTEN: 07-16-93 *
* *
* MODULE DESCRIPTION: *
* *
* Part of the 'DRGTHRND' drag/drop sample program. *
* *
* This module handles all the rendering for the source window. *
* *
* NOTES: *
* *
* FUNCTIONS AVALABLE TO OTHER MODULES: *
* *
* srcRenderPrepare *
* srcCreateWindow *
* *
* HISTORY: *
* *
* 07-16-93 - Program coded. *
* *
* Rick Fishman *
* Code Blazers, Inc. *
* 4113 Apricot *
* Irvine, CA. 92720 *
* CIS ID: 72251,750 *
* *
*********************************************************************/
#pragma strings(readonly) // used for debug version of memory mgmt routines
/*********************************************************************/
/*------- Include relevant sections of the OS/2 header files --------*/
/*********************************************************************/
#define INCL_DOSERRORS
#define INCL_DOSPROCESS
#define INCL_WINDIALOGS
#define INCL_WINERRORS
#define INCL_WINFRAMEMGR
#define INCL_WINSTDCNR
#define INCL_WINSTDDRAG
#define INCL_WINWINDOWMGR
/**********************************************************************/
/*----------------------------- INCLUDES -----------------------------*/
/**********************************************************************/
#include <os2.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "drgthrnd.h"
/*********************************************************************/
/*------------------- APPLICATION DEFINITIONS -----------------------*/
/*********************************************************************/
#define STACKSIZE 0xE000 // Stacksize for secondary threads
/**********************************************************************/
/*---------------------------- STRUCTURES ----------------------------*/
/**********************************************************************/
typedef struct _WINSTARTUP
{
ULONG cb;
HWND hwndFrame;
} WINSTARTUP, *PWINSTARTUP;
/**********************************************************************/
/*----------------------- FUNCTION PROTOTYPES ------------------------*/
/**********************************************************************/
void SourceThread ( void *pvHwndFrame );
MRESULT Render ( HWND hwndFrame, PDRAGTRANSFER pDragXfer );
void DoTheRendering ( PDRAGTRANSFER pDragXfer );
MRESULT EndConversation( HWND hwndFrame );
FNWP wpSource;
/**********************************************************************/
/*------------------------ GLOBAL VARIABLES --------------------------*/
/**********************************************************************/
/**********************************************************************/
/*----------------------- srcRenderPrepare ---------------------------*/
/* */
/* PROCESS A DM_RENDERPREPARE MESSAGE */
/* */
/* PARMS: frame window handle, */
/* pointer to a DRAGTRANSFER structure */
/* */
/* NOTES: The source uses this message to create an object window */
/* that will process all source render messages. It creates */
/* this window in a separate thread so that the main container*/
/* window is available and it doesn't tie up the message */
/* queue. It only needs to create one window that will be */
/* used to process all items. */
/* */
/* RETURNS: MRESULT explaining if it's ok to render */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
MRESULT srcRenderPrepare( HWND hwndFrame, PDRAGTRANSFER pDragXfer )
{
BOOL fOkToRender = TRUE;
PINSTANCE pi = INSTDATA( hwndFrame );
if( !pi->hwndRender )
{
pi->hwndRender = srcCreateWindow( hwndFrame );
if( !pi->hwndRender )
fOkToRender = FALSE;
}
// Change the source window in the DRAGITEM structure so that the target
// automaticall routes the render messages to this window. The target
// always sends/posts render messages to pDragXfer->pditem->hwndItem.
if( fOkToRender )
pDragXfer->pditem->hwndItem = pi->hwndRender;
return (MRESULT) fOkToRender;
}
/**********************************************************************/
/*------------------------- srcCreateWindow --------------------------*/
/* */
/* CREATE A WINDOW IN ANOTHER THREAD THAT WILL PROCESS THE RENDERING */
/* FOR THE SOURCE. */
/* */
/* PARMS: frame window handle */
/* */
/* NOTES: */
/* */
/* RETURNS: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
HWND srcCreateWindow( HWND hwndFrame )
{
HWND hwndRender = NULLHANDLE;
TID tid;
// Start the thread. Then wait for the thread's window to be created, at
// which point it will post a UM_WINDOW_CREATED message to this thread.
// We take over the message queue not just to catch this message but so
// that the message queue will not be tied up while this message is being
// created. It does act as a cheap semaphore mechanism though...
tid = _beginthread( SourceThread, NULL, STACKSIZE, (void *) hwndFrame );
if( (int) tid != -1 )
{
HAB hab = ANCHOR( hwndFrame );
QMSG qmsg;
while( WinGetMsg( hab, &qmsg, NULLHANDLE, 0, 0 ) )
if( qmsg.msg == UM_WINDOW_CREATED )
{
hwndRender = (HWND) qmsg.mp1;
break;
}
else
WinDispatchMsg( hab, &qmsg );
}
else
Msg( "_beginthread for source window failed!" );
return hwndRender;
}
/**********************************************************************/
/*-------------------------- SourceThread ----------------------------*/
/* */
/* THREAD THAT HANDLES THE RENDERING ON THE SOURCE WINDOW SIDE. */
/* */
/* PARMS: frame window handle (this is passes as a void pointer to */
/* satisfy the requirements of _beginthread()) */
/* */
/* NOTES: The UM_WINDOW_CREATED message is our way of letting the */
/* creator of this thread know the window handle of the render*/
/* object window. It is our way of 'returning' that window */
/* handle. We place it in mp1 of that message. If anything */
/* happens to hurt the creation of that window we will pass */
/* back a NULL in mp1. */
/* */
/* RETURNS: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
#define SOURCE_CLASS "ThisIsTheSourceClass"
void SourceThread( void *pvHwndFrame )
{
HAB hab = WinInitialize( 0 );
HMQ hmq;
HWND hwndFrame = (HWND) pvHwndFrame;
if( hab )
hmq = WinCreateMsgQueue( hab, 0 );
else
{
WinPostMsg( hwndFrame, UM_WINDOW_CREATED, NULL, NULL );
DosBeep( 1000, 100 );
fprintf( stderr, "WinInitialize failed!" );
}
if( hmq )
{
WINSTARTUP WinStartup;
HWND hwndObj;
// Pass the frame window handle to the render window - it will need that
// handle to get at the frame window's window word. Remember that when
// passing a pointer to a structure via the pCtlData parameter, the
// first USHORT must be the size of the structure.
WinStartup.cb = sizeof WinStartup;
WinStartup.hwndFrame = hwndFrame;
WinRegisterClass( hab, SOURCE_CLASS, wpSource, 0, sizeof( void * ) );
hwndObj = WinCreateWindow( HWND_OBJECT, SOURCE_CLASS, NULL, 0, 0, 0, 0,
0, NULLHANDLE, HWND_TOP, 1, &WinStartup,
NULL );
if( hwndObj )
{
QMSG qmsg;
WinPostMsg( hwndFrame, UM_WINDOW_CREATED, MPFROMHWND( hwndObj ),
NULL );
while( WinGetMsg( hab, &qmsg, NULLHANDLE, 0, 0 ) )
WinDispatchMsg( hab, &qmsg );
WinDestroyWindow( hwndObj );
}
else
{
WinPostMsg( hwndFrame, UM_WINDOW_CREATED, NULL, NULL );
Msg( "WinCreateWindow( hwndObj ) RC(%X)", HABERR( hab ) );
}
}
else if( hab )
{
WinPostMsg( hwndFrame, UM_WINDOW_CREATED, NULL, NULL );
Msg( "WinCreateMsgQueue RC(%X)", HABERR( hab ) );
}
if( hmq )
WinDestroyMsgQueue( hmq );
if( hab )
WinTerminate( hab );
_endthread();
}
/**********************************************************************/
/*---------------------------- wpSource ------------------------------*/
/* */
/* WINDOW PROCEDURE FOR THE SOURCE RENDERING OBJECT WINDOW. */
/* */
/* PARMS: standard window procedure parameters */
/* */
/* NOTES: */
/* */
/* RETURNS: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
MRESULT EXPENTRY wpSource( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
HWND hwndFrame = (HWND) WinQueryWindowULong( hwnd, 0 );
switch( msg )
{
case WM_CREATE:
{
WinSetWindowULong( hwnd, 0, ((PWINSTARTUP) mp1)->hwndFrame );
break;
}
// Just figure out if we can render or not. If we can, all rendering
// will be done in the UM_DO_THE_RENDERING message.
case DM_RENDER:
{
MRESULT mr = Render( hwndFrame, (PDRAGTRANSFER) mp1 );
if( mr )
WinPostMsg( hwnd, UM_DO_THE_RENDERING, mp1, NULL );
return mr;
}
case UM_DO_THE_RENDERING:
DoTheRendering( (PDRAGTRANSFER) mp1 );
return 0;
// The target sends this when it is done processing the DM_RENDERCOMPLETE
// message that the source sent it. This means everything is complete
// on both sides.
case DM_ENDCONVERSATION:
return EndConversation( hwndFrame );
case DM_RENDERCOMPLETE:
{
PDRAGTRANSFER pDragXfer = (PDRAGTRANSFER) mp1;
// If the source gets this message it means that it requested a
// a retry and the target said no. So complete the loop...
DrgPostTransferMsg( pDragXfer->hwndClient, DM_RENDERCOMPLETE,
pDragXfer, DMFL_RENDERFAIL, 0, FALSE );
return 0;
}
}
return WinDefWindowProc( hwnd, msg, mp1, mp2 );
}
/**********************************************************************/
/*----------------------------- Render -------------------------------*/
/* */
/* PROCESS A DM_RENDER MESSAGE */
/* */
/* PARMS: frame window handle, */
/* pointer to a DRAGTRANSFER structure */
/* */
/* NOTES: This is a SOURCE window message */
/* */
/* RETURNS: MRESULT explaining the rendering availability */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
MRESULT Render( HWND hwndFrame, PDRAGTRANSFER pDragXfer )
{
hwndFrame=hwndFrame; // Keep the compiler happy
pDragXfer=pDragXfer;
// Normally here we would check some things and return TRUE if everything
// looked OK or we would return FALSE and set pDragXfer->fsReply to the
// reason for the FALSE. A typical reason to return FALSE would be if
// pDragXfer->hstrSelectedRMF was something we couldn't support or
// pDragXfer->usOperation was something we didn't want to do. In that case
// we'd return FALSE and set fsReply to DMFL_RENDERRETRY. It would then be
// up to the target to change its parameters and send us another DM_RENDER.
return (MRESULT) TRUE;
}
/**********************************************************************/
/*------------------------- DoTheRendering ---------------------------*/
/* */
/* DO THE RENDERING. */
/* */
/* PARMS: pointer to a DRAGTRANSFER structure */
/* */
/* NOTES: This is a SOURCE window message */
/* */
/* RETURNS: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
void DoTheRendering( PDRAGTRANSFER pDragXfer )
{
PSZ pszTableName, pszFileName, pszLoc;
ULONG cbString, flStatus = DMFL_RENDEROK;
// Form the 'database:table' string by combining the database name which
// is stored in hstrContainerName with the table name which is stored in
// hstrSourceName.
cbString = DrgQueryStrNameLen( pDragXfer->pditem->hstrContainerName ) +
DrgQueryStrNameLen( pDragXfer->pditem->hstrSourceName ) +
2; // Null terminator plus colon
pszTableName = pszLoc = _alloca( cbString );
DrgQueryStrName( pDragXfer->pditem->hstrContainerName, cbString, pszLoc );
strcat( pszTableName, ":" );
pszLoc += strlen( pszTableName );
cbString -= strlen( pszTableName );
DrgQueryStrName( pDragXfer->pditem->hstrSourceName, cbString, pszLoc );
// Get the file name that we (the source) should be rendering to. This
// name was decided by the target before it sent us the DM_RENDER message.
cbString = DrgQueryStrNameLen( pDragXfer->hstrRenderToName ) + 1;
pszFileName = _alloca( cbString );
DrgQueryStrName( pDragXfer->hstrRenderToName, cbString, pszFileName );
// Call this function which will copy the database data into the file.
if( !dbRenderToFile( pszTableName, pszFileName ) )
flStatus = DMFL_RENDERFAIL;
// Tell the target that we're done.
DrgPostTransferMsg( pDragXfer->hwndClient, DM_RENDERCOMPLETE, pDragXfer,
flStatus, 0, FALSE );
// Bot the target and the source must free this. Since we're done at the
// source, it is time to free it.
DrgFreeDragtransfer( pDragXfer );
}
/**********************************************************************/
/*-------------------------- EndConversation -------------------------*/
/* */
/* FREE THE RESOURCES USED BY DRAG/DROP PROCESSING. ONLY DO THIS IF */
/* THIS IS THE LAST ITEM (there is one end-conversation message sent */
/* to us for each item dropped). */
/* */
/* PARMS: frame window handle */
/* */
/* NOTES: This is a SOURCE window message that the target sends after*/
/* it is done processing the DM_RENDERCOMPLETE message that */
/* the source sent it. */
/* */
/* RETURNS: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
MRESULT EndConversation( HWND hwndFrame )
{
PINSTANCE pi = INSTDATA( hwndFrame );
if( !pi )
{
Msg( "EndConversation cant get Inst data RC(%X)", HWNDERR(hwndFrame) );
return 0;
}
// We need to keep a running total to know when all items in the drop have
// been processed. When that happens, it is time to free the resources that
// were allocated to the drag as a whole rather than to an indidvidual item.
if( --pi->cDragItems == 0 )
dragSourceCleanup( hwndFrame );
return 0;
}
/*************************************************************************
* E N D O F S O U R C E *
*************************************************************************/