382 lines
11 KiB
C++
382 lines
11 KiB
C++
//+-------------------------------------------------------------------
|
|
//
|
|
// File: status.cxx
|
|
//
|
|
// Contents: Functions implementing status bar.
|
|
//
|
|
// Classes: StatusBar
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
#include "headers.hxx"
|
|
#pragma hdrstop
|
|
|
|
TCHAR FAR lpstrStatBarClass[] = TEXT("classStatBar");
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Function: _PatB, private
|
|
//
|
|
// Synopsis: inline helper to fill rectangle with a color
|
|
//
|
|
//----------------------------------------------------------------
|
|
|
|
inline void _PatB(HDC hdc, int x, int y, int dx, int dy, COLORREF rgb)
|
|
{
|
|
RECT rc;
|
|
SetRect(&rc, x, y, x+dx, y+dy);
|
|
SetBkColor(hdc, rgb);
|
|
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
|
|
};
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: StatusBar::ClassInit
|
|
//
|
|
// Synopsis: Registers the status bar window class
|
|
//
|
|
// Arguments: [hinst] -- instance handle of module using status bar
|
|
//
|
|
// Returns: TRUE iff the status bar was registered successfully
|
|
//
|
|
// Notes: This static method is usually called from the WinMain
|
|
// or LibMain of the module using the status bar.
|
|
//
|
|
//----------------------------------------------------------------
|
|
|
|
BOOL StatusBar::ClassInit(HINSTANCE hinst)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
wc.style = 0L;
|
|
wc.lpfnWndProc = StatusWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = sizeof(void FAR*);
|
|
wc.hInstance = hinst;
|
|
wc.hIcon = NULL;
|
|
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = lpstrStatBarClass;
|
|
|
|
return RegisterClass(&wc)!=NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: StatusBar::StatusBar, public
|
|
//
|
|
// Synopsis: Constructor for status bar class
|
|
//
|
|
// Notes: Creating a status bar is a two step process.
|
|
// First construct the object, then call the
|
|
// Init method to actually create the status bar window.
|
|
//
|
|
//----------------------------------------------------------------
|
|
|
|
StatusBar::StatusBar()
|
|
{
|
|
_hwnd = NULL;
|
|
_hfont = NULL;
|
|
_wHeight = (WORD)-1;
|
|
_wUnitBorder = (WORD)-1;
|
|
_wSpace = 6;
|
|
_wAboveBelow = 2;
|
|
lstrcpy(_lpstrString, TEXT(""));
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: StatusBar::~StatusBar, public
|
|
//
|
|
// Synopsis: Destructor for status bar class
|
|
//
|
|
// Notes: This frees any resources held by the status bar
|
|
// including deleting the window
|
|
//
|
|
//----------------------------------------------------------------
|
|
|
|
StatusBar::~StatusBar()
|
|
{
|
|
if (_hfont != NULL)
|
|
DeleteObject(_hfont);
|
|
|
|
if (_hwnd != NULL)
|
|
DestroyWindow(_hwnd);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: StatusBar::Init, public
|
|
//
|
|
// Synopsis: Creates a status bar window as a child of another window
|
|
//
|
|
// Arguments: [hwnd] -- the window handle of the parent window
|
|
//
|
|
// Returns: The window handle of the status bar child window
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
HWND
|
|
StatusBar::Init(HINSTANCE hinst, HWND hwndParent)
|
|
{
|
|
//
|
|
// create font, save handle, find height of status bar.
|
|
//
|
|
|
|
HDC hdc = GetDC(NULL);
|
|
int iFontHeight;
|
|
TEXTMETRIC tm;
|
|
iFontHeight = MulDiv(-10, GetDeviceCaps(hdc, LOGPIXELSY), 72);
|
|
_hfont = CreateFont(iFontHeight, 0, 0, 0, 400, 0, 0, 0,
|
|
ANSI_CHARSET,
|
|
OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS,
|
|
DEFAULT_QUALITY,
|
|
VARIABLE_PITCH | FF_SWISS,
|
|
TEXT("Helv"));
|
|
|
|
HFONT hfontOld = SelectFont(hdc, _hfont);
|
|
GetTextMetrics(hdc, &tm);
|
|
SelectObject(hdc, hfontOld);
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
_wUnitBorder = GetSystemMetrics(SM_CYBORDER);
|
|
_wHeight = tm.tmHeight + tm.tmExternalLeading + // font height
|
|
4 + // 2 above/below
|
|
_wUnitBorder + // for border
|
|
_wAboveBelow * 2; // above and below
|
|
//
|
|
// create window
|
|
//
|
|
|
|
RECT rc;
|
|
GetClientRect(hwndParent, &rc);
|
|
|
|
// this will automatically set _hwnd!
|
|
CreateWindowEx(0L, // extended style
|
|
lpstrStatBarClass,
|
|
NULL,
|
|
WS_CHILD | WS_VISIBLE | WS_BORDER, // style
|
|
0, rc.bottom - _wHeight, // x, y
|
|
rc.right - rc.left, _wHeight, // cx, cy
|
|
hwndParent, // hwndParent
|
|
NULL, // hmenu
|
|
hinst,
|
|
this); // lpParam
|
|
|
|
return _hwnd;
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: StatusBar::OnSize, public
|
|
//
|
|
// Synopsis: Updates the position of the status bar when the
|
|
// parent is resized
|
|
//
|
|
// Arguments: [lprc] -- client rectangle of parent window
|
|
//
|
|
// Notes: The parent window should call this method during
|
|
// WM_SIZE processing. The parent should get its client
|
|
// rectangle and pass it to this method. This method will
|
|
// move the status bar window to occupy the bottom of
|
|
// the window and will update the rectangle to remove its
|
|
// area (i.e. the returned rectangle is the parent windows'
|
|
// new, effective client area).
|
|
//
|
|
//----------------------------------------------------------------
|
|
|
|
void
|
|
StatusBar::OnSize(LPRECT lprc)
|
|
{
|
|
lprc->bottom -= _wHeight;
|
|
MoveWindow(_hwnd, 0, lprc->bottom, lprc->right-lprc->left, _wHeight, TRUE);
|
|
InvalidateRect(_hwnd, NULL, TRUE);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: StatusBar::DisplayMessage, public
|
|
//
|
|
// Synopsis: Displays a string on the status bar
|
|
//
|
|
// Arguments: [lpstr] -- string to display in status bar. NULL
|
|
// means just clear the current message.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
void
|
|
StatusBar::DisplayMessage(LPCTSTR lpstr)
|
|
{
|
|
HDC hdc = GetDC(_hwnd);
|
|
RECT rc;
|
|
GetClientRect(_hwnd, &rc);
|
|
InflateRect(&rc, -1, -1);
|
|
rc.left += _wSpace;
|
|
rc.top += _wAboveBelow;
|
|
rc.right -= _wSpace;
|
|
rc.bottom -= _wAboveBelow;
|
|
InflateRect(&rc, -1, -1);
|
|
HFONT hfontOld = SelectFont(hdc, _hfont);
|
|
|
|
// clear out the old message
|
|
SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
|
|
ExtTextOut(hdc, 0, 0, ETO_OPAQUE|ETO_CLIPPED, &rc, NULL, 0, NULL);
|
|
|
|
// put up the new status message
|
|
if (lpstr != NULL)
|
|
{
|
|
lstrcpy(_lpstrString, lpstr);
|
|
|
|
SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
|
|
ExtTextOut(hdc,
|
|
rc.left,
|
|
rc.top,
|
|
ETO_OPAQUE | ETO_CLIPPED,
|
|
&rc,
|
|
_lpstrString,
|
|
lstrlen(_lpstrString),
|
|
(LPINT) NULL);
|
|
}
|
|
|
|
SelectObject(hdc, hfontOld);
|
|
ReleaseDC(_hwnd, hdc);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Function: StatusWndProc, private
|
|
//
|
|
// Synopsis: Window procedure for status bar window
|
|
//
|
|
//----------------------------------------------------------------
|
|
|
|
extern "C" LRESULT CALLBACK
|
|
StatusWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
//
|
|
//get a pointer to our object
|
|
//
|
|
LPSTATUSBAR pStatusBar = (LPSTATUSBAR)GetWindowLong(hwnd, 0);
|
|
|
|
//
|
|
//if it is NULL, then check for a WM_NCCREATE message
|
|
// when we get one stash the pointer to our object
|
|
//
|
|
if(pStatusBar == NULL)
|
|
{
|
|
if(msg == WM_NCCREATE)
|
|
{
|
|
CREATESTRUCT FAR *lpcs = (CREATESTRUCT FAR *)lParam;
|
|
pStatusBar = (LPSTATUSBAR)lpcs->lpCreateParams;
|
|
pStatusBar->_hwnd = hwnd;
|
|
SetWindowLong(hwnd, 0, (LONG)pStatusBar);
|
|
//drop through to forward the message
|
|
}
|
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
|
}
|
|
|
|
if(msg == WM_NCDESTROY)
|
|
{
|
|
SetWindowLong(hwnd, 0, 0L);
|
|
pStatusBar->_hwnd = NULL;
|
|
//drop through to forward the message to the window procedure
|
|
}
|
|
|
|
//handle any window message by passing it to the appropriate
|
|
//member function...
|
|
switch(msg)
|
|
{
|
|
HANDLE_MSG(hwnd, WM_PAINT, pStatusBar->OnPaint);
|
|
}
|
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: StatusBar::OnPaint, private
|
|
//
|
|
// Synopsis: Handles the WM_PAINT message for the status bar window
|
|
//
|
|
//----------------------------------------------------------------
|
|
|
|
void
|
|
StatusBar::OnPaint(HWND hwnd)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc = ::BeginPaint(hwnd, &ps);
|
|
RECT rc;
|
|
COLORREF rgbT;
|
|
|
|
// compute rectangle
|
|
GetClientRect(hwnd, &rc);
|
|
|
|
//
|
|
// draw highlight and shadow
|
|
//
|
|
rgbT = GetSysColor(COLOR_BTNHIGHLIGHT);
|
|
// left and top
|
|
_PatB(hdc, rc.left, rc.top, 1, rc.bottom - rc.top, rgbT);
|
|
_PatB(hdc, rc.left, rc.top, rc.right - rc.left, 1, rgbT);
|
|
rgbT = GetSysColor(COLOR_BTNSHADOW);
|
|
// right and bottom
|
|
_PatB(hdc, rc.right - 1, rc.top, 1, rc.bottom - rc.top, rgbT);
|
|
_PatB(hdc, rc.left, rc.bottom - 1, rc.right-rc.left, 1, rgbT);
|
|
|
|
InflateRect(&rc, -1, -1);
|
|
|
|
//
|
|
// first do the message box
|
|
//
|
|
RECT rcMbox;
|
|
SetRect(&rcMbox,
|
|
rc.left + _wSpace,
|
|
rc.top + _wAboveBelow,
|
|
rc.right - _wSpace,
|
|
rc.bottom - _wAboveBelow);
|
|
|
|
// draw 3d effects for this box.
|
|
// left and top
|
|
rgbT = GetSysColor(COLOR_BTNSHADOW);
|
|
int dxT = rcMbox.right - rcMbox.left;
|
|
int dyT = rcMbox.bottom - rcMbox.top;
|
|
_PatB(hdc, rcMbox.left, rcMbox.top, 1, dyT, rgbT);
|
|
_PatB(hdc, rcMbox.left, rcMbox.top, dxT, 1, rgbT);
|
|
rgbT = GetSysColor(COLOR_BTNHIGHLIGHT);
|
|
// right and bottom
|
|
_PatB(hdc, rcMbox.right - 1, rcMbox.top, 1, dyT, rgbT);
|
|
_PatB(hdc, rcMbox.left, rcMbox.bottom - 1, dxT, 1, rgbT);
|
|
|
|
InflateRect(&rcMbox, -1, -1);
|
|
|
|
HFONT hfontOld = SelectFont(hdc, _hfont);
|
|
|
|
SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
|
|
SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
|
|
ExtTextOut(hdc,
|
|
rcMbox.left,
|
|
rcMbox.top,
|
|
ETO_OPAQUE | ETO_CLIPPED,
|
|
&rcMbox,
|
|
_lpstrString,
|
|
lstrlen(_lpstrString),
|
|
(LPINT) NULL);
|
|
|
|
SelectObject(hdc, hfontOld);
|
|
|
|
InflateRect(&rcMbox, 1, 1);
|
|
ExcludeClipRect(hdc,
|
|
rcMbox.left, rcMbox.top, rcMbox.right, rcMbox.bottom);
|
|
|
|
// now do the background.
|
|
SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
|
|
ExtTextOut(hdc, 0, 0, ETO_OPAQUE|ETO_CLIPPED, &rc, NULL, 0, NULL);
|
|
|
|
EndPaint(hwnd, &ps);
|
|
}
|