home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / dlgedit / ctrlproc.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  13KB  |  448 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-1997 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. #ifdef JAPAN
  435.     {
  436.         TCHAR   szTmp[CCHTEXTMAX];
  437.  
  438.         KDExpandCopy(szTmp, szText, CCHTEXTMAX);
  439.         lstrcpy(szText, szTmp);
  440.     }
  441. #endif
  442.  
  443.     DrawText(lpdis->hDC, szText, -1, &lpdis->rcItem,
  444.             DT_CENTER | DT_NOCLIP | DT_VCENTER | DT_SINGLELINE);
  445.  
  446.     return TRUE;
  447. }
  448.