home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 14 Text / 14-Text.zip / RB3774.ZIP / DMCUST.ZIP / DMCUST.C next >
Text File  |  1992-05-07  |  15KB  |  440 lines

  1. //****************************************************************************************
  2. //
  3. //  DMCUST.C - a demo program by Alan Chambers - UK PS Technical Support, whilst on 
  4. //             a residency at the ITSC, Boca Raton
  5. //
  6. //  Updated to work with GA code, 6 May 1992
  7. //
  8. //  This program reads several names, addresses and phone numbers from a file (DMCUST.DAT)
  9. //  and displays them as icons in a container window.  These items can be moved from
  10. //  one instance of this program to another by direct manipulation; they can be dropped
  11. //  on an order form displayed by the DMORDER sample to fill in the customer details therein,
  12. //  and they can be dropped on the telephone icon shown by the DMPHONE sample, to simulate
  13. //  a telephone dialler.
  14. //
  15. //
  16. //  This sample illustrates several different aspects of drag/drop:
  17. //
  18. //      - initiating a drag from a container window
  19. //      - using the DRM_PRINT rendering mechanism to allow application printing by
  20. //        drag/drop to a workplace shell printer object
  21. //      - using the DRM_DISCARD rendering mechanism to allow deletion of application
  22. //        items by dragging them to the workplace shell shredder object
  23. //      - implementing both ends of a user defined rendering mechanism (here called
  24. //        DRM_SHAREMEM)
  25. //
  26. //****************************************************************************************
  27. //
  28. // The program concentrates on demonstrating drag/drop techniques and is therefore
  29. // very simple in other respects. In particular, the so called customers to be displayed
  30. // are read from a simple flat file called DMCUST.DAT that can be read with fscanf().  
  31. // The following lines illustrate the format of this file - note that each text 
  32. /* field must have no imbedded blanks:
  33.  
  34. Alan_Chambers Somewhere_nice 123-4567
  35. John_Major 10_Downing_Street 999-4444
  36. A.N.Other Somewhere_horrible 987-5432
  37. George_Bush The_Whitehouse 456-8765
  38.  
  39. ******************************************************************************************/
  40.  
  41.  
  42. #define INCL_WIN
  43. #define INCL_GPI
  44. #define INCL_DOS
  45.  
  46. #include <os2.h>                         
  47. #include "dmcust.h"                      
  48. #include <stdio.h>
  49. #include <string.h>
  50. #include <stdlib.h>
  51. #include <ctype.h>
  52. #include <memory.h>
  53.  
  54. //***************************************************************************** */
  55. //
  56. //  #defines, typedefs and function headers
  57. //
  58. //***************************************************************************** */
  59.  
  60.  
  61.  
  62. #define OBJECTDATASIZE 100
  63. #define DRAGXFERMEMNAME "\\SHAREMEM\\DragXfer.mem"
  64.  
  65.  
  66. typedef struct {
  67.                  char name[30];
  68.                  char address[100];
  69.                  char phone[15];
  70.                } 
  71.                  CUSTOMER, *PCUSTOMER;
  72.  
  73. typedef struct{
  74.                 RECORDCORE core;          // control info for CONTAINER window
  75.                 CUSTOMER cust;            // application defined data
  76.               }
  77.                 CONTRECORD, *PCONTRECORD;
  78.  
  79. MRESULT EXPENTRY CustWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
  80. void FillWindow(HWND);
  81. void AddCustomer(HWND, PCUSTOMER, ULONG, ULONG);
  82. void RemoveCustomer(HWND, PCONTRECORD);
  83. void PrintCustomer(PCONTRECORD, PPRINTDEST);
  84.  
  85.  
  86.  
  87. //***************************************************************************** */
  88. //
  89. //  Some global variables
  90. //
  91. //***************************************************************************** */
  92.  
  93. HAB  hab;                               /* PM anchor block handle           */
  94. HPOINTER hptrCustIcon;                  /* Icon used for dragging customers */
  95.  
  96. //***************************************************************************** */
  97. //
  98. //  Main procedure - designed to create main (only) window and process messages
  99. //
  100. //***************************************************************************** */
  101.  
  102. INT main (VOID)
  103.   HMQ  hmq;                                   /* Message queue handle         */
  104.   QMSG qmsg;                                  /* Message from message queue   */
  105.   HWND hwndMain;
  106.   ULONG flCreate = FCF_STANDARD & ~FCF_MENU;  /* frame window creation flags */
  107.  
  108.   hab = WinInitialize(0);
  109.  
  110.   hmq = WinCreateMsgQueue(hab, 0);
  111.  
  112.   hptrCustIcon = WinLoadPointer(HWND_DESKTOP, 0, ID_CUSTPOINTER);
  113.  
  114.   WinRegisterClass(                       
  115.        hab,                               
  116.         (PSZ)"CustWindow",                
  117.         (PFNWP)CustWindowProc,            
  118.         CS_SIZEREDRAW,                    
  119.         sizeof(PVOID)
  120.         );
  121.  
  122.   hwndMain = WinCreateStdWindow(
  123.                    HWND_DESKTOP,           
  124.                    0,                      
  125.                    &flCreate,              
  126.                    "CustWindow",           
  127.                    "Customer Window",
  128.                    0,                      
  129.                    (HMODULE)0L,            
  130.                    ID_WINDOW,              
  131.                    NULL
  132.                    );
  133.  
  134.  
  135.   while(WinGetMsg(hab, &qmsg, 0L, 0, 0))       // message processing loop
  136.      WinDispatchMsg(hab, &qmsg);
  137.  
  138.  
  139.   WinDestroyWindow(hwndMain);
  140.   WinDestroyMsgQueue( hmq );             
  141.   WinTerminate( hab );                   
  142.  
  143.   return(0);
  144.  
  145.  
  146. //***************************************************************************** */
  147. //
  148. //  Window procedure for main (only) window
  149. //
  150. //***************************************************************************** */
  151.  
  152. MRESULT EXPENTRY CustWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  153. {
  154.   typedef struct {
  155.                    HWND hwndContainer;
  156.                  } 
  157.                    INSTANCE, *PINSTANCE;
  158.  
  159.   PINSTANCE wd;
  160.   SWP swp;
  161.   PCONTRECORD pcrec;
  162.   PCNRDRAGINIT pcnrdinit;
  163.   PCNRDRAGINFO pcnrdinfo;
  164.   PDRAGINFO pdinfo;
  165.   DRAGITEM ditem;
  166.   DRAGIMAGE dimg;
  167.   PDRAGTRANSFER pdxfer;
  168.   PCUSTOMER pxfercust, pxferfromcust;
  169.   PDRAGITEM pditem;
  170.   char dragxfermemname[100];
  171.   ULONG rc;
  172.   char srceType[100], srceRMF[100];
  173.   char srceFileName[100], srcePath[100];
  174.  
  175.   wd = (PINSTANCE)WinQueryWindowPtr(hwnd, 0);    // retrieve instance data pointer
  176.  
  177.   switch( msg )
  178.   {
  179.      case WM_CREATE:
  180.        wd = (PINSTANCE)malloc(sizeof(INSTANCE));   // allocate instance data space
  181.        WinSetWindowPtr(hwnd, 0, (PVOID)wd);        // and store in window words
  182.  
  183.        wd->hwndContainer = WinCreateWindow( hwnd, WC_CONTAINER, NULL, 
  184.                                         CCS_AUTOPOSITION | WS_VISIBLE | CCS_EXTENDSEL, 
  185.                                         0, 0, 0, 0, 
  186.                                         hwnd, HWND_TOP, ID_CONTAINER,
  187.                                         0, 0);
  188.  
  189.        FillWindow(wd->hwndContainer); 
  190.      
  191.        rc = WinSetWindowPos( WinQueryWindow(hwnd, QW_PARENT), 
  192.                       HWND_TOP, 100, 90, 400, 300,
  193.                       SWP_SIZE | SWP_ACTIVATE | SWP_SHOW | SWP_MOVE);
  194.       break;
  195.  
  196.  
  197.     case WM_CONTROL:
  198.       switch (SHORT2FROMMP(mp1))
  199.       {
  200.         case CN_INITDRAG:
  201.            pcnrdinit = (PCNRDRAGINIT)mp2;
  202.            if((pcrec = (PCONTRECORD)(pcnrdinit->pRecord)) != NULL)
  203.            {          
  204.               pdinfo = DrgAllocDraginfo(1);
  205.  
  206.               ditem.hwndItem = hwnd;
  207.               ditem.ulItemID = (ULONG)pcrec;
  208.               ditem.hstrType = DrgAddStrHandle("DRT_CUSTOMER");    
  209.               ditem.hstrRMF = DrgAddStrHandle("(DRM_SHAREMEM,DRM_PRINT,DRM_DISCARD)x(DRF_TEXT)");
  210.               ditem.hstrContainerName = DrgAddStrHandle("Boca Raton Branch");
  211.               ditem.hstrSourceName = DrgAddStrHandle(pcrec->cust.name);
  212.               ditem.hstrTargetName = (HSTR)0;
  213.               ditem.fsControl = 0;  ditem.fsSupportedOps = 0;
  214.  
  215.               rc = DrgSetDragitem(pdinfo, &ditem, (ULONG)sizeof(ditem), 0);
  216.  
  217.               dimg.cb = sizeof(DRAGIMAGE);
  218.               dimg.cptl = 0;
  219.               dimg.hImage = hptrCustIcon;
  220.               dimg.sizlStretch.cx = 10L;
  221.               dimg.sizlStretch.cy = 10L;
  222.               dimg.fl = DRG_ICON;
  223.               dimg.cxOffset = 0;
  224.               dimg.cyOffset = 0;
  225.  
  226.               DrgDrag(hwnd, pdinfo, (PDRAGIMAGE)&dimg, 1, VK_ENDDRAG, NULL); 
  227.  
  228.               DrgFreeDraginfo(pdinfo);
  229.            }
  230.            break;
  231.  
  232.  
  233.         case CN_DRAGOVER:
  234.            pcnrdinfo = (PCNRDRAGINFO)mp2;
  235.            pdinfo = pcnrdinfo->pDragInfo;
  236.            pditem = DrgQueryDragitemPtr(pdinfo, 0);
  237.  
  238.            if(DrgVerifyRMF(pditem, "DRM_SHAREMEM", "DRF_TEXT"))
  239.            {
  240.              DrgFreeDraginfo(pdinfo);
  241.              return(MPFROM2SHORT(DOR_DROP, DO_MOVE));
  242.            }
  243.            else
  244.            {
  245.              DrgFreeDraginfo(pdinfo);
  246.              return(MPFROM2SHORT(DOR_NEVERDROP, 0));
  247.            }
  248.            break;
  249.  
  250.  
  251.         case CN_DROP:
  252.            pcnrdinfo = (PCNRDRAGINFO)mp2;
  253.            pdinfo = pcnrdinfo->pDragInfo;
  254.            pditem = DrgQueryDragitemPtr(pdinfo, 0);
  255.            
  256.            DrgQueryStrName(pditem->hstrSourceName, 100, srceFileName);
  257.            DrgQueryStrName(pditem->hstrContainerName, 100, srcePath);
  258.            DrgQueryStrName(pditem->hstrType, 100, srceType);
  259.            DrgQueryStrName(pditem->hstrRMF, 100, srceRMF);
  260.  
  261.  
  262.            // allocated a named shared memory object for a customer *pxfercust
  263.  
  264.            rc = DosAllocSharedMem((PPVOID)&pxfercust, DRAGXFERMEMNAME, sizeof(CUSTOMER), PAG_COMMIT | PAG_WRITE | PAG_READ);
  265.  
  266.  
  267.            // allocate and fill the dxfer structure;
  268.  
  269.            pdxfer = DrgAllocDragtransfer(1);      
  270.  
  271.            pdxfer->cb = sizeof(DRAGTRANSFER);
  272.            pdxfer->hwndClient = hwnd;
  273.            pdxfer->pditem = pditem;
  274.            pdxfer->hstrSelectedRMF = DrgAddStrHandle("DRM_CUSTOMER");
  275.            pdxfer->hstrRenderToName = DrgAddStrHandle(DRAGXFERMEMNAME);
  276.            pdxfer->ulTargetInfo = 0;
  277.            pdxfer->usOperation = DO_MOVE;
  278.  
  279.            // This is like a WinSendMsg except that it also does a DosGiveMem for the dragtransfer struct
  280.            rc = (ULONG)DrgSendTransferMsg(pdinfo->hwndSource, DM_RENDER, (MPARAM)pdxfer, NULL);
  281.  
  282.            
  283.            if(rc == TRUE)
  284.            {
  285.              AddCustomer(wd->hwndContainer, pxfercust, 10, 10);
  286.            }
  287.  
  288.            DrgFreeDraginfo(pdinfo);
  289.            DrgFreeDragtransfer(pdxfer);
  290.            DosFreeMem((PVOID)pxfercust);
  291.  
  292.            break;           
  293.  
  294.         default: ;
  295.       }
  296.       break;
  297.  
  298.  
  299.     case DM_RENDER:
  300.       pdxfer = (PDRAGTRANSFER)mp1;
  301.       pxferfromcust = &(((PCONTRECORD)(pdxfer->pditem->ulItemID))->cust);   //pointer to recordcore for dragged item
  302.  
  303.       DrgQueryStrName(pdxfer->hstrRenderToName, 100, dragxfermemname);  // get shared mem name
  304.        
  305.       DosGetNamedSharedMem((PPVOID)&pxfercust, dragxfermemname, PAG_WRITE | PAG_READ);
  306.       memcpy(pxfercust, pxferfromcust, sizeof(CUSTOMER));
  307.       DosFreeMem((PVOID)pxfercust);
  308.  
  309.       if(pdxfer->usOperation == DO_MOVE)      // if it's a move, remove the customer
  310.       {
  311.         RemoveCustomer(wd->hwndContainer, (PCONTRECORD)(pdxfer->pditem->ulItemID));
  312.       }
  313.  
  314.       return((MRESULT)TRUE);
  315.       break;
  316.    
  317.     case DM_PRINTOBJECT:         /* mp1 points to a DRAGITEM, mp2 to a PRINTDEST structure */
  318.       pditem = (PDRAGITEM)mp1;   /* PLEASE NOTE: there is an error in the online PM Reference */
  319.                                  /* which says that mp1 points to a DRAGINFO structure      */
  320.  
  321.       PrintCustomer((PCONTRECORD)(pditem->ulItemID), ((PPRINTDEST)mp2));
  322.  
  323.       return((MRESULT)DRR_SOURCE);      /* indicates that we will do the printing, */
  324.       break;                            /* rather than the printer object          */
  325.  
  326.  
  327.     case DM_DISCARDOBJECT:                       /* mp1 points to a DRAGINFO structure */
  328.       pdinfo = (PDRAGINFO)mp1;                   /* the item to be deleted             */
  329.       pditem = DrgQueryDragitemPtr(pdinfo, 0);
  330.  
  331.       RemoveCustomer((HWND)wd->hwndContainer, (PCONTRECORD)(pditem->ulItemID));
  332.  
  333.       return((MRESULT)DRR_SOURCE);               /* indicates that we take responsibility */
  334.       break;                                      /* for deleting the item                 */
  335.  
  336.  
  337.     case WM_COMMAND:
  338.       switch (SHORT1FROMMP(mp1))          /* test the command value from mp1 */
  339.       {
  340.         case ID_EXITPROG:
  341.           WinPostMsg( hwnd, WM_CLOSE, (MPARAM)0, (MPARAM)0 );
  342.           break;
  343.  
  344.         default:
  345.           return WinDefWindowProc(hwnd, msg, mp1, mp2);
  346.       }
  347.       break;
  348.  
  349.  
  350.     case WM_SIZE:
  351.       WinQueryWindowPos(hwnd, &swp);
  352.       WinSetWindowPos(wd->hwndContainer, HWND_TOP, swp.x, swp.y, swp.cx, swp.cy,  
  353.                       SWP_SIZE | SWP_SHOW); 
  354.       break;
  355.  
  356.     case WM_CLOSE:
  357.       WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 );     
  358.       break;
  359.    
  360.     case WM_DESTROY:
  361.       free(wd);
  362.       break;
  363.  
  364.     default:
  365.       return WinDefWindowProc(hwnd, msg, mp1, mp2);
  366.   }
  367.   return (MRESULT)FALSE;
  368.  
  369.  
  370. //***************************************************************************** */
  371. //
  372. //  Three utility functions used in program
  373. //
  374. //***************************************************************************** */
  375. void FillWindow(HWND hwndContainer)
  376. {
  377.   CUSTOMER cust;
  378.   FILE *finput;
  379.  
  380.   if((finput = fopen("dmcust.dat", "r")) != NULL)
  381.     while(fscanf(finput, "%s%s%s", cust.name, cust.address, cust.phone) == 3)
  382.     {
  383.       WinSendMsg(hwndContainer, CM_ALLOCRECORD,
  384.                                        (MPARAM)(sizeof(CONTRECORD) - sizeof(RECORDCORE)), (MPARAM)1);
  385.       AddCustomer(hwndContainer, &cust, 10, 10);
  386.     }
  387. }
  388.  
  389.  
  390. void AddCustomer(HWND hwndContainer, CUSTOMER* pcustomer, ULONG x, ULONG y)
  391. {
  392.   PCONTRECORD pcrec;
  393.   RECORDINSERT rci;
  394.  
  395.   pcrec = (PCONTRECORD)WinSendMsg(hwndContainer, CM_ALLOCRECORD,
  396.                                    (MPARAM)(sizeof(CONTRECORD) - sizeof(RECORDCORE)), (MPARAM)1);
  397.   pcrec->core.ptlIcon.x = x;  pcrec->core.ptlIcon.y = y;
  398.   pcrec->core.preccNextRecord = NULL;
  399.   
  400.   memcpy(&pcrec->cust, pcustomer, sizeof(CUSTOMER));
  401.   pcrec->core.pszIcon = pcrec->cust.name;
  402.   pcrec->core.hptrIcon = hptrCustIcon;
  403.   rci.cb = sizeof(RECORDINSERT);
  404.   rci.pRecordOrder = (PRECORDCORE)CMA_FIRST;
  405.   rci.pRecordParent = NULL;
  406.   rci.zOrder = CMA_TOP;
  407.   rci.cRecordsInsert = 1;
  408.   rci.fInvalidateRecord = TRUE;
  409.  
  410.   (ULONG)WinSendMsg(hwndContainer, CM_INSERTRECORD, (MPARAM)pcrec, (MPARAM)&rci);
  411. }
  412.  
  413. void RemoveCustomer(HWND container, PCONTRECORD pcrec)
  414. {
  415.   PRECORDCORE aprc[10];
  416.  
  417.   aprc[0] = &(pcrec->core);
  418.   WinSendMsg(container, CM_ERASERECORD, (MPARAM)&(pcrec->core), 0L);
  419.   WinSendMsg(container, CM_REMOVERECORD, (MPARAM)aprc, MPFROM2SHORT(1, CMA_FREE));
  420. }
  421.  
  422. void PrintCustomer(PCONTRECORD pcrec, PPRINTDEST pdest)
  423. {
  424.   // Here one should extract the print queue name from the PRINTDEST structure
  425.   // and use PM printing functions to print to that queue.  For sample PM
  426.   // printing code, please see the PRTSAMP toolkit sample.
  427.   //
  428.   // To keep this drag/drop sample simple we will will just copy the data to LPT1
  429.   // regardless of which print object the item was dropped on.
  430.  
  431.   FILE *fprt;
  432.   fprt = fopen("LPT1", "w");
  433.   fprintf(fprt, "\n\nCustomer name: %s\n         Address: %s\n         Phone: %s",
  434.                  pcrec->cust.name, pcrec->cust.address, pcrec->cust.phone);
  435.   fclose(fprt);
  436. }
  437.