|
|
1.1 ! 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: ! 12: /****************************** Module Header ******************************* ! 13: * Module Name: ctrlproc.c ! 14: * ! 15: * Contains the window procedures for controls in the dialog being edited. ! 16: * ! 17: * Functions: ! 18: * ! 19: * DialogCtrlWndProc() ! 20: * CtrlWndProc() ! 21: * ChildWndProc() ! 22: * DrawOwnerDrawButton() ! 23: * ! 24: * Comments: ! 25: * ! 26: ****************************************************************************/ ! 27: ! 28: #include "dlgedit.h" ! 29: #include "dlgfuncs.h" ! 30: #include "dlgextrn.h" ! 31: ! 32: ! 33: ! 34: /************************************************************************ ! 35: * DialogCtrlWndProc ! 36: * ! 37: * This is the window procedure that subclasses the dialog being ! 38: * edited. It handles a few messages that have to be special-cased ! 39: * for the dialog. Most messages, however, are passed on to the ! 40: * generic control subclass procedure (CtrlWndProc). ! 41: * ! 42: * Arguments: ! 43: * HWND - Handle to the dialog window ! 44: * UINT - window message ! 45: * WPARAM - message parameter ! 46: * LPARAM - message parameter ! 47: * ! 48: * Returns: ! 49: * The default window procedure ! 50: * ! 51: ************************************************************************/ ! 52: ! 53: WINDOWPROC DialogCtrlWndProc( ! 54: HWND hwnd, ! 55: UINT msg, ! 56: WPARAM wParam, ! 57: LPARAM lParam) ! 58: { ! 59: POINT pt; ! 60: BOOL fTracking; ! 61: ! 62: switch (msg) { ! 63: case WM_NCPAINT: ! 64: case WM_PAINT: ! 65: if (gfTrackRectShown) { ! 66: fTracking = TRUE; ! 67: HideTrackRect(); ! 68: } ! 69: else { ! 70: fTracking = FALSE; ! 71: } ! 72: ! 73: /* ! 74: * Allow the dialog to paint first. ! 75: */ ! 76: CallWindowProc((WNDPROC)CtrlWndProc, hwnd, msg, wParam, lParam); ! 77: ! 78: /* ! 79: * Draw the handles if the dialog is selected. ! 80: */ ! 81: if (gfDlgSelected) { ! 82: HDC hDC; ! 83: ! 84: hDC = GetWindowDC(hwnd); ! 85: DrawHandles(hwnd, hDC, TRUE); ! 86: ReleaseDC(hwnd, hDC); ! 87: } ! 88: ! 89: if (fTracking) ! 90: ShowTrackRect(); ! 91: ! 92: break; ! 93: ! 94: case WM_LBUTTONDOWN: ! 95: /* ! 96: * Discard all mouse messages during certain operations. ! 97: */ ! 98: if (gfDisabled) ! 99: break; ! 100: ! 101: /* ! 102: * Also, be sure any outstanding changes get applied ! 103: * without errors. ! 104: */ ! 105: if (!StatusApplyChanges()) ! 106: break; ! 107: ! 108: /* ! 109: * Check to see if we are in a normal mode. If we are ! 110: * in some other mode, like dragging a new control, ! 111: * we want to ignore this mouse down and wait for the ! 112: * mouse up. For instance, this can happen when the ! 113: * Duplicate command is selected from the Edit menu. ! 114: */ ! 115: if (gState == STATE_NORMAL) { ! 116: ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y); ! 117: MapDlgClientPoint(&pt, TRUE); ! 118: ! 119: /* ! 120: * Is the dialog selected and was one of its handles hit? ! 121: * If so, call CtrlButtonDown as if we are a drag window. ! 122: */ ! 123: if (gfDlgSelected && ! 124: HandleHitTest(hwnd, pt.x, pt.y) != DRAG_CENTER) { ! 125: CtrlButtonDown(hwnd, pt.x, pt.y, TRUE); ! 126: } ! 127: else { ! 128: /* ! 129: * If the click was within the client area and ! 130: * there is not a tool selected, start an outline ! 131: * selection operation. Otherwise call CtrlButtonDown ! 132: * which will either begin dragging the dialog or ! 133: * dragging the new control. ! 134: */ ! 135: if (gCurTool == W_NOTHING && ! 136: PtInRect(&grcDlgClient, pt)) ! 137: OutlineSelectBegin(pt.x, pt.y); ! 138: else ! 139: CtrlButtonDown(hwnd, pt.x, pt.y, FALSE); ! 140: } ! 141: } ! 142: ! 143: break; ! 144: ! 145: case WM_MOUSEMOVE: ! 146: ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y); ! 147: ! 148: /* ! 149: * If we are not dragging a new control, then this ! 150: * message is for the dialog, and we map it from ! 151: * the dialog client to the dialog window. ! 152: */ ! 153: if (gState != STATE_DRAGGINGNEW) ! 154: MapDlgClientPoint(&pt, TRUE); ! 155: ! 156: /* ! 157: * Now we process the mouse move message. If the dialog is ! 158: * selected, and if we are not dragging a new control, we ! 159: * pass in a TRUE for fDragWindow. This is because the ! 160: * dialog itself does not have a separate drag window like ! 161: * controls, and if it is selected this message needs to ! 162: * be processed as if a drag window was hit. ! 163: */ ! 164: CtrlMouseMove(hwnd, ! 165: (gfDlgSelected && gState != STATE_DRAGGINGNEW) ? ! 166: TRUE : FALSE, pt.x, pt.y); ! 167: ! 168: break; ! 169: ! 170: case WM_LBUTTONUP: ! 171: ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y); ! 172: ! 173: /* ! 174: * If we are not dragging a new control, then this ! 175: * message is for the dialog, and we map it from ! 176: * the dialog client to the dialog window. ! 177: */ ! 178: if (gState != STATE_DRAGGINGNEW) ! 179: MapDlgClientPoint(&pt, TRUE); ! 180: ! 181: CtrlButtonUp(pt.x, pt.y); ! 182: ! 183: break; ! 184: ! 185: case WM_DRAWITEM: ! 186: return DrawOwnerDrawButton((LPDRAWITEMSTRUCT)lParam); ! 187: ! 188: default: ! 189: return CallWindowProc( ! 190: (WNDPROC)CtrlWndProc, hwnd, msg, wParam, lParam); ! 191: } ! 192: ! 193: return 0L; ! 194: } ! 195: ! 196: ! 197: ! 198: /************************************************************************ ! 199: * CtrlWndProc ! 200: * ! 201: * This is the window procedure that subclasses all of the controls. ! 202: * The dialog being edited will also pass messages that it does not ! 203: * handle through this procedure. ! 204: * ! 205: * Arguments: ! 206: * HWND - Handle to the control window ! 207: * UINT - window message ! 208: * WPARAM - message parameter ! 209: * LPARAM - message parameter ! 210: * ! 211: * Returns: ! 212: * The default window procedure ! 213: * ! 214: ************************************************************************/ ! 215: ! 216: WINDOWPROC CtrlWndProc( ! 217: HWND hwnd, ! 218: UINT msg, ! 219: WPARAM wParam, ! 220: LPARAM lParam) ! 221: { ! 222: POINT pt; ! 223: ! 224: switch (msg) { ! 225: case WM_NCPAINT: ! 226: case WM_PAINT: ! 227: { ! 228: BOOL fTracking; ! 229: ! 230: if (gfTrackRectShown) { ! 231: fTracking = TRUE; ! 232: HideTrackRect(); ! 233: } ! 234: else { ! 235: fTracking = FALSE; ! 236: } ! 237: ! 238: /* ! 239: * Allow the control to paint first. ! 240: */ ! 241: CallWindowProc((WNDPROC)PCFROMHWND(hwnd)->pwcd->pfnOldWndProc, ! 242: hwnd, msg, wParam, lParam); ! 243: ! 244: if (fTracking) ! 245: ShowTrackRect(); ! 246: } ! 247: ! 248: break; ! 249: ! 250: case WM_SETCURSOR: ! 251: /* ! 252: * Defeat the system changing cursors on us. We do it based ! 253: * on our own hit testing. ! 254: */ ! 255: return TRUE; ! 256: ! 257: case WM_TIMER: ! 258: PreDragTimeout(hwnd, TRUE); ! 259: break; ! 260: ! 261: case WM_LBUTTONDOWN: ! 262: ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y); ! 263: CtrlButtonDown(hwnd, pt.x, pt.y, FALSE); ! 264: break; ! 265: ! 266: case WM_MOUSEMOVE: ! 267: ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y); ! 268: CtrlMouseMove(hwnd, FALSE, pt.x, pt.y); ! 269: break; ! 270: ! 271: case WM_LBUTTONUP: ! 272: ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y); ! 273: CtrlButtonUp(pt.x, pt.y); ! 274: break; ! 275: ! 276: case WM_LBUTTONDBLCLK: ! 277: if (gfDisabled) ! 278: break; ! 279: ! 280: /* ! 281: * Also, be sure any outstanding changes get applied ! 282: * without errors. ! 283: */ ! 284: if (!StatusApplyChanges()) ! 285: break; ! 286: ! 287: StylesDialog(); ! 288: ! 289: break; ! 290: ! 291: case WM_NCHITTEST: ! 292: return HTCLIENT; ! 293: ! 294: case WM_RBUTTONDOWN: ! 295: case WM_MBUTTONDOWN: ! 296: case WM_RBUTTONDBLCLK: ! 297: case WM_MBUTTONDBLCLK: ! 298: /* ! 299: * Helps prevent anything from happening when ! 300: * the middle or right mouse buttons are pressed ! 301: * (or doubleclicked). ! 302: */ ! 303: break; ! 304: ! 305: case WM_MOUSEACTIVATE: ! 306: /* ! 307: * Defeat this message so that mouse clicks do not activate ! 308: * the control. ! 309: */ ! 310: return MA_NOACTIVATE; ! 311: ! 312: case WM_DESTROY: ! 313: /* ! 314: * Unsubclass the control. ! 315: */ ! 316: SetWindowLong(hwnd, GWL_WNDPROC, ! 317: (DWORD)(WNDPROC)(PCFROMHWND(hwnd)->pwcd->pfnOldWndProc)); ! 318: ! 319: UNSETPCINTOHWND(hwnd); ! 320: ! 321: break; ! 322: ! 323: default: ! 324: return CallWindowProc( ! 325: (WNDPROC)PCFROMHWND(hwnd)->pwcd->pfnOldWndProc, ! 326: hwnd, msg, wParam, lParam); ! 327: } ! 328: ! 329: return 0L; ! 330: } ! 331: ! 332: ! 333: ! 334: /************************************************************************ ! 335: * ChildWndProc ! 336: * ! 337: * This is the window procedure that subclasses all of the children ! 338: * of controls that have them. Currently this is only comboboxes. ! 339: * ! 340: * Arguments: ! 341: * HWND - Handle to the child control window ! 342: * UINT - window message ! 343: * WPARAM - message parameter ! 344: * LPARAM - message parameter ! 345: * ! 346: * Returns: ! 347: * The default window procedure ! 348: * ! 349: ************************************************************************/ ! 350: ! 351: WINDOWPROC ChildWndProc( ! 352: HWND hwnd, ! 353: UINT msg, ! 354: WPARAM wParam, ! 355: LPARAM lParam) ! 356: { ! 357: /* ! 358: * Is this a mouse message? ! 359: */ ! 360: if (msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) { ! 361: POINT pt; ! 362: ! 363: /* ! 364: * Yes, convert the coordinates and send it to the parent. ! 365: */ ! 366: ((pt).x = (SHORT)LOWORD(lParam), (pt).y = (SHORT)HIWORD(lParam)); ! 367: ClientToScreen(hwnd, &pt); ! 368: ScreenToClient(GetParent(hwnd), &pt); ! 369: POINT2LONG(pt, lParam); ! 370: SendMessage(GetParent(hwnd), msg, wParam, lParam); ! 371: return FALSE; ! 372: } ! 373: else if (msg == WM_SETCURSOR) { ! 374: /* ! 375: * Defeat the system changing cursors on us. We do it based ! 376: * on our own hit testing. ! 377: */ ! 378: return TRUE; ! 379: } ! 380: else if (msg == WM_NCDESTROY) { ! 381: /* ! 382: * Unsubclass the child. ! 383: */ ! 384: SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)(WNDPROC)GETCHILDPROC(hwnd)); ! 385: ! 386: /* ! 387: * When destroying the child window, we must be sure and ! 388: * remove the properties associated with it. ! 389: */ ! 390: UNSETCHILDPROC(hwnd); ! 391: ! 392: return 0; ! 393: } ! 394: else { ! 395: /* ! 396: * A benign message, call the class proc. ! 397: */ ! 398: return CallWindowProc(GETCHILDPROC(hwnd), hwnd, msg, wParam, lParam); ! 399: } ! 400: } ! 401: ! 402: ! 403: ! 404: /************************************************************************ ! 405: * DrawOwnerDrawButton ! 406: * ! 407: * Draws the owner-draw buttons. ! 408: * ! 409: * Arguments: ! 410: * LPDRAWITEMSTRUCT - owner-draw item structure ! 411: * ! 412: * Returns: ! 413: * TRUE if the button was drawn; FALSE if the button could not be drawn. ! 414: * ! 415: ************************************************************************/ ! 416: ! 417: BOOL DrawOwnerDrawButton( ! 418: LPDRAWITEMSTRUCT lpdis) ! 419: { ! 420: TCHAR szText[CCHTEXTMAX]; ! 421: ! 422: if (lpdis->CtlType != ODT_BUTTON || lpdis->itemAction != ODA_DRAWENTIRE) ! 423: return FALSE; ! 424: ! 425: RoundRect(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, ! 426: lpdis->rcItem.right, lpdis->rcItem.bottom, 4, 4); ! 427: ! 428: GetWindowText(lpdis->hwndItem, szText, CCHTEXTMAX); ! 429: SetBkMode(lpdis->hDC, TRANSPARENT); ! 430: ! 431: if (gcd.hFont) ! 432: SelectObject(lpdis->hDC, gcd.hFont); ! 433: ! 434: DrawText(lpdis->hDC, szText, -1, &lpdis->rcItem, ! 435: DT_CENTER | DT_NOCLIP | DT_VCENTER | DT_SINGLELINE); ! 436: ! 437: return TRUE; ! 438: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.