CTRLPROC.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:13k
源码类别:

Windows编程

开发平台:

Visual C++

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