home *** CD-ROM | disk | FTP | other *** search
- // ObjectWindows - (C) Copyright 1992 by Borland International
- //
- // ddesvr.cpp
-
- /*
- * This is a sample application using the OWL library that demonstrats the
- * use of the Windows 3.1 DDEML API in a server application. You should
- * first build this application and run it. Run the client application,
- * DDECLI.EXE, to start a conversation with this Server. Detailed
- * information on DDEML can found in the online help and is suggested
- * reading for anyone interested in writing DDEML applications. Search on
- * the keyword DDEML.
- */
-
- #include "ddesvr.h"
-
- PTDMLSrWnd pStaticThis = NULL;
-
- TDMLSrApp::TDMLSrApp( LPSTR lpszNam, HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLn, int nCmdShw )
- : TApplication( lpszNam, hInst, hPrevInst, lpszCmdLn, nCmdShw )
- {
- nCmdShow = SW_SHOWMINIMIZED;
- }
-
- TDMLSrApp::~TDMLSrApp()
- {
- }
-
- void TDMLSrApp::InitMainWindow()
- {
- MainWindow = new TDMLSrWnd( NULL, "DDESVR (A DDE Server)" );
- }
-
- /*
- There are 16 available timers in Windows. This little trick uses the
- OWL IdleAction() member function to save that scarce resource.
- */
- void TDMLSrApp::IdleAction()
- {
- static DWORD dwTime = GetTickCount();
-
- if( (MainWindow != NULL) && (((PTDMLSrWnd)MainWindow)->tfLoop == TRUE) )
- {
- if( (GetTickCount() - dwTime) > 1000 )
- {
- dwTime = GetTickCount(); ((PTDMLSrWnd)MainWindow)->UpdateData();
- }
- }
- }
-
- TDMLSrWnd::TDMLSrWnd( PTWindowsObject AParent, LPSTR ATitle )
- : TWindow( AParent, ATitle )
- {
- }
-
- TDMLSrWnd::~TDMLSrWnd()
- {
- /*
- * This clean up is required for those resources that were allocated during the
- * DDE conversation.
- */
- if( hConv != 0 )
- {
- DdeDisconnect( hConv ); // Let the other party know we are leaving
- hConv = 0;
- }
- if( idInst != 0 )
- {
- DdeNameService( idInst, hszService, NULL, DNS_UNREGISTER );
- if( hszService != NULL )
- {
- DdeFreeStringHandle( idInst, hszService );
- hszService = NULL;
- }
- if( hszTopic != NULL )
- {
- DdeFreeStringHandle( idInst, hszTopic );
- hszTopic = NULL;
- }
- if( hszItem != NULL )
- {
- DdeFreeStringHandle( idInst, hszItem );
- hszItem = NULL;
- }
- DdeUninitialize(idInst);
- idInst = 0;
- }
- if( lpfnCallBack != NULL )
- {
- FreeProcInstance( lpfnCallBack );
- lpfnCallBack = NULL;
- }
- }
-
- void TDMLSrWnd::SetupWindow()
- {
- HMENU hMenu;
-
- pStaticThis = this;
- idInst = 0;
- hConv = 0;
- tfLoop = FALSE;
- hszService = hszTopic = hszItem = 0;
- /*
- * The code below sets up the DDE call back function that is used by the
- * DDE Management Library to carry out data transfers between applications.
- */
- lpfnCallBack = MakeProcInstance( (FARPROC)TDMLSrWnd::CallBack, GetApplication()->hInstance );
- if( lpfnCallBack != NULL )
- {
- if( DdeInitialize( &idInst, (PFNCALLBACK)lpfnCallBack, 0, 0L ) == DMLERR_NO_ERROR )
- {
- /*
- * The strings below are the 'Service', 'Topic' and 'Item' identifiers that
- * this application makes available, through DDE, to other applications.
- */
- hszService = DdeCreateStringHandle( idInst, "TDMLSR_Server", CP_WINANSI );
- hszTopic = DdeCreateStringHandle( idInst, "Borland", CP_WINANSI );
- hszItem = DdeCreateStringHandle( idInst, "Products", CP_WINANSI );
- if( (hszService != NULL) && (hszTopic != NULL) && (hszItem != NULL) )
- {
- if( DdeNameService( idInst, hszService, NULL, DNS_REGISTER ) != 0 )
- {
- // If everything is successful then an About choice is added to the system menu.
- hMenu = GetSystemMenu( HWindow, 0 );
- AppendMenu( hMenu, MF_BYCOMMAND | MF_SEPARATOR, -1, "" );
- AppendMenu( hMenu, MF_BYCOMMAND | MF_STRING, CM_U_ABOUT, "&About DDESVR" );
- } else {
- MessageBox( HWindow, "Registration failed.", Title, MB_ICONSTOP );
- PostQuitMessage( 0 );
- }
- } else {
- MessageBox( HWindow, "String creation failed.", Title, MB_ICONSTOP );
- PostQuitMessage( 0 );
- }
- } else {
- MessageBox( HWindow, "Initialization failed.", Title, MB_ICONSTOP );
- PostQuitMessage( 0 );
- }
- } else {
- MessageBox( HWindow, "Setup of callback failed.", Title, MB_ICONSTOP );
- PostQuitMessage( 0 );
- }
- }
-
- /*
- The code below is used to trap the About menu choice when it is selected
- from the system menu.
- */
- void TDMLSrWnd::WMSysCommand( RTMessage Msg )
- {
- if( (Msg.WParam & 0xFFF0) == CM_U_ABOUT )
- {
- MessageBox( HWindow, "DDESVR.EXE\nWritten using ObjectWindows\nCopyright (c) 1992 by Borland International", "About DDESVR", MB_ICONINFORMATION );
- } else {
- DefWndProc( Msg );
- }
- }
-
- /*
- This seemingly insignificant function is what keeps this program
- minimized, no matter what the user might try to do.
- */
- void TDMLSrWnd::WMQueryOpen( RTMessage Msg )
- {
- Msg.Result = 0;
- }
-
- /*
- This function is used to compare incoming Topic and Service requests.
- This example DDE Server only makes one Service and one Topic available
- so the logic is simple for this case but could be more complex for
- Servers that offer multiple Services or Topics.
- */
- BOOL TDMLSrWnd::MatchTopicAndService( HSZ hsz1, HSZ hsz2 )
- {
- if( DdeCmpStringHandles( hszTopic, hsz1 ) == 0 )
- {
- if( DdeCmpStringHandles( hszService, hsz2 ) == 0 )
- {
- return TRUE;
- }
- }
- return FALSE;
- }
-
- /*
- This function is used to compare incoming Topic and Item pair requests.
- This Server only makes one Topic with one Item available so the logic is
- simple for this case but could be more complex if the Server offered
- multiple Items for multiple Topics.
- */
- BOOL TDMLSrWnd::MatchTopicAndItem( HSZ hsz1, HSZ hsz2 )
- {
- if( DdeCmpStringHandles( hszTopic, hsz1 ) == 0 )
- {
- if( DdeCmpStringHandles( hszItem, hsz2 ) == 0 )
- {
- return TRUE;
- }
- }
- return FALSE;
- }
-
- /*
- This function responds to 'system wide' polling of any available
- Services with specific Topics, any Topics with specific Services or any
- Services with any Topics. It simply replies with a match, if there is
- one, so that the polling application can open data discussions later, if
- desired.
- */
- HDDEDATA TDMLSrWnd::WildConnect( HSZ hsz1, HSZ hsz2, WORD wFmt )
- {
- HSZPAIR hszpTemp[] = { { hszService, hszTopic }, { 0, 0 } };
-
- if( (hsz1 == NULL) && (hsz2 == NULL) ) // Returns all if true
- {
- return DdeCreateDataHandle( idInst, (LPBYTE)&hszpTemp[0], sizeof( hszpTemp ), 0L, 0, wFmt, 0 );
- }
- if( (hsz1 == NULL) && (DdeCmpStringHandles( hsz2, hszService ) == 0) )
- {
- return DdeCreateDataHandle( idInst, (LPBYTE)&hszpTemp[0], sizeof( hszpTemp ), 0L, 0, wFmt, 0 );
- }
- if( (DdeCmpStringHandles( hsz1, hszTopic) == 0) && (hsz2 == NULL) )
- {
- return DdeCreateDataHandle( idInst, (LPBYTE)&hszpTemp[0], sizeof( hszpTemp ), 0L, 0, wFmt, 0 );
- }
- return NULL;
- }
-
- HDDEDATA TDMLSrWnd::DataRequested( WORD wFmt )
- {
- static int iLoop = 0; // Loop counter for the array below
- static char szItems[][42] =
- {
- "Borland C++",
- "Turbo C++",
- "Turbo Pascal",
- "ObjectVision",
- "Paradox",
- "dBase",
- "Quattro Pro",
- "Brief",
- "Borland Version Control"
- };
-
- if( wFmt == CF_TEXT )
- {
- iLoop++;
- iLoop %= (sizeof( szItems ) / sizeof( szItems[0] ));
- return DdeCreateDataHandle( idInst, &szItems[iLoop], sizeof( szItems[iLoop] ), 0, hszItem, wFmt, 0 );
- }
- return NULL;
- }
-
- /*
- This is triggered by the IdleAction() loop above whenever the user
- enters an advise loop.
- */
- void TDMLSrWnd::UpdateData( void )
- {
- DdePostAdvise( idInst, hszTopic, hszItem );
- }
-
- /*
- This call back function is the heart of interaction between this program
- and DDE. Because Windows doesn't pass C++ 'this' pointers to call
- back functions, a static 'this' pointer was used. If you wanted to
- create a Server that would allow for more than one conversation, using a
- List of conversations and their associated 'this' pointers would be one
- possible method to try. The XTYP_ constants are described in detail in
- the online help.
- */
-
- HDDEDATA FAR PASCAL TDMLSrWnd::CallBack( WORD wType, WORD wFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD, DWORD )
- {
- char szTemp[128];
- int iSize;
-
- switch( wType )
- {
- case XTYP_ADVREQ :
- if( pStaticThis->MatchTopicAndItem( hsz1, hsz2 ) == TRUE )
- {
- return pStaticThis->DataRequested( wFmt );
- }
- return NULL;
- case XTYP_ADVSTART :
- if( (pStaticThis->tfLoop == FALSE) && (pStaticThis->MatchTopicAndItem( hsz1, hsz2 ) == TRUE) )
- {
- pStaticThis->tfLoop = TRUE;
- return (HDDEDATA)1;
- } else {
- return 0;
- }
- case XTYP_ADVSTOP :
- if( (pStaticThis->tfLoop == TRUE) && (pStaticThis->MatchTopicAndItem( hsz1, hsz2 ) == TRUE) )
- {
- pStaticThis->tfLoop = FALSE;
- }
- break;
- case XTYP_CONNECT :
- if( pStaticThis->hConv == 0 )
- {
- if( pStaticThis->MatchTopicAndService( hsz1, hsz2 ) == TRUE )
- {
- return (HDDEDATA)1;
- }
- }
- return 0;
- case XTYP_CONNECT_CONFIRM :
- pStaticThis->hConv = hConv;
- break;
- case XTYP_DISCONNECT :
- if( hConv == pStaticThis->hConv )
- {
- pStaticThis->hConv = 0;
- pStaticThis->tfLoop = FALSE;
- }
- break;
- case XTYP_ERROR :
- MessageBox( pStaticThis->HWindow, "A critical DDE error has occured.", pStaticThis->Title, MB_ICONINFORMATION );
- break;
- case XTYP_EXECUTE :
- return DDE_FNOTPROCESSED;
- case XTYP_POKE :
- wsprintf( szTemp, "The server received : " );
- iSize = strlen( szTemp );
- DdeGetData( hData, &szTemp[iSize], (sizeof( szTemp ) - iSize), 0 );
- MessageBox( GetFocus(), szTemp, pStaticThis->Title, MB_ICONINFORMATION );
- return (HDDEDATA)DDE_FACK;
- case XTYP_REQUEST :
- if( pStaticThis->MatchTopicAndItem( hsz1, hsz2 ) == TRUE )
- {
- return pStaticThis->DataRequested( wFmt );
- }
- return NULL;
- case XTYP_WILDCONNECT :
- return pStaticThis->WildConnect( hsz1, hsz2, wFmt );
- default :
- break;
- }
- return NULL;
- }
-
- int PASCAL WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLn, int nCmdShw )
- {
- TDMLSrApp App( "DDESVR Application", hInst, hPrevInst, lpszCmdLn, nCmdShw );
-
- App.Run();
- return App.Status;
- }
-