Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2680 lines
83 KiB

/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved.
//
// MODULE: itbar.cpp
//
// PURPOSE: Implements the sizable coolbar window.
//
/********************************************************************************
Please do not make any changes to this file because this file is going to be
deleted from this project soon
Instead add the changes to tbbands.cpp and tbbands.h
*********************************************************************************/
#include "pch.hxx"
#include "ourguid.h"
#include "browser.h"
#include <resource.h>
#include "itbar.h"
#include "strconst.h"
#include "thormsgs.h"
#include <error.h>
#include "xpcomm.h"
#include "conman.h"
#include "mailnews.h"
#include "shared.h"
#include <shlwapi.h>
#include "statnery.h"
#include "goptions.h"
#include "menuutil.h"
#include "menures.h"
#include <shlobjp.h>
#include <shlguidp.h>
#include "demand.h"
#include "baui.h"
UINT GetCurColorRes(void);
CCoolbar::CCoolbar() : m_cRef(1), m_yCapture(-1)
{
DOUTL(1, TEXT("ctor CCoolbar %x"), this);
m_cRef = 1;
m_ptbSite = NULL;
m_cxMaxButtonWidth = 70;
m_ftType = FOLDER_TYPESMAX;
m_ptai = NULL;
m_fSmallIcons = FALSE;
m_hwndParent = NULL;
m_hwndTools = NULL;
m_hwndBrand = NULL;
m_hwndSizer = NULL;
m_hwndRebar = NULL;
ZeroMemory(&m_cbsSavedInfo, sizeof(COOLBARSAVE));
m_csSide = COOLBAR_TOP;
m_dwState = 0;
m_idbBack = 0;
m_hbmBack = NULL;
m_hbmBrand = NULL;
Assert(2 == CIMLISTS);
m_rghimlTools[IMLIST_DEFAULT] = NULL;
m_rghimlTools[IMLIST_HOT] = NULL;
m_hpal = NULL;
m_hdc = NULL;
m_xOrg = 0;
m_yOrg = 0;
m_cxBmp = 0;
m_cyBmp = 0;
m_cxBrand = 0;
m_cyBrand = 0;
m_cxBrandExtent = 0;
m_cyBrandExtent = 0;
m_cyBrandLeadIn = 0;
m_rgbUpperLeft = 0;
m_pMenuBand = NULL;
m_pDeskBand = NULL;
m_pShellMenu = NULL;
m_pWinEvent = NULL;
m_mbCallback = NULL;
m_xCapture = -1;
m_yCapture = -1;
// Bug #12953 - Try to load the localized max button width from the resources
TCHAR szBuffer[32];
if (AthLoadString(idsMaxCoolbarBtnWidth, szBuffer, ARRAYSIZE(szBuffer)))
{
m_cxMaxButtonWidth = StrToInt(szBuffer);
if (m_cxMaxButtonWidth == 0)
m_cxMaxButtonWidth = 70;
}
}
CCoolbar::~CCoolbar()
{
int i;
DOUTL(1, TEXT("dtor CCoolbar %x"), this);
if (m_ptbSite)
{
AssertSz(m_ptbSite == NULL, _T("CCoolbar::~CCoolbar() - For some reason ")
_T("we still have a pointer to the site."));
m_ptbSite->Release();
m_ptbSite = NULL;
}
if (m_hpal)
DeleteObject(m_hpal);
if (m_hdc)
DeleteDC(m_hdc);
if (m_hbmBrand)
DeleteObject(m_hbmBrand);
if ( m_hbmBack )
DeleteObject( m_hbmBack );
for (i = 0; i < CIMLISTS; i++)
{
if (m_rghimlTools[i])
ImageList_Destroy(m_rghimlTools[i]);
}
SafeRelease(m_pDeskBand);
SafeRelease(m_pMenuBand);
SafeRelease(m_pWinEvent);
SafeRelease(m_pShellMenu);
SafeRelease(m_mbCallback);
}
//
// FUNCTION: CCoolbar::HrInit()
//
// PURPOSE: Initializes the coolbar with the information needed to load
// any persisted reg settings and the correct arrays of buttons
// to display.
//
// PARAMETERS:
// <in> idBackground - Resource ID of the background bitmap to use.
//
// RETURN VALUE:
// S_OK - Everything initialized correctly.
//
HRESULT CCoolbar::HrInit(DWORD idBackground, HMENU hmenu)
{
DWORD cbData;
DWORD dwType;
// Save the path and value so we can save ourselves on exit
m_idbBack = idBackground;
// See if we can get the previously saved information first
ZeroMemory(&m_cbsSavedInfo, sizeof(COOLBARSAVE));
cbData = sizeof(COOLBARSAVE);
AthUserGetValue(NULL, c_szRegCoolbarLayout, &dwType, (LPBYTE)&m_cbsSavedInfo, &cbData);
if (m_cbsSavedInfo.dwVersion != COOLBAR_VERSION)
{
// Either the version didn't match, or we didn't read anything. Use
// default values
m_cbsSavedInfo.dwVersion = COOLBAR_VERSION;
m_cbsSavedInfo.csSide = COOLBAR_TOP;
m_cbsSavedInfo.bs[0].wID = CBTYPE_MENUBAND;
m_cbsSavedInfo.bs[0].dwStyle = RBBS_GRIPPERALWAYS;
m_cbsSavedInfo.bs[1].wID = CBTYPE_BRAND;
m_cbsSavedInfo.bs[2].wID = CBTYPE_TOOLS;
m_cbsSavedInfo.bs[2].dwStyle = RBBS_BREAK;
m_cbsSavedInfo.dwState |= CBSTATE_COMPRESSED;
}
m_csSide = m_cbsSavedInfo.csSide;
m_dwState = m_cbsSavedInfo.dwState;
m_hMenu = hmenu;
return (S_OK);
}
HRESULT CCoolbar::QueryInterface(REFIID riid, LPVOID * ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IOleWindow)
|| IsEqualIID(riid, IID_IDockingWindow))
{
*ppvObj = (IDockingWindow*)this;
m_cRef++;
DOUTL(2, TEXT("CCoolbar::QI(IID_IDockingWindow) called. _cRef=%d"), m_cRef);
return S_OK;
}
else if (IsEqualIID(riid, IID_IObjectWithSite))
{
*ppvObj = (IObjectWithSite*)this;
m_cRef++;
DOUTL(2, TEXT("CCoolbar::QI(IID_IObjectWithSite) called. _cRef=%d"), m_cRef);
return S_OK;
}
else if (IsEqualIID(riid, IID_IShellMenuCallback))
{
*ppvObj = (IShellMenuCallback*)this;
m_cRef++;
DOUTL(2, TEXT("CCoolbar::QI(IID_IShellCallback) called. _cRef=%d"), m_cRef);
return S_OK;
}
*ppvObj = NULL;
return E_NOINTERFACE;
}
ULONG CCoolbar::AddRef()
{
m_cRef++;
DOUTL(4, TEXT("CCoolbar::AddRef() - m_cRef = %d"), m_cRef);
return m_cRef;
}
ULONG CCoolbar::Release()
{
m_cRef--;
DOUTL(4, TEXT("CCoolbar::Release() - m_cRef = %d"), m_cRef);
if (m_cRef > 0)
return m_cRef;
delete this;
return 0;
}
//
// FUNCTION: CCoolbar::GetWindow()
//
// PURPOSE: Returns the window handle of the top side rebar.
//
HRESULT CCoolbar::GetWindow(HWND * lphwnd)
{
if (m_hwndSizer)
{
*lphwnd = m_hwndSizer;
return (S_OK);
}
else
{
*lphwnd = NULL;
return (E_FAIL);
}
}
HRESULT CCoolbar::ContextSensitiveHelp(BOOL fEnterMode)
{
return (E_NOTIMPL);
}
//
// FUNCTION: CCoolbar::SetSite()
//
// PURPOSE: Allows the owner of the coolbar to tell it what the current
// IDockingWindowSite interface to use is.
//
// PARAMETERS:
// <in> punkSite - Pointer of the IUnknown to query for IDockingWindowSite.
// If this is NULL, we just release our current pointer.
//
// RETURN VALUE:
// S_OK - Everything worked
// E_FAIL - Could not get IDockingWindowSite from the punkSite provided.
//
HRESULT CCoolbar::SetSite(IUnknown* punkSite)
{
// If we had a previous pointer, release it.
if (m_ptbSite)
{
m_ptbSite->Release();
m_ptbSite = NULL;
}
// If a new site was provided, get the IDockingWindowSite interface from it.
if (punkSite)
{
if (FAILED(punkSite->QueryInterface(IID_IDockingWindowSite,
(LPVOID*) &m_ptbSite)))
{
Assert(m_ptbSite);
return E_FAIL;
}
}
return (S_OK);
}
HRESULT CCoolbar::GetSite(REFIID riid, LPVOID *ppvSite)
{
return E_NOTIMPL;
}
//
// FUNCTION: CCoolbar::ShowDW()
//
// PURPOSE: Causes the coolbar to be either shown or hidden.
//
// PARAMETERS:
// <in> fShow - TRUE if the coolbar should be shown, FALSE to hide.
//
// RETURN VALUE:
// HRESULT
//
#define SIZABLECLASS TEXT("SizableRebar")
HRESULT CCoolbar::ShowDW(BOOL fShow)
{
HRESULT hres = S_OK;
int i = 0, j = 0;
// Check to see if our window has been created yet. If not, do that first.
if (!m_hwndSizer && m_ptbSite)
{
m_hwndParent = NULL;
hres = m_ptbSite->GetWindow(&m_hwndParent);
if (SUCCEEDED(hres))
{
WNDCLASSEX wc;
// Check to see if we need to register our window class
wc.cbSize = sizeof(WNDCLASSEX);
if (!GetClassInfoEx(g_hInst, SIZABLECLASS, &wc))
{
wc.style = 0;
wc.lpfnWndProc = SizableWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hInst;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = SIZABLECLASS;
wc.hIcon = NULL;
wc.hIconSm = NULL;
RegisterClassEx(&wc);
}
// Load the background bitmap to use for the coolbar and also get
// a handle to the HDC and Palette for the coolbar. This will be
// used to draw the animated logo later.
m_hdc = CreateCompatibleDC(NULL);
if (GetDeviceCaps(m_hdc, RASTERCAPS) & RC_PALETTE)
m_hpal = SHCreateShellPalette(m_hdc);
// If we're trying to show the coolbar, then create the rebar and
// add it's bands based on information saved in the registry.
if (SUCCEEDED(CreateRebar(fShow)))
{
for (i = 0; i < (int) CBANDS; i++)
{
switch (m_cbsSavedInfo.bs[i].wID)
{
case CBTYPE_BRAND:
hres = ShowBrand();
break;
case CBTYPE_MENUBAND:
hres = CreateMenuBand(&m_cbsSavedInfo.bs[i]);
break;
case CBTYPE_TOOLS:
hres = AddTools(&(m_cbsSavedInfo.bs[i]));
break;
}
}
}
}
}
// Set our state flags. If we're going to hide, then also save our current
// settings in the registry.
/*
if (fShow)
ClearFlag(CBSTATE_HIDDEN);
else
{
SetFlag(CBSTATE_HIDDEN);
//SaveSettings();
}
*/
// Resize the rebar based on it's new hidden / visible state and also
// show or hide the window.
if (m_hwndSizer)
{
ResizeBorderDW(NULL, NULL, FALSE);
//ShowWindow(m_hwndSizer, fShow ? SW_SHOW : SW_HIDE);
}
if (g_pConMan)
g_pConMan->Advise(this);
return hres;
}
void CCoolbar::HideToolbar(DWORD dwBandID)
{
REBARBANDINFO rbbi = {0};
DWORD cBands;
DWORD iBand;
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_ID | RBBIM_STYLE;
// Find the band
cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0);
for (iBand = 0; iBand < cBands; iBand++)
{
SendMessage(m_hwndRebar, RB_GETBANDINFO, iBand, (LPARAM) &rbbi);
if (rbbi.wID == dwBandID)
{
if (rbbi.fStyle & RBBS_HIDDEN)
{
rbbi.fStyle &= ~RBBS_HIDDEN;
}
else
{
rbbi.fStyle |= RBBS_HIDDEN;
}
rbbi.fMask = RBBIM_STYLE;
SendMessage(m_hwndRebar, RB_SETBANDINFO, iBand, (LPARAM) &rbbi);
return;
}
}
}
//
// FUNCTION: CCoolbar::CloseDW()
//
// PURPOSE: Destroys the coolbar.
//
HRESULT CCoolbar::CloseDW(DWORD dwReserved)
{
if (m_hwndSizer)
{
SaveSettings();
DestroyWindow(m_hwndSizer);
m_hwndSizer = NULL;
}
if (m_pDeskBand)
{
IInputObject *pinpobj;
if (SUCCEEDED(m_pDeskBand->QueryInterface(IID_IInputObject, (LPVOID*)&pinpobj)))
{
pinpobj->UIActivateIO(FALSE, NULL);
pinpobj->Release();
}
IObjectWithSite *pobjsite;
if (SUCCEEDED(m_pDeskBand->QueryInterface(IID_IObjectWithSite, (LPVOID*)&pobjsite)))
{
pobjsite->SetSite(NULL);
pobjsite->Release();
}
m_pDeskBand->ShowDW(FALSE);
}
return S_OK;
}
//
// FUNCTION: CCoolbar::ResizeBorderDW()
//
// PURPOSE: This is called when the coolbar needs to resize. The coolbar
// in return figures out how much border space will be required
// from the parent frame and tells the parent to reserve that
// space. The coolbar then resizes itself to those dimensions.
//
// PARAMETERS:
// <in> prcBorder - Rectangle containing the border space for the
// parent.
// <in> punkToolbarSite - Pointer to the IDockingWindowSite that we are
// part of.
// <in> fReserved - Ignored.
//
// RETURN VALUE:
// HRESULT
//
HRESULT CCoolbar::ResizeBorderDW(LPCRECT prcBorder,
IUnknown* punkToolbarSite,
BOOL fReserved)
{
const DWORD c_cxResizeBorder = 3;
const DWORD c_cyResizeBorder = 3;
HRESULT hres = S_OK;
RECT rcRequest = { 0, 0, 0, 0 };
// If we don't have a stored site pointer, we can't resize.
if (!m_ptbSite)
{
AssertSz(m_ptbSite, _T("CCoolbar::ResizeBorderDW() - Can't resize ")
_T("without an IDockingWindowSite interface to call."));
return (E_INVALIDARG);
}
// If we're visible, then calculate our border rectangle.
/*
if (IsFlagClear(CBSTATE_HIDDEN))
{
*/
RECT rcBorder, rcRebar, rcT;
int cx, cy;
// Get the size this rebar currently is
GetWindowRect(m_hwndRebar, &rcRebar);
cx = rcRebar.right - rcRebar.left;
cy = rcRebar.bottom - rcRebar.top;
// Find out how big our parent's border space is
m_ptbSite->GetBorderDW((IDockingWindow*) this, &rcBorder);
// If we're vertical, then we need to adjust our height to
// match what the parent has. If we're horizontal, then
// adjust our width.
if (VERTICAL(m_csSide))
cy = rcBorder.bottom - rcBorder.top;
else
cx = rcBorder.right - rcBorder.left;
// Bug #31007 - There seems to be a problem in commctrl
// IEBug #5574 either with the REBAR or with the Toolbar
// when they are vertical. If the we try to
// size them to 2 or less, we lock up. This
// is a really poor fix, but there's no way
// to get commctrl fixed this late in the game.
if (cy < 5) cy = 10;
if (cx < 5) cx = 10;
// Move the rebar to the new position.
if (m_csSide == COOLBAR_LEFT || m_csSide == COOLBAR_TOP)
{
SetWindowPos(m_hwndRebar, NULL, 0, 0, cx, cy,
SWP_NOZORDER | SWP_NOACTIVATE);
}
else
{
if (m_csSide == COOLBAR_BOTTOM)
SetWindowPos(m_hwndRebar, NULL, 0, c_cyResizeBorder,
cx, cy, SWP_NOZORDER | SWP_NOACTIVATE);
else
SetWindowPos(m_hwndRebar, NULL, c_cxResizeBorder, 0,
cx, cy, SWP_NOZORDER | SWP_NOACTIVATE);
}
// Figure out how much border space to ask the site for
GetWindowRect(m_hwndRebar, &rcRebar);
switch (m_csSide)
{
case COOLBAR_TOP:
rcRequest.top = rcRebar.bottom - rcRebar.top + c_cxResizeBorder;
break;
case COOLBAR_LEFT:
rcRequest.left = rcRebar.right - rcRebar.left + c_cyResizeBorder;
break;
case COOLBAR_BOTTOM:
rcRequest.bottom = rcRebar.bottom - rcRebar.top + c_cxResizeBorder;
break;
case COOLBAR_RIGHT:
rcRequest.right = rcRebar.right - rcRebar.left + c_cyResizeBorder;
break;
default:
AssertSz(FALSE, _T("CCoolbar::ResizeBorderDW() - What other")
_T(" sides are there???"));
break;
}
// Ask the site for that border space
if (SUCCEEDED(m_ptbSite->RequestBorderSpaceDW((IDockingWindow*) this, &rcRequest)))
{
// Position the window based on the area given to us
switch (m_csSide)
{
case COOLBAR_TOP:
SetWindowPos(m_hwndSizer, NULL,
rcBorder.left,
rcBorder.top,
rcRebar.right - rcRebar.left,
rcRequest.top + rcBorder.top,
SWP_NOZORDER | SWP_NOACTIVATE);
break;
case COOLBAR_LEFT:
SetWindowPos(m_hwndSizer, NULL,
rcBorder.left,
rcBorder.top,
rcRequest.left,
rcBorder.bottom - rcBorder.top,
SWP_NOZORDER | SWP_NOACTIVATE);
break;
case COOLBAR_BOTTOM:
SetWindowPos(m_hwndSizer, NULL,
rcBorder.left,
rcBorder.bottom - rcRequest.bottom,
rcBorder.right - rcBorder.left,
rcRequest.bottom,
SWP_NOZORDER | SWP_NOACTIVATE);
GetClientRect(m_hwndSizer, &rcT);
break;
case COOLBAR_RIGHT:
SetWindowPos(m_hwndSizer, NULL,
rcBorder.right - rcRequest.right,
rcBorder.top,
rcRequest.right,
rcBorder.bottom - rcBorder.top,
SWP_NOZORDER | SWP_NOACTIVATE);
break;
}
}
/*
}
*/
// Now tell the site how much border space we're using.
m_ptbSite->SetBorderSpaceDW((IDockingWindow*) this, &rcRequest);
return hres;
}
//
// FUNCTION: CCoolbar::Invoke()
//
// PURPOSE: Allows the owner of the coolbar to force the coolbar to do
// something.
//
// PARAMETERS:
// <in> id - ID of the command the caller wants the coolbar to do.
// <in> pv - Pointer to any parameters the coolbar might need to carry
// out the command.
//
// RETURN VALUE:
// S_OK - The command was carried out.
//
// COMMENTS:
// <???>
//
HRESULT CCoolbar::Invoke(DWORD id, LPVOID pv)
{
switch (id)
{
// Starts animating the logo
case idDownloadBegin:
StartDownload();
break;
// Stops animating the logo
case idDownloadEnd:
StopDownload();
break;
// Update the enabled / disabled state of buttons on the toolbar
case idStateChange:
{
// pv is a pointer to a COOLBARSTATECHANGE struct
COOLBARSTATECHANGE* pcbsc = (COOLBARSTATECHANGE*) pv;
SendMessage(m_hwndTools, TB_ENABLEBUTTON, pcbsc->id,
MAKELONG(pcbsc->fEnable, 0));
break;
}
case idToggleButton:
{
COOLBARSTATECHANGE* pcbsc = (COOLBARSTATECHANGE *) pv;
SendMessage(m_hwndTools, TB_CHECKBUTTON, pcbsc->id,
MAKELONG(pcbsc->fEnable, 0));
break;
}
case idBitmapChange:
{
// pv is a pointer to a COOLBARBITMAPCHANGE struct
COOLBARBITMAPCHANGE *pcbc = (COOLBARBITMAPCHANGE*) pv;
SendMessage(m_hwndTools, TB_CHANGEBITMAP, pcbc->id, MAKELPARAM(pcbc->index, 0));
break;
}
// Sends a message directly to the toolbar.
case idSendToolMessage:
#define ptm ((TOOLMESSAGE *)pv)
ptm->lResult = SendMessage(m_hwndTools, ptm->uMsg, ptm->wParam, ptm->lParam);
break;
#undef ptm
case idCustomize:
SendMessage(m_hwndTools, TB_CUSTOMIZE, 0, 0);
break;
}
return S_OK;
}
//
// FUNCTION: CCoolbar::StartDownload()
//
// PURPOSE: Starts animating the logo.
//
void CCoolbar::StartDownload()
{
if (m_hwndBrand)
{
SetFlag(CBSTATE_ANIMATING);
SetFlag(CBSTATE_FIRSTFRAME);
m_yOrg = 0;
SetTimer(m_hwndSizer, ANIMATION_TIMER, 100, NULL);
}
}
//
// FUNCTION: CCoolbar::StopDownload()
//
// PURPOSE: Stops animating the logo. Restores the logo to it's default
// first frame.
//
void CCoolbar::StopDownload()
{
int i, cBands;
REBARBANDINFO rbbi;
// Set the background colors for this band back to the first frame
cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0);
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_ID;
for (i = 0; i < cBands; i++)
{
SendMessage(m_hwndRebar, RB_GETBANDINFO, i, (LPARAM) &rbbi);
if (CBTYPE_BRAND == rbbi.wID)
{
rbbi.fMask = RBBIM_COLORS;
rbbi.clrFore = m_rgbUpperLeft;
rbbi.clrBack = m_rgbUpperLeft;
SendMessage(m_hwndRebar, RB_SETBANDINFO, i, (LPARAM) &rbbi);
break;
}
}
// Reset the state flags
ClearFlag(CBSTATE_ANIMATING);
ClearFlag(CBSTATE_FIRSTFRAME);
KillTimer(m_hwndSizer, ANIMATION_TIMER);
InvalidateRect(m_hwndBrand, NULL, FALSE);
UpdateWindow(m_hwndBrand);
}
BOOL CCoolbar::CheckForwardWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres)
{
HWND hwndForward = NULL;
switch(uMsg)
{
case WM_NOTIFY:
hwndForward = ((LPNMHDR)lParam)->hwndFrom;
break;
case WM_COMMAND:
hwndForward = GET_WM_COMMAND_HWND(wParam, lParam);
break;
case WM_SYSCOLORCHANGE:
case WM_WININICHANGE:
case WM_PALETTECHANGED:
hwndForward = m_hwndRebar;
break;
}
if (hwndForward && m_pWinEvent && m_pWinEvent->IsWindowOwner(hwndForward) == S_OK)
{
LRESULT lres;
m_pWinEvent->OnWinEvent(hwndForward, uMsg, wParam, lParam, &lres);
if (plres)
*plres = lres;
return TRUE;
}
return FALSE;
}
//
// FUNCTION: CCoolbar::SizableWndProc()
//
// PURPOSE: Handles messages sent to the coolbar root window.
//
LRESULT EXPORT_16 CALLBACK CCoolbar::SizableWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CCoolbar* pitbar = (CCoolbar*)GetProp(hwnd, TEXT("CCoolbar"));
DWORD dw;
if (!pitbar)
goto CallDWP;
switch(uMsg)
{
case WM_SYSCOLORCHANGE:
// Reload the graphics
LoadGlyphs(pitbar->m_hwndTools, CIMLISTS, pitbar->m_rghimlTools, (fIsWhistler() ? TB_BMP_CX : TB_BMP_CX_W2K),
(fIsWhistler() ? ((GetCurColorRes() > 24) idb32256Browser : idbBrowser) :
((GetCurColorRes() > 8) ? idbNW256Browser : idbNWBrowser)));
pitbar->UpdateToolbarColors();
InvalidateRect(pitbar->m_hwndTools, NULL, TRUE);
pitbar->CheckForwardWinEvent(hwnd, uMsg, wParam, lParam, NULL);
break;
case WM_WININICHANGE:
case WM_FONTCHANGE:
// Forward this to our child windows
LoadGlyphs(pitbar->m_hwndTools, CIMLISTS, pitbar->m_rghimlTools, (fIsWhistler() ? TB_BMP_CX : TB_BMP_CX_W2K),
(fIsWhistler() ? ((GetCurColorRes() > 24) idb32256Browser : idbBrowser) :
((GetCurColorRes() > 8) ? idbNW256Browser : idbNWBrowser)));
SendMessage(pitbar->m_hwndTools, uMsg, wParam, lParam);
InvalidateRect(pitbar->m_hwndTools, NULL, TRUE);
pitbar->SetMinDimensions();
pitbar->CheckForwardWinEvent(hwnd, uMsg, wParam, lParam, NULL);
break;
case WM_SETCURSOR:
// We play with the cursor a bit to make the resizing cursor show
// up when the user is over the edge of the coolbar that allows
// them to drag to resize etc.
if ((HWND) wParam == hwnd)
{
if (pitbar->m_dwState & CBSTATE_INMENULOOP)
SetCursor(LoadCursor(NULL, IDC_ARROW));
else
SetCursor(LoadCursor(NULL,
VERTICAL(pitbar->m_csSide) ? IDC_SIZEWE : IDC_SIZENS));
return (TRUE);
}
return (FALSE);
case WM_LBUTTONDOWN:
// The user is about to resize the bar. Capture the cursor so we
// can watch the changes.
if (VERTICAL(pitbar->m_csSide))
pitbar->m_xCapture = GET_X_LPARAM(lParam);
else
pitbar->m_yCapture = GET_Y_LPARAM(lParam);
SetCapture(hwnd);
break;
case WM_MOUSEMOVE:
// The user is resizing the bar. Handle updating the sizes as
// they drag.
if (VERTICAL(pitbar->m_csSide))
{
if (pitbar->m_xCapture != -1)
{
if (hwnd != GetCapture())
pitbar->m_xCapture = -1;
else
pitbar->TrackSlidingX(GET_X_LPARAM(lParam));
}
}
else
{
if (pitbar->m_yCapture != -1)
{
if (hwnd != GetCapture())
pitbar->m_yCapture = -1;
else
pitbar->TrackSlidingY(GET_Y_LPARAM(lParam));
}
}
break;
case WM_LBUTTONUP:
// The user is done resizing. release our capture and reset our
// state.
if (pitbar->m_yCapture != -1 || pitbar->m_xCapture != -1)
{
ReleaseCapture();
pitbar->m_yCapture = -1;
pitbar->m_xCapture = -1;
}
break;
case WM_VKEYTOITEM:
case WM_CHARTOITEM:
// We must swallow these messages to avoid infinit SendMessage
break;
case WM_DRAWITEM:
// Draws the animating brand
if (wParam == idcBrand)
pitbar->DrawBranding((LPDRAWITEMSTRUCT) lParam);
break;
case WM_MEASUREITEM:
// Draws the animating brand
if (wParam == idcBrand)
{
((LPMEASUREITEMSTRUCT) lParam)->itemWidth = pitbar->m_cxBrand;
((LPMEASUREITEMSTRUCT) lParam)->itemHeight = pitbar->m_cyBrand;
}
break;
case WM_TIMER:
// This timer fires every time we need to draw the next frame in
// animating brand.
if (wParam == ANIMATION_TIMER)
{
if (pitbar->m_hwndBrand)
{
pitbar->m_yOrg += pitbar->m_cyBrand;
if (pitbar->m_yOrg >= pitbar->m_cyBrandExtent)
pitbar->m_yOrg = pitbar->m_cyBrandLeadIn;
InvalidateRect(pitbar->m_hwndBrand, NULL, FALSE);
UpdateWindow(pitbar->m_hwndBrand);
}
}
break;
case WM_NOTIFY:
{
LRESULT lres;
if (pitbar->CheckForwardWinEvent(hwnd, uMsg, wParam, lParam, &lres))
return lres;
return pitbar->OnNotify(hwnd, lParam);
}
case WM_COMMAND:
{
LRESULT lres;
if (pitbar->CheckForwardWinEvent(hwnd, uMsg, wParam, lParam, &lres))
return lres;
return SendMessage(pitbar->m_hwndParent, WM_COMMAND, wParam, lParam);
}
case WM_CONTEXTMENU:
pitbar->OnContextMenu((HWND) wParam, LOWORD(lParam), HIWORD(lParam));
break;
case WM_PALETTECHANGED:
// BUGBUG: we could optimize this by realizing and checking the
// return value
//
// for now we will just invalidate ourselves and all children...
RedrawWindow(pitbar->m_hwndSizer, NULL, NULL,
RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
break;
case CM_CONNECT:
// wParam is hMenuConnect, lParam is CmdID
g_pConMan->Connect((HMENU) wParam, lParam, pitbar->m_hwndParent);
g_pConMan->FreeConnectMenu((HMENU) wParam);
break;
case TT_ISTEXTVISIBLE:
return (!(pitbar->m_dwState & CBSTATE_COMPRESSED));
case WM_DESTROY:
// Clean up our pointers
RemoveProp(hwnd, TEXT("CCoolbar"));
pitbar->Release(); // Corresponding to AddRef at SetProp
DOUTL(1, _T("CCoolbar::WM_DESTROY - Called RemoveProp. Called")
_T(" Release() new m_cRef=%d"), pitbar->m_cRef);
//Unregister with the connection manager
if (g_pConMan)
g_pConMan->Unadvise(pitbar);
// fall through
default:
CallDWP:
return(DefWindowProc(hwnd, uMsg, wParam, lParam));
}
return 0L;
}
HRESULT CCoolbar::OnCommand(HWND hwnd, int idCmd, HWND hwndControl, UINT cmd)
{
LPTSTR pszTest;
switch (idCmd)
{
case idcBrand: // click on the spinning globe
OnHelpGoto(hwnd, ID_MSWEB_PRODUCT_NEWS);
break;
case ID_CUSTOMIZE:
SendMessage(m_hwndTools, TB_CUSTOMIZE, 0, 0);
break;
case ID_TOOLBAR_TOP:
//case ID_TOOLBAR_LEFT:
case ID_TOOLBAR_BOTTOM:
//case ID_TOOLBAR_RIGHT:
{
// There's a painting problem that occurs going from top to bottom
// and vice versa. If that's what we're doing, we repaint when
// we're done.
BOOL fRepaint;
fRepaint = (VERTICAL(m_csSide) == VERTICAL(idCmd - ID_TOOLBAR_TOP));
m_csSide = (COOLBAR_SIDE) (idCmd - ID_TOOLBAR_TOP);
ChangeOrientation();
if (fRepaint)
InvalidateRect(m_hwndTools, NULL, FALSE);
}
break;
case ID_TEXT_LABELS:
CompressBands(!IsFlagSet(CBSTATE_COMPRESSED));
break;
default:
return S_FALSE;
}
return S_OK;
}
HRESULT CCoolbar::OnInitMenuPopup(HMENU hMenuContext)
{
CheckMenuRadioItem(hMenuContext, ID_TOOLBAR_TOP, ID_TOOLBAR_RIGHT,
ID_TOOLBAR_TOP + m_csSide, MF_BYCOMMAND);
CheckMenuItem(hMenuContext, ID_TEXT_LABELS,
MF_BYCOMMAND | IsFlagSet(CBSTATE_COMPRESSED) ? MF_UNCHECKED : MF_CHECKED);
return S_OK;
}
LRESULT CCoolbar::OnNotify(HWND hwnd, LPARAM lparam)
{
NMHDR *lpnmhdr = (NMHDR*)lparam;
switch (lpnmhdr->idFrom)
{
case idcCoolbar:
switch (lpnmhdr->code)
{
case RBN_HEIGHTCHANGE:
ResizeBorderDW(NULL, NULL, FALSE);
break;
case RBN_CHILDSIZE:
NMREBARCHILDSIZE *lpchildsize = (NMREBARCHILDSIZE*)lparam;
if (lpchildsize->wID == CBTYPE_TOOLS)
{
SetWindowPos(m_hwndTools, NULL, lpchildsize->rcChild.left, lpchildsize->rcChild.right,
lpchildsize->rcChild.right - lpchildsize->rcChild.left,
lpchildsize->rcChild.bottom - lpchildsize->rcChild.top,
SWP_NOZORDER | SWP_NOACTIVATE);
}
else
if (lpchildsize->wID == CBTYPE_BRAND)
{
SetWindowPos(m_hwndBrand, NULL, lpchildsize->rcChild.left, lpchildsize->rcChild.right,
lpchildsize->rcChild.right - lpchildsize->rcChild.left,
lpchildsize->rcChild.bottom - lpchildsize->rcChild.top,
SWP_NOZORDER | SWP_NOACTIVATE);
}
break;
}
case idcToolbar:
if (lpnmhdr->code == TBN_GETBUTTONINFOA)
return OnGetButtonInfo((TBNOTIFY*) lparam);
if (lpnmhdr->code == TBN_QUERYDELETE)
return (TRUE);
if (lpnmhdr->code == TBN_QUERYINSERT)
return (TRUE);
if (lpnmhdr->code == TBN_ENDADJUST)
{
IAthenaBrowser *psbwr;
// Update the size of the sizer
SetMinDimensions();
ResizeBorderDW(NULL, NULL, FALSE);
// check IDockingWindowSite
if (m_ptbSite)
{
// get IAthenaBrowser interface
if (SUCCEEDED(m_ptbSite->QueryInterface(IID_IAthenaBrowser,(void**)&psbwr)))
{
psbwr->UpdateToolbar();
psbwr->Release();
}
}
}
if (lpnmhdr->code == TBN_RESET)
{
// Remove all the buttons from the toolbar
int cButtons = SendMessage(m_hwndTools, TB_BUTTONCOUNT, 0, 0);
while (--cButtons >= 0)
SendMessage(m_hwndTools, TB_DELETEBUTTON, cButtons, 0);
// Set the buttons back to the default
SendMessage(m_hwndTools, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
SendMessage(m_hwndTools, TB_ADDBUTTONS, m_ptai->cDefButtons,
(LPARAM) m_ptai->rgDefButtons);
return (TRUE);
}
if (lpnmhdr->code == TBN_CUSTHELP)
{
// WinHelp(m_hwndTools, c_szMailHelpFile, HELP_CONTEXT, IDH_NEWS_COMM_GROUPBOX);
OEHtmlHelp(m_hwndTools, c_szCtxHelpFileHTMLCtx, HH_DISPLAY_TOPIC, (DWORD) (LPCSTR) "idh_proced_cust_tool.htm");
return (TRUE);
}
if (lpnmhdr->code == TBN_DROPDOWN)
{
return OnDropDown(hwnd, lpnmhdr);
}
break;
}
return (0L);
}
LRESULT CCoolbar::OnDropDown(HWND hwnd, LPNMHDR lpnmh)
{
HMENU hMenuPopup = NULL;
TBNOTIFY *ptbn = (TBNOTIFY *)lpnmh ;
UINT uiCmd = ptbn->iItem ;
RECT rc;
DWORD dwCmd = 0;
IAthenaBrowser *pBrowser;
BOOL fPostCmd = TRUE;
IOleCommandTarget *pTarget;
// Load and initialize the appropriate dropdown menu
switch (uiCmd)
{
case ID_POPUP_LANGUAGE:
{
// check IDockingWindowSite
if (m_ptbSite)
{
// get IAthenaBrowser interface
if (SUCCEEDED(m_ptbSite->QueryInterface(IID_IAthenaBrowser, (void**) &pBrowser)))
{
// get language menu from shell/browser
pBrowser->GetLanguageMenu(&hMenuPopup, 0);
pBrowser->Release();
}
}
}
break;
case ID_NEW_MSG_DEFAULT:
GetStationeryMenu(&hMenuPopup);
/* $INFOCOLUMN
// Disable Send Instant Msg item
if (SUCCEEDED(m_ptbSite->QueryInterface(IID_IAthenaBrowser, (void**) &pBrowser)))
{
CInfoColumn * pInfoColumn = NULL;
if(SUCCEEDED(pBrowser->GetInfoColumn(&pInfoColumn)))
{
IMsgrAb * pMsgrAb = pInfoColumn->GetBAComtrol();
if(pMsgrAb)
{
BOOL fRet;
pMsgrAb->get_InstMsg(&fRet);
if(fRet == FALSE)
EnableMenuItem(hMenuPopup, ID_SEND_INSTANT_MESSAGE, MF_BYCOMMAND | MF_GRAYED);
}
pInfoColumn->Release();
}
pBrowser->Release();
}
*/
break;
case ID_PREVIEW_PANE:
{
// Load the menu
hMenuPopup = LoadPopupMenu(IDR_PREVIEW_POPUP);
if (!hMenuPopup)
break;
// check IDockingWindowSite
if (m_ptbSite)
{
// get IAthenaBrowser interface
if (SUCCEEDED(m_ptbSite->QueryInterface(IID_IOleCommandTarget, (void**) &pTarget)))
{
MenuUtil_EnablePopupMenu(hMenuPopup, pTarget);
pTarget->Release();
}
}
break;
}
default:
AssertSz(FALSE, "CCoolbar::OnDropDown() - Unhandled TBN_DROPDOWN notification");
return (TBDDRET_NODEFAULT);
}
// If we loaded a menu, then go ahead and display it
if (hMenuPopup)
{
SendMessage(m_hwndTools, TB_GETRECT, ptbn->iItem, (LPARAM)&rc);
MapWindowRect(m_hwndTools, HWND_DESKTOP, &rc);
SetFlag(CBSTATE_INMENULOOP);
dwCmd = TrackPopupMenuEx(hMenuPopup, TPM_RETURNCMD | TPM_LEFTALIGN,
rc.left, rc.bottom, m_hwndParent, NULL);
ClearFlag(CBSTATE_INMENULOOP);
}
// Clean up anything needing to be cleaned up
switch (uiCmd)
{
case ID_LANGUAGE:
break;
case ID_NEW_MSG_DEFAULT:
DestroyMenu(hMenuPopup);
break;
}
if (fPostCmd && dwCmd)
PostMessage(m_hwndSizer, WM_COMMAND, dwCmd, 0);
return (TBDDRET_DEFAULT);
}
void CCoolbar::OnContextMenu(HWND hwndFrom, int xPos, int yPos)
{
HMENU hMenu, hMenuContext;
TCHAR szBuf[256];
HWND hwnd;
HWND hwndSizer = GetParent(hwndFrom);
POINT pt = {xPos, yPos};
// Make sure the context menu only appears on the toolbar bars
hwnd = WindowFromPoint(pt);
/*
if (GetClassName(hwnd, szBuf, ARRAYSIZE(szBuf)))
if (0 != lstrcmpi(szBuf, TOOLBARCLASSNAME))
return;
*/
if (hwnd == m_hwndTools)
{
if (NULL != (hMenu = LoadMenu(g_hLocRes, MAKEINTRESOURCE(IDR_TOOLBAR_POPUP))))
{
hMenuContext = GetSubMenu(hMenu, 0);
OnInitMenuPopup(hMenuContext);
SetFlag(CBSTATE_INMENULOOP);
TrackPopupMenu(hMenuContext, TPM_RIGHTBUTTON, xPos, yPos, 0,
hwndFrom, NULL);
ClearFlag(CBSTATE_INMENULOOP);
DestroyMenu(hMenu);
}
}
else
if (hwnd == m_hwndMenuBand)
{
HandleCoolbarPopup(xPos, yPos);
}
}
//
// FUNCTION: CCoolbar::OnGetButtonInfo()
//
// PURPOSE: Handles the TBN_GETBUTTONINFO notification by returning
// the buttons availble for the toolbar.
//
// PARAMETERS:
// ptbn - pointer to the TBNOTIFY struct we need to fill in.
//
// RETURN VALUE:
// Returns TRUE to tell the toolbar to use this button, or FALSE
// otherwise.
//
LRESULT CCoolbar::OnGetButtonInfo(TBNOTIFY* ptbn)
{
// Start by returning information for the first array of
// buttons
if ((ptbn->iItem < (int) m_ptai->cDefButtons && (ptbn->iItem >= 0)))
{
// Grab the button info out of the array
ptbn->tbButton = m_ptai->rgDefButtons[ptbn->iItem];
// Return the string info from the string resource. Note,
// pszText already points to a buffer allocated by the
// control and cchText has the length of that buffer.
LoadString(g_hLocRes, m_ptai->rgidsButtons[ptbn->tbButton.iString],
ptbn->pszText, ptbn->cchText);
return (TRUE);
}
else
{
// Now return information for the extra buttons not on the `
// toolbar by default.
if (ptbn->iItem < (int) (m_ptai->cDefButtons + m_ptai->cExtraButtons))
{
ptbn->tbButton = m_ptai->rgExtraButtons[ptbn->iItem - m_ptai->cDefButtons];
// The control has already created a buffer for us to copy
// the string into.
LoadString(g_hLocRes, m_ptai->rgidsButtons[ptbn->tbButton.iString],
ptbn->pszText, ptbn->cchText);
return (TRUE);
}
else
{
// No more buttons to add, so return FALSE.
return (FALSE);
}
}
}
HRESULT CCoolbar::ShowBrand(void)
{
REBARBANDINFO rbbi;
// create branding window
/*
m_hwndBrand = CreateWindow(TEXT("button"), NULL,WS_CHILD | BS_OWNERDRAW,
0, 0, 400, 200, m_hwndRebar, (HMENU) idcBrand,
g_hInst, NULL);
*/
m_hwndBrand = CreateWindow(TEXT("button"), NULL,WS_CHILD | BS_OWNERDRAW,
0, 0, 0, 0, m_hwndRebar, (HMENU) idcBrand,
g_hInst, NULL);
if (!m_hwndBrand)
{
DOUTL(1, TEXT("!!!ERROR!!! CITB:Show CreateWindow(BRANDING) failed"));
return(E_OUTOFMEMORY);
}
LoadBrandingBitmap();
// add branding band
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_STYLE | RBBIM_COLORS | RBBIM_CHILD | RBBIM_ID;
rbbi.fStyle = RBBS_FIXEDSIZE;
rbbi.wID = CBTYPE_BRAND;
rbbi.clrFore = m_rgbUpperLeft;
rbbi.clrBack = m_rgbUpperLeft;
rbbi.hwndChild = m_hwndBrand;
SendMessage(m_hwndRebar, RB_INSERTBAND, (UINT) -1, (LPARAM) (LPREBARBANDINFO) &rbbi);
return (S_OK);
}
HRESULT CCoolbar::LoadBrandingBitmap()
{
HKEY hKey;
DIBSECTION dib;
DWORD dwcbData;
DWORD dwType = 0;
BOOL fReg = FALSE;
BOOL fRegLoaded = FALSE;
TCHAR szScratch[MAX_PATH];
TCHAR szExpanded[MAX_PATH];
LPTSTR psz;
if (m_hbmBrand)
{
DeleteObject(m_hbmBrand);
m_hbmBrand = NULL;
}
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegKeyCoolbar, 0, KEY_QUERY_VALUE, &hKey))
{
fReg = TRUE;
dwcbData = MAX_PATH;
if (fReg && (ERROR_SUCCESS == RegQueryValueEx(hKey, IsFlagSet(CBSTATE_COMPRESSED) ? c_szValueSmBrandBitmap : c_szValueBrandBitmap, NULL, &dwType,
(LPBYTE)szScratch, &dwcbData)))
{
if (REG_EXPAND_SZ == dwType)
{
ExpandEnvironmentStrings(szScratch, szExpanded, ARRAYSIZE(szExpanded));
psz = szExpanded;
}
else
psz = szScratch;
m_hbmBrand = (HBITMAP) LoadImage(NULL, psz, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION | LR_LOADFROMFILE);
if (m_hbmBrand)
fRegLoaded = TRUE;
}
}
if (!m_hbmBrand)
{
int id = IsFlagSet(CBSTATE_COMPRESSED) ? (fIsWhistler() ? idbHiBrand26 : idbBrand26) :
(fIsWhistler() ? idbHiBrand38 : idbBrand38);
m_hbmBrand = (HBITMAP)LoadImage(g_hLocRes, MAKEINTRESOURCE(id), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
}
GetObject(m_hbmBrand, sizeof(DIBSECTION), &dib);
m_cxBrandExtent = dib.dsBm.bmWidth;
m_cyBrandExtent = dib.dsBm.bmHeight;
m_cxBrand = m_cxBrandExtent;
dwcbData = sizeof(DWORD);
if (!fRegLoaded || (ERROR_SUCCESS != RegQueryValueEx(hKey, IsFlagSet(CBSTATE_COMPRESSED) ? c_szValueSmBrandHeight : c_szValueBrandHeight, NULL, &dwType,
(LPBYTE)&m_cyBrand, &dwcbData)))
m_cyBrand = m_cxBrandExtent;
if (!fRegLoaded || (ERROR_SUCCESS != RegQueryValueEx(hKey, IsFlagSet(CBSTATE_COMPRESSED) ? c_szValueSmBrandLeadIn : c_szValueBrandLeadIn, NULL, &dwType,
(LPBYTE)&m_cyBrandLeadIn, &dwcbData)))
m_cyBrandLeadIn = 4;
m_cyBrandLeadIn *= m_cyBrand;
SelectObject(m_hdc, m_hbmBrand);
m_rgbUpperLeft = GetPixel(m_hdc, 1, 1);
if (fReg)
RegCloseKey(hKey);
// now look for old branding entries for IE2.0 and, if found, stick them
// in the first frame of the animation sequence
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyIEMain, 0, KEY_QUERY_VALUE, &hKey))
{
dwcbData = MAX_PATH;
if (ERROR_SUCCESS == RegQueryValueEx(hKey, IsFlagSet(CBSTATE_COMPRESSED) ? c_szValueSmallBitmap : c_szValueLargeBitmap, NULL, &dwType,
(LPBYTE)szScratch, &dwcbData))
{
if (REG_EXPAND_SZ == dwType)
{
ExpandEnvironmentStrings(szScratch, szExpanded, ARRAYSIZE(szExpanded));
psz = szExpanded;
}
else
psz = szScratch;
HBITMAP hbmOld = (HBITMAP) LoadImage(NULL, psz, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION | LR_LOADFROMFILE);
if (hbmOld)
{
HDC hdcOld = CreateCompatibleDC(m_hdc);
if (hdcOld)
{
GetObject(hbmOld, sizeof(DIBSECTION), &dib);
SelectObject(hdcOld, hbmOld);
m_rgbUpperLeft = GetPixel(hdcOld, 1, 1);
StretchBlt(m_hdc, 0, 0, m_cxBrandExtent, m_cyBrand, hdcOld, 0, 0,
dib.dsBm.bmWidth, dib.dsBm.bmHeight, SRCCOPY);
DeleteDC(hdcOld);
}
DeleteObject(hbmOld);
}
}
RegCloseKey(hKey);
}
return(S_OK);
}
void CCoolbar::DrawBranding(LPDRAWITEMSTRUCT lpdis)
{
HPALETTE hpalPrev;
int x, y, cx, cy;
int yOrg = 0;
if (IsFlagSet(CBSTATE_ANIMATING))
yOrg = m_yOrg;
if (IsFlagSet(CBSTATE_FIRSTFRAME))
{
REBARBANDINFO rbbi;
int cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0);
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_ID;
for (int i = 0; i < cBands; i++)
{
SendMessage(m_hwndRebar, RB_GETBANDINFO, i, (LPARAM) &rbbi);
if (CBTYPE_BRAND == rbbi.wID)
{
rbbi.fMask = RBBIM_COLORS;
rbbi.clrFore = m_rgbUpperLeft;
rbbi.clrBack = m_rgbUpperLeft;
SendMessage(m_hwndRebar, RB_SETBANDINFO, i, (LPARAM) &rbbi);
break;
}
}
ClearFlag(CBSTATE_FIRSTFRAME);
}
if (m_hpal)
{
hpalPrev = SelectPalette(lpdis->hDC, m_hpal, TRUE);
RealizePalette(lpdis->hDC);
}
x = lpdis->rcItem.left;
cx = lpdis->rcItem.right - x;
y = lpdis->rcItem.top;
cy = lpdis->rcItem.bottom - y;
if (m_cxBrand > m_cxBrandExtent)
{
HBRUSH hbrBack = CreateSolidBrush(m_rgbUpperLeft);
int xRight = lpdis->rcItem.right;
x += (m_cxBrand - m_cxBrandExtent) / 2;
cx = m_cxBrandExtent;
lpdis->rcItem.right = x;
FillRect(lpdis->hDC, &lpdis->rcItem, hbrBack);
lpdis->rcItem.right = xRight;
lpdis->rcItem.left = x + cx;
FillRect(lpdis->hDC, &lpdis->rcItem, hbrBack);
DeleteObject(hbrBack);
}
BitBlt(lpdis->hDC, x, y, cx, cy, m_hdc, 0, yOrg, SRCCOPY);
if (m_hpal)
{
SelectPalette(lpdis->hDC, hpalPrev, TRUE);
RealizePalette(lpdis->hDC);
}
}
BOOL CCoolbar::SetMinDimensions(void)
{
REBARBANDINFO rbbi;
LRESULT lButtonSize;
int i, cBands;
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0);
for (i = 0; i < cBands; i++)
{
rbbi.fMask = RBBIM_ID;
SendMessage(m_hwndRebar, RB_GETBANDINFO, i, (LPARAM) &rbbi);
switch (rbbi.wID)
{
case CBTYPE_BRAND:
rbbi.cxMinChild = m_cxBrand;
rbbi.cyMinChild = m_cyBrand;
break;
case CBTYPE_TOOLS:
case CBTYPE_MENUBAND:
lButtonSize = SendMessage(m_hwndTools, TB_GETBUTTONSIZE, 0, 0L);
rbbi.cxMinChild = VERTICAL(m_csSide) ? HIWORD(lButtonSize) : LOWORD(lButtonSize);
rbbi.cyMinChild = VERTICAL(m_csSide) ? LOWORD(lButtonSize) : HIWORD(lButtonSize);
break;
}
rbbi.fMask = RBBIM_CHILDSIZE;
SendMessage(m_hwndRebar, RB_SETBANDINFO, i, (LPARAM)&rbbi);
}
return TRUE;
}
BOOL CCoolbar::CompressBands(BOOL fCompress)
{
LRESULT lTBStyle = 0;
int i, cBands;
REBARBANDINFO rbbi;
if (!!fCompress == IsFlagSet(CBSTATE_COMPRESSED))
// no change -- return immediately
return(FALSE);
if (fCompress)
SetFlag(CBSTATE_COMPRESSED);
else
ClearFlag(CBSTATE_COMPRESSED);
m_yOrg = 0;
LoadBrandingBitmap();
cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0);
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
for (i = 0; i < cBands; i++)
{
rbbi.fMask = RBBIM_ID;
SendMessage(m_hwndRebar, RB_GETBANDINFO, i, (LPARAM) &rbbi);
if (fCompress)
{
switch (rbbi.wID)
{
case CBTYPE_TOOLS:
SendMessage(m_hwndTools, TB_SETMAXTEXTROWS, 0, 0L);
SendMessage(m_hwndTools, TB_SETBUTTONWIDTH, 0, (LPARAM) MAKELONG(0,MAX_TB_COMPRESSED_WIDTH));
break;
}
}
else
{
switch (rbbi.wID)
{
case CBTYPE_TOOLS:
SendMessage(m_hwndTools, TB_SETMAXTEXTROWS,
VERTICAL(m_csSide) ? MAX_TB_TEXT_ROWS_VERT : MAX_TB_TEXT_ROWS_HORZ, 0L);
SendMessage(m_hwndTools, TB_SETBUTTONWIDTH, 0, (LPARAM) MAKELONG(0, m_cxMaxButtonWidth));
break;
}
}
}
SetMinDimensions();
return(TRUE);
}
void CCoolbar::TrackSlidingX(int x)
{
int cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0L);
int cRows = SendMessage(m_hwndRebar, RB_GETROWCOUNT, 0, 0L);
int cxRow = SendMessage(m_hwndRebar, RB_GETROWHEIGHT, cBands - 1, 0L); // This should work correctly if vertical
REBARBANDINFO rbbi;
RECT rc;
int cxBefore;
BOOL fChanged = FALSE;
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_STYLE;
GetWindowRect(m_hwndRebar, &rc);
cxBefore = rc.right - rc.left;
if (((m_csSide == COOLBAR_LEFT) && (x < (m_xCapture - (cxRow / 2)))) ||
((m_csSide == COOLBAR_RIGHT) && (x > (m_xCapture + (cxRow / 2)))))
{
if (cRows == 1)
fChanged = CompressBands(TRUE);
/*
else
{
while (0 > --cBands)
{
SendMessage(m_hwndRebar, RB_GETBANDINFO, cBands, (LPARAM) &rbbi);
if (fChanged = (rbbi.fStyle & RBBS_BREAK))
{
rbbi.fStyle &= ~RBBS_BREAK;
SendMessage(m_hwndRebar, RB_SETBANDINFO, cBands, (LPARAM) &rbbi);
break;
}
}
}
*/
}
else if (((m_csSide == COOLBAR_LEFT) && (x > (m_xCapture + (cxRow / 2)))) ||
((m_csSide == COOLBAR_RIGHT) && (x < (m_xCapture - (cxRow / 2)))))
{
/*
if (!(fChanged = CompressBands(FALSE)) && (cRows < (cBands - 1)))
{
while (0 > --cBands)
{
SendMessage(m_hwndRebar, RB_GETBANDINFO, cBands, (LPARAM) &rbbi);
if (fChanged = !(rbbi.fStyle & (RBBS_BREAK | RBBS_FIXEDSIZE)))
{
rbbi.fStyle |= RBBS_BREAK;
SendMessage(m_hwndRebar, RB_SETBANDINFO, cBands, (LPARAM) &rbbi);
break;
}
}
}
*/
}
// TODO: There is a drawing glitch when you resize from 3 bars (No Text) to 3 bars
// with text. The _yCapture gets set to a value greater than y. So on the
// next MOUSEMOVE it figures that the user moved up and switches from 3 bars with text
// to 2 bars with text.
if (fChanged)
{
GetWindowRect(m_hwndRebar, &rc);
m_xCapture += (rc.right - rc.left) - cxBefore;
}
}
void CCoolbar::TrackSlidingY(int y)
{
int cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0L);
int cRows = SendMessage(m_hwndRebar, RB_GETROWCOUNT, 0, 0L);
int cyRow = SendMessage(m_hwndRebar, RB_GETROWHEIGHT, cBands - 1, 0L);
REBARBANDINFO rbbi;
RECT rc;
int cyBefore;
BOOL fChanged = FALSE;
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_STYLE;
GetWindowRect(m_hwndRebar, &rc);
cyBefore = rc.bottom - rc.top;
if (((m_csSide == COOLBAR_TOP) && (y < (m_yCapture - (cyRow / 2)))) ||
((m_csSide == COOLBAR_BOTTOM) && (y > (m_yCapture + (cyRow / 2)))))
{
if (cRows == 1)
fChanged = CompressBands(TRUE);
/*
else
{
while (0 > --cBands)
{
SendMessage(m_hwndRebar, RB_GETBANDINFO, cBands, (LPARAM) &rbbi);
if (fChanged = (rbbi.fStyle & RBBS_BREAK))
{
rbbi.fStyle &= ~RBBS_BREAK;
SendMessage(m_hwndRebar, RB_SETBANDINFO, cBands, (LPARAM) &rbbi);
break;
}
}
}
*/
}
else if (((m_csSide == COOLBAR_TOP) && (y > (m_yCapture + (cyRow / 2)))) ||
((m_csSide == COOLBAR_BOTTOM) && (y < (m_yCapture - (cyRow / 2)))))
{
/*
if (!(fChanged = CompressBands(FALSE)) && (cRows < (cBands - 1)))
{
while (0 > --cBands)
{
SendMessage(m_hwndRebar, RB_GETBANDINFO, cBands, (LPARAM) &rbbi);
if (fChanged = !(rbbi.fStyle & (RBBS_BREAK | RBBS_FIXEDSIZE)))
{
rbbi.fStyle |= RBBS_BREAK;
SendMessage(m_hwndRebar, RB_SETBANDINFO, cBands, (LPARAM) &rbbi);
break;
}
}
}
*/
}
// TODO: There is a drawing glitch when you resize from 3 bars (No Text) to 3 bars
// with text. The _yCapture gets set to a value greater than y. So on the
// next MOUSEMOVE it figures that the user moved up and switches from 3 bars with text
// to 2 bars with text.
if (fChanged)
{
GetWindowRect(m_hwndRebar, &rc);
m_yCapture += (rc.bottom - rc.top) - cyBefore;
}
}
// Flips the rebar from being horizontal to to vertical or the other way.
BOOL CCoolbar::ChangeOrientation()
{
LONG lStyle, lTBStyle;
lTBStyle = SendMessage(m_hwndTools, TB_GETSTYLE, 0, 0L);
lStyle = GetWindowLong(m_hwndRebar, GWL_STYLE);
SendMessage(m_hwndTools, WM_SETREDRAW, 0, 0L);
if (VERTICAL(m_csSide))
{
// Moving to Vertical
lStyle |= CCS_VERT;
lTBStyle |= TBSTYLE_WRAPABLE;
}
else
{
// Moving to Horizontal
lStyle &= ~CCS_VERT;
lTBStyle &= ~TBSTYLE_WRAPABLE;
}
SendMessage(m_hwndTools, TB_SETSTYLE, 0, lTBStyle);
SendMessage(m_hwndTools, WM_SETREDRAW, 1, 0L);
SetWindowLong(m_hwndRebar, GWL_STYLE, lStyle);
SetMinDimensions();
ResizeBorderDW(NULL, NULL, FALSE);
return TRUE;
}
//
// FUNCTION: CCoolbar::CreateRebar(BOOL fVisible)
//
// PURPOSE: Creates a new rebar and sizer window.
//
// RETURN VALUE:
// Returns S_OK if the bar was created and inserted correctly,
// hrAlreadyExists if a band already is in that position,
// E_OUTOFMEMORY if a window couldn't be created.
//
HRESULT CCoolbar::CreateRebar(BOOL fVisible)
{
if (m_hwndSizer)
return (hrAlreadyExists);
// $TODO: Only give the bar with the address bar the WS_TABSTOP style.
m_hwndSizer = CreateWindowEx(0, SIZABLECLASS, NULL, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | (fVisible ? WS_VISIBLE : 0),
0, 0, 100, 36, m_hwndParent, (HMENU) 0, g_hInst, NULL);
if (m_hwndSizer)
{
DOUTL(4, TEXT("Calling SetProp. AddRefing new m_cRef=%d"), m_cRef + 1);
AddRef(); // Note we Release in WM_DESTROY
SetProp(m_hwndSizer, TEXT("CCoolbar"), this);
/*
m_hwndRebar = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL,
RBS_FIXEDORDER | RBS_VARHEIGHT | RBS_BANDBORDERS | WS_VISIBLE |
WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
CCS_NODIVIDER | CCS_NOPARENTALIGN | (VERTICAL(m_csSide) ? CCS_VERT : 0),
0, 0, 100, 136, m_hwndSizer, (HMENU) idcCoolbar, g_hInst, NULL);
*/
m_hwndRebar = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL,
RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_REGISTERDROP | RBS_DBLCLKTOGGLE |
WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN |
(VERTICAL(m_csSide) ? CCS_VERT : 0),
0, 0, 100, 136, m_hwndSizer, (HMENU) idcCoolbar, g_hInst, NULL);
if (m_hwndRebar)
{
SendMessage(m_hwndRebar, RB_SETTEXTCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNTEXT));
SendMessage(m_hwndRebar, RB_SETBKCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
//SendMessage(m_hwndRebar, RB_SETEXTENDEDSTYLE, RBS_EX_OFFICE9, RBS_EX_OFFICE9);
return (S_OK);
}
}
DestroyWindow(m_hwndSizer);
return (E_OUTOFMEMORY);
}
void SendSaveRestoreMessage(HWND hwnd, const TOOLBARARRAYINFO *ptai, BOOL fSave)
{
TBSAVEPARAMS tbsp;
char szSubKey[MAX_PATH], sz[MAX_PATH];
DWORD dwType;
DWORD dwVersion;
DWORD cbData = sizeof(DWORD);
DWORD dwError;
tbsp.hkr = AthUserGetKeyRoot();
AthUserGetKeyPath(sz, ARRAYSIZE(sz));
if (ptai->pszRegKey != NULL)
{
wnsprintf(szSubKey, ARRAYSIZE(szSubKey),c_szPathFileFmt, sz, ptai->pszRegKey);
tbsp.pszSubKey = szSubKey;
}
else
{
tbsp.pszSubKey = sz;
}
tbsp.pszValueName = ptai->pszRegValue;
// First check to see if the version has changed
if (!fSave)
{
if (ERROR_SUCCESS == AthUserGetValue(ptai->pszRegKey, c_szRegToolbarVersion, &dwType, (LPBYTE) &dwVersion, &cbData))
{
if (dwVersion == COOLBAR_VERSION)
SendMessage(hwnd, TB_SAVERESTORE, (WPARAM)fSave, (LPARAM)&tbsp);
}
}
else
{
dwVersion = COOLBAR_VERSION;
SendMessage(hwnd, TB_SAVERESTORE, (WPARAM)fSave, (LPARAM)&tbsp);
dwError = AthUserSetValue(ptai->pszRegKey, c_szRegToolbarVersion, REG_DWORD, (LPBYTE) &dwVersion, cbData);
}
}
//
// FUNCTION: CCoolbar::SaveSettings()
//
// PURPOSE: Called when we should save our state out to the specified reg
// key.
//
void CCoolbar::SaveSettings(void)
{
char szSubKey[MAX_PATH], sz[MAX_PATH];
DWORD iBand;
REBARBANDINFO rbbi;
HKEY hKey;
DWORD cBands;
// If we don't have the window, there is nothing to save.
if (!m_hwndRebar || !m_ptai)
return;
ZeroMemory(&rbbi, sizeof(REBARBANDINFO));
cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0);
// Collect the bar-specific information
m_cbsSavedInfo.dwVersion = COOLBAR_VERSION;
m_cbsSavedInfo.dwState = m_dwState;
m_cbsSavedInfo.csSide = m_csSide;
// Loop through the bands and save their information as well
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_SIZE | RBBIM_ID;
for (iBand = 0; iBand < cBands; iBand++)
{
Assert(IsWindow(m_hwndRebar));
if (SendMessage(m_hwndRebar, RB_GETBANDINFO, iBand, (LPARAM) &rbbi))
{
// Save the information that we care about with this band
m_cbsSavedInfo.bs[iBand].cx = rbbi.cx;
m_cbsSavedInfo.bs[iBand].dwStyle = rbbi.fStyle;
m_cbsSavedInfo.bs[iBand].wID = rbbi.wID;
// If this band has a toolbar, then we should instruct the toolbar
// to save it's information now
if (m_cbsSavedInfo.bs[iBand].wID == CBTYPE_TOOLS)
{
SendSaveRestoreMessage(rbbi.hwndChild, m_ptai, TRUE);
}
}
else
{
// Default Values
m_cbsSavedInfo.bs[iBand].wID = CBTYPE_NONE;
m_cbsSavedInfo.bs[iBand].dwStyle = 0;
m_cbsSavedInfo.bs[iBand].cx = 0;
}
}
// We have all the information collected, now save that to the specified
// registry location
AthUserSetValue(NULL, c_szRegCoolbarLayout, REG_BINARY, (const LPBYTE)&m_cbsSavedInfo, sizeof(COOLBARSAVE));
}
//
// FUNCTION: CCoolbar::AddTools()
//
// PURPOSE: Inserts the primary toolbar into the coolbar.
//
// PARAMETERS:
// pbs - Pointer to a PBANDSAVE struct with the styles and size of the
// band to insert.
//
// RETURN VALUE:
// Returns an HRESULT signifying success or failure.
//
HRESULT CCoolbar::AddTools(PBANDSAVE pbs)
{
REBARBANDINFO rbbi;
// add tools band
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_SIZE | RBBIM_ID | RBBIM_STYLE;
rbbi.fStyle = pbs->dwStyle;
rbbi.cx = pbs->cx;
// rbbi.wID = CBTYPE_TOOLS;
rbbi.wID = pbs->wID;
if (IsFlagClear(CBSTATE_NOBACKGROUND) && !m_hbmBack && m_idbBack)
m_hbmBack = (HBITMAP) LoadImage(g_hLocRes, MAKEINTRESOURCE(m_idbBack),
IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
if (m_hbmBack)
{
rbbi.fMask |= RBBIM_BACKGROUND;
rbbi.fStyle |= RBBS_FIXEDBMP;
rbbi.hbmBack = m_hbmBack;
}
else
{
rbbi.fMask |= RBBIM_COLORS;
rbbi.clrFore = GetSysColor(COLOR_BTNTEXT);
rbbi.clrBack = GetSysColor(COLOR_BTNFACE);
}
SendMessage(m_hwndRebar, RB_INSERTBAND, (UINT) -1, (LPARAM) (LPREBARBANDINFO) &rbbi);
return(S_OK);
}
HRESULT CCoolbar::SetFolderType(FOLDERTYPE ftType)
{
TCHAR szToolsText[(MAX_TB_TEXT_LENGTH+2) * MAX_TB_BUTTONS];
int i, cBands;
REBARBANDINFO rbbi;
HWND hwndDestroy = NULL;
// If we haven't created the rebar yet, this will fail. Call ShowDW() first.
if (!IsWindow(m_hwndRebar))
return (E_FAIL);
// Check to see if this would actually be a change
if (ftType == m_ftType)
return (S_OK);
// First find the band with the toolbar
cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0);
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_ID;
for (i = 0; i < cBands; i++)
{
SendMessage(m_hwndRebar, RB_GETBANDINFO, i, (LPARAM) &rbbi);
if (CBTYPE_TOOLS == rbbi.wID)
break;
}
// We didn't find it.
if (i >= cBands)
return (E_FAIL);
// Destroy the old toolbar if it exists
if (IsWindow(m_hwndTools))
{
// Save it's button configuration
SendSaveRestoreMessage(m_hwndTools, m_ptai, TRUE);
SendMessage(m_hwndTools, TB_SETIMAGELIST, 0, NULL);
SendMessage(m_hwndTools, TB_SETHOTIMAGELIST, 0, NULL);
hwndDestroy = m_hwndTools;
}
// Update our internal state information with the new folder type
Assert(ftType < FOLDER_TYPESMAX);
m_ftType = ftType;
m_ptai = &(g_rgToolbarArrayInfo[m_ftType]);
// Create a new toolbar
m_hwndTools = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL,
WS_CHILD | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS
| WS_CLIPCHILDREN | WS_CLIPSIBLINGS
| CCS_NODIVIDER | CCS_NOPARENTALIGN
| CCS_ADJUSTABLE | CCS_NORESIZE |
(VERTICAL(m_csSide) ? TBSTYLE_WRAPABLE : 0),
0, 0, 0, 0, m_hwndRebar, (HMENU) idcToolbar,
g_hInst, NULL);
Assert(m_hwndTools);
if (!m_hwndTools)
{
DOUTL(1, TEXT("CCoolbar::SetFolderType() CreateWindow(TOOLBAR) failed"));
return(E_OUTOFMEMORY);
}
InitToolbar();
// If we have previously save configuration info for this toolbar, load it
SendSaveRestoreMessage(m_hwndTools, m_ptai, FALSE);
// First find the band with the toolbar
cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0);
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_ID;
for (i = 0; i < cBands; i++)
{
SendMessage(m_hwndRebar, RB_GETBANDINFO, i, (LPARAM) &rbbi);
if (CBTYPE_TOOLS == rbbi.wID)
break;
}
// Add the toolbar to the rebar
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_CHILD;
rbbi.hwndChild = m_hwndTools;
SendMessage(m_hwndRebar, RB_SETBANDINFO, (UINT) i, (LPARAM) (LPREBARBANDINFO) &rbbi);
if (hwndDestroy)
DestroyWindow(hwndDestroy);
SetMinDimensions();
ResizeBorderDW(NULL, NULL, FALSE);
return (S_OK);
}
void CCoolbar::SetSide(COOLBAR_SIDE csSide)
{
m_csSide = csSide;
ChangeOrientation();
}
void CCoolbar::SetText(BOOL fText)
{
CompressBands(!fText);
}
UINT GetCurColorRes(void)
{
HDC hdc;
UINT uColorRes;
hdc = GetDC(NULL);
uColorRes = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(NULL, hdc);
return uColorRes;
}
/* InitToolbar:
**
** Purpose:
** makes decisions about small/large bitmaps and which
** imagelist given the colordepth, then calls the
** barutil InitToolbar
*/
void CCoolbar::InitToolbar()
{
TCHAR szToolsText[(MAX_TB_TEXT_LENGTH+2) * MAX_TB_BUTTONS];
HKEY hKey;
TCHAR szValue[32];
DWORD cbValue = sizeof(szValue);
int idBmp;
// Check to see if the user has decided to use that crazy 16x16 images
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegSmallIconsPath,
0, KEY_READ, &hKey))
{
if (ERROR_SUCCESS == RegQueryValueEx(hKey, c_szRegSmallIconsValue, 0,
0, (LPBYTE) szValue, &cbValue))
{
// people in IE decided it would be cool to store a boolean
// value as REG_SZ "Yes" and "No". Lovely.
m_fSmallIcons = !lstrcmpi(szValue, c_szYes);
}
RegCloseKey(hKey);
}
if (m_fSmallIcons)
{
idBmp = (fIsWhistler() ? ((GetCurColorRes() > 24) ? idb32SmBrowser : idbSmBrowser): idbNWSmBrowser);
}
// Check to see what our color depth is
else if (GetCurColorRes() > 24)
{
idBmp = (fIsWhistler() ? idb32256Browser : idbNW256Browser);
}
else if (GetCurColorRes() > 8)
{
idBmp = (fIsWhistler() ? idb256Browser : idbNW256Browser);
}
else
{
idBmp = (fIsWhistler() ? idbBrowser : idbNWBrowser);
}
LoadToolNames((UINT*) m_ptai->rgidsButtons, m_ptai->cidsButtons, szToolsText);
SendMessage(m_hwndTools, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS);
::InitToolbar(m_hwndTools, CIMLISTS, m_rghimlTools, m_ptai->cDefButtons,
m_ptai->rgDefButtons, szToolsText,
m_fSmallIcons ? TB_SMBMP_CX : (fIsWhistler() ? TB_BMP_CX : TB_BMP_CX_W2K),
m_fSmallIcons ? TB_SMBMP_CY : TB_BMP_CY,
IsFlagSet(CBSTATE_COMPRESSED) ? MAX_TB_COMPRESSED_WIDTH : m_cxMaxButtonWidth,
idBmp,
IsFlagSet(CBSTATE_COMPRESSED), VERTICAL(m_csSide));
//Register with the connection manager
if (g_pConMan)
{
//If Work offline is set then we should check the work offline button
SendMessage(m_hwndTools, TB_CHECKBUTTON, ID_WORK_OFFLINE, (LPARAM)(MAKELONG(g_pConMan->IsGlobalOffline(), 0)));
}
}
void CCoolbar::UpdateToolbarColors(void)
{
REBARBANDINFO rbbi;
UINT i;
UINT cBands;
// First find the band with the toolbar
cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0);
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_ID;
for (i = 0; i < cBands; i++)
{
SendMessage(m_hwndRebar, RB_GETBANDINFO, i, (LPARAM) &rbbi);
if (CBTYPE_TOOLS == rbbi.wID)
break;
}
// add tools band
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_COLORS;
rbbi.clrFore = GetSysColor(COLOR_BTNTEXT);
rbbi.clrBack = GetSysColor(COLOR_BTNFACE);
SendMessage(m_hwndRebar, RB_SETBANDINFO, i, (LPARAM) (LPREBARBANDINFO) &rbbi);
}
HRESULT CCoolbar::OnConnectionNotify(CONNNOTIFY nCode,
LPVOID pvData,
CConnectionManager *pConMan)
{
if ((m_hwndTools) && (nCode == CONNNOTIFY_WORKOFFLINE))
{
SendMessage(m_hwndTools, TB_CHECKBUTTON, ID_WORK_OFFLINE, (LPARAM)MAKELONG((BOOL)pvData, 0));
}
return S_OK;
}
//
// FUNCTION: InitToolbar()
//
// PURPOSE: Given all the parameters needed to configure a toolbar,
// this function loads the image lists and configures the
// toolbar.
//
// PARAMETERS:
// hwnd - Handle of the toolbar window to init.
// phiml - Array of imagelists where the hot, disabled, and normal
// buttons are returned.
// nBtns - The number of buttons in the ptbb array.
// ptbb - Array of buttons to add to the toolbar.
// pStrings - List of toolbar button / tooltip strings to add.
// cx, cy - Size of the bitmaps being added to the toolbar.
// cxMax - Maximum button width.
// idBmp - Resource id of the first image list to load.
//
void InitToolbar(const HWND hwnd, const int cHiml, HIMAGELIST *phiml,
UINT nBtns, const TBBUTTON *ptbb,
const TCHAR *pStrings,
const int cxImg, const int cyImg, const int cxMax,
const int idBmp, const BOOL fCompressed,
const BOOL fVertical)
{
int nRows;
if (fCompressed)
nRows = 0;
else
nRows = fVertical ? MAX_TB_TEXT_ROWS_VERT : MAX_TB_TEXT_ROWS_HORZ;
LoadGlyphs(hwnd, cHiml, phiml, cxImg, idBmp);
// this tells the toolbar what version we are
SendMessage(hwnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
SendMessage(hwnd, TB_SETMAXTEXTROWS, nRows, 0L);
SendMessage(hwnd, TB_SETBITMAPSIZE, 0, MAKELONG(cxImg, cyImg));
SendMessage(hwnd, TB_SETBUTTONWIDTH, 0, MAKELONG(0, cxMax));
if (pStrings) SendMessage(hwnd, TB_ADDSTRING, 0, (LPARAM) pStrings);
if (nBtns) SendMessage(hwnd, TB_ADDBUTTONS, nBtns, (LPARAM) ptbb);
}
void LoadGlyphs(const HWND hwnd, const int cHiml, HIMAGELIST *phiml, const int cx,
const int idBmp)
{
const UINT uFlags = LR_LOADMAP3DCOLORS | LR_CREATEDIBSECTION;
HIMAGELIST LocHiml[CIMLISTS];
if (phiml == NULL)
{
phiml = LocHiml;
}
for (int i = 0; i < cHiml; i++)
{
if (phiml[i])
ImageList_Destroy(phiml[i]);
phiml[i] = ImageList_LoadImage(g_hLocRes,
MAKEINTRESOURCE(idBmp + i), cx, 0, RGB(255, 0, 255),
IMAGE_BITMAP, uFlags);
}
SendMessage(hwnd, TB_SETIMAGELIST, 0, (LPARAM) phiml[IMLIST_DEFAULT]);
// if we weren't given a full set of lists to do, then don't set this
if (CIMLISTS == cHiml)
{
SendMessage(hwnd, TB_SETHOTIMAGELIST, 0, (LPARAM) phiml[IMLIST_HOT]);
}
}
BOOL LoadToolNames(const UINT *rgIds, const UINT cIds, TCHAR *szTools)
{
for (UINT i = 0; i < cIds; i++)
{
LoadString(g_hLocRes, rgIds[i], szTools, MAX_TB_TEXT_LENGTH);
szTools += lstrlen(szTools) + 1;
}
*szTools = TEXT('\0');
return(TRUE);
}
HRESULT CCoolbar::Update(void)
{
DWORD cButtons = 0;
OLECMD *rgCmds;
TBBUTTON tb;
DWORD cCmds = 0;
IOleCommandTarget *pTarget = NULL;
DWORD i;
DWORD dwState;
// Get the number of buttons on the toolbar
cButtons = SendMessage(m_hwndTools, TB_BUTTONCOUNT, 0, 0);
if (0 == cButtons)
return (S_OK);
// Allocate an array of OLECMD structures for the buttons
if (!MemAlloc((LPVOID *) &rgCmds, sizeof(OLECMD) * cButtons))
return (E_OUTOFMEMORY);
// Loop through the buttons and get the ID for each
for (i = 0; i < cButtons; i++)
{
if (SendMessage(m_hwndTools, TB_GETBUTTON, i, (LPARAM) &tb))
{
// Toolbar returns zero for seperators
if (tb.idCommand)
{
rgCmds[cCmds].cmdID = tb.idCommand;
rgCmds[cCmds].cmdf = 0;
cCmds++;
}
}
}
// I don't see how this can be false
Assert(m_ptbSite);
// Do the QueryStatus thing
if (SUCCEEDED(m_ptbSite->QueryInterface(IID_IOleCommandTarget, (void**) &pTarget)))
{
if (SUCCEEDED(pTarget->QueryStatus(NULL, cCmds, rgCmds, NULL)))
{
// Go through the array now and do the enable / disable thing
for (i = 0; i < cCmds; i++)
{
// Get the current state of the button
dwState = SendMessage(m_hwndTools, TB_GETSTATE, rgCmds[i].cmdID, 0);
// Update the state with the feedback we've been provided
if (rgCmds[i].cmdf & OLECMDF_ENABLED)
dwState |= TBSTATE_ENABLED;
else
dwState &= ~TBSTATE_ENABLED;
if (rgCmds[i].cmdf & OLECMDF_LATCHED)
dwState |= TBSTATE_CHECKED;
else
dwState &= ~TBSTATE_CHECKED;
// Radio check has no meaning here.
Assert(0 == (rgCmds[i].cmdf & OLECMDF_NINCHED));
SendMessage(m_hwndTools, TB_SETSTATE, rgCmds[i].cmdID, dwState);
// If this is the work offline button, we need to do a bit more work
if (rgCmds[i].cmdID == ID_WORK_OFFLINE)
{
_UpdateWorkOffline(rgCmds[i].cmdf);
}
}
}
pTarget->Release();
}
MemFree(rgCmds);
return (S_OK);
}
void CCoolbar::_UpdateWorkOffline(DWORD cmdf)
{
TBBUTTONINFO tbbi = { 0 };
TCHAR szRes[CCHMAX_STRINGRES];
int idString;
// Because we change the text and image for the "Work Offline" button,
// we need to do some work here based on whether or not the button is
// checked or not.
if (cmdf & OLECMDF_LATCHED)
{
idString = idsWorkOnline;
tbbi.iImage = iCBWorkOnline;
}
else
{
idString = idsWorkOffline;
tbbi.iImage = iCBWorkOffline;
}
// Load the new string
AthLoadString(idString, szRes, ARRAYSIZE(szRes));
// Fill in the struct
tbbi.cbSize = sizeof(TBBUTTONINFO);
tbbi.dwMask = TBIF_IMAGE | TBIF_TEXT;
tbbi.pszText = szRes;
// Update the button
SendMessage(m_hwndTools, TB_SETBUTTONINFO, ID_WORK_OFFLINE, (LPARAM) &tbbi);
}
HRESULT CCoolbar::CreateMenuBand(PBANDSAVE pbs)
{
HRESULT hres;
HWND hwndBrowser;
HMENU hMenu;
IShellMenu *pShellMenu;
//Get the hwnd for the browser
if (g_pBrowser)
{
hres = g_pBrowser->GetWindow(&hwndBrowser);
if (hres != S_OK)
return hres;
}
//hMenu = ::GetMenu(hwndBrowser);
//Cocreate menuband
hres = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER, IID_IShellMenu, (LPVOID*)&m_pShellMenu);
if (hres != S_OK)
{
return hres;
}
/*
m_mbCallback = new CMenuCallback;
if (m_mbCallback == NULL)
{
hres = S_FALSE;
return hres;
}
*/
m_pShellMenu->Initialize(m_mbCallback, -1, ANCESTORDEFAULT, SMINIT_DEFAULTTOTRACKPOPUP | SMINIT_HORIZONTAL |
/*SMINIT_USEMESSAGEFILTER|*/ SMINIT_TOPLEVEL);
m_pShellMenu->SetMenu(m_hMenu, hwndBrowser, SMSET_DONTOWN);
hres = AddMenuBand(pbs);
return hres;
}
HRESULT CCoolbar::AddMenuBand(PBANDSAVE pbs)
{
REBARBANDINFO rbbi;
HRESULT hres;
HWND hwndMenuBand = NULL;
IObjectWithSite *pObj;
hres = m_pShellMenu->QueryInterface(IID_IDeskBand, (LPVOID*)&m_pDeskBand);
if (FAILED(hres))
return hres;
hres = m_pShellMenu->QueryInterface(IID_IMenuBand, (LPVOID*)&m_pMenuBand);
if (FAILED(hres))
return hres;
hres = m_pDeskBand->QueryInterface(IID_IWinEventHandler, (LPVOID*)&m_pWinEvent);
if (FAILED(hres))
return hres;
hres = m_pDeskBand->QueryInterface(IID_IObjectWithSite, (LPVOID*)&pObj);
if (FAILED(hres))
return hres;
pObj->SetSite((IDockingWindow*)this);
pObj->Release();
m_pDeskBand->GetWindow(&m_hwndMenuBand);
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_SIZE | RBBIM_ID | RBBIM_STYLE | RBBIM_CHILD;
rbbi.fStyle = pbs->dwStyle;
rbbi.cx = pbs->cx;
rbbi.wID = pbs->wID;
rbbi.hwndChild = m_hwndMenuBand;
SendMessage(m_hwndRebar, RB_INSERTBAND, (UINT)-1, (LPARAM)(LPREBARBANDINFO)&rbbi);
HWND hwndBrowser;
if (g_pBrowser)
{
hres = g_pBrowser->GetWindow(&hwndBrowser);
if (hres != S_OK)
return hres;
}
SetForegroundWindow(hwndBrowser);
/*
IInputObject* pio;
if (SUCCEEDED(m_pDeskBand->QueryInterface(IID_IInputObject, (void**)&pio)))
{
pio->UIActivateIO(TRUE, NULL);
pio->Release();
}
*/
m_pDeskBand->ShowDW(TRUE);
SetNotRealSite();
//Get Bandinfo and set
return S_OK;
}
HRESULT CCoolbar::TranslateMenuMessage(MSG *pmsg, LRESULT *lpresult)
{
if (m_pMenuBand)
return m_pMenuBand->TranslateMenuMessage(pmsg, lpresult);
else
return S_FALSE;
}
HRESULT CCoolbar::IsMenuMessage(MSG *lpmsg)
{
if (m_pMenuBand)
return m_pMenuBand->IsMenuMessage(lpmsg);
else
return S_FALSE;
}
void CCoolbar::SetNotRealSite()
{
IOleCommandTarget *pOleCmd;
if (m_pDeskBand->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&pOleCmd) == S_OK)
{
//pOleCmd->Exec(&CGID_MenuBand, MBANDCID_NOTAREALSITE, TRUE, NULL, NULL);
pOleCmd->Exec(&CLSID_MenuBand, 3, TRUE, NULL, NULL);
pOleCmd->Release();
}
}
void CCoolbar::HandleCoolbarPopup(UINT xPos, UINT yPos)
{
// Load the context menu
HMENU hMenu = LoadPopupMenu(IDR_COOLBAR_POPUP);
if (!hMenu)
return;
// Loop through the bands and see which ones are visible
DWORD cBands, iBand;
REBARBANDINFO rbbi = {0};
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_STYLE | RBBIM_ID;
cBands = SendMessage(m_hwndRebar, RB_GETBANDCOUNT, 0, 0);
for (iBand = 0; iBand < cBands; iBand++)
{
if (SendMessage(m_hwndRebar, RB_GETBANDINFO, iBand, (LPARAM) &rbbi))
{
if (!(rbbi.fStyle & RBBS_HIDDEN))
{
switch (rbbi.wID)
{
case CBTYPE_TOOLS:
CheckMenuItem(hMenu, ID_COOLTOOLBAR, MF_BYCOMMAND | MF_CHECKED);
break;
}
}
}
}
SetFlag(CBSTATE_INMENULOOP);
DWORD cmd;
cmd = TrackPopupMenuEx(hMenu, TPM_RETURNCMD | TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
xPos, yPos, m_hwndSizer, NULL);
if (cmd != 0)
{
switch (cmd)
{
case ID_COOLTOOLBAR:
HideToolbar(CBTYPE_TOOLS);
break;
}
}
ClearFlag(CBSTATE_INMENULOOP);
if (hMenu)
DestroyMenu(hMenu);
}