home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 6.ddi / DDEML.ZIP / DDECLI.CPP next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  8.4 KB  |  256 lines

  1. // ObjectWindows - (C) Copyright 1992 by Borland International
  2. //
  3. // ddecli.cpp
  4.  
  5. /*
  6.  * This is a sample application using the OWL library that demonstrats the
  7.  * use of the Windows 3.1 DDEML API in a client application.  You should
  8.  * first build the server application, DDESVR.EXE, and run it.  Then run the
  9.  * client application, DDECLI.EXE, to start a conversation.  Detailed
  10.  * information on DDEML can found in the online help and is suggested
  11.  * reading for anyone interested in writing DDEML applications.  Search on
  12.  * the keyword DDEML.
  13. */
  14.  
  15. #include "ddecli.h"
  16.  
  17. PTDMLClWnd pStaticThis = NULL;
  18.  
  19. TDMLClApp::TDMLClApp( LPSTR lpszNam, HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLn, int nCmdShw )
  20.     : TApplication( lpszNam, hInst, hPrevInst, lpszCmdLn, nCmdShw )
  21. {
  22. }
  23.  
  24. TDMLClApp::~TDMLClApp()
  25. {
  26. }
  27.  
  28. void TDMLClApp::InitMainWindow()
  29. {
  30.     MainWindow = new TDMLClWnd( NULL, "DDECLI (A DDE Client)" );
  31. }
  32.  
  33. TDMLClWnd::TDMLClWnd( PTWindowsObject AParent, LPSTR ATitle )
  34.     : TWindow( AParent, ATitle )
  35. {
  36. }
  37.  
  38. TDMLClWnd::~TDMLClWnd()
  39. {
  40. /*
  41.  * This clean up is required for those resources that were allocated during the
  42.  * DDEML conversation.
  43. */
  44.     if( hConv != 0 )
  45.     {
  46.         DdeDisconnect( hConv );     // Let the other party know we are leaving
  47.         hConv = 0;
  48.     }
  49.     if( idInst != 0 )
  50.     {
  51.         DdeFreeStringHandle( idInst, hszService );
  52.         DdeFreeStringHandle( idInst, hszTopic );
  53.         DdeFreeStringHandle( idInst, hszItem );
  54.         DdeUninitialize(idInst);
  55.         idInst = 0;
  56.     }
  57.     if( lpCallBack != NULL )
  58.     {
  59.         FreeProcInstance( (FARPROC)lpCallBack );
  60.         lpCallBack = NULL;
  61.     }
  62. }
  63.  
  64. void TDMLClWnd::SetupWindow()
  65. {
  66.     AssignMenu( TDMLClWnd_MENU );
  67.     pStaticThis = this;
  68.     idInst = 0;         // MUST be 0 the first time DdeInitialize() is called!
  69.     hConv = 0;
  70.     tfLoop = 0;
  71.     szData[0] = '\0';
  72.     hszService = hszTopic = hszItem = 0;
  73. /*
  74.  * The code below sets up the DDEML call back function that is used by the
  75.  * DDE Management Library to carry out data transfers between applications.
  76. */
  77.     lpCallBack = MakeProcInstance( (FARPROC)TDMLClWnd::CallBack, GetApplication()->hInstance );
  78.     if( lpCallBack != NULL )
  79.     {
  80.         if( DdeInitialize( &idInst, (PFNCALLBACK)lpCallBack, APPCMD_CLIENTONLY, 0 ) == DMLERR_NO_ERROR )
  81.         {
  82.             hszService = DdeCreateStringHandle( idInst, "TDMLSR_Server", CP_WINANSI );
  83.             hszTopic = DdeCreateStringHandle( idInst, "Borland", CP_WINANSI );
  84.             hszItem = DdeCreateStringHandle( idInst, "Products", CP_WINANSI );
  85.             if( (hszService == NULL) || (hszTopic == NULL) || (hszItem == NULL) )
  86.             {
  87.                 MessageBox( HWindow, "Creation of strings failed.", Title, MB_ICONSTOP );
  88.                 PostQuitMessage( 0 );
  89.             }
  90.         } else {
  91.             MessageBox( HWindow, "Initialization failed.", Title, MB_ICONSTOP );
  92.             PostQuitMessage( 0 );
  93.         }
  94.     } else {
  95.         MessageBox( HWindow, "Setup of callback failed.", Title, MB_ICONSTOP );
  96.         PostQuitMessage( 0 );
  97.     }
  98. }
  99.  
  100. void TDMLClWnd::Paint( HDC hdc, PAINTSTRUCT _FAR & )
  101. {
  102.     RECT rTemp;
  103.     char szTemp[] = "This example of the Dynamic Data Exchange Management \
  104. Library obtains the names of various Borland products from the server \
  105. DDESVR.EXE. To get started, first run DDESVR.EXE and then select the \"Connect!\" menu item.";
  106.  
  107.     GetClientRect( HWindow, &rTemp );
  108.     if( szData[0] != '\0' )
  109.     {
  110. // The szData string is obtained from the DDESVR.EXE DDE Server.
  111.         DrawText( hdc, szData, strlen( szData ), &rTemp, DT_SINGLELINE | DT_CENTER | DT_VCENTER );
  112.     } else {
  113.         DrawText( hdc, szTemp, strlen( szTemp ), &rTemp, DT_WORDBREAK );
  114.     }
  115. }
  116.  
  117. void TDMLClWnd::CMExit( RTMessage Msg )
  118. {
  119.     TWindow::CMExit( Msg );
  120. }
  121.  
  122. void TDMLClWnd::WMInitMenu( RTMessage Msg )
  123. {
  124.     HMENU hmTemp;
  125.  
  126. /*
  127. This trick is used to automatically update the status of the various
  128. menu choices just before it is displayed.
  129. */
  130.     hmTemp = (HMENU)Msg.WParam;
  131.     EnableMenuItem( hmTemp, CM_U_CONNECT, ( hConv == 0 )? MF_ENABLED : MF_GRAYED );
  132.     EnableMenuItem( hmTemp, CM_U_REQUEST, ( hConv != 0 )? MF_ENABLED : MF_GRAYED );
  133.     EnableMenuItem( hmTemp, CM_U_POKE, ( hConv != 0 )? MF_ENABLED : MF_GRAYED );
  134.     EnableMenuItem( hmTemp, CM_U_ADVISE, ( hConv != 0 )? MF_ENABLED : MF_GRAYED );
  135.     CheckMenuItem( hmTemp, CM_U_ADVISE, MF_BYCOMMAND | ( tfLoop == TRUE )? MF_CHECKED : MF_UNCHECKED );
  136.     DrawMenuBar( HWindow );
  137. }
  138.  
  139. // The following 4 functions are used to communicate with DDE Server(s).
  140.  
  141. void TDMLClWnd::CMUConnect( RTMessage )
  142. {
  143.     hConv = DdeConnect( idInst, hszService, hszTopic, NULL );
  144.     if( hConv != 0 )
  145.     {
  146.         PostMessage( HWindow, WM_INITMENU, (WPARAM)GetMenu( HWindow ), 0 );
  147.     } else {
  148.         MessageBox( HWindow, "Can't start conversation.\nTry running DDESVR (the server).", Title, MB_ICONSTOP );
  149.     }
  150. }
  151.  
  152. void TDMLClWnd::CMURequest( RTMessage )
  153. {
  154.     HDDEDATA hData;
  155.  
  156.     hData = DdeClientTransaction( NULL, 0, hConv, hszItem, CF_TEXT, XTYP_REQUEST, 0, NULL );
  157.     if( hData != FALSE ) ReceivedData( hData );
  158. }
  159.  
  160. void TDMLClWnd::CMUPoke( RTMessage )
  161. {
  162.     char szTemp[42] = "";
  163.  
  164.     if( GetApplication()->ExecDialog( new TInputDialog( this, Title, "Poke string : ", szTemp, sizeof( szTemp ) ) ) == IDOK )
  165.     {
  166.         DdeClientTransaction( (LPBYTE)szTemp, strlen( szTemp ) + 1, hConv, hszItem, CF_TEXT, XTYP_POKE, 1000, NULL );
  167.     }
  168. }
  169.  
  170. void TDMLClWnd::CMUAdvise( RTMessage Msg )
  171. {
  172.     HMENU hTempMenu;
  173.     DWORD dwTempResult;
  174.  
  175.     hTempMenu = GetMenu( HWindow );
  176.     if( GetMenuState( hTempMenu, Msg.WParam, MF_BYCOMMAND ) == MF_UNCHECKED )
  177.     {
  178.         if( (BOOL)DdeClientTransaction( NULL, 0, hConv, hszItem, CF_TEXT, XTYP_ADVSTART | XTYPF_ACKREQ, 1000, &dwTempResult ) == TRUE )
  179.         {
  180.             CheckMenuItem( hTempMenu, Msg.WParam, MF_BYCOMMAND | MF_CHECKED );
  181.             tfLoop = TRUE;
  182.         }
  183.     } else {
  184.         if( (BOOL)DdeClientTransaction( NULL, 0, hConv, hszItem, CF_TEXT, XTYP_ADVSTOP, 1000, &dwTempResult ) == TRUE )
  185.         {
  186.             CheckMenuItem( hTempMenu, Msg.WParam, MF_BYCOMMAND | MF_UNCHECKED );
  187.             tfLoop = FALSE;
  188.         }
  189.     }
  190.     DrawMenuBar( HWindow );
  191. }
  192.  
  193. void TDMLClWnd::CMUHelpAbout( RTMessage )
  194. {
  195.     MessageBox( HWindow, "DDECLI.EXE\nWritten using ObjectWindows\nCopyright (c) 1992 by Borland International", "About DDECLI", MB_ICONINFORMATION );
  196. }
  197.  
  198. void TDMLClWnd::ReceivedData( HDDEDATA hData )
  199. {
  200. /*
  201. This function is called when the callback function is notified of
  202. available data.
  203. */
  204.     if( hData != NULL )
  205.     {
  206.         DdeGetData( hData, &szData, sizeof( szData ), 0 );
  207.         InvalidateRect( HWindow, NULL, TRUE );
  208.     }
  209. }
  210.  
  211. /*
  212. This call back function is the heart of interaction between this program
  213. and DDEML.  Because Windows doesn't pass C++ 'this' pointers to call
  214. back functions, a static 'this' pointer was used.  If you wanted to
  215. create a Client that would allow for more than one conversation, using a
  216. List of conversations and their associated 'this' pointers would be one
  217. possible method to try.  The XTYP_ constants are described in detail in
  218. the online help.
  219. */
  220. HDDEDATA FAR PASCAL _export TDMLClWnd::CallBack( WORD wType, WORD, HCONV hConv, HSZ, HSZ, HDDEDATA hData, DWORD, DWORD )
  221. {
  222.     switch( wType )
  223.     {
  224.         case XTYP_ADVDATA :
  225.             if( hConv == pStaticThis->hConv )
  226.             {
  227.                 pStaticThis->ReceivedData( hData );
  228.             }
  229.             return (HDDEDATA)DDE_FACK;
  230.         case XTYP_XACT_COMPLETE :
  231.             if( hConv == pStaticThis->hConv ) pStaticThis->ReceivedData( hData );
  232.             break;
  233.         case XTYP_DISCONNECT :
  234.             MessageBox( pStaticThis->HWindow, "Disconnected.", pStaticThis->Title, MB_ICONINFORMATION );
  235.             pStaticThis->hConv = 0;
  236.             pStaticThis->tfLoop = 0;
  237.             PostMessage( pStaticThis->HWindow, WM_INITMENU, (WPARAM)GetMenu( pStaticThis->HWindow ), 0 );
  238.             break;
  239.         case XTYP_ERROR :
  240.             MessageBox( pStaticThis->HWindow, "A critical DDE error has occured.", pStaticThis->Title, MB_ICONINFORMATION );
  241.             break;
  242.         default :
  243.             break;
  244.     }
  245.     return NULL;
  246. }
  247.  
  248. int PASCAL WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLn, int nCmdShw )
  249. {
  250.     TDMLClApp App( "DDECLI Application", hInst, hPrevInst, lpszCmdLn, nCmdShw );
  251.  
  252.     App.Run();
  253.     return App.Status;
  254. }
  255.  
  256.