home *** CD-ROM | disk | FTP | other *** search
- /*
-
- EDIT.C -- Sample Application DDE Server
- Copyright 1987-1991 Authorware Inc.
-
- Revision History
-
- 7/25/91 - Initial version
-
-
- General notes:
-
- This application is a sample server application for demonstrating a
- DDE converstation with APW. The server only handles cold link DDE
- communication.
-
- The application name is APWServer
- The topic name is EditInfo
- The item name is EI
-
- This is the only topic and item supported by this server. The data that
- is generated by this request is the text from the edit control which
- covers the client area of the main window. The server can handle
- multiple clients at one time (each DDE link is given its own window and
- the client window handle is stored in the extra bytes at the end of
- the window handle).
-
- For information on DDE see:
-
- Microsoft (R) Windows SDK 3.0
- Reference Manual Volume 2
-
- Programming for Windows by Charles Petzold
- Microsoft Press (R)
- Second Edition.
-
- */
- #include <string.h>
- #include "windows.h"
- #include "dde.h"
- #include "edit.h"
-
- #define DDE_TIMEOUT 3000
-
- // Defines for cbWndExtra bytes on the window class.
- #define CLIENTWND 0 // Handle to the client window
-
- #define VALID_WINDOW(w) ((w) && IsWindow(w)) // Make NULL an invalid window
-
- // Static globals
- static char szServerClass[] = "edit.server"; // class name
- static char szMenu[] = "EditCntlMenu"; // menu name
- static HANDLE hInst = 0; // instance handle
- static HWND hEditWnd = 0; // handle to edit window
- static HWND hWndMain = 0; // handle to main window
-
-
- // Server Communication variables for the APPLICATION, TOPIC and ITEM supported
- static char APWServer[] = "APWServer";
- static char szTopic[] = "EditInfo";
- static char szItem[] = "EI";
-
- static BOOL NEAR PASCAL DDERequest( HWND server, HWND client, WORD cfFormat, ATOM aItem );
- static BOOL NEAR PASCAL DDEInitialize( HWND parent, HWND client, ATOM a, ATOM t );
- static BOOL NEAR PASCAL DDEPostDataMessage(HWND server, HWND client );
- static BOOL NEAR PASCAL InitInstance( HANDLE hInstance, short nCmdShow );
- static BOOL NEAR PASCAL InitApplication( HANDLE hInstance );
- long FAR PASCAL ServerProc( HWND hWnd, WORD message, WORD wParam, LONG lParam );
- BOOL FAR PASCAL About( HWND hDlg, unsigned message, WORD wParam, LONG lParam);
- long FAR PASCAL MainWndProc( HWND hWnd, unsigned message, WORD wParam, LONG lParam);
- int FAR PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, short nCmdShow);
-
-
- int FAR PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, short nCmdShow)
- /*
- Application entry point. Does initialization and the main event loop.
- */
- {
- MSG msg;
- FARPROC fp;
-
- // Initialize only for the first instance
- if (!hPrevInstance)
- if (!InitApplication(hInstance))
- return 0;
-
- // Initialize every instance
- if (!InitInstance(hInstance, nCmdShow))
- return 0;
-
- // Main message loop
- while (GetMessage(&msg, NULL, NULL, NULL))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- return msg.wParam;
- }
-
-
- static BOOL NEAR PASCAL InitApplication( HANDLE hInstance )
- /*
- Initialization for the first instance of the application.
-
- Returns:
-
- TRUE - success
- FALSE - failure
- */
- {
- WNDCLASS wc;
-
-
- // Main window class
- wc.style = NULL;
- wc.lpfnWndProc = MainWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = szMenu;
- wc.lpszClassName = APWServer;
-
- if (RegisterClass(&wc) == 0)
- return FALSE;
-
-
- /*
- Server window class. The Extra bytes at the end of the window contain
- the client window handle.
- */
- wc.lpfnWndProc = ServerProc;
- wc.cbWndExtra = sizeof (short);
- wc.hIcon = NULL;
- wc.hCursor = NULL;
- wc.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
- wc.lpszClassName = szServerClass;
-
- if (RegisterClass(&wc) == 0)
- return FALSE;
-
- return TRUE;
- }
-
-
- static BOOL NEAR PASCAL InitInstance( HANDLE hInstance, short nCmdShow )
- /*
- Main initialization routine for every instance of the application.
-
- Returns:
-
- TRUE - success
- FALSE - failure
- */
- {
- RECT Rect;
-
- hInst = hInstance;
-
- // Create the main window
- hWndMain = CreateWindow(APWServer,
- "Sample Server Window for APW",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL,
- NULL,
- hInstance,
- NULL);
-
- if (!hWndMain)
- return FALSE;
-
- GetClientRect(hWndMain, (LPRECT) &Rect);
-
- // Create a child edit window the size of the client rect of the main window
- hEditWnd = CreateWindow("Edit",
- "",
- WS_CHILD | WS_VISIBLE | ES_MULTILINE,
- 0,
- 0,
- (Rect.right-Rect.left),
- 30,
- hWndMain,
- IDC_EDIT, // Child control i.d.
- hInst,
- NULL);
-
-
- if (!hEditWnd)
- {
- DestroyWindow(hWndMain);
- return NULL;
- }
-
- // Set the initial text in the edit control
- SetWindowText(hEditWnd, "This is a sample \"server\" application that understands DDE protocol. You can now return to Authorware and proceed.");
-
- // Show the main window
- ShowWindow(hWndMain, nCmdShow);
- UpdateWindow(hWndMain);
-
- return TRUE;
- }
-
-
- long FAR PASCAL MainWndProc( HWND hWnd, unsigned message, WORD wParam, LONG lParam)
- /*
- This is the main window procedure for the top level window.
- */
- {
- FARPROC lpProcAbout;
- PAINTSTRUCT ps;
-
- switch (message)
- {
- case WM_COMMAND:
- switch (wParam)
- {
- case IDM_ABOUT:
- if ((lpProcAbout = MakeProcInstance(About, hInst)) != 0L)
- {
- DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
- FreeProcInstance(lpProcAbout);
- }
- break;
-
- case IDM_EXIT:
- DestroyWindow(hWnd);
- break;
-
- }
- break;
-
- case WM_SETFOCUS:
- if (hEditWnd)
- SetFocus (hEditWnd);
- break;
-
- case WM_SIZE:
- if (hEditWnd)
- MoveWindow(hEditWnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
- break;
-
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
-
- case WM_DDE_INITIATE:
- if (DDEInitialize(hWnd, wParam, LOWORD(lParam), HIWORD(lParam)))
- break;
-
- // No break here - if Initialize request ignored use DefWindowProc
-
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
-
- return NULL;
- }
-
-
- BOOL FAR PASCAL About( HWND hDlg, unsigned message, WORD wParam, LONG lParam)
- /*
- This is the about dialog procedure handler.
- */
- {
- switch (message)
- {
- case WM_INITDIALOG:
- return TRUE;
-
- case WM_COMMAND:
- if (wParam == IDOK || wParam == IDCANCEL)
- {
- EndDialog(hDlg, TRUE);
- return TRUE;
- }
- break;
- }
- return FALSE;
- }
-
-
- long FAR PASCAL ServerProc( HWND hWnd, WORD message, WORD wParam, LONG lParam )
- /*
- This is the message handler for the server window. Only WM_DDE_REQUEST
- and WM_DDE_TERMINATE messages are handled by this server.
- */
- {
- HWND hWndClient;
- DWORD dwTime;
- MSG msg;
-
- switch (message)
- {
- case WM_DDE_REQUEST:
- DDERequest(hWnd, wParam, LOWORD(lParam), HIWORD(lParam));
- break;
-
- case WM_DDE_TERMINATE:
- PostMessage(wParam, WM_DDE_TERMINATE, hWnd, 0L);
- DestroyWindow(hWnd);
- break;
-
- case WM_CLOSE:
- hWndClient = GetWindowWord(hWnd, CLIENTWND);
- if (VALID_WINDOW(hWndClient))
- {
- PostMessage(hWndClient, WM_DDE_TERMINATE, hWnd, 0L);
-
- // Request the client to terminate and wait for a response if recieved
- dwTime = GetCurrentTime();
- while(GetCurrentTime() - dwTime < DDE_TIMEOUT)
- if (PeekMessage(&msg, hWnd, WM_DDE_TERMINATE,
- WM_DDE_TERMINATE, PM_REMOVE))
- break;
- }
-
- DestroyWindow(hWnd);
- break;
-
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
-
- return 0L;
- }
-
-
- static BOOL NEAR PASCAL DDEPostDataMessage(HWND server, HWND client )
- /*
- This function gets the text from the edit control and sends it via dde
- to the client window. It does not require the client to send an ACK back.
- It is the responsiblity of the caller to free memory.
-
- Returns:
-
- TRUE - data sent
- FALSE - data not sent.
- */
- {
- ATOM aItem;
- DDEDATA FAR *Ack_ptr;
- GLOBALHANDLE ddeData;
- MSG msg;
- BOOL rv = FALSE;
- short len;
-
- if ((aItem = GlobalAddAtom(szItem)) != 0)
- {
- // Get the length of the text from the edit control window
- len = SendMessage(hEditWnd, WM_GETTEXTLENGTH, 0, 0L);
-
- // Allocate a buffer for the text
- if ((ddeData = GlobalAlloc(GHND | GMEM_DDESHARE, (DWORD)sizeof(DDEDATA)+len+1)) != 0)
- {
- Ack_ptr = (DDEDATA FAR *)GlobalLock(ddeData);
-
- Ack_ptr->fResponse = TRUE;
- Ack_ptr->cfFormat = CF_TEXT;
-
- // Let the client release the memory
- Ack_ptr->fRelease = TRUE;
- Ack_ptr->fAckReq = TRUE;
-
- // Get the text from the control
- GetWindowText(hEditWnd, Ack_ptr->Value, len+1);
- GlobalUnlock(ddeData);
-
- // Post the data to the client
- if (!PostMessage(client, WM_DDE_DATA, server, MAKELONG(ddeData, aItem)))
- {
- GlobalFree(ddeData);
- GlobalDeleteAtom(aItem);
- }
- else
- rv = TRUE;
- }
- else
- GlobalDeleteAtom(aItem);
- }
-
- return rv;
- }
-
-
- static BOOL NEAR PASCAL DDEInitialize( HWND parent, HWND client, ATOM a, ATOM t )
- /*
- Handle the WM_DDE_INITIALIZE message.
-
- parent - Server window parent
- client - Client window
- a - Atom for the Application name.
- t - Atom for the Topic name.
-
- Returns:
-
- TRUE - handled request
- FALSE - ignored request
- */
- {
- ATOM aApp=0, aTop=0;
- HWND hWndServer;
- BOOL rv = FALSE;
-
-
- // Don't act on incomplete information
- if (a == NULL || t == NULL)
- return rv;
-
- // Add the Server atoms - only 1 atom with the same name is allowed.
- // thus if the passed in atoms are the same, the initialize request
- // is for us. - Remember duplicate adds increment the reference count!
-
- if ((aApp = GlobalAddAtom(APWServer)) != 0)
- {
- if ((aTop = GlobalAddAtom(szTopic)) != 0)
- {
- // Is the application name the same?
- if (a == aApp)
- {
- // Reference count should be decremented
- GlobalDeleteAtom(aApp);
- aApp = 0;
-
- // Is the topic the same?
- if (t == aTop)
- {
- // Reference count should be decremented
- GlobalDeleteAtom(aTop);
- aTop = 0;
-
- hWndServer = CreateWindow(szServerClass, NULL, WS_CHILD, 0, 0,
- 0, 0, parent, NULL, hInst, NULL);
-
- // Set the client window handle in CLIENTWND
- SetWindowWord(hWndServer, CLIENTWND, client);
-
- // Let the client cleanup the atoms it passed in.
- SendMessage(client, WM_DDE_ACK, hWndServer, MAKELONG(a,t));
- rv = TRUE;
- }
- }
- }
- }
-
- // Cleanup on error
- if (rv == FALSE)
- {
- if (aApp)
- GlobalDeleteAtom(aApp);
- if (aTop)
- GlobalDeleteAtom(aTop);
- }
-
- return rv;
- }
-
-
- static BOOL NEAR PASCAL DDERequest( HWND server, HWND client, WORD cfFormat, ATOM aItem )
- /*
- Handle the WM_DDE_REQUEST message.
-
- server - Server window
- client - Client window
- cfFormat - Format of the data requested - we only support CF_TEXT.
- aItem - Atom for the item.
-
- Returns:
-
- TRUE - handled request
- FALSE - ignored request
- */
- {
- WORD wStatus;
- char szRequestedItem[10];
- DDEACK ddeAck;
-
- if (cfFormat == CF_TEXT && aItem != 0)
- {
- // Get the item atom name
- GlobalGetAtomName(aItem, szRequestedItem, sizeof(szRequestedItem));
-
- // Is it the same as our item name. - We only support szRequestedItem
- if (strcmp(szRequestedItem, szItem) == NULL)
- {
- GlobalDeleteAtom(aItem);
- if (DDEPostDataMessage(server, client))
- return TRUE;
- }
- }
-
- // No match - negative acknowledgement
-
- ddeAck.bAppReturnCode = 0;
- ddeAck.reserved = 0;
- ddeAck.fBusy = FALSE;
- ddeAck.fAck = FALSE;
-
- wStatus = *(WORD *)&ddeAck;
-
- if (!PostMessage(client, WM_DDE_ACK, server, MAKELONG(wStatus, aItem)))
- if (aItem)
- GlobalDeleteAtom(aItem);
-
- return FALSE;
- }
-
-