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 >
Wrap
C/C++ Source or Header
|
1997-10-05
|
19KB
|
627 lines
/******************************************************************************\
* This is a part of the Microsoft Source Code Samples.
* Copyright (C) 1993-1997 Microsoft Corporation.
* All rights reserved.
* This source code is only intended as a supplement to
* Microsoft Development Tools and/or WinHelp documentation.
* See these sources for detailed information regarding the
* Microsoft samples programs.
\******************************************************************************/
/****************************** Module Header *******************************
* Module Name: toolbox.c
*
* Contains routines that handle the toolbox.
*
* Functions:
*
* ToolboxShow()
* ToolboxOnTop()
* ToolboxWndProc()
* ToolBtnWndProc()
* ToolboxSelectTool()
* ToolboxCreate()
* ToolboxDrawBitmap()
*
* Comments:
*
****************************************************************************/
#include "dlgedit.h"
#include "dlgfuncs.h"
#include "dlgextrn.h"
#include "dialogs.h"
#define TOOLBOXMARGIN 2 // Pixels around the buttons in the Toolbox.
#define TOOLBOXCOLUMNS 2 // Columns in the Toolbox.
/*
* Style of the toolbox window.
*/
#define TOOLBOXSTYLE (WS_POPUP | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU)
STATICFN VOID ToolboxCreate(VOID);
STATICFN VOID ToolboxDrawBitmap(HDC hDC, INT type);
/*
* Dimensions of a tool button bitmap.
*/
static INT cxToolBtn;
static INT cyToolBtn;
/****************************************************************************
* ToolboxShow
*
* This function shows or hides the toolbox window. It will create
* the Toolbox if necessary.
*
* Arguments:
* BOOL fShow - whether to show or hide the toolbox window.
*
****************************************************************************/
VOID ToolboxShow(
BOOL fShow)
{
if (fShow) {
/*
* Don't allow a toolbox to be shown in Translate mode.
*/
if (gfTranslateMode)
return;
/*
* Create it if it doesn't exist yet.
*/
if (!ghwndToolbox)
ToolboxCreate();
if (ghwndToolbox)
ShowWindow(ghwndToolbox, SW_SHOWNA);
}
else {
if (ghwndToolbox)
ShowWindow(ghwndToolbox, SW_HIDE);
}
}
/****************************************************************************
* ToolboxOnTop
*
* This function positions the toolbox window on top. It needs to be
* called any time that a new dialog window is created to be sure the
* dialog does not cover the toolbox.
*
* It can be called even if the toolbox is not created yet (it will
* be a noop in that case).
*
****************************************************************************/
VOID ToolboxOnTop(VOID)
{
if (ghwndToolbox) {
SetWindowPos(ghwndToolbox, NULL, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
}
/****************************************************************************
* ToolboxCreate
*
* This function creates the toolbox window.
*
****************************************************************************/
STATICFN VOID ToolboxCreate(VOID)
{
BITMAP bmp;
INT i;
INT x;
INT y;
INT cx;
INT cy;
INT cxDummy;
INT cyDummy;
RECT rc;
RECT rcSubClient;
BOOL fMaximized;
/*
* Load the bitmaps.
*/
if (!(ghbmPointerToolUp = LoadBitmap(ghInst,
MAKEINTRESOURCE(IDBM_TUPOINTR))) ||
!(ghbmPointerToolDown = LoadBitmap(ghInst,
MAKEINTRESOURCE(IDBM_TDPOINTR))))
return;
for (i = 0; i < CCONTROLS; i++) {
if (!(awcd[i].hbmToolBtnUp = LoadBitmap(ghInst,
MAKEINTRESOURCE(awcd[i].idbmToolBtnUp))))
return;
if (!(awcd[i].hbmToolBtnDown = LoadBitmap(ghInst,
MAKEINTRESOURCE(awcd[i].idbmToolBtnDown))))
return;
}
/*
* Get the dimensions of the tool button bitmaps.
*/
GetObject(awcd[0].hbmToolBtnUp, sizeof(BITMAP), &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 = TOOLBOXMARGIN + ((cxToolBtn - 1) * 2) + 1 + TOOLBOXMARGIN;
rc.bottom = TOOLBOXMARGIN + ((cyToolBtn - 1) *
((CCONTROLS / 2) + 1)) + 1 + TOOLBOXMARGIN;
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.
*/
GetWindowRect(ghwndSubClient, &rcSubClient);
x = rcSubClient.right - cx - (2 * TOOLBOXMARGIN);
y = rcSubClient.top + (2 * TOOLBOXMARGIN);
SetRect(&rc, x, y, x + cx, y + cy);
FitRectToScreen(&rc);
x = rc.left;
y = rc.top;
}
/*
* Create the toolbox window.
*/
if (!(ghwndToolbox = CreateWindow(szToolboxClass, NULL, TOOLBOXSTYLE,
x, y, cx, cy, ghwndMain, NULL, ghInst, NULL)))
return;
/*
* Create the Pointer (W_NOTHING) button.
*/
CreateWindow(szToolBtnClass, NULL,
WS_CHILD | WS_VISIBLE,
TOOLBOXMARGIN, TOOLBOXMARGIN, (cxToolBtn * 2) - 1, cyToolBtn,
ghwndToolbox, (HMENU)W_NOTHING, ghInst, NULL);
/*
* Create the other buttons.
*/
x = TOOLBOXMARGIN;
y = TOOLBOXMARGIN + cyToolBtn - 1;
for (i = 0; i < CCONTROLS; i++) {
CreateWindow(szToolBtnClass, NULL,
WS_CHILD | WS_VISIBLE,
x, y, cxToolBtn, cyToolBtn,
ghwndToolbox, (HMENU)i, ghInst, NULL);
if (x == TOOLBOXMARGIN) {
x += cxToolBtn - 1;
}
else {
x = TOOLBOXMARGIN;
y += cyToolBtn - 1;
}
}
}
/****************************************************************************
* ToolboxWndProc
*
* This is the window procedure for the toolbox window.
*
****************************************************************************/
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)
iToolNext = W_NOTHING;
ToolboxSelectTool(iToolNext, FALSE);
break;
case VK_DOWN:
if ((GetKeyState(VK_SHIFT) & 0x8000) ||
(GetKeyState(VK_CONTROL) & 0x8000))
break;
if (gCurTool == W_NOTHING) {
iToolNext = 0;
}
else {
/*
* Go down a row, but don't go beyond the bottom.
*/
iToolNext = gCurTool + TOOLBOXCOLUMNS;
if (iToolNext >= CCONTROLS)
break;
}
ToolboxSelectTool(iToolNext, FALSE);
break;
case VK_LEFT:
if ((GetKeyState(VK_SHIFT) & 0x8000) ||
(GetKeyState(VK_CONTROL) & 0x8000))
break;
if (gCurTool == W_NOTHING ||
!(gCurTool % TOOLBOXCOLUMNS))
break;
/*
* Go left a column.
*/
ToolboxSelectTool(gCurTool - 1, FALSE);
break;
case VK_RIGHT:
if ((GetKeyState(VK_SHIFT) & 0x8000) ||
(GetKeyState(VK_CONTROL) & 0x8000))
break;
if (gCurTool == W_NOTHING ||
(gCurTool % TOOLBOXCOLUMNS) ==
TOOLBOXCOLUMNS - 1)
break;
/*
* Go right a column.
*/
ToolboxSelectTool(gCurTool + 1, FALSE);
break;
case VK_TAB:
if (GetKeyState(VK_CONTROL) & 0x8000)
break;
/*
* Is the shift key pressed also?
*/
if (GetKeyState(VK_SHIFT) & 0x8000) {
if (gCurTool == W_NOTHING)
iToolNext = CCONTROLS - 1;
else if (gCurTool == 0)
iToolNext = W_NOTHING;
else
iToolNext = gCurTool - 1;
}
else {
if (gCurTool == W_NOTHING)
iToolNext = 0;
else if (gCurTool == CCONTROLS - 1)
iToolNext = W_NOTHING;
else
iToolNext = gCurTool + 1;
}
ToolboxSelectTool(iToolNext, FALSE);
break;
case VK_END:
if ((GetKeyState(VK_SHIFT) & 0x8000) ||
(GetKeyState(VK_CONTROL) & 0x8000))
break;
ToolboxSelectTool(CCONTROLS - 1, FALSE);
break;
case VK_HOME:
case VK_ESCAPE:
if ((GetKeyState(VK_SHIFT) & 0x8000) ||
(GetKeyState(VK_CONTROL) & 0x8000))
break;
ToolboxSelectTool(W_NOTHING, FALSE);
break;
}
}
break;
case WM_ACTIVATE:
if (LOWORD(wParam))
gidCurrentDlg = DID_TOOLBOX;
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;
DeleteObject(ghbmPointerToolUp);
ghbmPointerToolUp = NULL;
DeleteObject(ghbmPointerToolDown);
ghbmPointerToolDown = NULL;
for (i = 0; i < CCONTROLS; i++) {
DeleteObject(awcd[i].hbmToolBtnUp);
awcd[i].hbmToolBtnUp = NULL;
DeleteObject(awcd[i].hbmToolBtnDown);
awcd[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.
*
****************************************************************************/
WINDOWPROC ToolBtnWndProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
switch (msg) {
case WM_LBUTTONDOWN:
/*
* Be sure any outstanding changes get applied
* without errors.
*/
if (!StatusApplyChanges())
return TRUE;
/*
* Select the tool that was clicked on. If the Ctrl
* key is down, lock the tool also.
*/
ToolboxSelectTool((UINT)GetWindowLong((hwnd), GWL_ID),
(GetKeyState(VK_CONTROL) & 0x8000) ? TRUE : FALSE);
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
*
* Draws the current tool bitmap.
*
* Arguments:
* HDC hDC - handle to the DC for the toolbox window.
* INR type - type of bitmap to draw.
*
****************************************************************************/
STATICFN VOID ToolboxDrawBitmap(
HDC hDC,
INT type)
{
HDC hMemDC;
HBITMAP hbm;
HBITMAP hbmOld;
INT cxBitmap;
if (type == W_NOTHING) {
hbm = (type == gCurTool) ? ghbmPointerToolDown : ghbmPointerToolUp;
/*
* Note that the size of the Pointer tool is twice the width
* of the other bitmaps, but less one pixel. This is because
* the other tools overlap their adjacent borders.
*/
cxBitmap = (cxToolBtn * 2) - 1;
}
else {
hbm = (type == gCurTool) ?
awcd[type].hbmToolBtnDown : awcd[type].hbmToolBtnUp;
cxBitmap = cxToolBtn;
}
/*
* Draw the image.
*/
hMemDC = CreateCompatibleDC(hDC);
hbmOld = SelectObject(hMemDC, hbm);
BitBlt(hDC, 0, 0, cxBitmap, cyToolBtn, hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hbmOld);
DeleteDC(hMemDC);
}
/****************************************************************************
* ToolboxSelectTool
*
* This function selects a tool to be the current tool.
*
* Arguments:
* INT type - Type of control (one of the W_* defines).
* BOOL fLock - TRUE if the tool should be locked down.
*
****************************************************************************/
VOID ToolboxSelectTool(
INT type,
BOOL fLock)
{
PWINDOWCLASSDESC pwcd;
if (gCurTool != type) {
/*
* Set the current wcd global for the current tool type.
* This will point to the WINDOWCLASSDESC structure of the
* current tool. If the Custom tool was selected, the user
* is asked which of the installed custom controls that they
* really want.
*/
if (type == W_CUSTOM) {
/*
* There are no custom controls installed. Beep and
* return without doing anything.
*/
if (!gpclHead) {
MessageBeep(0);
return;
}
/*
* If there are multiple custom controls installed,
* ask the user which one they want. Note that they
* can press Cancel and return NULL!
*/
if (gpclHead->pclNext) {
if (!(pwcd = SelCustDialog()))
return;
gpwcdCurTool = pwcd;
}
else {
/*
* Since there is only one type of custom control
* installed, there is no need to ask the user
* which one they want.
*/
gpwcdCurTool = gpclHead->pwcd;
}
}
else {
gpwcdCurTool = (type == W_NOTHING) ? NULL : &awcd[type];
}
/*
* Force the previous and current buttons to repaint.
*/
if (ghwndToolbox) {
InvalidateRect(GetDlgItem(ghwndToolbox, gCurTool), NULL, FALSE);
InvalidateRect(GetDlgItem(ghwndToolbox, type), NULL, FALSE);
}
/*
* Set the current tool type global. This will be W_CUSTOM for
* all custom controls.
*/
gCurTool = type;
}
gfToolLocked = fLock;
}