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 / toolbox.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  19KB  |  627 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: toolbox.c
  14. *
  15. * Contains routines that handle the toolbox.
  16. *
  17. * Functions:
  18. *
  19. *    ToolboxShow()
  20. *    ToolboxOnTop()
  21. *    ToolboxWndProc()
  22. *    ToolBtnWndProc()
  23. *    ToolboxSelectTool()
  24. *    ToolboxCreate()
  25. *    ToolboxDrawBitmap()
  26. *
  27. * Comments:
  28. *
  29. ****************************************************************************/
  30.  
  31. #include "dlgedit.h"
  32. #include "dlgfuncs.h"
  33. #include "dlgextrn.h"
  34.  
  35. #include "dialogs.h"
  36.  
  37.  
  38. #define TOOLBOXMARGIN   2       // Pixels around the buttons in the Toolbox.
  39. #define TOOLBOXCOLUMNS  2       // Columns in the Toolbox.
  40.  
  41. /*
  42.  * Style of the toolbox window.
  43.  */
  44. #define TOOLBOXSTYLE    (WS_POPUP | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU)
  45.  
  46. STATICFN VOID ToolboxCreate(VOID);
  47. STATICFN VOID ToolboxDrawBitmap(HDC hDC, INT type);
  48.  
  49. /*
  50.  * Dimensions of a tool button bitmap.
  51.  */
  52. static INT cxToolBtn;
  53. static INT cyToolBtn;
  54.  
  55.  
  56.  
  57. /****************************************************************************
  58. * ToolboxShow
  59. *
  60. * This function shows or hides the toolbox window.  It will create
  61. * the Toolbox if necessary.
  62. *
  63. * Arguments:
  64. *   BOOL fShow - whether to show or hide the toolbox window.
  65. *
  66. ****************************************************************************/
  67.  
  68. VOID ToolboxShow(
  69.     BOOL fShow)
  70. {
  71.     if (fShow) {
  72.         /*
  73.          * Don't allow a toolbox to be shown in Translate mode.
  74.          */
  75.         if (gfTranslateMode)
  76.             return;
  77.  
  78.         /*
  79.          * Create it if it doesn't exist yet.
  80.          */
  81.         if (!ghwndToolbox)
  82.             ToolboxCreate();
  83.  
  84.         if (ghwndToolbox)
  85.             ShowWindow(ghwndToolbox, SW_SHOWNA);
  86.     }
  87.     else {
  88.         if (ghwndToolbox)
  89.             ShowWindow(ghwndToolbox, SW_HIDE);
  90.     }
  91. }
  92.  
  93.  
  94.  
  95. /****************************************************************************
  96. * ToolboxOnTop
  97. *
  98. * This function positions the toolbox window on top.  It needs to be
  99. * called any time that a new dialog window is created to be sure the
  100. * dialog does not cover the toolbox.
  101. *
  102. * It can be called even if the toolbox is not created yet (it will
  103. * be a noop in that case).
  104. *
  105. ****************************************************************************/
  106.  
  107. VOID ToolboxOnTop(VOID)
  108. {
  109.    if (ghwndToolbox) {
  110.        SetWindowPos(ghwndToolbox, NULL, 0, 0, 0, 0,
  111.                SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  112.    }
  113. }
  114.  
  115.  
  116.  
  117. /****************************************************************************
  118. * ToolboxCreate
  119. *
  120. * This function creates the toolbox window.
  121. *
  122. ****************************************************************************/
  123.  
  124. STATICFN VOID ToolboxCreate(VOID)
  125. {
  126.     BITMAP bmp;
  127.     INT i;
  128.     INT x;
  129.     INT y;
  130.     INT cx;
  131.     INT cy;
  132.     INT cxDummy;
  133.     INT cyDummy;
  134.     RECT rc;
  135.     RECT rcSubClient;
  136.     BOOL fMaximized;
  137.  
  138.     /*
  139.      * Load the bitmaps.
  140.      */
  141.     if (!(ghbmPointerToolUp = LoadBitmap(ghInst,
  142.             MAKEINTRESOURCE(IDBM_TUPOINTR))) ||
  143.             !(ghbmPointerToolDown = LoadBitmap(ghInst,
  144.             MAKEINTRESOURCE(IDBM_TDPOINTR))))
  145.         return;
  146.  
  147.     for (i = 0; i < CCONTROLS; i++) {
  148.         if (!(awcd[i].hbmToolBtnUp = LoadBitmap(ghInst,
  149.                 MAKEINTRESOURCE(awcd[i].idbmToolBtnUp))))
  150.             return;
  151.  
  152.         if (!(awcd[i].hbmToolBtnDown = LoadBitmap(ghInst,
  153.                 MAKEINTRESOURCE(awcd[i].idbmToolBtnDown))))
  154.             return;
  155.     }
  156.  
  157.     /*
  158.      * Get the dimensions of the tool button bitmaps.
  159.      */
  160.     GetObject(awcd[0].hbmToolBtnUp, sizeof(BITMAP), &bmp);
  161.     cxToolBtn = bmp.bmWidth;
  162.     cyToolBtn = bmp.bmHeight;
  163.  
  164.     /*
  165.      * Calculate the required window size for the client area
  166.      * size we want.  The size leaves room for a margin, and
  167.      * assumes that adjacent buttons overlap their borders by
  168.      * one pixel.
  169.      */
  170.     rc.left = 0;
  171.     rc.top = 0;
  172.     rc.right = TOOLBOXMARGIN + ((cxToolBtn - 1) * 2) + 1 + TOOLBOXMARGIN;
  173.     rc.bottom = TOOLBOXMARGIN + ((cyToolBtn - 1) *
  174.             ((CCONTROLS / 2) + 1)) + 1 + TOOLBOXMARGIN;
  175.     AdjustWindowRect(&rc, TOOLBOXSTYLE, FALSE);
  176.     cx = rc.right - rc.left;
  177.     cy = rc.bottom - rc.top;
  178.  
  179.     /*
  180.      * Get the saved position of the Toolbox.  Note that we throw away
  181.      * the size fields, because we just calculated the required size.
  182.      */
  183.     if (!ReadWindowPos(szTBPos, &x, &y, &cxDummy, &cyDummy, &fMaximized)) {
  184.         /*
  185.          * The previous position of the Toolbox  couldn't be found.
  186.          * Position the toolbox to the upper right corner of the
  187.          * "client" area of the editor, but make sure it is completely
  188.          * visible.
  189.          */
  190.         GetWindowRect(ghwndSubClient, &rcSubClient);
  191.         x = rcSubClient.right - cx - (2 * TOOLBOXMARGIN);
  192.         y = rcSubClient.top + (2 * TOOLBOXMARGIN);
  193.         SetRect(&rc, x, y, x + cx, y + cy);
  194.         FitRectToScreen(&rc);
  195.         x = rc.left;
  196.         y = rc.top;
  197.     }
  198.  
  199.     /*
  200.      * Create the toolbox window.
  201.      */
  202.     if (!(ghwndToolbox = CreateWindow(szToolboxClass, NULL, TOOLBOXSTYLE,
  203.             x, y, cx, cy, ghwndMain, NULL, ghInst, NULL)))
  204.         return;
  205.  
  206.     /*
  207.      * Create the Pointer (W_NOTHING) button.
  208.      */
  209.     CreateWindow(szToolBtnClass, NULL,
  210.             WS_CHILD | WS_VISIBLE,
  211.             TOOLBOXMARGIN, TOOLBOXMARGIN, (cxToolBtn * 2) - 1, cyToolBtn,
  212.             ghwndToolbox, (HMENU)W_NOTHING, ghInst, NULL);
  213.  
  214.     /*
  215.      * Create the other buttons.
  216.      */
  217.     x = TOOLBOXMARGIN;
  218.     y = TOOLBOXMARGIN + cyToolBtn - 1;
  219.     for (i = 0; i < CCONTROLS; i++) {
  220.         CreateWindow(szToolBtnClass, NULL,
  221.                 WS_CHILD | WS_VISIBLE,
  222.                 x, y, cxToolBtn, cyToolBtn,
  223.                 ghwndToolbox, (HMENU)i, ghInst, NULL);
  224.  
  225.         if (x == TOOLBOXMARGIN) {
  226.             x += cxToolBtn - 1;
  227.         }
  228.         else {
  229.             x = TOOLBOXMARGIN;
  230.             y += cyToolBtn - 1;
  231.         }
  232.     }
  233. }
  234.  
  235.  
  236.  
  237. /****************************************************************************
  238. * ToolboxWndProc
  239. *
  240. * This is the window procedure for the toolbox window.
  241. *
  242. ****************************************************************************/
  243.  
  244. WINDOWPROC ToolboxWndProc(
  245.     HWND hwnd,
  246.     UINT msg,
  247.     WPARAM wParam,
  248.     LPARAM lParam)
  249. {
  250.     switch (msg) {
  251.         case WM_CREATE:
  252.             {
  253.                 HMENU hmenu = GetSystemMenu(hwnd, FALSE);
  254.  
  255.                 RemoveMenu(hmenu, 7, MF_BYPOSITION);    // Second separator.
  256.                 RemoveMenu(hmenu, 5, MF_BYPOSITION);    // First separator.
  257.  
  258.                 RemoveMenu(hmenu, SC_RESTORE, MF_BYCOMMAND);
  259.                 RemoveMenu(hmenu, SC_SIZE, MF_BYCOMMAND);
  260.                 RemoveMenu(hmenu, SC_MINIMIZE, MF_BYCOMMAND);
  261.                 RemoveMenu(hmenu, SC_MAXIMIZE, MF_BYCOMMAND);
  262.                 RemoveMenu(hmenu, SC_TASKLIST, MF_BYCOMMAND);
  263.             }
  264.  
  265.             return 0;
  266.  
  267.         case WM_KEYDOWN:
  268.             {
  269.                 INT iToolNext;
  270.  
  271.                 switch (wParam) {
  272.                     case VK_UP:
  273.                         if ((GetKeyState(VK_SHIFT) & 0x8000) ||
  274.                                 (GetKeyState(VK_CONTROL) & 0x8000))
  275.                             break;
  276.  
  277.                         /*
  278.                          * Go up a row, but don't go beyond the top.
  279.                          */
  280.                         iToolNext = gCurTool - TOOLBOXCOLUMNS;
  281.                         if (iToolNext < 0)
  282.                             iToolNext = W_NOTHING;
  283.  
  284.                         ToolboxSelectTool(iToolNext, FALSE);
  285.  
  286.                         break;
  287.  
  288.                     case VK_DOWN:
  289.                         if ((GetKeyState(VK_SHIFT) & 0x8000) ||
  290.                                 (GetKeyState(VK_CONTROL) & 0x8000))
  291.                             break;
  292.  
  293.                         if (gCurTool == W_NOTHING) {
  294.                             iToolNext = 0;
  295.                         }
  296.                         else {
  297.                             /*
  298.                              * Go down a row, but don't go beyond the bottom.
  299.                              */
  300.                             iToolNext = gCurTool + TOOLBOXCOLUMNS;
  301.                             if (iToolNext >= CCONTROLS)
  302.                                 break;
  303.                         }
  304.  
  305.                         ToolboxSelectTool(iToolNext, FALSE);
  306.  
  307.                         break;
  308.  
  309.                     case VK_LEFT:
  310.                         if ((GetKeyState(VK_SHIFT) & 0x8000) ||
  311.                                 (GetKeyState(VK_CONTROL) & 0x8000))
  312.                             break;
  313.  
  314.                         if (gCurTool == W_NOTHING ||
  315.                                 !(gCurTool % TOOLBOXCOLUMNS))
  316.                             break;
  317.  
  318.                         /*
  319.                          * Go left a column.
  320.                          */
  321.                         ToolboxSelectTool(gCurTool - 1, FALSE);
  322.  
  323.                         break;
  324.  
  325.                     case VK_RIGHT:
  326.                         if ((GetKeyState(VK_SHIFT) & 0x8000) ||
  327.                                 (GetKeyState(VK_CONTROL) & 0x8000))
  328.                             break;
  329.  
  330.                         if (gCurTool == W_NOTHING ||
  331.                                 (gCurTool % TOOLBOXCOLUMNS) ==
  332.                                 TOOLBOXCOLUMNS - 1)
  333.                             break;
  334.  
  335.                         /*
  336.                          * Go right a column.
  337.                          */
  338.                         ToolboxSelectTool(gCurTool + 1, FALSE);
  339.  
  340.                         break;
  341.  
  342.                     case VK_TAB:
  343.                         if (GetKeyState(VK_CONTROL) & 0x8000)
  344.                             break;
  345.  
  346.                         /*
  347.                          * Is the shift key pressed also?
  348.                          */
  349.                         if (GetKeyState(VK_SHIFT) & 0x8000) {
  350.                             if (gCurTool == W_NOTHING)
  351.                                 iToolNext = CCONTROLS - 1;
  352.                             else if (gCurTool == 0)
  353.                                 iToolNext = W_NOTHING;
  354.                             else
  355.                                 iToolNext = gCurTool - 1;
  356.                         }
  357.                         else {
  358.                             if (gCurTool == W_NOTHING)
  359.                                 iToolNext = 0;
  360.                             else if (gCurTool == CCONTROLS - 1)
  361.                                 iToolNext = W_NOTHING;
  362.                             else
  363.                                 iToolNext = gCurTool + 1;
  364.                         }
  365.  
  366.                         ToolboxSelectTool(iToolNext, FALSE);
  367.  
  368.                         break;
  369.  
  370.                     case VK_END:
  371.                         if ((GetKeyState(VK_SHIFT) & 0x8000) ||
  372.                                 (GetKeyState(VK_CONTROL) & 0x8000))
  373.                             break;
  374.  
  375.                         ToolboxSelectTool(CCONTROLS - 1, FALSE);
  376.  
  377.                         break;
  378.  
  379.                     case VK_HOME:
  380.                     case VK_ESCAPE:
  381.                         if ((GetKeyState(VK_SHIFT) & 0x8000) ||
  382.                                 (GetKeyState(VK_CONTROL) & 0x8000))
  383.                             break;
  384.  
  385.                         ToolboxSelectTool(W_NOTHING, FALSE);
  386.  
  387.                         break;
  388.                 }
  389.             }
  390.  
  391.             break;
  392.  
  393.         case WM_ACTIVATE:
  394.             if (LOWORD(wParam))
  395.                 gidCurrentDlg = DID_TOOLBOX;
  396.  
  397.             break;
  398.  
  399.         case WM_CLOSE:
  400.             /*
  401.              * The user closed the toolbox from the system menu.
  402.              * Hide the toolbox (we don't actually destroy it so
  403.              * that it will appear in the same spot when they show
  404.              * it again).
  405.              */
  406.             ToolboxShow(FALSE);
  407.             gfShowToolbox = FALSE;
  408.             break;
  409.  
  410.         case WM_DESTROY:
  411.             {
  412.                 INT i;
  413.                 RECT rc;
  414.  
  415.                 DeleteObject(ghbmPointerToolUp);
  416.                 ghbmPointerToolUp = NULL;
  417.                 DeleteObject(ghbmPointerToolDown);
  418.                 ghbmPointerToolDown = NULL;
  419.  
  420.                 for (i = 0; i < CCONTROLS; i++) {
  421.                     DeleteObject(awcd[i].hbmToolBtnUp);
  422.                     awcd[i].hbmToolBtnUp = NULL;
  423.                     DeleteObject(awcd[i].hbmToolBtnDown);
  424.                     awcd[i].hbmToolBtnDown = NULL;
  425.                 }
  426.  
  427.                 /*
  428.                  * Save the position of the toolbox.
  429.                  */
  430.                 GetWindowRect(hwnd, &rc);
  431.                 WriteWindowPos(&rc, FALSE, szTBPos);
  432.  
  433.                 /*
  434.                  * Null out the global window handle for the toolbox
  435.                  * for safety's sake.
  436.                  */
  437.                 ghwndToolbox = NULL;
  438.             }
  439.  
  440.             break;
  441.  
  442.         default:
  443.             return DefWindowProc(hwnd, msg, wParam, lParam);
  444.     }
  445.  
  446.     return 0;
  447. }
  448.  
  449.  
  450.  
  451. /****************************************************************************
  452. * ToolBtnWndProc
  453. *
  454. * This is the window procedure for the buttons in the toolbox window.
  455. *
  456. ****************************************************************************/
  457.  
  458. WINDOWPROC ToolBtnWndProc(
  459.     HWND hwnd,
  460.     UINT msg,
  461.     WPARAM wParam,
  462.     LPARAM lParam)
  463. {
  464.     switch (msg) {
  465.         case WM_LBUTTONDOWN:
  466.             /*
  467.              * Be sure any outstanding changes get applied
  468.              * without errors.
  469.              */
  470.             if (!StatusApplyChanges())
  471.                 return TRUE;
  472.  
  473.             /*
  474.              * Select the tool that was clicked on.  If the Ctrl
  475.              * key is down, lock the tool also.
  476.              */
  477.             ToolboxSelectTool((UINT)GetWindowLong((hwnd), GWL_ID),
  478.                     (GetKeyState(VK_CONTROL) & 0x8000) ? TRUE : FALSE);
  479.  
  480.             break;
  481.  
  482.         case WM_PAINT:
  483.             {
  484.                 HDC hDC;
  485.                 PAINTSTRUCT ps;
  486.  
  487.                 hDC = BeginPaint(hwnd, &ps);
  488.                 ToolboxDrawBitmap(hDC, (UINT)GetWindowLong((hwnd), GWL_ID));
  489.                 EndPaint(hwnd, &ps);
  490.             }
  491.  
  492.             break;
  493.  
  494.         default:
  495.             return DefWindowProc(hwnd, msg, wParam, lParam);
  496.     }
  497.  
  498.     return 0;
  499. }
  500.  
  501.  
  502.  
  503. /****************************************************************************
  504. * ToolboxDrawBitmap
  505. *
  506. * Draws the current tool bitmap.
  507. *
  508. * Arguments:
  509. *   HDC hDC - handle to the DC for the toolbox window.
  510. *   INR type - type of bitmap to draw.
  511. *
  512. ****************************************************************************/
  513.  
  514. STATICFN VOID ToolboxDrawBitmap(
  515.     HDC hDC,
  516.     INT type)
  517. {
  518.     HDC hMemDC;
  519.     HBITMAP hbm;
  520.     HBITMAP hbmOld;
  521.     INT cxBitmap;
  522.  
  523.     if (type == W_NOTHING) {
  524.         hbm = (type == gCurTool) ? ghbmPointerToolDown : ghbmPointerToolUp;
  525.  
  526.         /*
  527.          * Note that the size of the Pointer tool is twice the width
  528.          * of the other bitmaps, but less one pixel.  This is because
  529.          * the other tools overlap their adjacent borders.
  530.          */
  531.         cxBitmap = (cxToolBtn * 2) - 1;
  532.     }
  533.     else {
  534.         hbm = (type == gCurTool) ?
  535.                 awcd[type].hbmToolBtnDown : awcd[type].hbmToolBtnUp;
  536.         cxBitmap = cxToolBtn;
  537.     }
  538.  
  539.     /*
  540.      * Draw the image.
  541.      */
  542.     hMemDC = CreateCompatibleDC(hDC);
  543.     hbmOld = SelectObject(hMemDC, hbm);
  544.     BitBlt(hDC, 0, 0, cxBitmap, cyToolBtn, hMemDC, 0, 0, SRCCOPY);
  545.     SelectObject(hMemDC, hbmOld);
  546.     DeleteDC(hMemDC);
  547. }
  548.  
  549.  
  550.  
  551. /****************************************************************************
  552. * ToolboxSelectTool
  553. *
  554. * This function selects a tool to be the current tool.
  555. *
  556. * Arguments:
  557. *   INT type   - Type of control (one of the W_* defines).
  558. *   BOOL fLock - TRUE if the tool should be locked down.
  559. *
  560. ****************************************************************************/
  561.  
  562. VOID ToolboxSelectTool(
  563.     INT type,
  564.     BOOL fLock)
  565. {
  566.     PWINDOWCLASSDESC pwcd;
  567.  
  568.     if (gCurTool != type) {
  569.         /*
  570.          * Set the current wcd global for the current tool type.
  571.          * This will point to the WINDOWCLASSDESC structure of the
  572.          * current tool.  If the Custom tool was selected, the user
  573.          * is asked which of the installed custom controls that they
  574.          * really want.
  575.          */
  576.         if (type == W_CUSTOM) {
  577.             /*
  578.              * There are no custom controls installed.  Beep and
  579.              * return without doing anything.
  580.              */
  581.             if (!gpclHead) {
  582.                 MessageBeep(0);
  583.                 return;
  584.             }
  585.  
  586.             /*
  587.              * If there are multiple custom controls installed,
  588.              * ask the user which one they want.  Note that they
  589.              * can press Cancel and return NULL!
  590.              */
  591.             if (gpclHead->pclNext) {
  592.                 if (!(pwcd = SelCustDialog()))
  593.                     return;
  594.  
  595.                 gpwcdCurTool = pwcd;
  596.             }
  597.             else {
  598.                 /*
  599.                  * Since there is only one type of custom control
  600.                  * installed, there is no need to ask the user
  601.                  * which one they want.
  602.                  */
  603.                 gpwcdCurTool = gpclHead->pwcd;
  604.             }
  605.         }
  606.         else {
  607.             gpwcdCurTool = (type == W_NOTHING) ? NULL : &awcd[type];
  608.         }
  609.  
  610.         /*
  611.          * Force the previous and current buttons to repaint.
  612.          */
  613.         if (ghwndToolbox) {
  614.             InvalidateRect(GetDlgItem(ghwndToolbox, gCurTool), NULL, FALSE);
  615.             InvalidateRect(GetDlgItem(ghwndToolbox, type), NULL, FALSE);
  616.         }
  617.  
  618.         /*
  619.          * Set the current tool type global.  This will be W_CUSTOM for
  620.          * all custom controls.
  621.          */
  622.         gCurTool = type;
  623.     }
  624.  
  625.     gfToolLocked = fLock;
  626. }
  627.