home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
drgfil.zip
/
srcwin.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-01
|
32KB
|
721 lines
/*********************************************************************
* *
* MODULE NAME : srcwin.c AUTHOR: Rick Fishman *
* DATE WRITTEN: 07-28-93 *
* *
* MODULE DESCRIPTION: *
* *
* Part of the 'DRGFILES' drag/drop sample program. *
* *
* This module takes care of all the code relating to the source *
* window (the initiator of the drag operation) *
* *
* NOTES: *
* *
* *
* FUNCTIONS AVALABLE TO OTHER MODULES: *
* *
* srcCreateWindow *
* *
* *
* HISTORY: *
* *
* 07-28-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_WINERRORS
#define INCL_WINDIALOGS
#define INCL_WINFRAMEMGR
#define INCL_WININPUT
#define INCL_WINPOINTERS
#define INCL_WINSHELLDATA
#define INCL_WINSTDCNR
#define INCL_WINSTDDRAG
#define INCL_WINSYS
#define INCL_WINWINDOWMGR
/**********************************************************************/
/*----------------------------- INCLUDES -----------------------------*/
/**********************************************************************/
#include <os2.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "drgfiles.h"
/*********************************************************************/
/*------------------- APPLICATION DEFINITIONS -----------------------*/
/*********************************************************************/
#define ID_FRAME 1
#define WINDOW_TITLE "'Drag' Window"
#define FRAME_FLAGS (FCF_TASKLIST | FCF_TITLEBAR | \
FCF_SYSMENU | FCF_MINMAX | \
FCF_SIZEBORDER | FCF_ICON | \
FCF_ACCELTABLE)
#define CONTAINER_STYLES (flSelType | CCS_MINIRECORDCORE | \
CCS_AUTOPOSITION)
#define BASE_TEMPFILE_NAME "TEMP"
/**********************************************************************/
/*---------------------------- STRUCTURES ----------------------------*/
/**********************************************************************/
/**********************************************************************/
/*----------------------- FUNCTION PROTOTYPES ------------------------*/
/**********************************************************************/
BOOL InsertRecords ( HWND hwndCnr );
void DragInit ( HWND hwndFrame, PCNRDRAGINIT pcdi );
int CountSelectedRecs ( HWND hwndFrame, PCNRREC pCnrRecUnderMouse,
PBOOL pfUseSelectedRecs );
MRESULT RenderFile ( PRENDERFILE pRenderFile );
void DragFileComplete ( HWND hwndFrame, HSTR hstrFileName, USHORT fsDrop);
void RemoveSourceEmphasis( HWND hwndFrame );
FNWP wpFrame;
/**********************************************************************/
/*------------------------ GLOBAL VARIABLES --------------------------*/
/**********************************************************************/
PFNWP pfnwpFrame;
char szDragCnrTitle[] = "Drag an icon to the drop spot over there ══>";
// Set this to TRUE if you want to enable rendering. At this time (10/30//93)
// using 2.1 there are major bugs that cause rendering to trap in PMDRAG.DLL,
// so it is not enabled. All the code is in place - you just have to set
// fRender to TRUE;
BOOL fRender = FALSE;
// Set this to CCS_EXTENDSEL if you want to enable multi-icon dragging. At this
// time (10/30//93) using 2.1 there are major bugs that cause a second drop
// to cause a trap in PMDRAG.DLL, so it is not enabled. All the code is in
// place - you just have to set flSelType to CCS_EXTENDSEL;
ULONG flSelType = CCS_SINGLESEL;
/**********************************************************************/
/*------------------------- srcCreateWindow --------------------------*/
/* */
/* CREATE THE SOURCE WINDOW */
/* */
/* PARMS: anchor block handle */
/* */
/* NOTES: */
/* */
/* RETURNS: Frame window handle */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
HWND srcCreateWindow( HAB hab )
{
HWND hwndFrame = NULLHANDLE, hwndCnr;
FRAMECDATA fcdata;
memset( &fcdata, 0, sizeof fcdata );
fcdata.cb = sizeof( FRAMECDATA );
fcdata.idResources = ID_RESOURCES;
fcdata.flCreateFlags = FRAME_FLAGS;
// Create the container as the client window of the frame. There is no
// need for a normal client window. Because of this we must subclass the
// frame window so we can catch the messages that the container sends to
// its owner.
hwndFrame = WinCreateWindow( HWND_DESKTOP, WC_FRAME, NULL,
FS_NOBYTEALIGN | WS_CLIPCHILDREN,
0, 0, 0, 0, NULLHANDLE, HWND_TOP,
ID_FRAME, &fcdata, NULL );
if( hwndFrame )
{
pfnwpFrame = WinSubclassWindow( hwndFrame, wpFrame );
if( pfnwpFrame )
{
hwndCnr = WinCreateWindow( hwndFrame, WC_CONTAINER, NULL,
WS_VISIBLE | CONTAINER_STYLES,
0, 0, 0, 0, hwndFrame, HWND_TOP,
FID_CLIENT, NULL, NULL );
if( hwndCnr )
WinSetWindowText( hwndFrame, WINDOW_TITLE );
else
{
WinDestroyWindow( hwndFrame );
hwndFrame = NULLHANDLE;
Msg( "WinCreateWindow(hwndCnr,%s) RC(%X)", WINDOW_TITLE,
HABERR( hab ) );
}
}
else
{
WinDestroyWindow( hwndFrame );
hwndFrame = NULLHANDLE;
Msg( "WinSubclassWindow(%s) RC(%X)", WINDOW_TITLE, HABERR( hab ) );
}
}
else
Msg( "WinCreateWindow(%s) RC(%X)", WINDOW_TITLE, HABERR( hab ) );
if( hwndFrame )
{
CNRINFO cnri;
// Set container into Icon view and give it a read-only title
cnri.cb = sizeof( CNRINFO );
cnri.pszCnrTitle = szDragCnrTitle;
cnri.flWindowAttr = CV_ICON | CA_CONTAINERTITLE | CA_TITLESEPARATOR |
CA_TITLEREADONLY;
if( !WinSendMsg( hwndCnr, CM_SETCNRINFO, MPFROMP( &cnri ),
MPFROMLONG( CMA_FLWINDOWATTR | CMA_CNRTITLE ) ) )
{
WinDestroyWindow( hwndFrame );
hwndFrame = NULLHANDLE;
Msg( "CM_SETCNRINFO(%S) RC(%X)", WINDOW_TITLE, HABERR( hab ) );
}
}
if( hwndFrame )
if( ! InsertRecords( hwndCnr ) )
{
WinDestroyWindow( hwndFrame );
hwndFrame = NULLHANDLE;
}
return hwndFrame;
}
/**********************************************************************/
/*-------------------------- InsertRecords ---------------------------*/
/* */
/* INSERT RECORDS INTO A CONTAINER */
/* */
/* PARMS: container window handle */
/* */
/* NOTES: We just insert a few records to start us off. Each record */
/* represents a temp file that we create. */
/* */
/* RETURNS: TRUE if successful, FALSE if not */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
#define INITIAL_CONTAINER_RECS 5
BOOL InsertRecords( HWND hwndCnr )
{
BOOL fSuccess = TRUE;
RECORDINSERT ri;
PCNRREC pCnrRec, pCnrRecSave;
pCnrRec = WinSendMsg( hwndCnr, CM_ALLOCRECORD, MPFROMLONG( EXTRA_BYTES ),
MPFROMLONG( INITIAL_CONTAINER_RECS ) );
if( pCnrRec )
{
FILE *fh;
int i;
PSZ pszFileExt;
ICONINFO iconinfo;
memset( &iconinfo, 0, sizeof iconinfo );
pCnrRecSave = pCnrRec;
for( i = 0; fSuccess && (i < INITIAL_CONTAINER_RECS); i++ )
{
// Create a temporary filename (zero-length).
strcpy( pCnrRec->szFileName, BASE_TEMPFILE_NAME );
strcat( pCnrRec->szFileName, "." );
pszFileExt = pCnrRec->szFileName + strlen( pCnrRec->szFileName );
_itoa( i + 1, pszFileExt, 10 );
strcpy( pCnrRec->szFullFileName, szCurrentPath );
strcat( pCnrRec->szFullFileName, pCnrRec->szFileName );
fh = fopen( pCnrRec->szFileName, "w" );
if( fh )
{
fclose( fh );
// Set the icon attached to the temporary file so it will show
// up when dropped onto other containers.
iconinfo.fFormat = ICON_FILE;
iconinfo.pszFileName = DRGFILES_ICON_FILENAME;
WinSetFileIcon( pCnrRec->szFileName, &iconinfo );
pCnrRec->mrc.pszIcon = (PSZ) &pCnrRec->szFileName;
pCnrRec->mrc.hptrIcon = hptrCnrRec;
}
else
{
fSuccess = FALSE;
Msg( "Could not create %s file", pCnrRec->szFileName );
}
pCnrRec = (PCNRREC) pCnrRec->mrc.preccNextRecord;
}
memset( &ri, 0, sizeof( RECORDINSERT ) );
ri.cb = sizeof( RECORDINSERT );
ri.pRecordOrder = (PRECORDCORE) CMA_END;
ri.pRecordParent = (PRECORDCORE) NULL;
ri.zOrder = (USHORT) CMA_TOP;
ri.cRecordsInsert = INITIAL_CONTAINER_RECS;
ri.fInvalidateRecord = TRUE;
if( !WinSendMsg( hwndCnr, CM_INSERTRECORD, MPFROMP( pCnrRecSave ),
MPFROMP( &ri ) ) )
{
fSuccess = FALSE;
Msg( "InsertRecords CM_INSERTRECORD RC(%X)", HWNDERR( hwndCnr ) );
}
}
else
{
fSuccess = FALSE;
Msg( "InsertRecords CM_ALLOCRECORD RC(%X)", HWNDERR( hwndCnr ) );
}
return fSuccess;
}
/**********************************************************************/
/*----------------------------- wpFrame ------------------------------*/
/* */
/* SUBCLASSED FRAME WINDOW PROCEDURE. */
/* */
/* PARMS: normal winproc parms */
/* */
/* NOTES: */
/* */
/* RETURNS: MRESULT value */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
MRESULT EXPENTRY wpFrame( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
switch( msg )
{
// Don't let the message queue be destroyed until the user has closed
// *both* windows. If SC_CLOSE gets processed by the default window
// proc, a WM_QUIT message will get posted to the queue which will in
// effect end this program.
case WM_SYSCOMMAND:
if( SHORT1FROMMP( mp1 ) == SC_CLOSE )
if( hwndDrop )
{
WinDestroyWindow( hwnd );
hwndDrag = NULLHANDLE;
WinSetActiveWindow( HWND_DESKTOP, hwndDrop );
return 0;
}
break;
// From the F3 accelerator key
case WM_COMMAND:
if( SHORT1FROMMP( mp1 ) == IDM_EXIT )
{
WinPostMsg( hwnd, WM_SYSCOMMAND, MPFROMSHORT( SC_CLOSE ),
MPFROM2SHORT( CMDSRC_ACCELERATOR, FALSE ) );
return 0;
}
break;
case WM_DESTROY:
// Free all container resources associated with any records that
// were inserted (note that the container is actually the client
// window.
WinSendDlgItemMsg( hwnd, FID_CLIENT, CM_REMOVERECORD, NULL,
MPFROM2SHORT( 0, CMA_FREE ) );
break;
case WM_CONTROL:
if( SHORT1FROMMP( mp1 ) == FID_CLIENT )
switch( SHORT2FROMMP( mp1 ) )
{
case CN_INITDRAG:
DragInit( hwnd, (PCNRDRAGINIT) mp2 );
return 0;
}
break;
// These are the only messages that we need to process if we use the
// DrgDragFiles API.
case DM_DRAGERROR:
return DragError( SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ),
(HSTR) mp2 );
case DM_RENDERFILE:
return RenderFile( (PRENDERFILE) mp1 );
case DM_DRAGFILECOMPLETE:
DragFileComplete( hwnd, (HSTR) mp1, SHORT1FROMMP( mp2 ) );
return 0;
}
return pfnwpFrame( hwnd, msg, mp1, mp2 );
}
/**********************************************************************/
/*----------------------------- DragInit -----------------------------*/
/* */
/* PROCESS CN_INITDRAG NOTIFY MESSAGE. */
/* */
/* PARMS: frame window handle, */
/* pointer to the CNRDRAGINIT structure */
/* */
/* NOTES: the CN_INITDRAG message is equivalent to the WM_BEGINDRAG */
/* message. The reason I mention this is because if the source*/
/* window in the drag is not a container you will get the */
/* WM_BEGINDRAG message. */
/* */
/* WM_BEGINDRAG is sent to windows to allow them to know that */
/* the user is requesting a drag from their window. This */
/* message contains only the x,y coordinates of the mouse at */
/* the time of WM_BEGINDRAG. */
/* */
/* The reason for CN_INITDRAG is first so that the container */
/* can notify its owner when it gets a WM_BEGINDRAG message */
/* and second so that the container can give its owner more */
/* info, like what container record the mouse pointer is over.*/
/* To accomplish this, the container packages up this informa-*/
/* tion in a CNRDRAGINIT structure and sends that structure */
/* along with the CN_INITDRAG message. */
/* */
/* DrgDragFiles takes a pointer to an array of filename */
/* pointers. First the array of PSZ's is allocated. Then */
/* memory for each filename is allocated and its pointer */
/* placed in the array of PSZ's. */
/* */
/* RETURNS: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
void DragInit( HWND hwndFrame, PCNRDRAGINIT pcdi )
{
PCNRREC pCnrRecUnderMouse = (PCNRREC) pcdi->pRecord;
BOOL fUseSelectedRecs;
int cRecs;
cRecs = CountSelectedRecs( hwndFrame, pCnrRecUnderMouse, &fUseSelectedRecs);
if( cRecs )
{
int i;
PSZ *apszFiles;
PCNRREC pCnrRec = (PCNRREC) CMA_FIRST;
apszFiles = _alloca( sizeof( PSZ ) * cRecs );
// CountSelectedRecs returned in the fUseSelected variable whether or
// not we should go thru the container and drag all records that have
// selection emphasis or if we should just drag the record under the
// mouse. We continue accordingly.
if( fUseSelectedRecs )
for( i = 0; i < cRecs; i++ )
{
pCnrRec = (PCNRREC) WinSendDlgItemMsg( hwndFrame, FID_CLIENT,
CM_QUERYRECORDEMPHASIS,
MPFROMP( pCnrRec ),
MPFROMSHORT( CRA_SELECTED ) );
if( pCnrRec == (PCNRREC) -1 )
Msg( "DragInit..CM_QUERYRECORDEMPHASIS RC(%X)",
HWNDERR( hwndFrame ) );
else
{
apszFiles[ i ] =
_alloca( strlen( pCnrRec->szFullFileName ) + 1 );
strcpy( apszFiles[ i ], pCnrRec->szFullFileName );
// Give the selected record source emphasis
if( !WinSendDlgItemMsg( hwndFrame, FID_CLIENT,
CM_SETRECORDEMPHASIS,
MPFROMP( pCnrRec ),
MPFROM2SHORT( TRUE, CRA_SOURCE ) ) )
Msg( "DragInit..CM_SETRECORDEMPHASIS RC(%X)",
HWNDERR( hwndFrame ) );
}
}
else
{
apszFiles[ 0 ] =
_alloca( strlen( pCnrRecUnderMouse->szFullFileName ) + 1 );
strcpy( apszFiles[ 0 ], pCnrRecUnderMouse->szFullFileName );
// Give the selected record source emphasis
if( !WinSendDlgItemMsg( hwndFrame, FID_CLIENT, CM_SETRECORDEMPHASIS,
MPFROMP( pCnrRecUnderMouse ),
MPFROM2SHORT( TRUE, CRA_SOURCE ) ) )
Msg( "DragInit..CM_SETRECORDEMPHASIS RC(%X)",
HWNDERR( hwndFrame ) );
}
// The fRender parameter determines if rendering is going to be done
// when files are dropped. If set to TRUE, the source needs to process
// one more message (DM_RENDERFILE) and the target needs to process
// one more message (DM_FILERENDERED). The code is in place to do this
// but is only enabled if fRender is set to TRUE.
DrgDragFiles( hwndFrame, (const char **) apszFiles, NULL, NULL, cRecs,
hptrCnrRec, VK_ENDDRAG, fRender, 0 );
RemoveSourceEmphasis( hwndFrame );
}
}
/**********************************************************************/
/*------------------------ CountSelectedRecs -------------------------*/
/* */
/* COUNT THE NUMBER OF RECORDS THAT ARE CURRENTLY SELECTED. */
/* */
/* PARMS: frame window handle, */
/* pointer to the record that was under the pointer, */
/* address of BOOL - should we process selected records? */
/* */
/* NOTES: */
/* */
/* RETURNS: number of records to process */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
int CountSelectedRecs( HWND hwndFrame, PCNRREC pCnrRecUnderMouse,
PBOOL pfUseSelectedRecs )
{
int cRecs = 0;
*pfUseSelectedRecs = FALSE;
// If the record under the mouse is NULL, we must be over whitespace, in
// which case we don't want to drag any records.
if( pCnrRecUnderMouse )
{
PCNRREC pCnrRec = (PCNRREC) CMA_FIRST;
// Count the records with 'selection' emphasis. These are the records
// we want to drag, unless the container record under the mouse does
// not have selection emphasis. If that is the case, we only want to
// process that one.
while( pCnrRec )
{
pCnrRec = (PCNRREC) WinSendDlgItemMsg( hwndFrame, FID_CLIENT,
CM_QUERYRECORDEMPHASIS,
MPFROMP( pCnrRec ),
MPFROMSHORT( CRA_SELECTED ));
if( pCnrRec == (PCNRREC) -1 )
Msg( "CountSelectedRecs..CM_QUERYRECORDEMPHASIS RC(%X)",
HWNDERR( hwndFrame ) );
else if( pCnrRec )
{
if( pCnrRec == pCnrRecUnderMouse )
*pfUseSelectedRecs = TRUE;
cRecs++;
}
}
if( !(*pfUseSelectedRecs) )
cRecs = 1;
}
return cRecs;
}
/**********************************************************************/
/*--------------------------- RenderFile -----------------------------*/
/* */
/* PROCESS A DM_RENDERFILE MESSAGE. */
/* */
/* PARMS: pointer to a RENDERFILE struct */
/* */
/* NOTES: PM sends this to the source for each file that was dropped,*/
/* but only if the fRender global variable is set to TRUE. */
/* */
/* RETURNS: TRUE if we do the rendering, FALSE if not */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
MRESULT RenderFile( PRENDERFILE pRenderFile )
{
char szSource[ CCHMAXPATH ];
char szTarget[ CCHMAXPATH ];
int cbSource;
// hstrSource file is not fully qualified, hstrTarget is
strcpy( szSource, szCurrentPath );
cbSource = strlen( szSource );
DrgQueryStrName( pRenderFile->hstrSource,
sizeof szSource - cbSource, szSource + cbSource );
DrgQueryStrName( pRenderFile->hstrTarget, sizeof szTarget, szTarget );
// If the filenames are the same there is nothing to do. Otherwise we
// do the copy or move as instructed.
if( stricmp( szSource, szTarget ) != 0 )
{
APIRET rc;
rc = DosCopy( szSource, szTarget, DCPY_EXISTING );
if( rc )
Msg( "DosCopy of %s to %s failed with a return code of %u\n",
szSource, szTarget, rc );
if( pRenderFile->fMove )
{
rc = DosDelete( szSource );
if( rc )
Msg( "DosDelete of %s failed with a return code of %u\n",
szSource, rc );
}
}
// Let the target know that the rendering is complete. As of 10/3/93 using
// 2.1 GA, this message currently causes PMDRAG.DLL to trap.
WinSendMsg( pRenderFile->hwndDragFiles, DM_FILERENDERED,
MPFROMP( pRenderFile ), MPFROMLONG( TRUE ) );
return (MRESULT) TRUE;
}
/**********************************************************************/
/*------------------------ DragFileComplete --------------------------*/
/* */
/* PROCESS A DM_DRAGFILECOMPLETE MESSAGE. */
/* */
/* PARMS: frame window handle, */
/* HSTR that contains the dragged filename, */
/* flags that indicate what happened on the drop */
/* */
/* NOTES: PM sends this to the source for each file that was dragged.*/
/* */
/* RETURNS: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
void DragFileComplete( HWND hwndFrame, HSTR hstrFileName, USHORT fsDrop )
{
char szFileName[ CCHMAXPATH ];
USHORT usCmd = CMA_FIRST;
PCNRREC pCnrRec = NULL;
DrgQueryStrName( hstrFileName, sizeof szFileName, szFileName );
// Find the container record that was dropped by matching the name with
// one that has source emphasis (we applied source emphasis to all records
// that were dragged). If the record was moved, remove it from the
// container.
for( ; ; )
{
pCnrRec = (PCNRREC) WinSendDlgItemMsg( hwndFrame, FID_CLIENT,
CM_QUERYRECORD, MPFROMP( pCnrRec ),
MPFROM2SHORT( usCmd, CMA_ITEMORDER ) );
if( pCnrRec == (PCNRREC) -1 )
{
Msg( "DragFileComplete..CM_QUERYRECORDEMPHASIS RC(%X)",
HWNDERR( hwndFrame ) );
break;
}
else if( pCnrRec )
{
// The returned filename is not qualified (no path info)
if( strcmp( pCnrRec->szFileName, szFileName ) == 0 )
{
if( (fsDrop & DF_MOVE) && (fsDrop & DF_SUCCESSFUL) )
WinSendDlgItemMsg( hwndFrame, FID_CLIENT, CM_REMOVERECORD,
MPFROMP( &pCnrRec ),
MPFROM2SHORT( 1, CMA_INVALIDATE | CMA_FREE ) );
break;
}
}
usCmd = CMA_NEXT;
}
}
/**********************************************************************/
/*----------------------- RemoveSourceEmphasis -----------------------*/
/* */
/* REMOVE SOURCE EMPHASIS FROM THE DRAGGED RECORDS. */
/* */
/* PARMS: frame window handle */
/* */
/* NOTES: */
/* */
/* RETURNS: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
void RemoveSourceEmphasis( HWND hwndFrame )
{
PCNRREC pCnrRec = (PCNRREC) CMA_FIRST;
// For every record with source emphasis, remove it.
while( pCnrRec )
{
pCnrRec = (PCNRREC) WinSendDlgItemMsg( hwndFrame, FID_CLIENT,
CM_QUERYRECORDEMPHASIS,
MPFROMP( pCnrRec ),
MPFROMSHORT( CRA_SOURCE ) );
if( pCnrRec == (PCNRREC) -1 )
{
Msg( "RemoveSourceEmphasis..CM_QUERYRECORDEMPHASIS RC(%X)",
HWNDERR( hwndFrame ) );
break;
}
else if( pCnrRec )
if( !WinSendDlgItemMsg( hwndFrame, FID_CLIENT,
CM_SETRECORDEMPHASIS, MPFROMP( pCnrRec ),
MPFROM2SHORT( FALSE, CRA_SOURCE ) ) )
Msg( "RemoveSourceEmphasis..CM_SETRECORDEMPHASIS RC(%X)",
HWNDERR( hwndFrame ) );
}
}
/*************************************************************************
* E N D O F S O U R C E *
*************************************************************************/