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);
}