home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
prgramer
/
info
/
redbook4
/
dmcust.c
< prev
next >
Wrap
Text File
|
1992-06-28
|
15KB
|
440 lines
//****************************************************************************************
//
// DMCUST.C - a demo program by Alan Chambers - UK PS Technical Support, whilst on
// a residency at the ITSC, Boca Raton
//
// Updated to work with GA code, 6 May 1992
//
// This program reads several names, addresses and phone numbers from a file (DMCUST.DAT)
// and displays them as icons in a container window. These items can be moved from
// one instance of this program to another by direct manipulation; they can be dropped
// on an order form displayed by the DMORDER sample to fill in the customer details therein,
// and they can be dropped on the telephone icon shown by the DMPHONE sample, to simulate
// a telephone dialler.
//
//
// This sample illustrates several different aspects of drag/drop:
//
// - initiating a drag from a container window
// - using the DRM_PRINT rendering mechanism to allow application printing by
// drag/drop to a workplace shell printer object
// - using the DRM_DISCARD rendering mechanism to allow deletion of application
// items by dragging them to the workplace shell shredder object
// - implementing both ends of a user defined rendering mechanism (here called
// DRM_SHAREMEM)
//
//****************************************************************************************
//
// The program concentrates on demonstrating drag/drop techniques and is therefore
// very simple in other respects. In particular, the so called customers to be displayed
// are read from a simple flat file called DMCUST.DAT that can be read with fscanf().
// The following lines illustrate the format of this file - note that each text
/* field must have no imbedded blanks:
Alan_Chambers Somewhere_nice 123-4567
John_Major 10_Downing_Street 999-4444
A.N.Other Somewhere_horrible 987-5432
George_Bush The_Whitehouse 456-8765
******************************************************************************************/
#define INCL_WIN
#define INCL_GPI
#define INCL_DOS
#include <os2.h>
#include "dmcust.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <memory.h>
//***************************************************************************** */
//
// #defines, typedefs and function headers
//
//***************************************************************************** */
#define OBJECTDATASIZE 100
#define DRAGXFERMEMNAME "\\SHAREMEM\\DragXfer.mem"
typedef struct {
char name[30];
char address[100];
char phone[15];
}
CUSTOMER, *PCUSTOMER;
typedef struct{
RECORDCORE core; // control info for CONTAINER window
CUSTOMER cust; // application defined data
}
CONTRECORD, *PCONTRECORD;
MRESULT EXPENTRY CustWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
void FillWindow(HWND);
void AddCustomer(HWND, PCUSTOMER, ULONG, ULONG);
void RemoveCustomer(HWND, PCONTRECORD);
void PrintCustomer(PCONTRECORD, PPRINTDEST);
//***************************************************************************** */
//
// Some global variables
//
//***************************************************************************** */
HAB hab; /* PM anchor block handle */
HPOINTER hptrCustIcon; /* Icon used for dragging customers */
//***************************************************************************** */
//
// Main procedure - designed to create main (only) window and process messages
//
//***************************************************************************** */
INT main (VOID)
{
HMQ hmq; /* Message queue handle */
QMSG qmsg; /* Message from message queue */
HWND hwndMain;
ULONG flCreate = FCF_STANDARD & ~FCF_MENU; /* frame window creation flags */
hab = WinInitialize(0);
hmq = WinCreateMsgQueue(hab, 0);
hptrCustIcon = WinLoadPointer(HWND_DESKTOP, 0, ID_CUSTPOINTER);
WinRegisterClass(
hab,
(PSZ)"CustWindow",
(PFNWP)CustWindowProc,
CS_SIZEREDRAW,
sizeof(PVOID)
);
hwndMain = WinCreateStdWindow(
HWND_DESKTOP,
0,
&flCreate,
"CustWindow",
"Customer Window",
0,
(HMODULE)0L,
ID_WINDOW,
NULL
);
while(WinGetMsg(hab, &qmsg, 0L, 0, 0)) // message processing loop
WinDispatchMsg(hab, &qmsg);
WinDestroyWindow(hwndMain);
WinDestroyMsgQueue( hmq );
WinTerminate( hab );
return(0);
}
//***************************************************************************** */
//
// Window procedure for main (only) window
//
//***************************************************************************** */
MRESULT EXPENTRY CustWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
typedef struct {
HWND hwndContainer;
}
INSTANCE, *PINSTANCE;
PINSTANCE wd;
SWP swp;
PCONTRECORD pcrec;
PCNRDRAGINIT pcnrdinit;
PCNRDRAGINFO pcnrdinfo;
PDRAGINFO pdinfo;
DRAGITEM ditem;
DRAGIMAGE dimg;
PDRAGTRANSFER pdxfer;
PCUSTOMER pxfercust, pxferfromcust;
PDRAGITEM pditem;
char dragxfermemname[100];
ULONG rc;
char srceType[100], srceRMF[100];
char srceFileName[100], srcePath[100];
wd = (PINSTANCE)WinQueryWindowPtr(hwnd, 0); // retrieve instance data pointer
switch( msg )
{
case WM_CREATE:
wd = (PINSTANCE)malloc(sizeof(INSTANCE)); // allocate instance data space
WinSetWindowPtr(hwnd, 0, (PVOID)wd); // and store in window words
wd->hwndContainer = WinCreateWindow( hwnd, WC_CONTAINER, NULL,
CCS_AUTOPOSITION | WS_VISIBLE | CCS_EXTENDSEL,
0, 0, 0, 0,
hwnd, HWND_TOP, ID_CONTAINER,
0, 0);
FillWindow(wd->hwndContainer);
rc = WinSetWindowPos( WinQueryWindow(hwnd, QW_PARENT),
HWND_TOP, 100, 90, 400, 300,
SWP_SIZE | SWP_ACTIVATE | SWP_SHOW | SWP_MOVE);
break;
case WM_CONTROL:
switch (SHORT2FROMMP(mp1))
{
case CN_INITDRAG:
pcnrdinit = (PCNRDRAGINIT)mp2;
if((pcrec = (PCONTRECORD)(pcnrdinit->pRecord)) != NULL)
{
pdinfo = DrgAllocDraginfo(1);
ditem.hwndItem = hwnd;
ditem.ulItemID = (ULONG)pcrec;
ditem.hstrType = DrgAddStrHandle("DRT_CUSTOMER");
ditem.hstrRMF = DrgAddStrHandle("(DRM_SHAREMEM,DRM_PRINT,DRM_DISCARD)x(DRF_TEXT)");
ditem.hstrContainerName = DrgAddStrHandle("Boca Raton Branch");
ditem.hstrSourceName = DrgAddStrHandle(pcrec->cust.name);
ditem.hstrTargetName = (HSTR)0;
ditem.fsControl = 0; ditem.fsSupportedOps = 0;
rc = DrgSetDragitem(pdinfo, &ditem, (ULONG)sizeof(ditem), 0);
dimg.cb = sizeof(DRAGIMAGE);
dimg.cptl = 0;
dimg.hImage = hptrCustIcon;
dimg.sizlStretch.cx = 10L;
dimg.sizlStretch.cy = 10L;
dimg.fl = DRG_ICON;
dimg.cxOffset = 0;
dimg.cyOffset = 0;
DrgDrag(hwnd, pdinfo, (PDRAGIMAGE)&dimg, 1, VK_ENDDRAG, NULL);
DrgFreeDraginfo(pdinfo);
}
break;
case CN_DRAGOVER:
pcnrdinfo = (PCNRDRAGINFO)mp2;
pdinfo = pcnrdinfo->pDragInfo;
pditem = DrgQueryDragitemPtr(pdinfo, 0);
if(DrgVerifyRMF(pditem, "DRM_SHAREMEM", "DRF_TEXT"))
{
DrgFreeDraginfo(pdinfo);
return(MPFROM2SHORT(DOR_DROP, DO_MOVE));
}
else
{
DrgFreeDraginfo(pdinfo);
return(MPFROM2SHORT(DOR_NEVERDROP, 0));
}
break;
case CN_DROP:
pcnrdinfo = (PCNRDRAGINFO)mp2;
pdinfo = pcnrdinfo->pDragInfo;
pditem = DrgQueryDragitemPtr(pdinfo, 0);
DrgQueryStrName(pditem->hstrSourceName, 100, srceFileName);
DrgQueryStrName(pditem->hstrContainerName, 100, srcePath);
DrgQueryStrName(pditem->hstrType, 100, srceType);
DrgQueryStrName(pditem->hstrRMF, 100, srceRMF);
// allocated a named shared memory object for a customer *pxfercust
rc = DosAllocSharedMem((PPVOID)&pxfercust, DRAGXFERMEMNAME, sizeof(CUSTOMER), PAG_COMMIT | PAG_WRITE | PAG_READ);
// allocate and fill the dxfer structure;
pdxfer = DrgAllocDragtransfer(1);
pdxfer->cb = sizeof(DRAGTRANSFER);
pdxfer->hwndClient = hwnd;
pdxfer->pditem = pditem;
pdxfer->hstrSelectedRMF = DrgAddStrHandle("DRM_CUSTOMER");
pdxfer->hstrRenderToName = DrgAddStrHandle(DRAGXFERMEMNAME);
pdxfer->ulTargetInfo = 0;
pdxfer->usOperation = DO_MOVE;
// This is like a WinSendMsg except that it also does a DosGiveMem for the dragtransfer struct
rc = (ULONG)DrgSendTransferMsg(pdinfo->hwndSource, DM_RENDER, (MPARAM)pdxfer, NULL);
if(rc == TRUE)
{
AddCustomer(wd->hwndContainer, pxfercust, 10, 10);
}
DrgFreeDraginfo(pdinfo);
DrgFreeDragtransfer(pdxfer);
DosFreeMem((PVOID)pxfercust);
break;
default: ;
}
break;
case DM_RENDER:
pdxfer = (PDRAGTRANSFER)mp1;
pxferfromcust = &(((PCONTRECORD)(pdxfer->pditem->ulItemID))->cust); //pointer to recordcore for dragged item
DrgQueryStrName(pdxfer->hstrRenderToName, 100, dragxfermemname); // get shared mem name
DosGetNamedSharedMem((PPVOID)&pxfercust, dragxfermemname, PAG_WRITE | PAG_READ);
memcpy(pxfercust, pxferfromcust, sizeof(CUSTOMER));
DosFreeMem((PVOID)pxfercust);
if(pdxfer->usOperation == DO_MOVE) // if it's a move, remove the customer
{
RemoveCustomer(wd->hwndContainer, (PCONTRECORD)(pdxfer->pditem->ulItemID));
}
return((MRESULT)TRUE);
break;
case DM_PRINTOBJECT: /* mp1 points to a DRAGITEM, mp2 to a PRINTDEST structure */
pditem = (PDRAGITEM)mp1; /* PLEASE NOTE: there is an error in the online PM Reference */
/* which says that mp1 points to a DRAGINFO structure */
PrintCustomer((PCONTRECORD)(pditem->ulItemID), ((PPRINTDEST)mp2));
return((MRESULT)DRR_SOURCE); /* indicates that we will do the printing, */
break; /* rather than the printer object */
case DM_DISCARDOBJECT: /* mp1 points to a DRAGINFO structure */
pdinfo = (PDRAGINFO)mp1; /* the item to be deleted */
pditem = DrgQueryDragitemPtr(pdinfo, 0);
RemoveCustomer((HWND)wd->hwndContainer, (PCONTRECORD)(pditem->ulItemID));
return((MRESULT)DRR_SOURCE); /* indicates that we take responsibility */
break; /* for deleting the item */
case WM_COMMAND:
switch (SHORT1FROMMP(mp1)) /* test the command value from mp1 */
{
case ID_EXITPROG:
WinPostMsg( hwnd, WM_CLOSE, (MPARAM)0, (MPARAM)0 );
break;
default:
return WinDefWindowProc(hwnd, msg, mp1, mp2);
}
break;
case WM_SIZE:
WinQueryWindowPos(hwnd, &swp);
WinSetWindowPos(wd->hwndContainer, HWND_TOP, swp.x, swp.y, swp.cx, swp.cy,
SWP_SIZE | SWP_SHOW);
break;
case WM_CLOSE:
WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 );
break;
case WM_DESTROY:
free(wd);
break;
default:
return WinDefWindowProc(hwnd, msg, mp1, mp2);
}
return (MRESULT)FALSE;
}
//***************************************************************************** */
//
// Three utility functions used in program
//
//***************************************************************************** */
void FillWindow(HWND hwndContainer)
{
CUSTOMER cust;
FILE *finput;
if((finput = fopen("dmcust.dat", "r")) != NULL)
while(fscanf(finput, "%s%s%s", cust.name, cust.address, cust.phone) == 3)
{
WinSendMsg(hwndContainer, CM_ALLOCRECORD,
(MPARAM)(sizeof(CONTRECORD) - sizeof(RECORDCORE)), (MPARAM)1);
AddCustomer(hwndContainer, &cust, 10, 10);
}
}
void AddCustomer(HWND hwndContainer, CUSTOMER* pcustomer, ULONG x, ULONG y)
{
PCONTRECORD pcrec;
RECORDINSERT rci;
pcrec = (PCONTRECORD)WinSendMsg(hwndContainer, CM_ALLOCRECORD,
(MPARAM)(sizeof(CONTRECORD) - sizeof(RECORDCORE)), (MPARAM)1);
pcrec->core.ptlIcon.x = x; pcrec->core.ptlIcon.y = y;
pcrec->core.preccNextRecord = NULL;
memcpy(&pcrec->cust, pcustomer, sizeof(CUSTOMER));
pcrec->core.pszIcon = pcrec->cust.name;
pcrec->core.hptrIcon = hptrCustIcon;
rci.cb = sizeof(RECORDINSERT);
rci.pRecordOrder = (PRECORDCORE)CMA_FIRST;
rci.pRecordParent = NULL;
rci.zOrder = CMA_TOP;
rci.cRecordsInsert = 1;
rci.fInvalidateRecord = TRUE;
(ULONG)WinSendMsg(hwndContainer, CM_INSERTRECORD, (MPARAM)pcrec, (MPARAM)&rci);
}
void RemoveCustomer(HWND container, PCONTRECORD pcrec)
{
PRECORDCORE aprc[10];
aprc[0] = &(pcrec->core);
WinSendMsg(container, CM_ERASERECORD, (MPARAM)&(pcrec->core), 0L);
WinSendMsg(container, CM_REMOVERECORD, (MPARAM)aprc, MPFROM2SHORT(1, CMA_FREE));
}
void PrintCustomer(PCONTRECORD pcrec, PPRINTDEST pdest)
{
// Here one should extract the print queue name from the PRINTDEST structure
// and use PM printing functions to print to that queue. For sample PM
// printing code, please see the PRTSAMP toolkit sample.
//
// To keep this drag/drop sample simple we will will just copy the data to LPT1
// regardless of which print object the item was dropped on.
FILE *fprt;
fprt = fopen("LPT1", "w");
fprintf(fprt, "\n\nCustomer name: %s\n Address: %s\n Phone: %s",
pcrec->cust.name, pcrec->cust.address, pcrec->cust.phone);
fclose(fprt);
}