Size.cx = 2 * GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CYCAPTION) * 3;
}
- if (GetWindowTheme(m_hWnd))
- Size.cy = max(Size.cy, GetSystemMetrics(SM_CYCAPTION));
- else
- Size.cy = max(Size.cy, GetSystemMetrics(SM_CYSIZE) + (2 * GetSystemMetrics(SM_CYEDGE)));
+ Size.cy = max(Size.cy, GetSystemMetrics(SM_CYCAPTION));
/* Save the size of the start button */
m_Size = Size;
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public CWindowImpl < CTrayWindow, CWindow, CControlWinTraits >,
public ITrayWindow,
- public IShellDesktopTray
+ public IShellDesktopTray,
+ public IOleWindow
{
CStartButton m_StartButton;
CComPtr<IMenuBand> m_StartMenuBand;
CComPtr<IMenuPopup> m_StartMenuPopup;
+ CComPtr<IDeskBand> m_TaskBand;
HTHEME m_Theme;
HFONT m_Font;
void UpdateFonts()
{
+ /* There is nothing to do if themes are not enabled */
+ if (m_Theme)
+ return;
+
m_StartButton.UpdateFont();
NONCLIENTMETRICS ncm = {sizeof(ncm)};
VOID AdjustSizerRect(RECT *rc, DWORD pos)
{
+ int iSizerPart[4] = {TBP_SIZINGBARLEFT, TBP_SIZINGBARTOP, TBP_SIZINGBARRIGHT, TBP_SIZINGBARBOTTOM};
+ SIZE size;
+
+ if (pos > ABE_BOTTOM)
+ pos = ABE_BOTTOM;
+
+ HRESULT hr = GetThemePartSize(m_Theme, NULL, iSizerPart[pos], 0, NULL, TS_TRUE, &size);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return;
+
switch (pos)
{
case ABE_TOP:
- rc->bottom -= GetSystemMetrics(SM_CXSIZEFRAME);
+ rc->bottom -= size.cy;
break;
case ABE_BOTTOM:
- rc->top += GetSystemMetrics(SM_CXSIZEFRAME);
+ rc->top += size.cy;
break;
case ABE_LEFT:
- rc->right -= GetSystemMetrics(SM_CYSIZEFRAME);
+ rc->right -= size.cx;
break;
case ABE_RIGHT:
- rc->left += GetSystemMetrics(SM_CYSIZEFRAME);
+ rc->left += size.cx;
break;
}
-
}
VOID MakeTrayRectWithSize(IN DWORD Position,
*pRect = *pScreen;
- if(!IsThemeActive())
+ if(!m_Theme)
{
/* Move the border outside of the screen */
InflateRect(pRect,
entire window size, not just the client size. However, we
use a thinner border than a standard thick border, so that
the start button and bands are not stuck to the screen border. */
- if(!IsThemeActive())
+ if(!m_Theme)
{
sr.Size.cx = StartBtnSize.cx + (2 * (EdgeSize.cx + DlgFrameSize.cx));
sr.Size.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
loaded from the registry are at least. The windows explorer behaves
the same way, it allows the user to save a zero width vertical tray
window, but not a zero height horizontal tray window. */
- if(!IsThemeActive())
+ if(!m_Theme)
{
WndSize.cx = 2 * (EdgeSize.cx + DlgFrameSize.cx);
WndSize.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
case ABE_BOTTOM:
rebarRect.top = rebarRect.bottom - (pRect->bottom - pRect->top - margins.cy);
::SendMessageW(m_Rebar, RB_SIZETORECT, RBSTR_CHANGERECT, (LPARAM)&rebarRect);
- ERR("rebarRect: %d, %d, %d,%d\n", rebarRect.top, rebarRect.left, rebarRect.right, rebarRect.bottom);
pRect->top = pRect->bottom - (rebarRect.bottom - rebarRect.top + margins.cy);
break;
case ABE_LEFT:
LRESULT EraseBackgroundWithTheme(HDC hdc)
{
RECT rect;
- int partId;
- HRESULT res;
+ int iSBkgndPart[4] = {TBP_BACKGROUNDLEFT, TBP_BACKGROUNDTOP, TBP_BACKGROUNDRIGHT, TBP_BACKGROUNDBOTTOM};
- GetClientRect(&rect);
+ ASSERT(m_Position <= ABE_BOTTOM);
if (m_Theme)
{
GetClientRect(&rect);
- switch (m_Position)
- {
- case ABE_LEFT:
- partId = TBP_BACKGROUNDLEFT;
- break;
- case ABE_TOP:
- partId = TBP_BACKGROUNDTOP;
- break;
- case ABE_RIGHT:
- partId = TBP_BACKGROUNDRIGHT;
- break;
- case ABE_BOTTOM:
- default:
- partId = TBP_BACKGROUNDBOTTOM;
- break;
- }
- res = DrawThemeBackground(m_Theme, hdc, partId, 0, &rect, 0);
+ DrawThemeBackground(m_Theme, hdc, iSBkgndPart[m_Position], 0, &rect, 0);
}
- return res;
+ return 0;
}
int DrawSizerWithTheme(IN HRGN hRgn)
{
HDC hdc;
RECT rect;
- int backgroundPart;
+ int iSizerPart[4] = {TBP_SIZINGBARLEFT, TBP_SIZINGBARTOP, TBP_SIZINGBARRIGHT, TBP_SIZINGBARBOTTOM};
+ SIZE size;
+
+ ASSERT(m_Position <= ABE_BOTTOM);
+
+ HRESULT hr = GetThemePartSize(m_Theme, NULL, iSizerPart[m_Position], 0, NULL, TS_TRUE, &size);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return 0;
GetWindowRect(&rect);
OffsetRect(&rect, -rect.left, -rect.top);
switch (m_Position)
{
case ABE_LEFT:
- backgroundPart = TBP_SIZINGBARLEFT;
- rect.left = rect.right - GetSystemMetrics(SM_CXSIZEFRAME);
+ rect.left = rect.right - size.cx;
break;
case ABE_TOP:
- backgroundPart = TBP_SIZINGBARTOP;
- rect.top = rect.bottom - GetSystemMetrics(SM_CYSIZEFRAME);
+ rect.top = rect.bottom - size.cy;
break;
case ABE_RIGHT:
- backgroundPart = TBP_SIZINGBARRIGHT;
- rect.right = rect.left + GetSystemMetrics(SM_CXSIZEFRAME);
+ rect.right = rect.left + size.cx;
break;
case ABE_BOTTOM:
default:
- backgroundPart = TBP_SIZINGBARBOTTOM;
- rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZEFRAME);
+ rect.bottom = rect.top + size.cy;
break;
}
- if (IsThemeBackgroundPartiallyTransparent(m_Theme, backgroundPart, 0))
- {
- DrawThemeParentBackground(m_hWnd, hdc, &rect);
- }
- DrawThemeBackground(m_Theme, hdc, backgroundPart, 0, &rect, 0);
+
+ DrawThemeBackground(m_Theme, hdc, iSizerPart[m_Position], 0, &rect, 0);
ReleaseDC(hdc);
return 0;
dwExStyle |= WS_EX_TOPMOST;
DWORD dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
- if(!IsThemeActive())
+ if(!m_Theme)
{
dwStyle |= WS_THICKFRAME | WS_BORDER;
}
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
+ HRESULT hRet;
+
((ITrayWindow*)this)->AddRef();
SetWindowTheme(m_hWnd, L"TaskBar", NULL);
HBITMAP hbmBanner = LoadBitmapW(hExplorerInstance, MAKEINTRESOURCEW(IDB_STARTMENU));
m_StartMenuPopup = CreateStartMenu(this, &m_StartMenuBand, hbmBanner, 0);
- /* Create the tray band site and its rebar */
- m_TrayBandSite = CreateTrayBandSite(this, &m_Rebar, &m_TaskSwitch);
+ /* Create the task band */
+ hRet = CTaskBand_CreateInstance(this, m_StartButton.m_hWnd, IID_PPV_ARG(IDeskBand, &m_TaskBand));
+ if (FAILED_UNEXPECTEDLY(hRet))
+ return FALSE;
+
+ /* Create the rebar band site. This actually creates the rebar and the tasks toolbar. */
+ hRet = CTrayBandSite_CreateInstance(this, m_TaskBand, &m_TrayBandSite);
+ if (FAILED_UNEXPECTEDLY(hRet))
+ return FALSE;
+
+ /* Get the hwnd of the rebar */
+ hRet = IUnknown_GetWindow(m_TrayBandSite, &m_Rebar);
+ if (FAILED_UNEXPECTEDLY(hRet))
+ return FALSE;
+
+ /* Get the hwnd of the tasks toolbar */
+ hRet = IUnknown_GetWindow(m_TaskBand, &m_TaskSwitch);
+ if (FAILED_UNEXPECTEDLY(hRet))
+ return FALSE;
+
SetWindowTheme(m_Rebar, L"TaskBar", NULL);
/* Create the tray notification window */
if (m_Theme)
CloseThemeData(m_Theme);
- if (IsThemeActive())
- m_Theme = OpenThemeData(m_hWnd, L"TaskBar");
- else
- m_Theme = NULL;
+ m_Theme = OpenThemeData(m_hWnd, L"TaskBar");
if (m_Theme)
{
return TRUE;
}
+ LRESULT OnNcLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+ {
+ /* This handler implements the trick that makes the start button to
+ get pressed when the user clicked left or below the button */
+
+ POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
+ WINDOWINFO wi = {sizeof(WINDOWINFO)};
+ RECT rcStartBtn;
+
+ bHandled = FALSE;
+
+ m_StartButton.GetWindowRect(&rcStartBtn);
+ GetWindowInfo(m_hWnd, &wi);
+
+ switch (m_Position)
+ {
+ case ABE_TOP:
+ case ABE_LEFT:
+ {
+ if (pt.x > rcStartBtn.right || pt.y > rcStartBtn.bottom)
+ return 0;
+ break;
+ }
+ case ABE_RIGHT:
+ {
+ if (pt.x < rcStartBtn.left || pt.y > rcStartBtn.bottom)
+ return 0;
+
+ if (rcStartBtn.right + (int)wi.cxWindowBorders * 2 + 1 < wi.rcWindow.right &&
+ pt.x > rcStartBtn.right)
+ {
+ return 0;
+ }
+ break;
+ }
+ case ABE_BOTTOM:
+ {
+ if (pt.x > rcStartBtn.right || pt.y < rcStartBtn.top)
+ {
+ return 0;
+ }
+
+ if (rcStartBtn.bottom + (int)wi.cyWindowBorders * 2 + 1 < wi.rcWindow.bottom &&
+ pt.y > rcStartBtn.bottom)
+ {
+ return 0;
+ }
+
+ break;
+ }
+ }
+
+ bHandled = TRUE;
+ PopupStartMenu();
+ return 0;
+ }
+
LRESULT OnNcRButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
/* We want the user to be able to get a context menu even on the nonclient
{
RECT *rc = NULL;
/* Ignore WM_NCCALCSIZE if we are not themed or locked */
- if(!IsThemeActive() || Locked)
+ if(!m_Theme || Locked)
{
bHandled = FALSE;
return 0;
MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChange)
MESSAGE_HANDLER(WM_ENTERSIZEMOVE, OnEnterSizeMove)
MESSAGE_HANDLER(WM_EXITSIZEMOVE, OnExitSizeMove)
+ MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNcLButtonDown)
MESSAGE_HANDLER(WM_SYSCHAR, OnSysChar)
MESSAGE_HANDLER(WM_NCRBUTTONUP, OnNcRButtonUp)
MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClick)
return S_OK;
}
+ HRESULT WINAPI GetWindow(HWND* phwnd)
+ {
+ if (!phwnd)
+ return E_INVALIDARG;
+ *phwnd = m_hWnd;
+ return S_OK;
+ }
+
+ HRESULT WINAPI ContextSensitiveHelp(BOOL fEnterMode)
+ {
+ return E_NOTIMPL;
+ }
+
void _Init()
{
m_Position = (DWORD) -1;
BEGIN_COM_MAP(CTrayWindow)
/*COM_INTERFACE_ENTRY_IID(IID_ITrayWindow, ITrayWindow)*/
COM_INTERFACE_ENTRY_IID(IID_IShellDesktopTray, IShellDesktopTray)
+ COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
END_COM_MAP()
};