home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / gall231.zip / DDE.ZIP / CLIENT.C < prev    next >
Text File  |  1996-04-02  |  18KB  |  591 lines

  1. #pragma title    ("Galleria DDE client sample")
  2. #pragma subtitle ("Copyright (c) 1994  Bitware Australia Pty. Ltd.")
  3.  
  4. //
  5. //
  6. //   Galleria DDE client sample
  7. //
  8. //   Version 1.0
  9. //
  10. //
  11. //   Galleria currently supports the following DDE transactions:
  12. //   
  13. //      FILE      Specifies the full path name of an existing file on disk
  14. //                that Galleria is to read and display. The file can be in any
  15. //                format currently supported by Galleria.
  16. //
  17. //      BITMAP    Specifies an in-storage bitmap in OS/2 2.x bitmap format.
  18. //                The data sent includes a completed BITMAPINFO2 structure
  19. //                (plus RGB2 entries) followed by the image data itself.
  20. //
  21. //      ZOOM      Specifies a ZOOMDATA structure completed with scaling factor
  22. //                and zoom coordinates. Galleria will display its zoom window
  23. //                (if not already displayed) then update the contents.
  24. //
  25. //   See the comments in the source below for a description of how the DDE
  26. //   session is established/terminated and format of the above transactions.
  27. //
  28. //   For a more complete description of the DDE interface refer to:
  29. //
  30. //      OS/2 2.0 Technical Library: Programming Guide Volume II (Chapter 32)
  31. //
  32. //
  33. //   This DDE client requires Galleria Version 2.05 (or later).
  34. //
  35. //
  36. //   Copyright (c) 1994  
  37. //
  38. //   Bitware Australia Pty. Ltd.
  39. //   P.O. Box 3097
  40. //   Manuka  A.C.T.  2603
  41. //   Australia
  42. //
  43. //   Fax:        +61-6-2810175
  44. //   CompuServe: 100033,340
  45. //   Internet:   bitware@ibm.net
  46. //
  47. //
  48.  
  49.  
  50. #define     INCL_DOS
  51. #define     INCL_WIN
  52. #define     INCL_GPI
  53. #include    <os2.h>
  54.  
  55. #include    <stdlib.h>
  56. #include    <string.h>
  57.  
  58. #include    "client.h"
  59.  
  60. MRESULT EXPENTRY  MainProc (HWND, ULONG, MPARAM, MPARAM);
  61.  
  62.  
  63. //
  64. // These are the Server and Topic names you need to use for the
  65. // WinDdeInitiate call.
  66. //
  67. // Note that Galleria will *not* enumerate the available topics when
  68. // a WinDdeInitiate request is issued with a null topic.
  69. //
  70.  
  71. static CHAR    szServer [] = "GALLERIA";
  72. static CHAR    szTopic []  = "PRIVATE";
  73.  
  74.  
  75. //
  76. // This is the format of the data for a ZOOM request. It is appended to the
  77. // DDESTRUCT and pointed to by offabData.
  78. //
  79.  
  80. typedef struct
  81.    {
  82.    ULONG          ulFactor;            // Scaling factor 1-9
  83.    USHORT         xCoord, yCoord;      // x and y coordinates for the
  84.                                        // ZOOM request. (0,0) is bottom
  85.                                        // left. The units are relative pixel
  86.                                        // values in the unscaled image.
  87.    } ZOOMDATA, *PZOOMDATA;
  88.  
  89.  
  90. INT main
  91.    (
  92.    ULONG          argc,             // command line argument count
  93.    CHAR           *argv []          // command line argument addresses
  94.    )
  95.  
  96.    {
  97.    HAB            hab;
  98.    HMQ            hmq;
  99.    QMSG           qmsg;
  100.    HWND           hwndMain;
  101.  
  102.          // Initialize the application and create message queue
  103.  
  104.    hab = WinInitialize (0);
  105.  
  106.    hmq = WinCreateMsgQueue (hab, 0);
  107.  
  108.          // Create main window
  109.  
  110.    hwndMain = WinLoadDlg (HWND_DESKTOP, HWND_DESKTOP, MainProc,
  111.                (HMODULE) NULL, IDD_MAINBOX, NULL);
  112.  
  113.          // Message loop processing
  114.  
  115.    while ( WinGetMsg (hab, &qmsg, (HWND) NULL, 0, 0) )
  116.       WinDispatchMsg (hab, &qmsg);
  117.  
  118.          // Destroy main window
  119.  
  120.    WinDestroyWindow (hwndMain);
  121.  
  122.          // Destroy message queue and terminate application
  123.  
  124.    WinDestroyMsgQueue (hmq);
  125.  
  126.    WinTerminate (hab);
  127.  
  128.    return 0;
  129.    }
  130.  
  131. MRESULT EXPENTRY MainProc
  132.    (
  133.    HWND           hwnd,          // window handle
  134.    ULONG          msg,           // message
  135.    MPARAM         mp1,           // message parameter 1
  136.    MPARAM         mp2            // message parameter 2
  137.    )
  138.  
  139.    {
  140.    //
  141.    // You need to store the hwnd for the DDE server somewhere. This program
  142.    // puts it into the instance of "Window words" for the window but you
  143.    // could also use a static.
  144.    //
  145.  
  146.    struct WINDATA
  147.       {
  148.       HWND           hwndDDE;
  149.       } *pw;
  150.  
  151.    pw = WinQueryWindowPtr (hwnd, 0);
  152.  
  153.    switch ( msg )
  154.       {
  155.  
  156.       //
  157.       // Initialize variables and dialog elements.
  158.       //
  159.  
  160.       case WM_INITDLG:
  161.  
  162.          {
  163.          CHAR           szFileName [CCHMAXPATH];
  164.  
  165.                // Allocate area for window static and set pointer
  166.  
  167.          pw = malloc (sizeof (struct WINDATA));
  168.  
  169.          WinSetWindowPtr (hwnd, 0, pw);
  170.  
  171.                // Initialize variables
  172.  
  173.          pw->hwndDDE = (HWND) NULL;
  174.  
  175.                // Fill initial dialog values
  176.  
  177.          DosQueryPathInfo ("CLIENT.BMP", FIL_QUERYFULLNAME, szFileName,
  178.                      sizeof szFileName);
  179.  
  180.          WinSetDlgItemText (hwnd, IDD_FILENAME, szFileName);
  181.  
  182.          WinSendDlgItemMsg (hwnd, IDD_ZOOMFACTOR, SPBM_SETLIMITS,
  183.                      MPFROMSHORT (9), MPFROMSHORT (1));
  184.          WinSendDlgItemMsg (hwnd, IDD_ZOOMFACTOR, SPBM_SETCURRENTVALUE,
  185.                      MPFROMSHORT (4), NULL);
  186.  
  187.          WinSetDlgItemShort (hwnd, IDD_ZOOMX, 100, FALSE);
  188.          WinSetDlgItemShort (hwnd, IDD_ZOOMY, 100, FALSE);
  189.  
  190.          return 0;
  191.          }
  192.  
  193.       //
  194.       // WM_DDE_INITIATEACK is received as a response from the
  195.       // WinDdeInitiate call. The logic saves the hwnd for the server in
  196.       // hwndDDE.
  197.       //
  198.       // If we get multiple responses (i.e. hwndDDE is already set)
  199.       // then we post a WM_DDE_TERMINATE to the others.
  200.       //
  201.  
  202.       case WM_DDE_INITIATEACK:
  203.  
  204.          {
  205.          PDDEINIT       pddei;
  206.          COLOR          clr;
  207.  
  208.          pddei = PVOIDFROMMP (mp2);
  209.  
  210.          if ( pw->hwndDDE == (HWND) NULL )
  211.             {
  212.             pw->hwndDDE = (HWND) mp1;
  213.  
  214.             WinSetDlgItemText (hwnd, IDD_STATUS, "Active");
  215.             WinSetDlgItemText (hwnd, IDD_ACTIVATE, "Break");
  216.  
  217.             clr = CLR_RED;
  218.  
  219.             WinSetPresParam (WinWindowFromID (hwnd, IDD_ACTIVATE),
  220.                         PP_FOREGROUNDCOLORINDEX, 4, (PVOID) &clr);
  221.  
  222.             WinEnableControl (hwnd, IDD_SENDFILE, TRUE);
  223.             WinEnableControl (hwnd, IDD_SENDBITMAP, TRUE);
  224.             WinEnableControl (hwnd, IDD_SENDZOOM, TRUE);
  225.             }
  226.          else
  227.             WinDdePostMsg ((HWND) mp1, hwnd, WM_DDE_TERMINATE,
  228.                         (PDDESTRUCT) NULL, DDEPM_RETRY);
  229.  
  230.          DosFreeMem (pddei);
  231.  
  232.          return 0;
  233.          }
  234.  
  235.       //
  236.       // WM_DDE_ACK is received as a response from our WM_DDE_POKE
  237.       // request.
  238.       //
  239.       // Your logic may want to retry on busy conditions. Note that
  240.       // a DDE_FBUSY will be received when the server is active processing
  241.       // the last request or the user has initiated some activity.
  242.       //
  243.  
  244.       case WM_DDE_ACK:
  245.  
  246.          {
  247.          PDDESTRUCT     pdde;
  248.          PSZ            pszText;
  249.  
  250.          pdde = PVOIDFROMMP (mp2);
  251.  
  252.          if ( pdde->fsStatus & DDE_FACK )
  253.             pszText = "OK";
  254.          else if ( pdde->fsStatus & DDE_FBUSY )
  255.             pszText = "Busy";
  256.          else if ( pdde->fsStatus & DDE_NOTPROCESSED )
  257.             pszText = "Error";
  258.          else
  259.             pszText = "Unknown";
  260.  
  261.          WinSetDlgItemText (hwnd, IDD_RETURNCODE, pszText);
  262.  
  263.          DosFreeMem (pdde);
  264.  
  265.          return 0;
  266.          }
  267.  
  268.       //
  269.       // WM_DDE_TERMINATE is received when the server terminates or breaks
  270.       // the connection.
  271.       //
  272.       // We also need to send this when terminating the client.
  273.       //
  274.  
  275.       case WM_DDE_TERMINATE:
  276.  
  277.          {
  278.          COLOR          clr;
  279.  
  280.          if ( pw->hwndDDE == (HWND) mp1 )
  281.             {
  282.             pw->hwndDDE = (HWND) NULL;
  283.  
  284.             WinSetDlgItemText (hwnd, IDD_STATUS, "Inactive");
  285.             WinSetDlgItemText (hwnd, IDD_ACTIVATE, "Establish");
  286.  
  287.             clr = CLR_GREEN;
  288.  
  289.             WinSetPresParam (WinWindowFromID (hwnd, IDD_ACTIVATE),
  290.                         PP_FOREGROUNDCOLORINDEX, 4, (PVOID) &clr);
  291.  
  292.             WinEnableControl (hwnd, IDD_SENDFILE, FALSE);
  293.             WinEnableControl (hwnd, IDD_SENDBITMAP, FALSE);
  294.             WinEnableControl (hwnd, IDD_SENDZOOM, FALSE);
  295.  
  296.             WinDdePostMsg ((HWND) mp1, hwnd, WM_DDE_TERMINATE,
  297.                         (PDDESTRUCT) NULL, DDEPM_RETRY);
  298.             }
  299.  
  300.          return 0;
  301.          }
  302.  
  303.       //
  304.       // Intercept the Close command from the System Menu and post a
  305.       // WM_QUIT to kill the application.
  306.       //
  307.  
  308.       case WM_SYSCOMMAND:
  309.  
  310.          {
  311.          if ( SHORT1FROMMP (mp1) == SC_CLOSE )
  312.             {
  313.                   // Terminate
  314.  
  315.             WinPostMsg (hwnd, WM_QUIT, NULL, NULL);
  316.  
  317.             WinDismissDlg (hwnd, FALSE);
  318.  
  319.             return 0;
  320.             }
  321.  
  322.          break;
  323.          }
  324.  
  325.       //
  326.       // Command (in our case, pushbutton) processing.
  327.       //
  328.  
  329.       case WM_COMMAND:
  330.  
  331.          {
  332.          PDDESTRUCT     pdde;
  333.          CONVCONTEXT    cctxt;
  334.          FILEDLG        fdg;
  335.          ULONG          cbData, cbImage, cclr;
  336.          PZOOMDATA      pzoom;
  337.          CHAR           szFileName [CCHMAXPATH];
  338.          PBITMAPINFO2   pbmi2;
  339.          PBYTE          pbImage;
  340.          PBITMAPFILEHEADER2   pbfh2;
  341.  
  342.          switch ( SHORT1FROMMP (mp1) )
  343.             {
  344.  
  345.             //
  346.             // Here is where the DDE connection is established (or broken).
  347.             // The WinDdeInitiate must be called with the server name of
  348.             // "GALLERIA" and topic of "PRIVATE" ... all other requests
  349.             // will be ignored.
  350.             //
  351.             // We then need to wait for the WM_DDE_INITIATEACK to find out
  352.             // the hwnd of the server.
  353.             //
  354.  
  355.             case IDD_ACTIVATE:
  356.  
  357.                if ( pw->hwndDDE == (HWND) NULL )
  358.                   {
  359.                   cctxt.cb          = sizeof cctxt;
  360.                   cctxt.fsContext   = DDECTXT_CASESENSITIVE;
  361.                   cctxt.idCountry   = 1;
  362.                   cctxt.usCodepage  = 437;
  363.                   cctxt.usLangID    = 0;
  364.                   cctxt.usSubLangID = 0;
  365.  
  366.                   WinDdeInitiate (hwnd, szServer, szTopic, &cctxt);
  367.                   }
  368.                else
  369.                   WinSendMsg (hwnd, WM_DDE_TERMINATE, MPFROMLONG (pw->hwndDDE),
  370.                               NULL);
  371.  
  372.                break;
  373.  
  374.             //
  375.             // Invoke the File Open dialog to prompt for file name of image.
  376.             //
  377.  
  378.             case IDD_CHANGEFILE:
  379.  
  380.                memset (&fdg, 0, sizeof fdg);
  381.  
  382.                fdg.cbSize = sizeof fdg;
  383.                fdg.fl     = FDS_OPEN_DIALOG | FDS_CENTER;
  384.  
  385.                WinQueryDlgItemText (hwnd, IDD_FILENAME, sizeof fdg.szFullFile,
  386.                            fdg.szFullFile);
  387.  
  388.                if ( WinFileDlg (HWND_DESKTOP, hwnd, &fdg) &&
  389.                            (fdg.lReturn == DID_OK) )
  390.                   WinSetDlgItemText (hwnd, IDD_FILENAME, fdg.szFullFile);
  391.  
  392.                break;
  393.  
  394.             //
  395.             // Here is where we do a FILE request.
  396.             //
  397.             // The format for this is a DDESTRUCT followed by "FILE" (as
  398.             // the ItemName) then the actual file name (ASCIIZ string of
  399.             // full path as the Data).
  400.             //
  401.             // A WM_DDE_ACK will be received with return code info.
  402.             //
  403.  
  404.             case IDD_SENDFILE:
  405.  
  406.                WinSetDlgItemText (hwnd, IDD_RETURNCODE, "");
  407.  
  408.                WinQueryDlgItemText (hwnd, IDD_FILENAME, sizeof szFileName,
  409.                            szFileName);
  410.  
  411.                cbData = sizeof (DDESTRUCT) + 8 + strlen (szFileName) + 1;
  412.  
  413.                pdde = (PDDESTRUCT) NULL;
  414.  
  415.                if ( DosAllocSharedMem ((PPVOID) &pdde, NULL, cbData,
  416.                            PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE |
  417.                            OBJ_GIVEABLE) == 0 )
  418.                   {
  419.                   pdde->cbData        = cbData;
  420.                   pdde->fsStatus      = DDE_FACKREQ;
  421.                   pdde->usFormat      = 0;
  422.                   pdde->offszItemName = sizeof (DDESTRUCT);
  423.                   pdde->offabData     = sizeof (DDESTRUCT) + 8;
  424.  
  425.                   strcpy (DDES_PSZITEMNAME (pdde), "FILE");
  426.  
  427.                   strcpy (DDES_PABDATA (pdde), szFileName);
  428.  
  429.                   WinDdePostMsg (pw->hwndDDE, hwnd, WM_DDE_POKE, pdde,
  430.                               DDEPM_RETRY);
  431.                   }
  432.  
  433.                break;
  434.     
  435.             //
  436.             // Here is where we do a BITMAP request.
  437.             //
  438.             // The format for this is a DDESTRUCT followed by "BITMAP" (as
  439.             // the ItemName) then the image in memory. The image in memory
  440.             // consists of a completed BITMAPINFO2 structure (allowing for
  441.             // 256 RGB2 entries) followed by the image data itself. Note that
  442.             // the image data must be at offset 0x440 irrespective of the
  443.             // number of RGB2 entries. Both the BITMAPINFO2 and image data
  444.             // must be in standard OS/2 2.x format (cbSize = 64; cPlanes = 1;
  445.             // cBitCount = 1, 4, 8 or 24 ... be sure to initialize all other
  446.             // fields correctly).
  447.             //
  448.             // In this example the image data is obtained by dumping that
  449.             // from a bitmap resource but any logic that can create data in
  450.             // the above format will do.
  451.             //
  452.             // A WM_DDE_ACK will be received with return code info.
  453.             //
  454.  
  455.             case IDD_SENDBITMAP:
  456.  
  457.                WinSetDlgItemText (hwnd, IDD_RETURNCODE, "");
  458.  
  459.                pbfh2 = (PBITMAPFILEHEADER2) NULL;
  460.  
  461.                DosGetResource ((HMODULE) NULL, RT_BITMAP, IDB_IMAGE,
  462.                            (PPVOID) &pbfh2);
  463.  
  464.                cbImage = ((pbfh2->bmp2.cx * pbfh2->bmp2.cBitCount + 31) / 32) *
  465.                            4 * pbfh2->bmp2.cy;
  466.                cbData  = sizeof (DDESTRUCT) + 8 + sizeof (BITMAPINFOHEADER2) +
  467.                            256 * sizeof (RGB2) + cbImage;
  468.  
  469.                pdde = (PDDESTRUCT) NULL;
  470.  
  471.                if ( DosAllocSharedMem ((PPVOID) &pdde, NULL, cbData,
  472.                            PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE |
  473.                            OBJ_GIVEABLE) == 0 )
  474.                   {
  475.                   pdde->cbData        = cbData;
  476.                   pdde->fsStatus      = DDE_FACKREQ;
  477.                   pdde->usFormat      = 0;
  478.                   pdde->offszItemName = sizeof (DDESTRUCT);
  479.                   pdde->offabData     = sizeof (DDESTRUCT) + 8;
  480.  
  481.                   strcpy (DDES_PSZITEMNAME (pdde), "BITMAP");
  482.  
  483.                   pbmi2   = (PBITMAPINFO2) DDES_PABDATA (pdde);
  484.                   pbImage = (PBYTE) pbmi2 + sizeof (BITMAPINFOHEADER2) +
  485.                               256 * sizeof (RGB2);
  486.  
  487.                   *(PBITMAPINFOHEADER2) pbmi2 = pbfh2->bmp2;
  488.  
  489.                         // Copy RGB2 entries
  490.  
  491.                   if ( pbfh2->bmp2.cBitCount <= 8 )
  492.                      {
  493.                      cclr = ( pbfh2->bmp2.cclrUsed == 0 ?
  494.                                  1 << pbfh2->bmp2.cBitCount :
  495.                                  pbfh2->bmp2.cclrUsed );
  496.  
  497.                      memcpy (pbmi2->argbColor,
  498.                                  (PBYTE) pbfh2 + sizeof (BITMAPFILEHEADER2),
  499.                                  cclr * sizeof (RGB2));
  500.                      }
  501.  
  502.                   memcpy (pbImage, (PBYTE) pbfh2 + pbfh2->offBits, cbImage);
  503.  
  504.                   WinDdePostMsg (pw->hwndDDE, hwnd, WM_DDE_POKE, pdde,
  505.                               DDEPM_RETRY);
  506.                   }
  507.  
  508.                DosFreeResource (pbfh2);
  509.  
  510.                break;
  511.             
  512.             //
  513.             // Here is where we do a ZOOM request.
  514.             //
  515.             // The format for this is a DDESTRUCT followed by "ZOOM" (as
  516.             // the ItemName) then a completed ZOOMDATA structure (as the
  517.             // Data). The ZOOMDATA contains the zoom factor and coordinates.
  518.             //
  519.             // A WM_DDE_ACK will be received with return code info.
  520.             //
  521.  
  522.             case IDD_SENDZOOM:
  523.  
  524.                WinSetDlgItemText (hwnd, IDD_RETURNCODE, "");
  525.  
  526.                cbData = sizeof (DDESTRUCT) + 8 + sizeof (ZOOMDATA);
  527.  
  528.                pdde = (PDDESTRUCT) NULL;
  529.  
  530.                if ( DosAllocSharedMem ((PPVOID) &pdde, NULL, cbData,
  531.                            PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE |
  532.                            OBJ_GIVEABLE) == 0 )
  533.                   {
  534.                   pdde->cbData        = cbData;
  535.                   pdde->fsStatus      = DDE_FACKREQ;
  536.                   pdde->usFormat      = 0;
  537.                   pdde->offszItemName = sizeof (DDESTRUCT);
  538.                   pdde->offabData     = sizeof (DDESTRUCT) + 8;
  539.  
  540.                   strcpy (DDES_PSZITEMNAME (pdde), "ZOOM");
  541.  
  542.                   pzoom = (PZOOMDATA) DDES_PABDATA (pdde);
  543.  
  544.                   WinSendDlgItemMsg (hwnd, IDD_ZOOMFACTOR, SPBM_QUERYVALUE,
  545.                               MPFROMP (&pzoom->ulFactor), MPFROM2SHORT (0, 0));
  546.  
  547.                   WinQueryDlgItemShort (hwnd, IDD_ZOOMX,
  548.                               (PSHORT) &pzoom->xCoord, FALSE);
  549.                   WinQueryDlgItemShort (hwnd, IDD_ZOOMY,
  550.                               (PSHORT) &pzoom->yCoord, FALSE);
  551.  
  552.                   WinDdePostMsg (pw->hwndDDE, hwnd, WM_DDE_POKE, pdde,
  553.                               DDEPM_RETRY);
  554.                   }
  555.  
  556.                break;
  557.     
  558.             }
  559.  
  560.          return 0;
  561.          }
  562.  
  563.       //
  564.       // On termination we must send a WM_DDE_TERMINATE to the server. This
  565.       // could also be done in WM_CLOSE but WM_DESTROY is safer.
  566.       //
  567.  
  568.       case WM_DESTROY:
  569.  
  570.          {
  571.                // Kill DDE connection if still active
  572.  
  573.          if ( pw->hwndDDE != (HWND) NULL )
  574.             WinDdePostMsg (pw->hwndDDE, hwnd, WM_DDE_TERMINATE,
  575.                         (PDDESTRUCT) NULL, DDEPM_RETRY);
  576.  
  577.                // Release area for window data
  578.  
  579.          free (pw);
  580.  
  581.          break;
  582.          }
  583.  
  584.       }
  585.  
  586.          // Default dialog processing
  587.  
  588.    return ( WinDefDlgProc (hwnd, msg, mp1, mp2) );
  589.    }
  590.  
  591.