/****************************************************************************/ /* */ /* Copyright (C) 1987-1996 Microsoft Corp. */ /* All Rights Reserved */ /* */ /****************************************************************************/ /****************************** Module Header ******************************* * Module Name: toolbox.c * * Contains routines that handle the toolbox. * * History: * * 04/30/91 - Copied from DlgEdit. * ****************************************************************************/ #include "imagedit.h" #include "dialogs.h" #include #define TOOLBOXCOLUMNS 2 // Columns in the Toolbox. /* * Style of the toolbox window. */ #define TOOLBOXSTYLE (WS_POPUP | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU) STATICFN VOID NEAR ToolboxDrawBitmap(HDC hDC, INT tool); /* * Dimensions of a tool button bitmap. */ static INT cxToolBtn; static INT cyToolBtn; /* * Index to the last available tool. If tools at the end of the * toolbox are disabled, this number gets lowered. */ static INT iToolLast = CTOOLS - 1; /**************************************************************************** * ToolboxCreate * * This function creates the toolbox window. * * History: * ****************************************************************************/ VOID ToolboxCreate(VOID) { BITMAP bmp; INT i; INT x; INT y; INT cx; INT cy; INT cxDummy; INT cyDummy; RECT rc; RECT rcClient; POINT pt; BOOL fMaximized; /* * Load the bitmaps. */ for (i = 0; i < CTOOLS; i++) { if (!(gaTools[i].hbmToolBtnUp = LoadBitmap(ghInst, MAKEINTRESOURCE(gaTools[i].idbmToolBtnUp)))) return; if (!(gaTools[i].hbmToolBtnDown = LoadBitmap(ghInst, MAKEINTRESOURCE(gaTools[i].idbmToolBtnDown)))) return; } /* * Get the dimensions of the tool button bitmaps. */ GetObject(gaTools[0].hbmToolBtnUp, sizeof(BITMAP), (PSTR)&bmp); cxToolBtn = bmp.bmWidth; cyToolBtn = bmp.bmHeight; /* * Calculate the required window size for the client area * size we want. The size leaves room for a margin, and * assumes that adjacent buttons overlap their borders by * one pixel. */ rc.left = 0; rc.top = 0; rc.right = PALETTEMARGIN + ((cxToolBtn - 1) * 2) + 1 + PALETTEMARGIN; rc.bottom = PALETTEMARGIN + ((cyToolBtn - 1) * (CTOOLS / 2)) + 1 + PALETTEMARGIN; AdjustWindowRect(&rc, TOOLBOXSTYLE, FALSE); cx = rc.right - rc.left; cy = rc.bottom - rc.top; /* * Get the saved position of the Toolbox. Note that we throw away * the size fields, because we just calculated the required size. */ if (!ReadWindowPos(szTBPos, &x, &y, &cxDummy, &cyDummy, &fMaximized)) { /* * The previous position of the Toolbox couldn't be found. * Position the toolbox to the upper right corner of the * client area of the editor, but make sure it is completely * visible. */ GetClientRect(ghwndMain, &rcClient); pt.x = rcClient.right - cx - (2 * PALETTEMARGIN); pt.y = rcClient.top + gcyPropBar + (2 * PALETTEMARGIN); ClientToScreen(ghwndMain, &pt); SetRect(&rc, pt.x, pt.y, pt.x + cx, pt.y + cy); FitRectToScreen(&rc); x = rc.left; y = rc.top; } if (!(ghwndToolbox = CreateWindow(szToolboxClass, NULL, TOOLBOXSTYLE, x, y, cx, cy, ghwndMain, NULL, ghInst, NULL))) return; /* * Create the buttons. */ x = PALETTEMARGIN; y = PALETTEMARGIN; for (i = 0; i < CTOOLS; i++) { CreateWindow(szToolBtnClass, NULL, WS_CHILD | WS_VISIBLE, x, y, cxToolBtn, cyToolBtn, ghwndToolbox, (HMENU)i, ghInst, NULL); if (x == PALETTEMARGIN) { x += cxToolBtn - 1; } else { x = PALETTEMARGIN; y += cyToolBtn - 1; } } ToolboxUpdate(); } /**************************************************************************** * ToolboxShow * * This function shows or hides the toolbox window. * * History: * ****************************************************************************/ VOID ToolboxShow( BOOL fShow) { if (fShow) ShowWindow(ghwndToolbox, SW_SHOWNA); else ShowWindow(ghwndToolbox, SW_HIDE); } /**************************************************************************** * ToolboxUpdate * * This function updates the toolbox. It should be called any time that * a new file is opened/created for editing. * * History: * ****************************************************************************/ VOID ToolboxUpdate(VOID) { if (!ghwndToolbox) return; if (giType == FT_CURSOR) { ShowWindow(GetDlgItem(ghwndToolbox, TOOL_HOTSPOT), SW_SHOWNA); iToolLast = CTOOLS - 1; } else { ShowWindow(GetDlgItem(ghwndToolbox, TOOL_HOTSPOT), SW_HIDE); iToolLast = TOOL_HOTSPOT - 1; if (gCurTool == TOOL_HOTSPOT) ToolboxSelectTool(TOOL_FIRST); } } /**************************************************************************** * ToolboxWndProc * * This is the window procedure for the toolbox window. * * History: * ****************************************************************************/ WINDOWPROC ToolboxWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: { HMENU hmenu = GetSystemMenu(hwnd, FALSE); RemoveMenu(hmenu, 7, MF_BYPOSITION); // Second separator. RemoveMenu(hmenu, 5, MF_BYPOSITION); // First separator. RemoveMenu(hmenu, SC_RESTORE, MF_BYCOMMAND); RemoveMenu(hmenu, SC_SIZE, MF_BYCOMMAND); RemoveMenu(hmenu, SC_MINIMIZE, MF_BYCOMMAND); RemoveMenu(hmenu, SC_MAXIMIZE, MF_BYCOMMAND); RemoveMenu(hmenu, SC_TASKLIST, MF_BYCOMMAND); } return 0; case WM_KEYDOWN: { INT iToolNext; switch (wParam) { case VK_UP: if ((GetKeyState(VK_SHIFT) & 0x8000) || (GetKeyState(VK_CONTROL) & 0x8000)) break; /* * Go up a row, but don't go beyond the top. */ iToolNext = gCurTool - TOOLBOXCOLUMNS; if (iToolNext < 0) break; ToolboxSelectTool(iToolNext); break; case VK_DOWN: if ((GetKeyState(VK_SHIFT) & 0x8000) || (GetKeyState(VK_CONTROL) & 0x8000)) break; /* * Go down a row, but don't go beyond the bottom. */ iToolNext = gCurTool + TOOLBOXCOLUMNS; if (iToolNext > iToolLast) break; ToolboxSelectTool(iToolNext); break; case VK_LEFT: if ((GetKeyState(VK_SHIFT) & 0x8000) || (GetKeyState(VK_CONTROL) & 0x8000)) break; /* * Already at left edge. */ if (!(gCurTool % TOOLBOXCOLUMNS)) break; /* * Go left a column. */ ToolboxSelectTool(gCurTool - 1); break; case VK_RIGHT: if ((GetKeyState(VK_SHIFT) & 0x8000) || (GetKeyState(VK_CONTROL) & 0x8000)) break; /* * Already at right edge. */ if ((gCurTool % TOOLBOXCOLUMNS) == TOOLBOXCOLUMNS - 1) break; /* * Don't go off the end of the available tools. */ if (gCurTool + 1 > iToolLast) break; /* * Go right a column. */ ToolboxSelectTool(gCurTool + 1); break; case VK_TAB: if (GetKeyState(VK_CONTROL) & 0x8000) break; /* * Is the shift key pressed also? */ if (GetKeyState(VK_SHIFT) & 0x8000) { if (gCurTool == TOOL_FIRST) iToolNext = iToolLast; else iToolNext = gCurTool - 1; } else { if (gCurTool == iToolLast) iToolNext = TOOL_FIRST; else iToolNext = gCurTool + 1; } ToolboxSelectTool(iToolNext); break; case VK_END: if ((GetKeyState(VK_SHIFT) & 0x8000) || (GetKeyState(VK_CONTROL) & 0x8000)) break; ToolboxSelectTool(iToolLast); break; case VK_HOME: case VK_ESCAPE: if ((GetKeyState(VK_SHIFT) & 0x8000) || (GetKeyState(VK_CONTROL) & 0x8000)) break; ToolboxSelectTool(TOOL_FIRST); break; } } break; case WM_ACTIVATE: if (GET_WM_ACTIVATE_STATE(wParam, lParam)) gidCurrentDlg = DID_TOOLBOX; break; case WM_PAINT: { HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(hwnd, &ps); DrawMarginBorder(hwnd, hdc); EndPaint(hwnd, &ps); } break; case WM_CLOSE: /* * The user closed the toolbox from the system menu. * Hide the toolbox (we don't actually destroy it so * that it will appear in the same spot when they show * it again). */ ToolboxShow(FALSE); gfShowToolbox = FALSE; break; case WM_DESTROY: { INT i; RECT rc; for (i = 0; i < CTOOLS; i++) { DeleteObject(gaTools[i].hbmToolBtnUp); gaTools[i].hbmToolBtnUp = NULL; DeleteObject(gaTools[i].hbmToolBtnDown); gaTools[i].hbmToolBtnDown = NULL; } /* * Save the position of the toolbox. */ GetWindowRect(hwnd, &rc); WriteWindowPos(&rc, FALSE, szTBPos); /* * Null out the global window handle for the toolbox * for safety's sake. */ ghwndToolbox = NULL; } break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } /**************************************************************************** * ToolBtnWndProc * * This is the window procedure for the buttons in the toolbox window. * * History: * ****************************************************************************/ WINDOWPROC ToolBtnWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_LBUTTONDOWN: /* * Select the tool that was clicked on. */ ToolboxSelectTool((UINT)GetWindowLong((hwnd), GWL_ID)); break; case WM_PAINT: { HDC hDC; PAINTSTRUCT ps; hDC = BeginPaint(hwnd, &ps); ToolboxDrawBitmap(hDC, (UINT)GetWindowLong((hwnd), GWL_ID)); EndPaint(hwnd, &ps); } break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } /**************************************************************************** * ToolboxDrawBitmap * * * History: * ****************************************************************************/ STATICFN VOID NEAR ToolboxDrawBitmap( HDC hDC, INT tool) { HDC hMemDC; HBITMAP hbmOld; /* * Draw the image. */ hMemDC = CreateCompatibleDC(hDC); hbmOld = SelectObject(hMemDC, (tool == gCurTool) ? gaTools[tool].hbmToolBtnDown : gaTools[tool].hbmToolBtnUp); BitBlt(hDC, 0, 0, cxToolBtn, cyToolBtn, hMemDC, 0, 0, SRCCOPY); SelectObject(hMemDC, hbmOld); DeleteDC(hMemDC); } /**************************************************************************** * ToolboxSelectTool * * * History: * ****************************************************************************/ VOID ToolboxSelectTool( INT tool) { if (gCurTool != tool) { if (ghwndToolbox) { InvalidateRect(GetDlgItem(ghwndToolbox, gCurTool), NULL, FALSE); InvalidateRect(GetDlgItem(ghwndToolbox, tool), NULL, FALSE); } gCurTool = tool; gpfnDrawProc = gaTools[gCurTool].pfnDrawProc; } }