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