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.
 
 
 
 
 
 

1224 lines
32 KiB

//+---------------------------------------------------------------------
//
// File: iconbar.cxx
//
//------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
#include <windowsx.h>
#include <shellapi.h>
#include <stdlib.h>
#define ICONBAR_CLASS_NAME L"IconBar"
#define MARGIN_X 4
#define MARGIN_Y 4
#define ICON_WIDTH 32
#define ICON_HEIGHT 32
#define CELL_WIDTH (ICON_WIDTH + 8)
#define CELL_HEIGHT (ICON_HEIGHT + 8)
#define CAPTION_Y 7
#define FRAME_X 1
#define FRAME_Y 1
BOOL IconBar::_fInit = FALSE;
ATOM IconBar::_atomClass = 0;
COLORREF IconBar::crLtGray;
COLORREF IconBar::crGray;
COLORREF IconBar::crDkGray;
COLORREF IconBar::crBlack;
HBRUSH IconBar::hbrActiveCaption = NULL;
HBRUSH IconBar::hbrInActiveCaption = NULL;
HBRUSH IconBar::hbrWindowFrame = NULL;
HBRUSH IconBar::hbrSysBox = NULL;
WORD IconBar::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: IconBar::Create (static)
//
//---------------------------------------------------------------
LPICONBAR
IconBar::Create(HINSTANCE hinst,
HWND hwndParent,
HWND hwndNotify,
SHORT sIdChild)
{
//
//If we haven't yet done our base initialization, do it now
//
if(_fInit == FALSE)
{
if(IconBar::InitClass(hinst) == 0)
return NULL;
}
LPICONBAR pIconBar;
if ((pIconBar = new IconBar(hwndParent, hwndNotify, sIdChild)) != NULL)
{
if (hwndParent == NULL)
{
pIconBar->_hwnd = CreateWindow(
ICONBAR_CLASS_NAME,
NULL,
//WS_BORDER,
WS_OVERLAPPED,
0,0,0,0,
hwndNotify, // parent (for minimize behavior)
NULL, // menu
hinst,
pIconBar);
}
else
{
pIconBar->_hwnd = CreateWindow(
ICONBAR_CLASS_NAME,
NULL, // no title
WS_CHILD | WS_BORDER | WS_CLIPSIBLINGS,
0, 0, 0, 0, // will be resized
hwndParent,
(HMENU)sIdChild,
hinst,
pIconBar);
}
}
return pIconBar;
}
//+---------------------------------------------------------------
//
// Member: IconBar::IconBar
//
//---------------------------------------------------------------
IconBar::IconBar(HWND hwndParent, HWND hwndNotify, SHORT sIdChild)
{
_hwnd = NULL;
_cellsPerRow = 0;
_numCells = 0;
_selectedCell = 0;
_fStuck = FALSE;
_iCellAtCursor = -1;
_dxMargin = MARGIN_X;
_dyMargin = MARGIN_Y;
_dxCell = CELL_WIDTH;
_dyCell = CELL_HEIGHT;
_cyCaption = CAPTION_Y;
_cxFrame = FRAME_X;
_cyFrame = FRAME_Y;
_cxSize = _cyCaption;
_cySize = _cyCaption;
if(hwndParent == NULL)
_fFloating = TRUE;
else
_fFloating = FALSE;
_hwndNotify = hwndNotify;
_sIdChild = sIdChild;
}
//+---------------------------------------------------------------
//
// Member: IconBar::Position
//
//---------------------------------------------------------------
void
IconBar::Position(int sTop, int sLeft, int sWhere)
{
RECT rcBounds;
GetWindowRect(_hwnd,&rcBounds);
//int nWidth = (_cellsPerRow * _dxCell) + (2 * _dxMargin);
int nWidth = rcBounds.right - rcBounds.left;
int nHeight = rcBounds.bottom - rcBounds.top;
switch(sWhere)
{
default:
case IBP_LEFTBELOW:
sLeft -= nWidth;
break;
case IBP_RIGHTABOVE:
sTop -= nHeight;
break;
case IBP_RIGHTBELOW:
break;
case IBP_LEFTABOVE:
sLeft -= nWidth;
sTop -= nHeight;
break;
}
SetWindowPos(_hwnd, 0, //HWND_TOPMOST,
sLeft, sTop, nWidth, nHeight,
SWP_NOACTIVATE|SWP_NOZORDER);
}
//+---------------------------------------------------------------
//
// Member: IconBar::SetCellAspect
//
// Notes: Either cWide or cHigh must be > 0
//
//---------------------------------------------------------------
void
IconBar::SetCellAspect( int cWide, int cHigh )
{
Assert((cWide > 0) || (cHigh > 0));
int cCells = _numCells;
RECT rc = { 0, 0, 0, 0 };
if(cWide > 0)
{
rc.right = (cWide * _dxCell) + (2 * _dxMargin);
if(cHigh > 0)
{
rc.bottom = (cHigh * _dyCell) + (2 * _dyMargin);
}
else
{
cCells /= cWide;
// Account for a partially filled row.
if ((_numCells % cWide) > 0)
cCells++;
rc.bottom = (cCells * _dyCell) + (2 * _dyMargin);
}
}
else
{
rc.bottom = (cHigh * _dyCell) + (2 * _dyMargin);
cWide = cCells / cHigh;
// Account for a partially filled column.
if ((cCells % cHigh) > 0)
cWide++;
rc.right = (cWide * _dxCell) + (2 * _dxMargin);
}
_cellsPerRow = cWide;
if(_fFloating)
{
//
//using our special knowledge of non-client metrics...
//
InflateRect(&rc,_cxFrame,_cyFrame);
rc.top -= _cyCaption;
}
else
{
AdjustWindowRect(&rc, GetWindowLong(_hwnd, GWL_STYLE),
GetMenu(_hwnd) != NULL);
}
ClientToScreen(_hwnd,(LPPOINT)&rc.left);
ClientToScreen(_hwnd,(LPPOINT)&rc.right);
SetWindowPos(_hwnd, 0, //HWND_TOPMOST,
rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
SWP_NOACTIVATE|SWP_NOZORDER);
}
//+---------------------------------------------------------------
//
// Member: IconBar::~IconBar
//
//---------------------------------------------------------------
IconBar::~IconBar(void)
{
if (_hwnd != NULL)
DestroyWindow(_hwnd);
int i;
if (--_cUsed == 0)
{
#ifdef FIXED340BUGS
for (i = 0; i < _cCache; i++)
DestroyIcon(_cache[i].hIcon);
_cCache = 0;
#endif
}
for (i = 0; i < _numCells; i++)
{
if(_cell[i].hBmp != NULL)
DeleteObject(_cell[i].hBmp);
}
}
//+---------------------------------------------------------------
//
// Function: IconBarWndProc
//
//---------------------------------------------------------------
extern "C" LRESULT CALLBACK
IconBarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
//get a pointer to the IconBar object
LPICONBAR pIconBar = (LPICONBAR)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(pIconBar == NULL)
{
if(msg == WM_NCCREATE)
{
CREATESTRUCT FAR *lpcs = (CREATESTRUCT FAR *)lParam;
pIconBar = (LPICONBAR)lpcs->lpCreateParams;
SetWindowLong(hwnd, 0, (LONG)pIconBar);
if(pIconBar->_fFloating)
return(pIconBar->ncMsgFilter(hwnd, msg, wParam, lParam));
//
// drop through to forward the message
//
}
return(DefWindowProc(hwnd, msg, wParam, lParam));
}
if(msg == WM_NCDESTROY)
{
SetWindowLong(hwnd, 0, 0L);
//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_CREATE, pIconBar->OnCreate);
HANDLE_MSG(hwnd, WM_DESTROY, pIconBar->OnDestroy);
HANDLE_MSG(hwnd, WM_PAINT, pIconBar->OnPaint);
HANDLE_MSG(hwnd, WM_GETMINMAXINFO, pIconBar->OnGetMinMaxInfo);
HANDLE_MSG(hwnd, WM_MOUSEMOVE, pIconBar->OnMouseMove);
HANDLE_MSG(hwnd, WM_LBUTTONDOWN, pIconBar->OnLButtonDown);
HANDLE_MSG(hwnd, WM_LBUTTONDBLCLK, pIconBar->OnLButtonDown);
}
if(pIconBar->_fFloating)
{
return pIconBar->ncMsgFilter(hwnd, msg, wParam, lParam);
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
void
IconBar::OnGetMinMaxInfo(HWND hwnd, LPMINMAXINFO lpMinMaxInfo)
{
lpMinMaxInfo->ptMaxSize.x = 1024;
lpMinMaxInfo->ptMaxSize.y = 768;
lpMinMaxInfo->ptMaxPosition.x = lpMinMaxInfo->ptMaxPosition.y = 0;
lpMinMaxInfo->ptMinTrackSize.x = 8;
lpMinMaxInfo->ptMinTrackSize.y = 16;
lpMinMaxInfo->ptMaxTrackSize.x = 1024;
lpMinMaxInfo->ptMaxTrackSize.y = 768;
}
//+---------------------------------------------------------------
//
// Member: IconBar::ncCalcRect
//
//---------------------------------------------------------------
void
IconBar::ncCalcRect(HWND hwnd, LPRECT lprc)
{
InflateRect(lprc, -_cxFrame, -_cyFrame);
lprc->top += _cyCaption + _cyFrame;
}
//+---------------------------------------------------------------
//
// Member: IconBar::ncHitTest
//
//---------------------------------------------------------------
LONG
IconBar::ncHitTest(HWND hwnd, POINT pt)
{
register int x;
register int y;
RECT rcWindow;
RECT rcClient;
x = pt.x;
y = pt.y;
// If the window is minimized and iconic, return HTCAPTION
if (TestWF(hwnd, WF_MINIMIZED))
return HTCAPTION;
// Get Client and Window rects in screen coordinates
GetWindowRect(hwnd, &rcWindow);
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;
}
// Does the window have a frame?
if (TestWF(hwnd, WF_SIZEFRAME))
{
// Are we touching the frame?
InflateRect(&rcWindow, -_cxFrame, -_cyFrame);
if (!PtInRect(&rcWindow, pt))
{
// We're somewhere on the window frame.
if (y >= rcWindow.bottom)
{
if (x <= rcWindow.left + _cxSize)
return HTBOTTOMLEFT;
if (x >= rcWindow.right - _cxSize)
return HTBOTTOMRIGHT;
return HTBOTTOM;
}
else if (y <= rcWindow.top)
{
if (x <= rcWindow.left + _cxSize)
return(HTTOPLEFT);
if (x >= rcWindow.right - _cxSize)
return(HTTOPRIGHT);
return HTTOP;
}
else if (x <= rcWindow.left)
{
if (y <= rcWindow.top + _cySize)
return HTTOPLEFT;
if (y >= rcWindow.bottom - _cySize)
return HTBOTTOMLEFT;
return HTLEFT;
}
else
{
if (y <= rcWindow.top + _cySize)
return HTTOPRIGHT;
if (y >= rcWindow.bottom - _cySize)
return HTBOTTOMRIGHT;
return HTRIGHT;
}
}
}
else if(y >= rcClient.top)
{
return HTCAPTION;
}
// Are we above the client area?
if (y < rcClient.top)
{
if (y <= (rcWindow.top + _cyCaption + _cyFrame) && y >= rcWindow.top)
{
// In caption area. Now see if we're in the system menu box
if ((TestWF(hwnd, WF_SYSMENU)) &&
x < rcWindow.left +
(_cxSize + _cxFrame) && x >= rcWindow.left)
{
return HTSYSMENU;
}
// In caption area. Now see if we're in the grow box
if ((TestWF(hwnd, WF_SIZEBOX)) &&
x > rcWindow.right -
(_cxSize + _cxFrame) && x <= rcWindow.right)
{
return HTGROWBOX;
}
return HTCAPTION;
}
// We're hitting on the very top of a window without a sizing frame.
return HTNOWHERE;
}
return HTNOWHERE;
}
//+---------------------------------------------------------------
//
// Member: IconBar::ncDrawFrame
//
//---------------------------------------------------------------
void
IconBar::ncDrawFrame(HWND hwnd)
{
HDC hdc;
RECT rc;
hdc = GetWindowDC(hwnd);
GetWindowRect(hwnd, &rc);
OffsetRect(&rc, -rc.left, -rc.top);
SelectObject(hdc, hbrWindowFrame);
// This will work as long as cxFrame and cyFrame are both one.
FrameRect(hdc, &rc, hbrWindowFrame);
InflateRect(&rc, -_cxFrame, -_cyFrame);
rc.top += _cyCaption;
rc.bottom = rc.top + _cyFrame;
FillRect(hdc, &rc, hbrWindowFrame);
rc.top -= _cyCaption;
rc.bottom -= _cyFrame;
if (TestWF(hwnd, WF_ACTIVE))
{
FillRect(hdc, &rc, hbrActiveCaption);
if (TestWF(hwnd, WF_SYSMENU))
{
SelectObject(hdc, hbrSysBox);
PatBlt(hdc, rc.left + _cxFrame, rc.top + _cyFrame,
_cyCaption - 2 * _cyFrame, _cyCaption - 2 * _cyFrame,
PATCOPY);
}
if (TestWF(hwnd, WF_SIZEBOX))
{
SelectObject(hdc, hbrSysBox);
PatBlt(hdc, rc.right + _cxFrame - _cxSize, rc.top +
_cyFrame, _cyCaption - 2 * _cyFrame, _cyCaption - 2 *
_cyFrame, PATCOPY);
}
}
else
{
FillRect(hdc, &rc, hbrInActiveCaption);
}
ReleaseDC(hwnd, hdc);
}
//+---------------------------------------------------------------
//
// Member: IconBar::IconBar
//
//
// 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
IconBar::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;
case WM_INITMENU:
EnableMenuItem((HMENU)wParam, SC_SIZE, MF_GRAYED);
EnableMenuItem((HMENU)wParam, SC_MOVE, MF_ENABLED);
EnableMenuItem((HMENU)wParam, SC_MINIMIZE, MF_GRAYED);
EnableMenuItem((HMENU)wParam, SC_MAXIMIZE, MF_GRAYED);
EnableMenuItem((HMENU)wParam, SC_RESTORE, MF_GRAYED);
EnableMenuItem((HMENU)wParam, SC_TASKLIST, MF_ENABLED);
EnableMenuItem((HMENU)wParam, SC_CLOSE, MF_ENABLED);
return 0L;
case WM_COMMAND:
if (lParam == 0L && LOWORD(wParam) >= SC_SIZE)
PostMessage(hwnd, WM_SYSCOMMAND, wParam, lParam);
break;
case WM_SYSCOMMAND:
switch (wParam & 0xFFF0)
{
//
// Drop the system menu
//
case SC_KEYMENU:
if (LOWORD(lParam) != ' ')
{
break;
}
else
{
wParam = HTSYSMENU;
}
//
// Fall through!
//
case SC_MOUSEMENU:
if ((wParam & 0x000F) == HTSYSMENU)
{
RECT rc;
GetWindowRect(hwnd, &rc);
TrackPopupMenu(GetSystemMenu(hwnd, FALSE),
0,
rc.left + _cxFrame, rc.top + _cyFrame + _cyCaption,
0,
hwnd,
NULL);
return 0L;
}
break;
case SC_MOVE:
//
// Turn off the WS_THICKFRAME style bit during a
// move operation so we get a "thin" move frame
//
if (TestWF(hwnd, WS_THICKFRAME))
{
ClrWF(hwnd, WS_THICKFRAME);
lParam = DefWindowProc(hwnd, msg, wParam,
lParam);
SetWF(hwnd, WS_THICKFRAME);
return lParam;
}
break;
}
break;
case WM_NCLBUTTONDOWN:
case WM_NCMOUSEMOVE:
case WM_NCLBUTTONUP:
case WM_NCLBUTTONDBLCLK:
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONUP:
case WM_NCRBUTTONDBLCLK:
case WM_NCMBUTTONDOWN:
case WM_NCMBUTTONUP:
case WM_NCMBUTTONDBLCLK:
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
//+---------------------------------------------------------------
//
// Member: IconBar::InitClass (static)
//
//---------------------------------------------------------------
ATOM
IconBar::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 = IconBarWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 4; // for pointer to IconBar object
wc.hInstance = hinst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockBrush(LTGRAY_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = ICONBAR_CLASS_NAME;
if((IconBar::_atomClass = RegisterClass(&wc)) != 0)
{
IconBar::_fInit = TRUE;
}
return _atomClass;
}
//+---------------------------------------------------------------
//
// Member: IconBar::AddCell (internal version)
//
//---------------------------------------------------------------
int
IconBar::AddCell(LPICONCELL pCells,
int i,
CLSID& clsid,
HICON hIcon,
LPWSTR szTitle)
{
if (i < MAX_CELLS)
{
pCells[i].clsid = clsid;
pCells[i].hBmp = NULL;
pCells[i].hIcon = hIcon;
lstrcpy(pCells[i].achTitle,szTitle);
pCells[i].hBmp = NULL;
#ifdef LATER
HDC hdcScreen = GetDC(NULL);
HDC hdcSrc = CreateCompatibleDC(hdcScreen);
if (hdcSrc != NULL)
{
HBITMAP hbmpColor = CreateCompatibleBitmap(hdcScreen,
ICON_WIDTH,ICON_HEIGHT);
HBITMAP hbmpOldSrc = (HBITMAP)SelectObject(hdcSrc,hbmpColor);
SetMapMode(hdcSrc,MM_TEXT);
DrawIcon(hdcSrc,0,0,hIcon);
SelectObject(hdcSrc,hbmpOldSrc);
DeleteDC(hdcSrc);
//HANDLE hDib = CopyBmpToDib(hbmpColor,NULL);
//DeleteObject(hbmpColor);
//
//edit DIB bits such that we transform to grey-scale
// Y = (2R + 5G + 1B) >> 3
//
//hbmpColor = ConvertDibToBmp(hDib);
//GlobalFree(hDib);
pCells[i].hBmp = hbmpColor;
}
ReleaseDC(NULL,hdcScreen);
#endif
++i;
}
return i;
}
//+---------------------------------------------------------------
//
// Member: IconBar::AddCell (public version)
//
//---------------------------------------------------------------
void
IconBar::AddCell(CLSID& clsid, HICON hIcon, LPWSTR szTitle)
{
_numCells = AddCell(&_cell[0], _numCells, clsid, hIcon, szTitle);
}
int IconBar::_cUsed = 0; // outstanding users of cached cells
int IconBar::_cCache = 0; // total cached cells
IconBar::IconCell IconBar::_cache[MAX_CELLS]; // a cache array of icon cells
//+---------------------------------------------------------------
//
// Member: IconBar::AddCache (private)
//
// Notes: Either cWide or cHigh must be > 0
//
//---------------------------------------------------------------
void
IconBar::AddCache(void)
{
_cUsed++;
for(int i = 0; i < _cCache; i++)
{
AddCell(_cache[i].clsid, _cache[i].hIcon, _cache[i].achTitle);
}
}
//+---------------------------------------------------------------
//
// Member: IconBar::AddCellsFromRegDB
//
// pszFilter will be either:
// L"\\Insertable"
// OR
// L"\\Control"
//
//---------------------------------------------------------------
HRESULT
IconBar::AddCellsFromRegDB(LPWSTR pszFilter)
{
HINSTANCE hinst = (HINSTANCE)GetWindowLong(_hwnd, GWL_HINSTANCE);
HKEY hkRoot;
WCHAR szBuff[128], szValue[64], achName[64];
DWORD dwIndex;
LONG cb;
HICON hIcon = NULL;
if(_cCache != 0)
{
AddCache();
return NOERROR;
}
// enumerate the top-level keys
if (RegOpenKey(HKEY_CLASSES_ROOT, L"CLSID", &hkRoot) == ERROR_SUCCESS)
{
for (dwIndex = 0;
RegEnumKey(hkRoot,
dwIndex,
szBuff,
sizeof(szBuff)/sizeof(WCHAR)) == ERROR_SUCCESS;
++dwIndex)
{
lstrcat(szBuff,pszFilter);
cb = sizeof(szValue)/sizeof(WCHAR);
if (RegQueryValue(hkRoot, (LPWSTR)szBuff, szValue, &cb)
== ERROR_SUCCESS)
{
//
// extract the (presentable) class name
//
LPWSTR lpstr;
for (lpstr = szBuff; *lpstr != L'\\'; lpstr++);
*lpstr = L'\0';
cb = sizeof(achName)/sizeof(WCHAR);
RegQueryValue(hkRoot, (LPWSTR) szBuff, achName, &cb);
// query for the "DefaultIcon" entry
lstrcat(szBuff, L"\\DefaultIcon");
cb = sizeof(szValue)/sizeof(WCHAR);
if (RegQueryValue(hkRoot, (LPWSTR) szBuff, szValue,
&cb) == ERROR_SUCCESS)
{
UINT iIcon;
for (lpstr = szValue; *lpstr && *lpstr != L','; lpstr++)
;
if (*lpstr == L',')
{
*lpstr++ = L'\0';
iIcon = (int)wcstol(lpstr, NULL, 10);
}
else
{
iIcon = 0;
}
hIcon = ExtractIcon(hinst, szValue, iIcon);
}
// Provide default icon if class doesn't specify
if (hIcon == NULL)
hIcon = LoadIcon(NULL, IDI_APPLICATION);
if (hIcon != (HICON) -1)
{
CLSID clsid;
// convert the string to a class id
for (lpstr = szBuff; *lpstr != L'\\'; lpstr++)
;
*lpstr = L'\0';
// add (CLSID, HICON, DESCRIPTION) to our list.
if (SUCCEEDED(CLSIDFromString(szBuff, &clsid)))
{
_cCache = AddCell(_cache, _cCache,
clsid, hIcon, achName);
}
}
}
}
RegCloseKey(hkRoot);
}
AddCache();
return NOERROR; //BUGBUG sure?
}
//+---------------------------------------------------------------
//
// Member: IconBar::SelectCell
//
//---------------------------------------------------------------
void
IconBar::SelectCell(int iCell, BOOL fStick)
{
// if they have made a new selection...
if (iCell != _selectedCell)
{
// record the new selection and invalidate the cell rectangles
InvalidateCell(_hwnd, _selectedCell);
_selectedCell = iCell;
InvalidateCell(_hwnd, _selectedCell);
// send notification of selection
FORWARD_WM_COMMAND(_hwndNotify, _sIdChild, _hwnd,
IBI_NEWSELECTION, SendMessage);
}
// regardless of whether it was a new selection, if they
// want the button stuck then so be it!
_fStuck = fStick;
}
//+---------------------------------------------------------------
//
// Member: IconBar::GetSelectedClassId
//
//---------------------------------------------------------------
CLSID&
IconBar::GetSelectedClassId(void)
{
return _cell[_selectedCell].clsid;
}
//+---------------------------------------------------------------
//
// Member: IconBar::GetStatusMessage
//
//---------------------------------------------------------------
LPWSTR
IconBar::GetStatusMessage(void)
{
LPWSTR lpstr;
if (_iCellAtCursor == -1)
lpstr = NULL;
else
lpstr = _cell[_iCellAtCursor].achTitle;
return lpstr;
}
//+---------------------------------------------------------------
//
// Member: IconBar::GetCellPoint
//
//---------------------------------------------------------------
void
IconBar::GetCellPoint(LPPOINT lppt, int i)
{
lppt->x = _dxMargin + (i % _cellsPerRow) * _dxCell;
lppt->y = _dyMargin + (i / _cellsPerRow) * _dyCell;
}
//+---------------------------------------------------------------
//
// Member: IconBar::GetCellRect
//
//---------------------------------------------------------------
void
IconBar::GetCellRect(LPRECT lprc, int i)
{
POINT pt;
GetCellPoint(&pt, i);
lprc->left = pt.x;
lprc->top = pt.y;
lprc->right = lprc->left + _dxCell;
lprc->bottom = lprc->top + _dyCell;
}
//+---------------------------------------------------------------
//
// Member: IconBar::InvalidateCell
//
//---------------------------------------------------------------
void
IconBar::InvalidateCell(HWND hwnd, int i)
{
if(i < 0 || i >= _numCells)
{
return;
}
RECT rc;
GetCellRect(&rc, i);
InvalidateRect(hwnd, &rc, TRUE);
}
//+---------------------------------------------------------------
//
// Member: IconBar::OnPaint
//
//---------------------------------------------------------------
void
IconBar::OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
int i;
POINT pt;
if(_numCells)
{
//
//Draw an outline around the block of icons
//
RECT r;
GetCellPoint(&pt, 0);
r.top = pt.y - 1;
r.left = pt.x - 1;
GetCellPoint(&pt, _numCells - 1);
r.bottom = pt.y + _dyCell;
r.right = pt.x + _dxCell;
FrameRect(ps.hdc, &r, GetStockBrush(BLACK_BRUSH));
}
for (i = 0; i < _numCells; i++)
{
GetCellPoint(&pt, i);
Draw(ps.hdc, pt, i == _selectedCell, i);
}
EndPaint(hwnd, &ps);
return;
}
//+---------------------------------------------------------------
//
// Member: IconBar::OnMouseMove
//
//---------------------------------------------------------------
void
IconBar::OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags)
{
POINT pt; pt.x = x; pt.y = y;
int iCell = CellIndexFromPoint(pt);
if (iCell != _iCellAtCursor)
{
_iCellAtCursor = iCell;
// send status text change notification
FORWARD_WM_COMMAND(_hwndNotify, _sIdChild, _hwnd, IBI_STATUSAVAIL,
SendMessage);
}
}
//+---------------------------------------------------------------
//
// Member: IconBar::OnLButtonDown
//
//---------------------------------------------------------------
void
IconBar::OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)
{
POINT pt; pt.x = x; pt.y = y;
int newSel = CellIndexFromPoint(pt); // which cell that was hit?
if (newSel != -1)
SelectCell(newSel, keyFlags & MK_CONTROL);
}
//+---------------------------------------------------------------
//
// Member: IconBar::CellIndexFromPoint
//
//---------------------------------------------------------------
int
IconBar::CellIndexFromPoint(POINT pt)
{
int i; RECT rc;
for (i = 0; i < _numCells; i++)
{
GetCellRect(&rc, i);
if (PtInRect(&rc, pt))
break;
}
return i < _numCells ? i : -1;
}
//+---------------------------------------------------------------
//
// Member: IconBar::Draw
//
//---------------------------------------------------------------
void
IconBar::Draw(HDC hdc, POINT pt, BOOL fDown, int iCell )
{
if(hdc == NULL)
return;
HICON hIcon = _cell[iCell].hIcon;
//
// Erase the background
//
RECT rc;
SetRect(&rc, pt.x, pt.y, pt.x + _dxCell, pt.y + _dyCell);
FillRect(hdc, &rc, GetStockBrush(LTGRAY_BRUSH));
FrameRect(hdc, &rc, GetStockBrush(BLACK_BRUSH));
//
//Draw beveled edge around icon...
//
RECT rShade;
HBRUSH hbrGrey = GetStockBrush(GRAY_BRUSH);
HBRUSH hbrWhite = GetStockBrush(WHITE_BRUSH);
if(fDown)
{
//DOWN:
//
//draw darker (topleft) half of border
//
rShade.top = rc.top;
rShade.left = rc.left;
rShade.bottom = rc.top + 3;
rShade.right = rc.right - 1;
FillRect(hdc, &rShade, hbrGrey);
rShade.top = rc.top;
rShade.left = rc.left;
rShade.bottom = rc.bottom - 1;
rShade.right = rc.left + 3;
FillRect(hdc, &rShade, hbrGrey);
DrawIcon(hdc, pt.x + 6, pt.y + 6, hIcon);
}
else
{
//UP:
//
//draw brighter (topLeft) half of border
//
rShade.top = rc.top;
rShade.left = rc.left;
rShade.bottom = rc.top + 2;
rShade.right = rc.right - 1;
FillRect(hdc, &rShade, hbrWhite);
rShade.top = rc.top;
rShade.left = rc.left;
rShade.bottom = rc.bottom - 1;
rShade.right = rc.left + 2;
FillRect(hdc, &rShade, hbrWhite);
//
//draw darkter (bottomRight) half of border
//
rShade.top = rc.top;
rShade.left = rc.right - 2;
rShade.bottom = rc.bottom - 1;
rShade.right = rc.right - 1;
FillRect(hdc, &rShade, hbrGrey);
rShade.top = rc.bottom - 2;
rShade.left = rc.left;
rShade.bottom = rc.bottom - 1;
rShade.right = rc.right - 1;
FillRect(hdc, &rShade, hbrGrey);
//
rShade.top = rc.top + 1;
rShade.left = rc.right - 3;
rShade.bottom = rc.bottom - 1;
rShade.right = rc.right - 2;
FillRect(hdc, &rShade, hbrGrey);
rShade.top = rc.bottom - 3;
rShade.left = rc.left + 1;
rShade.bottom = rc.bottom - 2;
rShade.right = rc.right - 1;
FillRect(hdc, &rShade, hbrGrey);
if(_cell[iCell].hBmp)
{
//HDC hdcSrc = CreateCompatibleDC(hdc);
HDC hdcSrc = CreateCompatibleDC(NULL);
HBITMAP hbmpOldSrc = (HBITMAP)SelectObject(hdcSrc,_cell[iCell].hBmp);
BitBlt(hdc, pt.x + 4, pt.y + 4, ICON_WIDTH, ICON_HEIGHT,
hdcSrc, 0, 0, SRCCOPY);
SelectObject(hdcSrc,hbmpOldSrc);
DeleteDC(hdcSrc);
}
else
{
DrawIcon(hdc, pt.x + 4, pt.y + 4, hIcon);
}
}
}