Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

676 lines
16 KiB

//+---------------------------------------------------------------------
//
// File: tools.cxx
//
// Notes: Simple tool-tray window base class and derived
// trays for PBrush drawing tools
//
// Classes:
// PBToolTray (a window class)
// CTray
//
//------------------------------------------------------------------------
#include <stdlib.h>
#include <windows.h>
#include <windowsx.h>
#include <ole2.h>
#include <o2base.hxx> // the base classes and utilities
#include "pbs.hxx"
#define MARGIN_X 4
#define MARGIN_Y 4
#define FRAME_X 1
#define FRAME_Y 1
#define TRAY_DEFAULT_WIDTH 64
#define TRAY_DEFAULT_HEIGHT 256
#define LSIZETOOL_HEIGHT 64
#define COLORTRAY_WIDTH 256
#define COLORTRAY_HEIGHT 48
BOOL Tray::_fInit = FALSE;
ATOM Tray::_atomClass = 0;
COLORREF Tray::crLtGray;
COLORREF Tray::crGray;
COLORREF Tray::crDkGray;
COLORREF Tray::crBlack;
HBRUSH Tray::hbrActiveCaption = NULL;
HBRUSH Tray::hbrInActiveCaption = NULL;
HBRUSH Tray::hbrWindowFrame = NULL;
HBRUSH Tray::hbrSysBox = NULL;
WORD Tray::wCnt = 0;
//
// Routines & definitions for creating windows with custom NON-CLIENT areas
//
#define SetWF(hwnd,wf) SetWindowLong(hwnd, GWL_STYLE, \
GetWindowLong(hwnd,GWL_STYLE) | (wf))
#define ClrWF(hwnd,wf) SetWindowLong(hwnd, GWL_STYLE, \
GetWindowLong(hwnd,GWL_STYLE) &~(wf))
#define TestWF(hwnd,wf) (GetWindowLong(hwnd,GWL_STYLE) & (wf))
//
// Window styles used by ncMsgFilter
//
#define WF_SIZEFRAME WS_THICKFRAME
#define WF_SYSMENU WS_SYSMENU
#define WF_MINIMIZED WS_MINIMIZE
#define WF_SIZEBOX 0x0002
#define WF_ACTIVE 0x0001
//+---------------------------------------------------------------
//
// Member: Tray::Create (static)
//
//---------------------------------------------------------------
LPTRAY
Tray::Create(HINSTANCE hinst,
HWND hwndParent,
HWND hwndNotify,
int iChild)
{
DOUT(L"Tray::Create\r\n");
//
//If we haven't yet done our base initialization, do it now
//
if(_fInit == FALSE)
{
if(Tray::InitClass(hinst) == 0)
return NULL;
}
LPTRAY pTray;
if ((pTray = new Tray(hwndParent, hwndNotify, iChild)) != NULL)
{
if(NULL == pTray->CreateToolWindow(hinst, hwndParent))
{
DOUT(L"Tray::Create Failing!\r\n");
delete pTray;
pTray = NULL;
}
}
return pTray;
}
//+---------------------------------------------------------------
//
// Member: Tray::InitClass (static)
//
//---------------------------------------------------------------
ATOM
Tray::InitClass(HINSTANCE hinst)
{
crLtGray = PALETTEINDEX(7);
crGray = PALETTEINDEX(248);
crDkGray = PALETTEINDEX(249);
crBlack = PALETTEINDEX(0);
//
// register our window class
//
WNDCLASS wc;
wc.style = CS_NOCLOSE | CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW;
wc.lpfnWndProc = TrayWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 4; // for pointer to Tray object
wc.hInstance = hinst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = CLASS_NAME_PBTRAY;
if((Tray::_atomClass = RegisterClass(&wc)) != 0)
{
Tray::_fInit = TRUE;
}
return _atomClass;
}
//+---------------------------------------------------------------
//
// Member: Tray::Tray
//
//---------------------------------------------------------------
Tray::Tray(HWND hwndParent, HWND hwndNotify, int iChild)
{
_hwndNotify = hwndNotify;
_iChild = iChild;
_hwnd = NULL;
_cxFrame = FRAME_X;
_cyFrame = FRAME_Y;
_dxMargin = MARGIN_X;
_dyMargin = MARGIN_Y;
_xWidth = TRAY_DEFAULT_WIDTH;
_yHeight = TRAY_DEFAULT_HEIGHT;
}
//+---------------------------------------------------------------
//
// Member: Tray::~Tray
//
//---------------------------------------------------------------
Tray::~Tray(void)
{
if (_hwnd != NULL)
{
DOUT(L"Tray::~Tray Destroying Window\r\n");
DestroyWindow(_hwnd);
}
}
//+---------------------------------------------------------------
//
// Member: Tray::Position
//
// Notes: The idea for this method is for the derived class
// to provide behavior such that it positions itself
// in it's "natural" position relative to the x, y parms
//
//---------------------------------------------------------------
void
Tray::Position(int x, int y)
{
SetWindowPos(_hwnd, 0, x, y, _xWidth, _yHeight, SWP_NOACTIVATE | SWP_NOZORDER);
}
void
Tray::GetToolRect(LPRECT lprc)
{
GetClientRect(_hwnd, lprc);
InflateRect(lprc, -_dxMargin, -_dyMargin);
}
//+---------------------------------------------------------------
//
// Member: Tray::OnCreate
//
//---------------------------------------------------------------
BOOL
Tray::OnCreate(HWND hwnd, CREATESTRUCT FAR* lpCreateStruct)
{
return TRUE;
}
//+---------------------------------------------------------------
//
// Member: Tray::OnDestroy
//
//---------------------------------------------------------------
void
Tray::OnDestroy(HWND hwnd)
{
_hwnd = NULL;
}
//+---------------------------------------------------------------
//
// Member: Tray::OnPaint
//
//---------------------------------------------------------------
void
Tray::OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
HBRUSH hbr = (HBRUSH)GetStockBrush(LTGRAY_BRUSH);
FillRect(ps.hdc, &ps.rcPaint, hbr);
EndPaint(hwnd, &ps);
}
void
Tray::OnGetMinMaxInfo(HWND hwnd, LPMINMAXINFO lpMinMaxInfo)
{
lpMinMaxInfo->ptMaxSize.x = _xWidth;
lpMinMaxInfo->ptMaxSize.y = _yHeight;
lpMinMaxInfo->ptMaxPosition.x = lpMinMaxInfo->ptMaxPosition.y = 0;
lpMinMaxInfo->ptMinTrackSize.x = 8;
lpMinMaxInfo->ptMinTrackSize.y = 16;
lpMinMaxInfo->ptMaxTrackSize.x = 1024;
lpMinMaxInfo->ptMaxTrackSize.y = 768;
}
void
Tray::OnWindowPosChanged(HWND hwnd, LPWINDOWPOS lpwpos)
{
if (lpwpos->flags & SWP_HIDEWINDOW)
return;
DOUT(L"Tray::OnWindowPosChanged\r\n");
}
//+---------------------------------------------------------------
//
// Function: TrayWndProc
//
//---------------------------------------------------------------
extern "C" LRESULT CALLBACK
TrayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
//
// get a pointer to the Tray object
// if it is NULL, then check for a WM_NCCREATE message
// when we get one stash the pointer to our object
//
LPTRAY pTray = (LPTRAY)GetWindowLong(hwnd, 0);
if(pTray == NULL)
{
if(msg == WM_NCCREATE)
{
CREATESTRUCT FAR *lpcs = (CREATESTRUCT FAR *)lParam;
pTray = (LPTRAY)lpcs->lpCreateParams;
SetWindowLong(hwnd, 0, (LONG)pTray);
return(pTray->ncMsgFilter(hwnd, msg, wParam, lParam));
}
return(DefWindowProc(hwnd, msg, wParam, lParam));
}
if(msg == WM_NCDESTROY)
{
SetWindowLong(hwnd, 0, 0L);
return(DefWindowProc(hwnd, msg, wParam, lParam));
}
//
// handle any window message by passing it to the appropriate
// member function...
//
switch(msg)
{
HANDLE_MSG(hwnd, WM_CREATE, pTray->OnCreate);
HANDLE_MSG(hwnd, WM_DESTROY, pTray->OnDestroy);
HANDLE_MSG(hwnd, WM_PAINT, pTray->OnPaint);
HANDLE_MSG(hwnd, WM_GETMINMAXINFO, pTray->OnGetMinMaxInfo);
HANDLE_MSG(hwnd, WM_WINDOWPOSCHANGED, pTray->OnWindowPosChanged);
}
return pTray->ncMsgFilter(hwnd, msg, wParam, lParam);
}
//+---------------------------------------------------------------
//
// Member: Tray::ncCalcRect
//
//---------------------------------------------------------------
inline void
Tray::ncCalcRect(HWND hwnd, LPRECT lprc)
{
InflateRect(lprc, -_cxFrame, -_cyFrame);
}
//+---------------------------------------------------------------
//
// Member: Tray::ncHitTest
//
//---------------------------------------------------------------
LONG
Tray::ncHitTest(HWND hwnd, POINT pt)
{
//
// If the window is minimized and iconic, return HTCAPTION
//
if (TestWF(hwnd, WF_MINIMIZED))
return HTCAPTION;
//
// Get Client and Window rects in screen coordinates
//
RECT rcWindow;
GetWindowRect(hwnd, &rcWindow);
RECT rcClient = rcWindow;
ncCalcRect(hwnd, &rcClient);
//
//lie about actual client area: count the margin as NC
//
InflateRect(&rcClient, -_dxMargin, -_dyMargin);
if (PtInRect(&rcClient, pt))
return HTCLIENT;
return HTCAPTION;
}
//+---------------------------------------------------------------
//
// Member: Tray::ncDrawFrame
//
//---------------------------------------------------------------
void
Tray::ncDrawFrame(HWND hwnd)
{
HDC hdc = GetWindowDC(hwnd);
RECT rc;
GetWindowRect(hwnd, &rc);
OffsetRect(&rc, -rc.left, -rc.top);
SelectObject(hdc, hbrWindowFrame);
//
// This works as long as cxFrame and cyFrame are both one
//
FrameRect(hdc, &rc, hbrWindowFrame);
InflateRect(&rc, -_cxFrame, -_cyFrame);
rc.bottom = rc.top + _cyFrame;
FillRect(hdc, &rc, hbrWindowFrame);
ReleaseDC(hwnd, hdc);
}
//+---------------------------------------------------------------
//
// Member: Tray::ncMsgFilter
//
//
// This method handles Windows non-client
// messages so that the non-client area of a window is drawn as a low
// key floating tool box. The title bar of the window is much smaller
// than the standard Windows title bar, and no caption is displayed.
// The system menu box is replaced by a small black rectangle.
//
// When using this method, the following messages must be passed in
// order for the window to correctly operate within the Windows
// environment: all non-client messages, whose symbolic names begin with
// the prefix WM_NC, the WM_SYSCOMMAND, WM_COMMAND, and WM_INITMENU
// messages. If the caller also needs to process any of these messages,
// the caller must pre-process the message and then call ncMsgFilter.
//
// If an unrecognized message is passed to ncMsgFilter,
// DefWindowProc is called.
//
//---------------------------------------------------------------
LRESULT
Tray::ncMsgFilter(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_NCACTIVATE: // wParam == active state
if (wParam)
SetWF(hwnd, WF_ACTIVE);
else
ClrWF(hwnd, WF_ACTIVE);
ncDrawFrame(hwnd);
return TRUE;
case WM_NCCALCSIZE: // lParam == LPRECT of window rect
ncCalcRect(hwnd, (LPRECT)lParam);
if(wParam)
return WVR_REDRAW;
return 0L;
case WM_NCCREATE: // Sent before WM_CREATE
if (wCnt++ == 0)
{
hbrActiveCaption = CreateSolidBrush(
GetSysColor(COLOR_ACTIVECAPTION));
hbrInActiveCaption = CreateSolidBrush(
GetSysColor(COLOR_INACTIVECAPTION));
hbrWindowFrame = CreateSolidBrush(
GetSysColor(COLOR_WINDOWFRAME));
hbrSysBox = (HBRUSH)GetStockObject(BLACK_BRUSH);
}
break;
case WM_NCDESTROY: // Sent before WM_DESTROY
if (wCnt == 0)
break; // haven't created one yet - don't delete
if (--wCnt == 0)
{
DeleteObject(hbrActiveCaption);
DeleteObject(hbrInActiveCaption);
DeleteObject(hbrWindowFrame);
}
break;
case WM_NCHITTEST: // lParam is POINT in screen cords
{
POINT pt = { LOWORD(lParam), HIWORD(lParam) };
return ncHitTest(hwnd, pt);
}
case WM_NCPAINT:
ncDrawFrame(hwnd);
return 0L;
//
// Dont activate the window when it is clicked on in the CLIENT
// area, this is useful for "tool" windows.
//
// Should this behaviour be controled by a style bit?
//
case WM_MOUSEACTIVATE:
if (LOWORD(lParam) == HTCLIENT)
return MA_NOACTIVATE;
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
//
// Derived Classes
//======================
//
//+---------------------------------------------------------------
//
// ToolTray
//
//---------------------------------------------------------------
LPTOOLTRAY
ToolTray::Create(HINSTANCE hinst,
HWND hwndParent,
HWND hwndNotify,
int iChild)
{
DOUT(L"ToolTray::Create\r\n");
//
//If we haven't yet done our base initialization, do it now
//
if(Tray::_fInit == FALSE)
{
if(Tray::InitClass(hinst) == 0)
return NULL;
}
LPTOOLTRAY pTray;
if ((pTray = new ToolTray(hwndParent, hwndNotify, iChild)) != NULL)
{
if(NULL == pTray->CreateToolWindow(hinst, hwndParent))
{
DOUT(L"CreateTray::Create Failing!\r\n");
delete pTray;
pTray = NULL;
}
}
return pTray;
}
ToolTray::ToolTray(HWND hwndParent, HWND hwndNotify, int iChild) :
Tray(hwndParent, hwndNotify, iChild)
{
_yOffset = LSIZETOOL_HEIGHT;
_xWidth = TRAY_DEFAULT_WIDTH;
_yHeight = TRAY_DEFAULT_HEIGHT + _yOffset;
}
void
ToolTray::GetToolRect(LPRECT lprc)
{
GetClientRect(_hwnd, lprc);
InflateRect(lprc, -_dxMargin, -_dyMargin);
lprc->bottom -= _yOffset;
}
void
ToolTray::GetLSizeRect(LPRECT lprc)
{
GetClientRect(_hwnd, lprc);
InflateRect(lprc, -_dxMargin, -_dyMargin);
lprc->top = lprc->bottom - _yOffset;
}
void
ToolTray::Position(int x, int y)
{
int yMax = GetSystemMetrics(SM_CYSCREEN);
int yHeight = _yHeight + _dyMargin;
if(y > yMax - yHeight)
y = yMax - yHeight;
x -= _xWidth + _dxMargin;
if(x < 0)
x = 0;
Tray::Position(x, y);
}
void
ToolTray::OnWindowPosChanged(HWND hwnd, LPWINDOWPOS lpwpos)
{
if (lpwpos->flags & SWP_HIDEWINDOW)
return;
DOUT(L"ToolTray::OnWindowPosChanged\r\n");
GetToolRect(&gprcApp[iTool]);
MoveWindow(gpahwndApp[iTool],
gprcApp[iTool].left,
gprcApp[iTool].top,
gprcApp[iTool].right - gprcApp[iTool].left,
gprcApp[iTool].bottom - gprcApp[iTool].top,
TRUE);
UpdateWindow(gpahwndApp[iTool]);
GetLSizeRect(&gprcApp[iSize]);
MoveWindow(gpahwndApp[iSize],
gprcApp[iSize].left,
gprcApp[iSize].top,
gprcApp[iSize].right - gprcApp[iSize].left,
gprcApp[iSize].bottom - gprcApp[iSize].top,
TRUE);
UpdateWindow(gpahwndApp[iSize]);
//InvalidateRect(gpahwndApp[iSize], NULL, TRUE);
}
//+---------------------------------------------------------------
//
// ColorTray
//
//---------------------------------------------------------------
LPCOLORTRAY
ColorTray::Create(HINSTANCE hinst,
HWND hwndParent,
HWND hwndNotify,
int iChild)
{
DOUT(L"ColorTray::Create\r\n");
//
//If we haven't yet done our base initialization, do it now
//
if(Tray::_fInit == FALSE)
{
if(Tray::InitClass(hinst) == 0)
return NULL;
}
LPCOLORTRAY pTray;
if ((pTray = new ColorTray(hwndParent, hwndNotify, iChild)) != NULL)
{
if(NULL == pTray->CreateToolWindow(hinst, hwndParent))
{
DOUT(L"ColorTray::Create Failing!\r\n");
delete pTray;
pTray = NULL;
}
}
return pTray;
}
ColorTray::ColorTray(HWND hwndParent, HWND hwndNotify, int iChild) :
Tray(hwndParent, hwndNotify, iChild)
{
_xWidth = COLORTRAY_WIDTH;
_yHeight = COLORTRAY_HEIGHT;
}
void
ColorTray::GetColorRect(LPRECT lprc)
{
GetClientRect(_hwnd, lprc);
InflateRect(lprc, -_dxMargin, -_dyMargin);
}
void
ColorTray::Position(int x, int y)
{
int yMax = GetSystemMetrics(SM_CYSCREEN);
int yHeight = _yHeight + _dyMargin;
if(y > yMax - yHeight)
y = yMax - yHeight;
x += _dxMargin;
y += _dyMargin;
Tray::Position(x, y);
}
void
ColorTray::OnWindowPosChanged(HWND hwnd, LPWINDOWPOS lpwpos)
{
if (lpwpos->flags & SWP_HIDEWINDOW)
return;
DOUT(L"ColorTray::OnWindowPosChanged\r\n");
GetColorRect(&gprcApp[iColor]);
MoveWindow(gpahwndApp[iColor],
gprcApp[iColor].left,
gprcApp[iColor].top,
gprcApp[iColor].right - gprcApp[iColor].left,
gprcApp[iColor].bottom - gprcApp[iColor].top,
TRUE);
UpdateWindow(gpahwndApp[iColor]);
}