|
|
1.1 root 1: /***************************************************************************
2: * *
3: * PROGRAM : client.c *
4: * *
5: * PURPOSE : To demonstrate how to use the DDEML library from the *
6: * client side and for basic testing of the DDEML API. *
7: * *
8: ***************************************************************************/
9:
10: #include "client.h"
11: #include <string.h>
12: #include <memory.h>
13: #include "infoctrl.h"
14:
15: /* global variables used in this module or among more than one module */
16: CONVCONTEXT CCFilter = { sizeof(CONVCONTEXT), 0, 0, 0, 0L, 0L };
17: DWORD idInst = 0;
18: HANDLE hInst; /* Program instance handle */
19: HANDLE hAccel; /* Main accelerator resource */
20: HWND hwndFrame = NULL; /* Handle to main window */
21: HWND hwndMDIClient = NULL; /* Handle to MDI client */
22: HWND hwndActive = NULL; /* Handle to currently activated child */
23: LONG DefTimeout = DEFTIMEOUT; /* default synchronous transaction timeout */
24: DWORD wDelay = 0;
25: BOOL fBlockNextCB = FALSE; /* set if next callback causes a CBR_BLOCK */
26: BOOL fTermNextCB = FALSE; /* set to call DdeDisconnect() on next callback */
27: BOOL fAutoReconnect = FALSE; /* set if DdeReconnect() is to be called on XTYP_DISCONNECT callbacks */
28: HDDEDATA hDataOwned = NULL; /* Current owned huge data handle */
1.1.1.2 ! root 29: DWORD fmtLink = 0; /* link clipboard format number */
! 30: DWORD DefOptions = 0; /* default transaction optons */
1.1 root 31: OWNED aOwned[MAX_OWNED]; /* list of all owned handles. */
1.1.1.2 ! root 32: DWORD cOwned = 0; /* number of existing owned handles. */
1.1 root 33: FARPROC lpMsgFilterProc; /* instance proc from MSGF_DDEMGR filter */
1.1.1.2 ! root 34: HSZ hszHuge; /* used for checking huge item data */
! 35: HHOOK ghhk = 0;
1.1 root 36:
37: /*
38: * This is the array of formats we support
39: */
40: FORMATINFO aFormats[] = {
41: { CF_TEXT, "CF_TEXT" }, // exception! predefined format
42: { 0, "Dummy1" },
43: { 0, "Dummy2" },
44: };
45:
46: /* Forward declarations of helper functions in this module */
47: VOID NEAR PASCAL CloseAllChildren(VOID);
48: VOID NEAR PASCAL InitializeMenu (HANDLE);
49: VOID NEAR PASCAL CommandHandler (HWND,DWORD);
50: VOID NEAR PASCAL SetWrap (HWND,BOOL);
51:
52: /****************************************************************************
53: * *
54: * FUNCTION : WinMain(HANDLE, HANDLE, LPSTR, int) *
55: * *
56: * PURPOSE : Creates the "frame" window, does some initialization and *
57: * enters the message loop. *
58: * *
59: ****************************************************************************/
1.1.1.2 ! root 60: int WINAPI WinMain(
! 61: HANDLE hInstance,
! 62: HANDLE hPrevInstance,
! 63: LPSTR lpszCmdLine,
! 64: INT nCmdShow)
1.1 root 65: {
66: MSG msg;
67:
68: hInst = hInstance;
69:
70: /* If this is the first instance of the app. register window classes */
71: if (!hPrevInstance){
72: if (!InitializeApplication ())
73: return 0;
74: }
75:
76: /* Create the frame and do other initialization */
77: if (!InitializeInstance(nCmdShow))
78: return 0;
79:
80: /* Enter main message loop */
81: while (GetMessage (&msg, NULL, 0, 0)){
1.1.1.2 ! root 82: ((HOOKPROC)*lpMsgFilterProc)(MSGF_DDEMGR, 0, (LONG)(LPMSG)&msg);
1.1 root 83: }
84:
85: // free up any appowned handles
86: while (cOwned) {
87: DdeFreeDataHandle(aOwned[--cOwned].hData);
88: }
1.1.1.2 ! root 89: DdeFreeStringHandle(idInst, hszHuge);
1.1 root 90: DdeUninitialize(idInst);
91:
1.1.1.2 ! root 92: UnhookWindowsHook(WH_MSGFILTER, (HOOKPROC)lpMsgFilterProc);
1.1 root 93: FreeProcInstance(lpMsgFilterProc);
94:
95: return 0;
96: }
97:
98: /****************************************************************************
99: * *
100: * FUNCTION : FrameWndProc (hwnd, msg, wParam, lParam ) *
101: * *
102: * PURPOSE : The window function for the "frame" window, which controls *
103: * the menu and encompasses all the MDI child windows. Does *
104: * the major part of the message processing. Specifically, in *
105: * response to: *
106: * *
107: ****************************************************************************/
108: LONG APIENTRY FrameWndProc ( hwnd, msg, wParam, lParam )
109: HWND hwnd;
110: UINT msg;
111: WPARAM wParam;
112: LPARAM lParam;
113:
114: {
115: switch (msg){
116: case WM_CREATE:{
117: CLIENTCREATESTRUCT ccs;
118:
119: /* Find window menu where children will be listed */
120: ccs.hWindowMenu = GetSubMenu (GetMenu(hwnd),WINDOWMENU);
121: ccs.idFirstChild = IDM_WINDOWCHILD;
122:
123: /* Create the MDI client filling the client area */
124: hwndMDIClient = CreateWindow ("mdiclient",
125: NULL,
126: WS_CHILD | WS_CLIPCHILDREN |
127: WS_VSCROLL | WS_HSCROLL,
128: 0,
129: 0,
130: 0,
131: 0,
132: hwnd,
133: (HMENU)0xCAC,
134: hInst,
135: (LPSTR)&ccs);
136:
137:
138: ShowWindow (hwndMDIClient,SW_SHOW);
139: break;
140: }
141:
142: case WM_INITMENU:
143: InitializeMenu ((HMENU)wParam);
144: break;
145:
146: case WM_COMMAND:
1.1.1.2 ! root 147: CommandHandler (hwnd, LOWORD(wParam));
1.1 root 148: break;
149:
150: case WM_CLOSE:
151: CloseAllChildren();
152: DestroyWindow(hwnd);
153: break;
154:
155: case WM_DESTROY:
156: PostQuitMessage(0);
157: break;
158:
159: default:
160: /* use DefFrameProc() instead of DefWindowProc() since there
161: * are things that have to be handled differently because of MDI
162: */
163: return DefFrameProc (hwnd,hwndMDIClient,msg,wParam,lParam);
164: }
165: return 0;
166: }
167:
168:
169:
170:
171:
172: /****************************************************************************
173: * *
174: * FUNCTION : MDIChildWndProc *
175: * *
176: * PURPOSE : The window function for the "child" conversation and list *
177: * windows. *
178: * *
179: ****************************************************************************/
180: LONG APIENTRY MDIChildWndProc( hwnd, msg, wParam, lParam )
181: HWND hwnd;
182: UINT msg;
183: WPARAM wParam;
184: LPARAM lParam;
185: {
186: MYCONVINFO *pmci;
187: RECT rc;
188:
189: switch (msg){
190: case WM_CREATE:
191: /*
192: * Create a coresponding conversation info structure to link this
193: * window to the conversation or conversation list it represents.
194: *
195: * lParam: points to the conversation info to initialize our copy to.
196: */
197: pmci = (MYCONVINFO *)MyAlloc(sizeof(MYCONVINFO));
198: if (pmci != NULL) {
1.1.1.2 ! root 199: memcpy(pmci,
1.1 root 200: (LPSTR)((LPMDICREATESTRUCT)((LPCREATESTRUCT)lParam)->lpCreateParams)->lParam,
201: sizeof(MYCONVINFO));
202: pmci->hwndXaction = 0; /* no current transaction yet */
203: pmci->x = pmci->y = 0; /* new transaction windows start here */
204: DdeKeepStringHandle(idInst, pmci->hszTopic);/* keep copies of the hszs for us */
205: DdeKeepStringHandle(idInst, pmci->hszApp);
206:
207: // link hConv and hwnd together
208: SetWindowLong(hwnd, 0, (DWORD)pmci);
209:
210: /*
211: * non-list windows link the conversations to the windows via the
212: * conversation user handle.
213: */
214: if (!pmci->fList)
215: DdeSetUserHandle(pmci->hConv, QID_SYNC, (DWORD)hwnd);
216: }
217: goto CallDCP;
218: break;
219:
220: case UM_GETNEXTCHILDX:
221: case UM_GETNEXTCHILDY:
222: /*
223: * Calculate the next place to put the next transaction window.
224: */
225: {
226: pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
227: GetClientRect(hwnd, &rc);
228: if (msg == UM_GETNEXTCHILDX) {
229: pmci->x += 14;
230: if (pmci->x > (rc.right - 200 - rc.left))
231: pmci->x = 0;
232: return(pmci->x);
233: } else {
234: pmci->y += 12;
235: if (pmci->y > (rc.bottom - 100 - rc.top))
236: pmci->y = 0;
237: return(pmci->y);
238: }
239: }
240: break;
241:
242: case UM_DISCONNECTED:
243: /*
244: * Disconnected conversations can't have any transactions so we
245: * remove all the transaction windows here to show whats up.
246: */
247: {
248: HWND hwndT;
249: while (hwndT = GetWindow(hwnd, GW_CHILD))
250: DestroyWindow(hwndT);
251: InvalidateRect(hwnd, NULL, TRUE);
252: }
253: break;
254:
255: case WM_DESTROY:
256: /*
257: * Cleanup our conversation info structure, and disconnect all
258: * conversations associated with this window.
259: */
260: pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
261: pmci->hwndXaction = 0; /* clear this to avoid focus problems */
262: if (pmci->hConv) {
263: if (pmci->fList) {
264: DdeDisconnectList((HCONVLIST)pmci->hConv);
265: } else {
266: MyDisconnect(pmci->hConv);
267: }
268: }
269: DdeFreeStringHandle(idInst, pmci->hszTopic);
270: DdeFreeStringHandle(idInst, pmci->hszApp);
271: MyFree(pmci);
272: goto CallDCP;
273: break;
274:
275: case WM_SETFOCUS:
276: /*
277: * This catches focus changes caused by dialogs.
278: */
279: lParam = (LPARAM)hwnd;
280: // fall through
281:
282: case WM_MDIACTIVATE:
1.1.1.2 ! root 283: hwndActive = (HWND)(lParam);
1.1 root 284: pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
285: /*
286: * pass the focus onto the current transaction window.
287: */
1.1.1.2 ! root 288: if ((lParam == (LONG)hwnd) &&
1.1 root 289: IsWindow(pmci->hwndXaction))
290: SetFocus(pmci->hwndXaction);
291: break;
292:
293: case ICN_HASFOCUS:
294: /*
295: * update which transaction window is the main one.
296: */
297: pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
298: pmci->hwndXaction = wParam ? (HWND)lParam : NULL;
299: break;
300:
301: case ICN_BYEBYE:
302: /*
303: * Transaction window is closing...
304: *
305: * wParam = hwndXact
306: * lParam = lpxact
307: */
308: pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
309: if (pmci != NULL) {
310: XACT *pxact;
311:
312: pxact = (XACT *)lParam;
313: if (pxact != NULL) {
314: /*
315: * If this transaction is active, abandon it first.
316: */
317: if (pxact->fsOptions & XOPT_ASYNC &&
318: !(pxact->fsOptions & XOPT_COMPLETED)) {
319: DdeAbandonTransaction(idInst, pmci->hConv, pxact->Result);
320: }
321: /*
322: * release resources associated with transaction.
323: */
324: DdeFreeStringHandle(idInst, pxact->hszItem);
325: MyFree((PSTR)pxact);
326: /*
327: * Locate next apropriate transaction window to get focus.
328: */
329: if (!pmci->hwndXaction || pmci->hwndXaction == (HWND)wParam)
330: pmci->hwndXaction = GetWindow(hwnd, GW_CHILD);
331: if (pmci->hwndXaction == (HWND)wParam)
332: pmci->hwndXaction = GetWindow((HWND)wParam, GW_HWNDNEXT);
333: if (pmci->hwndXaction == (HWND)wParam ||
334: !IsWindow(pmci->hwndXaction) ||
335: !IsChild(hwnd, pmci->hwndXaction))
336: pmci->hwndXaction = NULL;
337: else
338: SetFocus(pmci->hwndXaction);
339: }
340: }
341: break;
342:
343: case WM_PAINT:
344: /*
345: * Paint this conversation's related information.
346: */
347: pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
348: {
349: PAINTSTRUCT ps;
350: PSTR psz;
351:
352: BeginPaint(hwnd, &ps);
353: SetBkMode(ps.hdc, TRANSPARENT);
354: psz = pmci->fList ? GetConvListText(pmci->hConv) :
355: GetConvInfoText(pmci->hConv, &pmci->ci);
356: if (psz) {
357: GetClientRect(hwnd, &rc);
358: DrawText(ps.hdc, psz, -1, &rc,
359: DT_WORDBREAK | DT_LEFT | DT_NOPREFIX | DT_TABSTOP);
360: MyFree(psz);
361: }
362: EndPaint(hwnd, &ps);
363: }
364: break;
365:
366: case WM_QUERYENDSESSION:
367: return TRUE;
368:
369: default:
370: CallDCP:
371: /* Again, since the MDI default behaviour is a little different,
372: * call DefMDIChildProc instead of DefWindowProc()
373: */
374: return DefMDIChildProc (hwnd, msg, wParam, lParam);
375: }
376: return FALSE;
377: }
378:
379:
380: /****************************************************************************
381: * *
382: * FUNCTION : Initializemenu ( hMenu ) *
383: * *
384: * PURPOSE : Sets up greying, enabling and checking of main menu items *
385: * based on the app's state. *
386: * *
387: ****************************************************************************/
388: VOID NEAR PASCAL InitializeMenu ( hmenu )
389: HANDLE hmenu;
390: {
391: BOOL fLink = FALSE; // set if Link format is on the clipboard;
392: BOOL fAny = FALSE; // set if hwndActive exists
393: BOOL fList = FALSE; // set if hwndActive is a list window
394: BOOL fConnected = FALSE; // set if hwndActive is a connection conversation.
395: BOOL fXaction = FALSE; // set if hwndActive has a selected transaction window
396: BOOL fXactions = FALSE; // set if hwndActive contains transaction windows
397: BOOL fBlocked = FALSE; // set if hwndActive conversation is blocked.
398: BOOL fBlockNext = FALSE; // set if handActive conversation is blockNext.
399: MYCONVINFO *pmci = NULL;
400:
401: if (OpenClipboard(hwndFrame)) {
402: fLink = (IsClipboardFormatAvailable(fmtLink));
403: CloseClipboard();
404: }
405:
406: if (fAny = (IsWindow(hwndActive) &&
407: (pmci = (MYCONVINFO *)GetWindowLong(hwndActive, 0)))) {
408: fXactions = (BOOL)GetWindow(hwndActive, GW_CHILD);
409: if (!(fList = pmci->fList)) {
410: CONVINFO ci;
411:
412: ci.cb = sizeof(CONVINFO);
413: DdeQueryConvInfo(pmci->hConv, QID_SYNC, &ci);
414: fConnected = ci.wStatus & ST_CONNECTED;
415: fXaction = IsWindow(pmci->hwndXaction);
416: fBlocked = ci.wStatus & ST_BLOCKED;
417: fBlockNext = ci.wStatus & ST_BLOCKNEXT;
418: }
419: }
420:
421: EnableMenuItem(hmenu, IDM_EDITPASTE,
422: fLink ? MF_ENABLED : MF_GRAYED);
423:
424: // IDM_CONNECTED - always enabled.
425:
426: EnableMenuItem(hmenu, IDM_RECONNECT,
427: fList ? MF_ENABLED : MF_GRAYED);
428:
429: EnableMenuItem (hmenu, IDM_DISCONNECT,
430: fConnected ? MF_ENABLED : MF_GRAYED);
431:
432: EnableMenuItem (hmenu, IDM_TRANSACT,
433: fConnected ? MF_ENABLED : MF_GRAYED);
434:
435: EnableMenuItem(hmenu, IDM_ABANDON,
436: fXaction ? MF_ENABLED : MF_GRAYED);
437:
438: EnableMenuItem(hmenu, IDM_ABANDONALL,
439: fXactions ? MF_ENABLED : MF_GRAYED);
440:
441:
442: EnableMenuItem (hmenu, IDM_BLOCKCURRENT,
443: fConnected && !fBlocked ? MF_ENABLED : MF_GRAYED);
444: CheckMenuItem(hmenu, IDM_BLOCKCURRENT,
445: fBlocked ? MF_CHECKED : MF_UNCHECKED);
446:
447: EnableMenuItem (hmenu, IDM_ENABLECURRENT,
448: fConnected && (fBlocked || fBlockNext) ? MF_ENABLED : MF_GRAYED);
449: CheckMenuItem(hmenu, IDM_ENABLECURRENT,
450: !fBlocked ? MF_CHECKED : MF_UNCHECKED);
451:
452: EnableMenuItem (hmenu, IDM_ENABLEONECURRENT,
453: fConnected && (fBlocked) ? MF_ENABLED : MF_GRAYED);
454: CheckMenuItem(hmenu, IDM_ENABLEONECURRENT,
455: fBlockNext ? MF_CHECKED : MF_UNCHECKED);
456:
457: EnableMenuItem (hmenu, IDM_BLOCKALLCBS,
458: fAny ? MF_ENABLED : MF_GRAYED);
459:
460: EnableMenuItem (hmenu, IDM_ENABLEALLCBS,
461: fAny ? MF_ENABLED : MF_GRAYED);
462:
463: EnableMenuItem (hmenu, IDM_ENABLEONECB,
464: fAny ? MF_ENABLED : MF_GRAYED);
465:
466: EnableMenuItem(hmenu, IDM_BLOCKNEXTCB,
467: fAny || fBlockNextCB ? MF_ENABLED : MF_GRAYED);
468: CheckMenuItem(hmenu, IDM_BLOCKNEXTCB,
469: fBlockNextCB ? MF_CHECKED : MF_UNCHECKED);
470:
471: EnableMenuItem(hmenu, IDM_TERMNEXTCB,
472: fAny || fTermNextCB ? MF_ENABLED : MF_GRAYED);
473: CheckMenuItem(hmenu, IDM_TERMNEXTCB,
474: fTermNextCB ? MF_CHECKED : MF_UNCHECKED);
475:
476: // IDM_DELAY - always enabled.
477:
478: // IDM_TIMEOUT - alwasy enabled.
479:
480: EnableMenuItem (hmenu, IDM_WINDOWTILE,
481: fAny ? MF_ENABLED : MF_GRAYED);
482:
483: EnableMenuItem (hmenu, IDM_WINDOWCASCADE,
484: fAny ? MF_ENABLED : MF_GRAYED);
485:
486: EnableMenuItem (hmenu, IDM_WINDOWICONS,
487: fAny ? MF_ENABLED : MF_GRAYED);
488:
489: EnableMenuItem (hmenu, IDM_WINDOWCLOSEALL,
490: fAny ? MF_ENABLED : MF_GRAYED);
491:
492: EnableMenuItem (hmenu, IDM_XACTTILE,
493: fXactions ? MF_ENABLED : MF_GRAYED);
494:
495: EnableMenuItem (hmenu, IDM_XACTCASCADE,
496: fXactions ? MF_ENABLED : MF_GRAYED);
497:
498: CheckMenuItem(hmenu, IDM_AUTORECONNECT,
499: fAutoReconnect ? MF_CHECKED : MF_UNCHECKED);
500:
501: // IDM_HELPABOUT - always enabled.
502: }
503:
504:
505:
506: /****************************************************************************
507: * *
508: * FUNCTION : CloseAllChildren () *
509: * *
510: * PURPOSE : Destroys all MDI child windows. *
511: * *
512: ****************************************************************************/
513: VOID NEAR PASCAL CloseAllChildren ()
514: {
515: HWND hwndT;
516:
517: /* hide the MDI client window to avoid multiple repaints */
518: ShowWindow(hwndMDIClient,SW_HIDE);
519:
520: /* As long as the MDI client has a child, destroy it */
521: while ( hwndT = GetWindow (hwndMDIClient, GW_CHILD)){
522:
523: /* Skip the icon title windows */
524: while (hwndT && GetWindow (hwndT, GW_OWNER))
525: hwndT = GetWindow (hwndT, GW_HWNDNEXT);
526:
527: if (!hwndT)
528: break;
529:
530: SendMessage(hwndMDIClient, WM_MDIDESTROY, (DWORD)hwndT, 0L);
531: }
532:
533: ShowWindow( hwndMDIClient, SW_SHOW);
534: }
535:
536: /****************************************************************************
537: * *
538: * FUNCTION : CommandHandler () *
539: * *
540: * PURPOSE : Processes all "frame" WM_COMMAND messages. *
541: * *
542: ****************************************************************************/
543: VOID NEAR PASCAL CommandHandler (
544: HWND hwnd,
545: DWORD id)
546:
547: {
548: MYCONVINFO *pmci = NULL;
549:
550: if (hwndActive)
551: pmci = (MYCONVINFO *)GetWindowLong(hwndActive, 0);
552:
553: switch (id){
554: case IDM_EDITPASTE:
555: {
556: HANDLE hClipData;
557: LPSTR psz;
558: XACT xact;
559:
560: if (OpenClipboard(hwnd)) {
561: if (hClipData = GetClipboardData(fmtLink)) {
562: if (psz = GlobalLock(hClipData)) {
563: /*
564: * Create a conversation with the link app and
565: * begin a request and advise start transaction.
566: */
567: xact.hConv = CreateConv(DdeCreateStringHandle(idInst, psz, NULL),
1.1.1.2 ! root 568: DdeCreateStringHandle(idInst, &psz[strlen(psz) + 1], NULL),
1.1 root 569: FALSE);
570: if (xact.hConv) {
1.1.1.2 ! root 571: psz += strlen(psz) + 1;
! 572: psz += strlen(psz) + 1;
1.1 root 573: xact.ulTimeout = DefTimeout;
574: xact.wType = XTYP_ADVSTART;
575: xact.hDdeData = 0;
576: xact.wFmt = CF_TEXT;
577: xact.hszItem = DdeCreateStringHandle(idInst, psz, NULL);
578: xact.fsOptions = 0;
579: ProcessTransaction(&xact);
580: xact.wType = XTYP_REQUEST;
581: ProcessTransaction(&xact);
582: }
583: GlobalUnlock(hClipData);
584: }
585: }
586: CloseClipboard();
587: }
588: }
589: break;
590:
591: case IDM_CONNECT:
592: case IDM_RECONNECT:
1.1.1.2 ! root 593: DoDialog(MAKEINTRESOURCE(IDD_CONNECT), (DLGPROC)ConnectDlgProc,
1.1 root 594: id == IDM_RECONNECT, FALSE);
595: break;
596:
597: case IDM_DISCONNECT:
598: if (hwndActive) {
599: SendMessage(hwndMDIClient, WM_MDIDESTROY, (DWORD)hwndActive, 0L);
600: }
601: break;
602:
603: case IDM_TRANSACT:
1.1.1.2 ! root 604: if (DoDialog(MAKEINTRESOURCE(IDD_TRANSACT), (DLGPROC)TransactDlgProc,
1.1 root 605: (DWORD)(LPSTR)pmci->hConv, FALSE))
606: SetFocus(GetWindow(hwndActive, GW_CHILD));
607: break;
608:
609: case IDM_ABANDON:
610: if (pmci != NULL && IsWindow(pmci->hwndXaction)) {
611: DestroyWindow(pmci->hwndXaction);
612: }
613: break;
614:
615: case IDM_ABANDONALL:
616: DdeAbandonTransaction(idInst, pmci->hConv, NULL);
617: {
618: HWND hwndXaction;
619:
620: hwndXaction = GetWindow(hwndActive, GW_CHILD);
621: while (hwndXaction) {
622: DestroyWindow(hwndXaction);
623: hwndXaction = GetWindow(hwndActive, GW_CHILD);
624: }
625: }
626: break;
627:
628: case IDM_BLOCKCURRENT:
629: DdeEnableCallback(idInst, pmci->hConv, EC_DISABLE);
630: InvalidateRect(hwndActive, NULL, TRUE);
631: break;
632:
633: case IDM_ENABLECURRENT:
634: DdeEnableCallback(idInst, pmci->hConv, EC_ENABLEALL);
635: InvalidateRect(hwndActive, NULL, TRUE);
636: break;
637:
638: case IDM_ENABLEONECURRENT:
639: DdeEnableCallback(idInst, pmci->hConv, EC_ENABLEONE);
640: InvalidateRect(hwndActive, NULL, TRUE);
641: break;
642:
643: case IDM_BLOCKALLCBS:
644: DdeEnableCallback(idInst, NULL, EC_DISABLE);
645: InvalidateRect(hwndMDIClient, NULL, TRUE);
646: break;
647:
648: case IDM_ENABLEALLCBS:
649: DdeEnableCallback(idInst, NULL, EC_ENABLEALL);
650: InvalidateRect(hwndMDIClient, NULL, TRUE);
651: break;
652:
653: case IDM_ENABLEONECB:
654: DdeEnableCallback(idInst, NULL, EC_ENABLEONE);
655: InvalidateRect(hwndMDIClient, NULL, TRUE);
656: break;
657:
658: case IDM_BLOCKNEXTCB:
659: fBlockNextCB = !fBlockNextCB;
660: break;
661:
662: case IDM_TERMNEXTCB:
663: fTermNextCB = !fTermNextCB;
664: break;
665:
666: case IDM_DELAY:
1.1.1.2 ! root 667: DoDialog(MAKEINTRESOURCE(IDD_VALUEENTRY), (DLGPROC)DelayDlgProc, NULL,
1.1 root 668: TRUE);
669: break;
670:
671: case IDM_TIMEOUT:
1.1.1.2 ! root 672: DoDialog(MAKEINTRESOURCE(IDD_VALUEENTRY), (DLGPROC)TimeoutDlgProc, NULL,
1.1 root 673: TRUE);
674: break;
675:
676: case IDM_CONTEXT:
1.1.1.2 ! root 677: DoDialog(MAKEINTRESOURCE(IDD_CONTEXT), (DLGPROC)ContextDlgProc, NULL, TRUE);
1.1 root 678: break;
679:
680: case IDM_AUTORECONNECT:
681: fAutoReconnect = !fAutoReconnect;
682: break;
683:
684: /* The following are window commands - these are handled by the
685: * MDI Client.
686: */
687: case IDM_WINDOWTILE:
688: /* Tile MDI windows */
689: SendMessage (hwndMDIClient, WM_MDITILE, 0, 0L);
690: break;
691:
692: case IDM_WINDOWCASCADE:
693: /* Cascade MDI windows */
694: SendMessage (hwndMDIClient, WM_MDICASCADE, 0, 0L);
695: break;
696:
697: case IDM_WINDOWICONS:
698: /* Auto - arrange MDI icons */
699: SendMessage (hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
700: break;
701:
702: case IDM_WINDOWCLOSEALL:
703: CloseAllChildren();
704: break;
705:
706: case IDM_XACTTILE:
707: TileChildWindows(hwndActive);
708: break;
709:
710: case IDM_XACTCASCADE:
711: MyCascadeChildWindows(hwndActive);
712: break;
713:
714: case IDM_HELPABOUT:{
1.1.1.2 ! root 715: DoDialog(MAKEINTRESOURCE(IDD_ABOUT), (DLGPROC)AboutDlgProc, NULL, TRUE);
1.1 root 716: break;
717: }
718:
719: default:
720: /*
721: * This is essential, since there are frame WM_COMMANDS generated
722: * by the MDI system for activating child windows via the
723: * window menu.
724: */
725: DefFrameProc(hwnd, hwndMDIClient, WM_COMMAND,
1.1.1.2 ! root 726: (WPARAM)MAKELONG(id, 0), (LONG)(0));
1.1 root 727: }
728: }
729:
730:
731: /****************************************************************************
732: * *
733: * FUNCTION : MPError (flags, id, ...) *
734: * *
735: * PURPOSE : Flashes a Message Box to the user. The format string is *
736: * taken from the STRINGTABLE. *
737: * *
738: * RETURNS : Returns value returned by MessageBox() to the caller. *
739: * *
740: ****************************************************************************/
741: INT FAR cdecl MPError(
742: DWORD bFlags,
743: DWORD id,
744: ...)
745: {
746: CHAR sz[160];
747: CHAR szFmt[128];
748:
749: LoadString (hInst, id, szFmt, sizeof (szFmt));
750: wvsprintf (sz, szFmt, (LPSTR)(&id + 1));
751: LoadString (hInst, IDS_APPNAME, szFmt, sizeof (szFmt));
752: return MessageBox (hwndFrame, sz, szFmt, bFlags);
753: }
754:
755:
756:
757: /****************************************************************************
758: * *
759: * FUNCTION : CreateConv() *
760: * *
761: * PURPOSE : *
762: * *
763: * RETURNS : *
764: * *
765: ****************************************************************************/
766: HCONV CreateConv(
767: HSZ hszApp,
768: HSZ hszTopic,
769: BOOL fList)
770: {
771: HCONV hConv;
772: HWND hwndConv = 0;
773: CONVINFO ci;
774:
775: if (fList) {
776: hConv = (HCONV)DdeConnectList(idInst, hszApp, hszTopic, NULL, &CCFilter);
777: } else {
778: hConv = DdeConnect(idInst, hszApp, hszTopic, &CCFilter);
779: }
780: if (hConv) {
781: if (fList) {
782: ci.hszSvcPartner = hszApp;
783: ci.hszTopic = hszTopic;
784: } else {
785: ci.cb = sizeof(CONVINFO);
786: DdeQueryConvInfo(hConv, QID_SYNC, &ci);
787: }
788: hwndConv = AddConv(ci.hszSvcPartner, ci.hszTopic, hConv, fList);
789: // HSZs get freed when window dies.
790: }
791: if (!hwndConv) {
792: DdeFreeStringHandle(idInst, hszApp);
793: DdeFreeStringHandle(idInst, hszTopic);
794: }
795: return(hConv);
796: }
797:
798:
799:
800:
801:
802:
803: /****************************************************************************
804: * *
805: * FUNCTION : AddConv() *
806: * *
807: * PURPOSE : Creates an MDI window representing a conversation *
808: * (fList = FALSE) or a set of MID windows for the list of *
809: * conversations (fList = TRUE). *
810: * *
811: * EFFECTS : Sets the hUser for the conversation to the created MDI *
812: * child hwnd. Keeps the hszs if successful. *
813: * *
814: * RETURNS : created MDI window handle. *
815: * *
816: ****************************************************************************/
817: HWND APIENTRY AddConv(
818: HSZ hszApp,
819: HSZ hszTopic,
820: HCONV hConv,
821: BOOL fList)
822: {
823: HWND hwnd;
824: MDICREATESTRUCT mcs;
825: MYCONVINFO mci;
826:
827: if (fList) {
828: /*
829: * Create all child windows FIRST so we have info for list window.
830: */
831: CONVINFO ci;
832: HCONV hConvChild = 0;
833:
834: ci.cb = sizeof(CONVINFO);
835: while (hConvChild = DdeQueryNextServer((HCONVLIST)hConv, hConvChild)) {
836: if (DdeQueryConvInfo(hConvChild, QID_SYNC, &ci)) {
837: AddConv(ci.hszSvcPartner, ci.hszTopic, hConvChild, FALSE);
838: }
839: }
840: }
841:
842: mcs.szTitle = GetConvTitleText(hConv, hszApp, hszTopic, fList);
843:
844: mcs.szClass = fList ? szList : szChild;
845: mcs.hOwner = hInst;
846: mcs.x = mcs.cx = CW_USEDEFAULT;
847: mcs.y = mcs.cy = CW_USEDEFAULT;
848: mcs.style = GetWindow(hwndMDIClient, GW_CHILD) ? 0L : WS_MAXIMIZE;
849:
850: // mci.hwndXaction =
851: mci.fList = fList;
852: mci.hConv = hConv;
853: mci.hszTopic = hszTopic;
854: mci.hszApp = hszApp;
855: // mci.x =
856: // mci.y =
857: // mci.ci =
858: mcs.lParam = (DWORD)(LPSTR)&mci;
859:
860: hwnd = (HWND)SendMessage (hwndMDIClient, WM_MDICREATE, 0,
861: (LONG)(LPMDICREATESTRUCT)&mcs);
862:
863: MyFree((PSTR)(DWORD)mcs.szTitle);
864:
865: return hwnd;
866: }
867:
868:
869:
870:
871:
872: /****************************************************************************
873: * *
874: * FUNCTION : GetConvListText() *
875: * *
876: * RETURN : Returns a ponter to a string containing a list of *
877: * conversations contained in the given hConvList freeable *
878: * by MyFree(); *
879: * *
880: ****************************************************************************/
881: PSTR GetConvListText(
882: HCONVLIST hConvList)
883: {
884: HCONV hConv = 0;
885: DWORD cConv = 0;
886: CONVINFO ci;
887: DWORD cb = 0;
888: CHAR *psz, *pszStart;
889:
890: ci.cb = sizeof(CONVINFO);
891:
892: // find out size needed.
893:
894: while (hConv = DdeQueryNextServer(hConvList, hConv)) {
895: if (DdeQueryConvInfo(hConv, QID_SYNC, &ci)) {
896: if (!IsWindow((HWND)ci.hUser)) {
897: if (ci.wStatus & ST_CONNECTED) {
898: /*
899: * This conversation doesn't have a corresponding
900: * MDI window. This is probably due to a reconnection.
901: */
902: ci.hUser = (DWORD)AddConv(ci.hszSvcPartner, ci.hszTopic, hConv, FALSE);
903: } else {
904: continue; // skip this guy - he was closed locally.
905: }
906: }
907: cb += GetWindowTextLength((HWND)ci.hUser);
908: if (cConv++)
909: cb += 2; // room for CRLF
910: }
911: }
912: cb++; // for terminator.
913:
914: // allocate and fill
915:
916: if (pszStart = psz = MyAlloc(cb)) {
917: *psz = '\0';
918: hConv = 0;
919: while (hConv = DdeQueryNextServer(hConvList, hConv)) {
920: if (DdeQueryConvInfo(hConv, QID_SYNC, &ci) &&
921: IsWindow((HWND)ci.hUser)) {
922: psz += GetWindowText((HWND)ci.hUser, psz, cb);
923: if (--cConv) {
924: *psz++ = '\r';
925: *psz++ = '\n';
926: }
927: }
928: }
929: }
930: return(pszStart);
931: }
932:
933:
934: /****************************************************************************
935: * *
936: * FUNCTION : GetConvInfoText() *
937: * *
938: * PURPOSE : Returns a pointer to a string that reflects a *
939: * conversation's information. Freeable by MyFree(); *
940: * *
941: ****************************************************************************/
942: PSTR GetConvInfoText(
943: HCONV hConv,
944: CONVINFO *pci)
945: {
946: PSTR psz;
947: PSTR szApp;
948:
949: psz = MyAlloc(300);
950: pci->cb = sizeof(CONVINFO);
951: if (hConv) {
952: if (!DdeQueryConvInfo(hConv, QID_SYNC, (PCONVINFO)pci)) {
953: strcpy(psz, "State=Disconnected");
954: return(psz);
955: }
956: szApp = GetHSZName(pci->hszServiceReq);
957: wsprintf(psz,
958: "hUser=0x%lx\r\nhConvPartner=0x%lx\r\nhszServiceReq=%s\r\nStatus=%s\r\nState=%s\r\nLastError=%s",
959: pci->hUser, pci->hConvPartner, (LPSTR)szApp,
960: (LPSTR)Status2String(pci->wStatus),
961: (LPSTR)State2String(pci->wConvst),
962: (LPSTR)Error2String(pci->wLastError));
963: MyFree(szApp);
964: } else {
965: strcpy(psz, Error2String(DdeGetLastError(idInst)));
966: }
967: return(psz);
968: }
969:
970:
971:
972: /****************************************************************************
973: * *
974: * FUNCTION : GetConvTitleText() *
975: * *
976: * PURPOSE : Creates standard window title text based on parameters. *
977: * *
978: * RETURNS : psz freeable by MyFree() *
979: * *
980: ****************************************************************************/
981: PSTR GetConvTitleText(
982: HCONV hConv,
983: HSZ hszApp,
984: HSZ hszTopic,
985: BOOL fList)
986: {
987: DWORD cb;
988: PSTR psz;
989:
990: cb = (DWORD)DdeQueryString(idInst, hszApp, NULL, 0, 0) +
991: (DWORD)DdeQueryString(idInst, hszTopic, (LPSTR)NULL, 0, 0) +
992: (fList ? 30 : 20);
993:
994: if (psz = MyAlloc(cb)) {
995: DdeQueryString(idInst, hszApp, psz, cb, 0);
996: strcat(psz, "|");
997: DdeQueryString(idInst, hszTopic, &psz[strlen(psz)], cb, 0);
998: if (fList)
999: strcat(psz, " - LIST");
1000: wsprintf(&psz[strlen(psz)], " - (%lx)", hConv);
1001: }
1002: return(psz);
1003: }
1004:
1005:
1006:
1007: /****************************************************************************
1008: * *
1009: * FUNCTION : Status2String() *
1010: * *
1011: * PURPOSE : Converts a conversation status word to a string and *
1012: * returns a pointer to that string. The string is valid *
1013: * till the next call to this function. *
1014: * *
1015: ****************************************************************************/
1016: PSTR Status2String(
1017: DWORD status)
1018: {
1019: DWORD c, i;
1020: static CHAR szStatus[6 * 18];
1021: static struct {
1022: CHAR *szStatus;
1023: DWORD status;
1024: } s2s[] = {
1025: { "Connected" , ST_CONNECTED },
1026: { "Advise" , ST_ADVISE },
1027: { "IsLocal" , ST_ISLOCAL },
1028: { "Blocked" , ST_BLOCKED },
1029: { "Client" , ST_CLIENT },
1030: { "Disconnected" , ST_TERMINATED },
1031: { "BlockNext" , ST_BLOCKNEXT },
1032: };
1033: #define CFLAGS 7
1034: szStatus[0] = '\0';
1035: c = 0;
1036: for (i = 0; i < CFLAGS; i++) {
1037: if (status & s2s[i].status) {
1038: if (c++)
1039: strcat(szStatus, " | ");
1040: strcat(szStatus, s2s[i].szStatus);
1041: }
1042: }
1043: return szStatus;
1044: #undef CFLAGS
1045: }
1046:
1047:
1048:
1049:
1050: /****************************************************************************
1051: * *
1052: * FUNCTION : State2String() *
1053: * *
1054: * PURPOSE : converts a conversation state word to a string and *
1055: * returns a pointer to that string. The string is valid *
1056: * till the next call to this routine. *
1057: * *
1058: ****************************************************************************/
1059: PSTR State2String(
1060: DWORD state)
1061: {
1062: static CHAR *s2s[] = {
1063: "NULL" ,
1064: "Incomplete" ,
1065: "Standby" ,
1066: "Initiating" ,
1067: "ReqSent" ,
1068: "DataRcvd" ,
1069: "PokeSent" ,
1070: "PokeAckRcvd" ,
1071: "ExecSent" ,
1072: "ExecAckRcvd" ,
1073: "AdvSent" ,
1074: "UnadvSent" ,
1075: "AdvAckRcvd" ,
1076: "UnadvAckRcvd" ,
1077: "AdvDataSent" ,
1078: "AdvDataAckRcvd" ,
1079: "?" , // 16
1080: };
1081:
1082: if (state >= 17)
1083: return s2s[17];
1084: else
1085: return s2s[state];
1086: }
1087:
1088: /****************************************************************************
1089: * *
1090: * FUNCTION : Error2String() *
1091: * *
1092: * PURPOSE : Converts an error code to a string and returns a pointer *
1093: * to that string. The string is valid until the next call *
1094: * to this function. *
1095: * *
1096: ****************************************************************************/
1097: PSTR Error2String(
1098: DWORD error)
1099: {
1100: static CHAR szErr[23];
1101: static CHAR *e2s[] = {
1102: "Advacktimeout" ,
1103: "Busy" ,
1104: "Dataacktimeout" ,
1105: "Dll_not_initialized" ,
1106: "Dll_usage" ,
1107: "Execacktimeout" ,
1108: "Invalidparameter" ,
1109: "Low Memory warning" ,
1110: "Memory_error" ,
1111: "Notprocessed" ,
1112: "No_conv_established" ,
1113: "Pokeacktimeout" ,
1114: "Postmsg_failed" ,
1115: "Reentrancy" ,
1116: "Server_died" ,
1117: "Sys_error" ,
1118: "Unadvacktimeout" ,
1119: "Unfound_queue_id" ,
1120: };
1121: if (!error) {
1122: strcpy(szErr, "0");
1123: } else if (error > DMLERR_LAST || error < DMLERR_FIRST) {
1124: strcpy(szErr, "???");
1125: } else {
1126: strcpy(szErr, e2s[error - DMLERR_FIRST]);
1127: }
1128: return(szErr);
1129: }
1130:
1131:
1132:
1133:
1134:
1135: /****************************************************************************
1136: * *
1137: * FUNCTION : Type2String() *
1138: * *
1139: * PURPOSE : Converts a wType word and fsOption flags to a string and *
1140: * returns a pointer to that string. the string is valid *
1141: * until the next call to this function. *
1142: * *
1143: ****************************************************************************/
1144: PSTR Type2String(
1145: DWORD wType,
1146: DWORD fsOptions)
1147: {
1148: static CHAR sz[30];
1149: static CHAR o2s[] = "^!#$X*<?";
1150: static CHAR *t2s[] = {
1151: "" ,
1152: "AdvData" ,
1153: "AdvReq" ,
1154: "AdvStart" ,
1155: "AdvStop" ,
1156: "Execute" ,
1157: "Connect" ,
1158: "ConnectConfirm" ,
1159: "XactComplete" ,
1160: "Poke" ,
1161: "Register" ,
1162: "Request" ,
1163: "Term" ,
1164: "Unregister" ,
1165: "WildConnect" ,
1166: "" ,
1167: };
1168: DWORD bit, c, i;
1169:
1170: strcpy(sz, t2s[((wType & XTYP_MASK) >> XTYP_SHIFT)]);
1171: c = strlen(sz);
1172: sz[c++] = ' ';
1173: for (i = 0, bit = 1; i < 7; bit = bit << 1, i++) {
1174: if (fsOptions & bit)
1175: sz[c++] = o2s[i];
1176: }
1177: sz[c] = '\0';
1178: return(sz);
1179: }
1180:
1181:
1182:
1183:
1184: /****************************************************************************
1185: * *
1186: * FUNCTION : GetHSZName() *
1187: * *
1188: * PURPOSE : Allocates local memory for and retrieves the string form *
1189: * of an HSZ. Returns a pointer to the local memory or NULL *
1190: * if failure. The string must be freed via MyFree(). *
1191: * *
1192: ****************************************************************************/
1193: PSTR GetHSZName(
1194: HSZ hsz)
1195: {
1196: PSTR psz;
1197: DWORD cb;
1198:
1199: cb = (DWORD)DdeQueryString(idInst, hsz, NULL, 0, 0) + 1;
1200: psz = MyAlloc(cb);
1201: DdeQueryString(idInst, hsz, psz, cb, 0);
1202: return(psz);
1203: }
1204:
1205:
1206: /****************************************************************************
1207: *
1208: * FUNCTION : MyMsgFilterProc
1209: *
1210: * PURPOSE : This filter proc gets called for each message we handle.
1211: * This allows our application to properly dispatch messages
1212: * that we might not otherwise see because of DDEMLs modal
1213: * loop that is used while processing synchronous transactions.
1214: *
1215: * Generally, applications that only do synchronous transactions
1216: * in response to user input (as this app does) does not need
1217: * to install such a filter proc because it would be very rare
1218: * that a user could command the app fast enough to cause
1219: * problems. However, this is included as an example.
1220: *
1221: ****************************************************************************/
1.1.1.2 ! root 1222: LRESULT CALLBACK MyMsgFilterProc(
! 1223: int nCode,
1.1 root 1224: WPARAM wParam,
1.1.1.2 ! root 1225: LPARAM lParam)
1.1 root 1226: {
1.1.1.2 ! root 1227: UNREFERENCED_PARAMETER(wParam);
1.1 root 1228:
1229: #define lpmsg ((LPMSG)lParam)
1230: if (nCode == MSGF_DDEMGR) {
1231:
1232: /* If a keyboard message is for the MDI , let the MDI client
1233: * take care of it. Otherwise, check to see if it's a normal
1234: * accelerator key. Otherwise, just handle the message as usual.
1235: */
1236:
1237: if ( !TranslateMDISysAccel (hwndMDIClient, lpmsg) &&
1238: !TranslateAccelerator (hwndFrame, hAccel, lpmsg)){
1239: TranslateMessage (lpmsg);
1240: DispatchMessage (lpmsg);
1241: }
1242: return(1);
1243: }
1.1.1.2 ! root 1244: if (nCode < 0) {
! 1245: CallNextHookEx(ghhk, nCode, wParam, lParam);
! 1246: }
1.1 root 1247: return(0);
1248: #undef lpmsg
1249: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.