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