//+--------------------------------------------------------------------- // // File: iconbar.cxx // //------------------------------------------------------------------------ #include "headers.hxx" #pragma hdrstop #include #include #include #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); } } }