Last updated: 21.12.1997, 22:18
(*----------------------------------------- SHOWPOP1.C -- DDE Client using DDEPOP1 (c) Charles Petzold, 1996 -----------------------------------------*) #include#include #include #include #include "showpop.h" #define WINUSER.WM_USER_INITIATE (WM_USER + 1) #define DDE_TIMEOUT 3000 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); char szAppName[] := "ShowPop1"; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; MSG msg; WNDCLASSEX wndclass; wndclass.cbSize := sizeof (wndclass); wndclass.style := CS_HREDRAW BOR CS_VREDRAW; wndclass.lpfnWndProc := WndProc; wndclass.cbClsExtra := 0; wndclass.cbWndExtra := 0; wndclass.hInstance := hInstance; wndclass.hIcon := LoadIcon (hInstance, szAppName); wndclass.hCursor := LoadCursor (NIL, IDC_ARROW); wndclass.hbrBackground := (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName := NIL; wndclass.lpszClassName := szAppName; wndclass.hIconSm := LoadIcon (hInstance, szAppName); RegisterClassEx (SYSTEM.ADR(wndclass)); hwnd := CreateWindow (szAppName, "DDE Client - US Population", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NIL, NIL, hInstance, NIL); ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); SendMessage (hwnd, WINUSER.WM_USER_INITIATE, 0, 0L); while (GetMessage (SYSTEM.ADR(msg), NIL, 0, 0)) { TranslateMessage (SYSTEM.ADR(msg)); DispatchMessage (SYSTEM.ADR(msg)); } RETURN msg.wParam; } LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { static BOOL fDoingInitiate := TRUE; static char szServerApp[] := "DdePop1", szTopic[] := "US_Population"; static HWND hwndServer := NIL; static long cxChar, cyChar; ATOM aApp, aTop, aItem; char szBuffer[24], szPopulation[16], szItem[16]; DDEACK DdeAck; DDEDATA *pDdeData; DDEADVISE *pDdeAdvise; DWORD dwTime; GLOBALHANDLE hDdeAdvise, hDdeData; HDC hdc; MSG msg; PAINTSTRUCT ps; short i; long x, y; TEXTMETRIC tm; WORD wStatus; UINT uiLow, uiHi; CASE (iMsg) OF { | WINUSER.WM_CREATE : hdc := GetDC (hwnd); GetTextMetrics (hdc, SYSTEM.ADR(tm)); cxChar := tm.tmAveCharWidth; cyChar := tm.tmHeight + tm.tmExternalLeading; ReleaseDC (hwnd, hdc); RETURN 0; | WINUSER.WM_USER_INITIATE : (* Broadcast WINUSER.WM_DDE_INITIATE iMsg *) aApp := GlobalAddAtom (szServerApp); aTop := GlobalAddAtom (szTopic); SendMessage (HWND_BROADCAST, WINUSER.WM_DDE_INITIATE, (WPARAM) hwnd, MAKELONG (aApp, aTop)); (* If no response, try loading DDEPOP first *) IF (hwndServer = NIL) THEN { WinExec (szServerApp, SW_SHOWMINNOACTIVE); SendMessage (HWND_BROADCAST, WINUSER.WM_DDE_INITIATE, (WPARAM) hwnd, MAKELONG (aApp, aTop)); } (* Delete the atoms *) GlobalDeleteAtom (aApp); GlobalDeleteAtom (aTop); fDoingInitiate := FALSE; (* If still no response, display message box *) IF (hwndServer = NIL) THEN { MessageBox (hwnd, "Cannot connect with DDEPOP1.EXENOT ", szAppName, WINUSER.MB_ICONEXCLAMATION BOR WINUSER.MB_OK); RETURN 0; } (* Post WINUSER.WM_DDE_ADVISE iMsgs *) FOR (i := 0; i < NUM_STATES; i++) DO { hDdeAdvise := GlobalAlloc (GHND BOR GMEM_DDESHARE, SIZE (DDEADVISE)); pDdeAdvise := (DDEADVISE *) GlobalLock (hDdeAdvise); pDdeAdvise^.fAckReq := TRUE; pDdeAdvise^.fDeferUpd := FALSE; pDdeAdvise^.cfFormat := CF_TEXT; GlobalUnlock (hDdeAdvise); aItem := GlobalAddAtom (pop[i].szAbb); IF (NOT PostMessage (hwndServer, WINUSER.WM_DDE_ADVISE, (WPARAM) THEN hwnd, PackDDElParam (WM_DDE_ADVISE, (UINT) hDdeAdvise, aItem))) { GlobalFree (hDdeAdvise); GlobalDeleteAtom (aItem); break; } DdeAck.fAck := FALSE; dwTime := GetCurrentTime (); while (GetCurrentTime () - dwTime < DDE_TIMEOUT) { if (PeekMessage (SYSTEM.ADR(msg), hwnd, WINUSER.WM_DDE_ACK, WINUSER.WM_DDE_ACK, PM_REMOVE)) { GlobalDeleteAtom (WINUSER.HIWORD (msg.lParam)); wStatus := WINUSER.LOWORD (msg.lParam); DdeAck := *((DDEACK *) SYSTEM.ADR(wStatus)); IF (DdeAck.fAck = FALSE) THEN GlobalFree (hDdeAdvise); break; } } IF (DdeAck.fAck = FALSE) THEN break; while (PeekMessage (SYSTEM.ADR(msg), hwnd, WINUSER.WM_DDE_FIRST, WINUSER.WM_DDE_LAST, PM_REMOVE)) { DispatchMessage (SYSTEM.ADR(msg)); } } IF (i < NUM_STATES) THEN { MessageBox (hwnd, "Failure on WINUSER.WM_DDE_ADVISENOT ", szAppName, WINUSER.MB_ICONEXCLAMATION BOR WINUSER.MB_OK); } RETURN 0; | WINUSER.WM_DDE_ACK : (* In response to WINUSER.WM_DDE_INITIATE, save server window *) IF (fDoingInitiate) THEN { UnpackDDElParam (WM_DDE_ACK, lParam, SYSTEM.ADR(uiLow), SYSTEM.ADR(uiHi)); FreeDDElParam (WM_DDE_ACK, lParam); hwndServer := (HWND) wParam; GlobalDeleteAtom ((ATOM) uiLow); GlobalDeleteAtom ((ATOM) uiHi); } RETURN 0; | WINUSER.WM_DDE_DATA : (* wParam -- sending window handle *) (* lParam -- DDEDATA memory handle BAND item atom *) UnpackDDElParam (WM_DDE_DATA, lParam, SYSTEM.ADR(uiLow), SYSTEM.ADR(uiHi)); FreeDDElParam (WM_DDE_DATA, lParam); hDdeData := (GLOBALHANDLE) uiLow; pDdeData := (DDEDATA *) GlobalLock (hDdeData); aItem := (ATOM) uiHi; (* Initialize DdeAck structure *) DdeAck.bAppReturnCode := 0; DdeAck.reserved := 0; DdeAck.fBusy := FALSE; DdeAck.fAck := FALSE; (* Check FOR matching format and data item DO *) IF (pDdeData^.cfFormat = CF_TEXT) THEN { GlobalGetAtomName (aItem, szItem, SIZE (szItem)); FOR (i := 0; i < NUM_STATES; i++) DO IF (strcmp (szItem, pop[i].szAbb) THEN = 0) break; IF (i < NUM_STATES) THEN { strcpy (szPopulation, (char *) pDdeData^.Value); pop[i].lPop := atol (szPopulation); InvalidateRect (hwnd, NIL, FALSE); DdeAck.fAck := TRUE; } } (* Acknowledge if necessary *) IF (pDdeData^.fAckReq = TRUE) THEN { wStatus := *((WORD *) SYSTEM.ADR(DdeAck)); IF (NOT PostMessage ((HWND) THEN wParam, WINUSER.WM_DDE_ACK, (WPARAM) hwnd, PackDDElParam (WM_DDE_ACK, wStatus, aItem))) { GlobalDeleteAtom (aItem); GlobalUnlock (hDdeData); GlobalFree (hDdeData); RETURN 0; } } ELSE { GlobalDeleteAtom (aItem); } (* Clean up *) IF (pDdeData^.fRelease = TRUE || DdeAck.fAck = FALSE) THEN { GlobalUnlock (hDdeData); GlobalFree (hDdeData); } ELSE { GlobalUnlock (hDdeData); } RETURN 0; | WINUSER.WM_PAINT : hdc := BeginPaint (hwnd, SYSTEM.ADR(ps)); FOR (i := 0; i < NUM_STATES; i++) DO { IF (i < (NUM_STATES + 1) THEN DIV 2) { x := cxChar; y := i * cyChar; } ELSE { x := 44 * cxChar; y := (i - (NUM_STATES + 1) DIV 2) * cyChar; } TextOut (hdc, x, y, szBuffer, wsprintf (szBuffer, "%-20s", (PSTR) pop[i].szState)); x += 36 * cxChar; SetTextAlign (hdc, TA_RIGHT BOR TA_TOP); TextOut (hdc, x, y, szBuffer, wsprintf (szBuffer, "%10ld", pop[i].lPop)); SetTextAlign (hdc, TA_LEFT BOR TA_TOP); } EndPaint (hwnd, SYSTEM.ADR(ps)); RETURN 0; | WINUSER.WM_DDE_TERMINATE : (* Respond with another WINUSER.WM_DDE_TERMINATE iMsg *) PostMessage (hwndServer, WINUSER.WM_DDE_TERMINATE, SYSTEM.CAST(WPARAM,hwnd, 0L)); hwndServer := NIL; RETURN 0; | WINUSER.WM_CLOSE : IF (hwndServer = NIL) THEN break; (* Post WINUSER.WM_DDE_UNADVISE iMsg *) PostMessage (hwndServer, WINUSER.WM_DDE_UNADVISE, (WPARAM) hwnd, MAKELONG (CF_TEXT, NIL)); dwTime := GetCurrentTime (); while (GetCurrentTime () - dwTime < DDE_TIMEOUT) { if (PeekMessage (SYSTEM.ADR(msg), hwnd, WINUSER.WM_DDE_ACK, WINUSER.WM_DDE_ACK, PM_REMOVE)) break; } (* Post WINUSER.WM_DDE_TERMINATE iMsg *) PostMessage (hwndServer, WINUSER.WM_DDE_TERMINATE, SYSTEM.CAST(WPARAM,hwnd, 0L)); dwTime := GetCurrentTime (); while (GetCurrentTime () - dwTime < DDE_TIMEOUT) { if (PeekMessage (SYSTEM.ADR(msg), hwnd, WINUSER.WM_DDE_TERMINATE, WINUSER.WM_DDE_TERMINATE, PM_REMOVE)) break; } break; (* FOR default processing DO *) | WINUSER.WM_DESTROY : PostQuitMessage (0); RETURN 0; } RETURN DefWindowProc (hwnd, iMsg, wParam, lParam); }