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