home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c081_7 / 2.ddi / WEXAMPLE.ZIP / DDECLNT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-13  |  15.5 KB  |  487 lines

  1. // Borland C++ - (C) Copyright 1991 by Borland International
  2.  
  3. //*******************************************************************
  4. //
  5. // program - DDEClnt.c
  6. // purpose - dde client interface routines. This file is part of the
  7. //           TSTAPP project.
  8. //
  9. //*******************************************************************
  10.  
  11.  
  12. #include <windows.h>
  13. #include <dde.h>
  14. #include <string.h>
  15. #include <time.h>
  16.  
  17. #include "ddeclnt.h"
  18.  
  19. # define WW_SERVER  0
  20. # define ACK        0x8000
  21. # define BUSY       0x4000
  22.  
  23. static int          nClientClassRegistered;
  24. static char         szClientClass[] = "ddeclient";
  25. static WORD         wLastDDEClientMsg;
  26. static int          nAckFlg;
  27. static int          nBusyFlg;
  28. static HANDLE       hData;
  29.  
  30. //*******************************************************************
  31. // DDEClientOpen - open a dde conversation with a server
  32. //
  33. // paramaters:
  34. //             hParentWnd    - The handle of the window trying to start
  35. //                             this dde conversation.
  36. //             szApp         - The name of the application to talk to.
  37. //             szTopic       - The name of the topic to talk about.
  38. //
  39. // returns:
  40. //             The handle of the channel to use to continue the conversation
  41. //                or
  42. //             NULL if conversation could not be opened.
  43. //
  44. //*******************************************************************
  45. HWND DDEClientOpen(HWND hParentWnd, char *szApp, char *szTopic)
  46. {
  47.     HANDLE   hInst;
  48.     HWND     hChannel;
  49.     ATOM     aApp;
  50.     ATOM     aTopic;
  51.     WNDCLASS wclass;
  52.  
  53.     // Get parents instance to use in creating window to carry on
  54.     // dde conversation.
  55.     hInst = GetWindowWord(hParentWnd, GWW_HINSTANCE);
  56.     if (!hInst)
  57.         return(0);
  58.  
  59.     // If we have not already done it, register the window class to
  60.     // carry on this conversation.
  61.     if (!nClientClassRegistered)
  62.     {
  63.         wclass.style         = CS_HREDRAW | CS_VREDRAW;
  64.         wclass.lpfnWndProc   = DDEClientWndProc;
  65.         wclass.cbClsExtra    = 0;
  66.         wclass.cbWndExtra    = 2;
  67.         wclass.hInstance     = hInst;
  68.         wclass.hIcon         = 0;
  69.         wclass.hCursor       = 0;
  70.         wclass.hbrBackground = 0;
  71.         wclass.lpszMenuName  = 0;
  72.     wclass.lpszClassName = szClientClass;
  73.  
  74.         // Do not fail if register fails, because another app may have
  75.         // already registered this class.
  76.         RegisterClass(&wclass);
  77.  
  78.         // So we won't try to register again.
  79.         nClientClassRegistered = 1;
  80.     }
  81.  
  82.     // Create the window that will remain hidden but will carry on the
  83.     // conversation wih the dde server.
  84.     hChannel = CreateWindow(szClientClass,    // window class name
  85.                             NULL,             // window title
  86.                             WS_CHILD,         // window style
  87.                             CW_USEDEFAULT,    // window origin
  88.                             0,
  89.                             CW_USEDEFAULT,    // window size
  90.                             0,
  91.                             hParentWnd,       // window parent
  92.                 NULL,             // window id
  93.                             hInst,            // window instance
  94.                             NULL);            // no parms
  95.  
  96.     // If create of window failed we cannot continue
  97.     if (!hChannel)
  98.         return(0);
  99.  
  100.     // Create atoms representing application and topic we want to talk about
  101.     aApp = GlobalAddAtom(szApp);
  102.     if (!aApp)
  103.         return(0);
  104.  
  105.     aTopic = GlobalAddAtom(szTopic);
  106.     if (!aTopic)
  107.     {
  108.         GlobalDeleteAtom(aApp);
  109.         return(0);
  110.     }
  111.  
  112.     // Remember the last dde message we sent, because the window proc we
  113.     // just created must know the last message sent by this application
  114.     // to properly respond to a dde response.
  115.     wLastDDEClientMsg = WM_DDE_INITIATE;
  116.  
  117.     // Broadcast a dde initiate to all apps on this system to see if any
  118.     // will talk to us about the requested application and topic.
  119.     SendMessage(0xFFFF, wLastDDEClientMsg, hChannel, MAKELONG(aApp, aTopic));
  120.  
  121.     // Get rid of the atoms because we don't need them any more.
  122.     GlobalDeleteAtom(aApp);
  123.     GlobalDeleteAtom(aTopic);
  124.  
  125.     // If no acknowledgement from any apps on the system to our initiate
  126.     // message, no server will talk on the application and topic we requested.
  127.     if (!nAckFlg)
  128.     {
  129.         DestroyWindow(hChannel);
  130.         hChannel = 0;
  131.     }
  132.  
  133.     nAckFlg = 0;
  134.  
  135.     return(hChannel);
  136. }
  137.  
  138. //*******************************************************************
  139. // DDEClientClose - close the dde conversation with a server
  140. //
  141. // paramaters:
  142. //             hChannel      - The handle of the window conducting
  143. //                             the dde conversation.
  144. //
  145. //*******************************************************************
  146. void DDEClientClose(HWND hChannel)
  147. {
  148.     HWND hServerWnd;
  149.  
  150.     // If the channel is still active.
  151.     if (IsWindow(hChannel))
  152.     {
  153.         wLastDDEClientMsg = WM_DDE_TERMINATE;
  154.  
  155.         // Get handle of server we were conversing with.
  156.         hServerWnd = GetWindowWord(hChannel, WW_SERVER);
  157.  
  158.         // If he is still active.
  159.         if (IsWindow(hServerWnd))
  160.             SendMessage(hServerWnd, wLastDDEClientMsg, hChannel, 0L);
  161.     }
  162. }
  163.  
  164. //*******************************************************************
  165. // DDEExecute - request an action from server
  166. //
  167. // paramaters:
  168. //             hChannel      - The handle of the window conducting
  169. //                             the dde conversation.
  170. //             lpszCommand   - The command string to send to the
  171. //                             dde server.
  172. //             nWait         - The time to wait for a response to the
  173. //                             command.  If zero, will return immediatly.
  174. //
  175. // returns:
  176. //             1 - successful transmission.
  177. //             0 - error.
  178. //
  179. //*******************************************************************
  180. int DDEExecute(HWND hChannel, LPSTR lpszCommand, int nWait)
  181. {
  182.     int          len;
  183.     HANDLE       hCommand;
  184.     HWND         hServerWnd;
  185.     LPSTR        lpCommand;
  186.     int          nRc;
  187.  
  188.     nRc = 0;
  189.  
  190.     // Get the handle of server we were talking to.
  191.     hServerWnd = GetWindowWord(hChannel, WW_SERVER);
  192.  
  193.     // If he is no longer active we can't talk to him.
  194.     if (!IsWindow(hServerWnd))
  195.         return(nRc);
  196.  
  197.     // Get shared memory to put our request to server in.
  198.     len = _fstrlen(lpszCommand);
  199.     hCommand = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_DDESHARE,
  200.                            (DWORD) (len + 1));
  201.     if (hCommand)
  202.     {
  203.         // Lock it down to get address of memory.
  204.         lpCommand = GlobalLock(hCommand);
  205.         if (lpCommand)
  206.         {
  207.             // Copy the command into the shared memory.
  208.             _fstrcpy(lpCommand, lpszCommand);
  209.             GlobalUnlock(hCommand);
  210.  
  211.             // Post the message to the server.
  212.             wLastDDEClientMsg = WM_DDE_EXECUTE;
  213.             if (!PostMessage(hServerWnd, wLastDDEClientMsg, hChannel,
  214.                              MAKELONG(0, hCommand)))
  215.             {
  216.                 // If post failed.
  217.                 GlobalFree(hCommand);
  218.             }
  219.             else
  220.             {
  221.                 nRc = 1;
  222.         nAckFlg = 0;
  223.  
  224.                 // Wait if caller told us to.
  225.                 if (nWait)
  226.                     nRc = DDEWait(hChannel, nWait);
  227.             }
  228.         }
  229.     }
  230.  
  231.     nAckFlg = 0;
  232.  
  233.     return(nRc);
  234. }
  235.  
  236. //*******************************************************************
  237. // DDERead - read some data from the server
  238. //
  239. // paramaters:
  240. //             hChannel      - The handle of the window conducting
  241. //                             the dde conversation.
  242. //             szItem        - The item to get from server.
  243. //
  244. // returns:
  245. //             Global Handle - of item requested if successful.
  246. //               or
  247. //             0 - if error.
  248. //
  249. //*******************************************************************
  250. HANDLE DDERead(HWND hChannel, char *szItem, int nWait)
  251. {
  252.     HWND         hServerWnd;
  253.     DDEDATA FAR *lpData;
  254.     int          nReleaseFlg;
  255.     HANDLE       hOurData;
  256.     LPSTR        lpOurData;
  257.     ATOM         aItem;
  258.     int          len;
  259.  
  260.     hOurData = 0;
  261.  
  262.     // Get the handle of server we were talking to.
  263.     hServerWnd = GetWindowWord(hChannel, WW_SERVER);
  264.  
  265.     // If he is no longer active we can't talk to him.
  266.     if (!IsWindow(hServerWnd))
  267.         return(hOurData);
  268.  
  269.     // Create an atom representing the data item we want read.
  270.     aItem = GlobalAddAtom(szItem);
  271.     hData = 0;
  272.  
  273.     // Post the request to the server.
  274.     wLastDDEClientMsg = WM_DDE_REQUEST;
  275.     PostMessage(hServerWnd, wLastDDEClientMsg, hChannel,
  276.                 MAKELONG(CF_TEXT, aItem));
  277.  
  278.     // Wait for a dde message in response or time to expire.
  279.     DDEWait(hChannel, nWait);
  280.  
  281.     // If we have a handle to returned data.
  282.     if (hData)
  283.     {
  284.         // Lock it down to get address.
  285.         lpData = (DDEDATA FAR *) GlobalLock(hData);
  286.         if (lpData)
  287.         {
  288.             // Remember release flag to see if we release or server releases.
  289.             nReleaseFlg = lpData->fRelease;
  290.  
  291.             // Get memory for our local copy of data.
  292.             len = _fstrlen(lpData->Value);
  293.             hOurData = GlobalAlloc(GMEM_MOVEABLE, (DWORD) (len + 1));
  294.             if (hOurData)
  295.             {
  296.                 // Lock it down to get address.
  297.                 lpOurData = GlobalLock(hOurData);
  298.                 if (lpOurData)
  299.                 {
  300.                     // Copy it in.
  301.                     _fstrcpy(lpOurData, lpData->Value);
  302.             GlobalUnlock(hOurData);
  303.                 }
  304.                 else
  305.                     hOurData = 0;
  306.             }
  307.  
  308.             GlobalUnlock(hData);
  309.         }
  310.  
  311.         // If server requested that we free shared memory.
  312.         if (nReleaseFlg)
  313.             GlobalFree(hData);
  314.     }
  315.  
  316.     // Return handle to our copy of data.
  317.     return(hOurData);
  318. }
  319.  
  320. //*******************************************************************
  321. // DDEWait - wait up to time for a dde messag
  322. //
  323. // paramaters:
  324. //             hChannel      - The handle of the window conducting
  325. //                             the dde conversation.
  326. //             nWait         - Length of time to wait for a dde msesage
  327. //                             in seconds.
  328. //
  329. // returns:
  330. //             1 - dde message recieved while waiting.
  331. //               or
  332. //             0 - time expired and no dde messages recieved.
  333. //
  334. //*******************************************************************
  335. int DDEWait(HWND hChannel, int nWait)
  336. {
  337.     time_t  t1;
  338.     time_t  t2;
  339.     int     nGotDDEMsg;
  340.     MSG     msg;
  341.  
  342.     time(&t1);
  343.     nGotDDEMsg = 0;
  344.  
  345.     do
  346.     {
  347.         if (PeekMessage(&msg, hChannel, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE))
  348.         {
  349.             DispatchMessage(&msg);
  350.             nGotDDEMsg = 1;
  351.         }
  352.     }
  353.     while (!nGotDDEMsg && ((time(&t2) - t1) < nWait));
  354.  
  355.     return(nGotDDEMsg);
  356. }
  357.  
  358. //*******************************************************************
  359. // DDESleep - wait for a time
  360. //
  361. // paramaters:
  362. //             nWait         - Length of time to wait in seconds
  363. //
  364. //*******************************************************************
  365. void DDESleep(int nWait)
  366. {
  367.     time_t  t1;
  368.     time_t  t2;
  369.     MSG     msg;
  370.  
  371.     time(&t1);
  372.  
  373.     do
  374.     {
  375.         PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
  376.     }
  377.     while ((time(&t2) - t1) < nWait);
  378. }
  379.  
  380. //*******************************************************************
  381. // DDEClientWndProc - window proc to manage interface with server
  382. //
  383. // paramaters:
  384. //             hWnd          - The window handle for this message
  385. //             message       - The message number
  386. //             wParam        - The WORD parmater for this message
  387. //             lParam        - The LONG parmater for this message
  388. //
  389. // returns:
  390. //             depends on message.
  391. //
  392. //*******************************************************************
  393. LONG FAR PASCAL DDEClientWndProc(HWND hWnd, WORD message,
  394.                                  WORD wParam, LONG lParam)
  395. {
  396.     HWND   hServerWnd;
  397.     WORD   wStatus;
  398.  
  399.     switch (message)
  400.     {
  401.         case WM_CREATE:              // create this window
  402.         // We will remember the handle of the server we are conversing
  403.             // with in the first extra window word, but for now we do not
  404.             // have a server.
  405.             SetWindowWord(hWnd, WW_SERVER, 0);
  406.             break;
  407.  
  408.         case WM_DDE_ACK:             // an ack from a server
  409.             switch (wLastDDEClientMsg)
  410.             {
  411.                 case WM_DDE_INITIATE:  // ack in response to initiate
  412.                     // Get rid of application and topic atoms used in
  413.                     // initiate request.
  414.                     GlobalDeleteAtom(LOWORD(lParam));
  415.                     GlobalDeleteAtom(HIWORD(lParam));
  416.  
  417.                     // Now we have a server for this conversation, so remember
  418.                     // who it is.
  419.                     SetWindowWord(hWnd, WW_SERVER, wParam);
  420.                     nAckFlg = 1;
  421.                     break;
  422.  
  423.                 case WM_DDE_EXECUTE:   // ack in response to execute
  424.                     // Server acknowledged our execute command.
  425.                     wStatus = LOWORD(lParam);
  426.                     nAckFlg = wStatus & ACK;
  427.                     if (!nAckFlg)
  428.                         nBusyFlg = wStatus & BUSY;
  429.                     GlobalFree(HIWORD(lParam));
  430.                     break;
  431.  
  432.                 case WM_DDE_REQUEST:   // ack in response to request
  433.                     // Get rid of item atom used in request.
  434.                     GlobalDeleteAtom(HIWORD(lParam));
  435.                     wStatus = LOWORD(lParam);
  436.                     nAckFlg = wStatus & ACK;
  437.                     if (!nAckFlg)
  438.                         nBusyFlg = wStatus & BUSY;
  439.                     break;
  440.             }
  441.             break;
  442.  
  443.         case WM_DDE_DATA:            // data from a server per request
  444.             // Get rid of item atom used in request.
  445.             GlobalDeleteAtom(HIWORD(lParam));
  446.  
  447.             // Save handle to global data item returned.
  448.             hData = LOWORD(lParam);
  449.             break;
  450.  
  451.         case WM_DDE_TERMINATE:      // server says terminate conversation
  452.             // Get handle of server we are dealing with.
  453.             hServerWnd = GetWindowWord(hWnd, WW_SERVER);
  454.  
  455.             // Ignore if this terminate is not from that server.
  456.             if (wParam != hServerWnd)
  457.                 return(0L);
  458.  
  459.             // Forget who server is.
  460.             SetWindowWord(hWnd, WW_SERVER, 0);
  461.  
  462.         // Tell our parent conversation with server is closed.
  463.             SendMessage(GetParent(hWnd), WMU_DDE_CLOSED, hWnd, 0L);
  464.  
  465.             // Send terminate to server to acknowledge we recieved
  466.             // terminate,  if we did not initiate the termination ourselves.
  467.             if ((wLastDDEClientMsg != WM_DDE_TERMINATE) && IsWindow(hServerWnd))
  468.                 PostMessage(hServerWnd, WM_DDE_TERMINATE, hWnd, 0L);
  469.  
  470.             // Terminate this child window.
  471.             DestroyWindow(hWnd);
  472.             break;
  473.  
  474.         case WM_DESTROY:            // destroy this window
  475.             // Terminate any ongoing conversation on our way out.
  476.             DDEClientClose(hWnd);
  477.             break;
  478.  
  479.         default:
  480.             return(DefWindowProc(hWnd, message, wParam, lParam));
  481.     }
  482.  
  483.     return(0L);
  484. }
  485.  
  486. //*******************************************************************
  487.