reactos/sdk/lib/cicero/cicuif.cpp
Katayama Hirofumi MZ a55345be29
[MSCTFIME][CICERO] Implement CDefCompFrameWindow (#6512)
Supporting TIPs...
JIRA issue: CORE-19360
- Add delay link to uxtheme.dll.
- Implement CDefCompFrameGripper,
  CCompFinalizeButton,
  CCompButtonFrameWindow, and
  CDefCompFrameWindow classes.
2024-02-21 10:36:32 +09:00

5473 lines
140 KiB
C++

/*
* PROJECT: ReactOS Cicero
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Cicero UIF Library
* COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include "precomp.h"
#include "cicuif.h"
/////////////////////////////////////////////////////////////////////////////
// static members
HINSTANCE CUIFTheme::s_hUXTHEME = NULL;
FN_OpenThemeData CUIFTheme::s_fnOpenThemeData = NULL;
FN_CloseThemeData CUIFTheme::s_fnCloseThemeData = NULL;
FN_DrawThemeBackground CUIFTheme::s_fnDrawThemeBackground = NULL;
FN_DrawThemeParentBackground CUIFTheme::s_fnDrawThemeParentBackground = NULL;
FN_DrawThemeText CUIFTheme::s_fnDrawThemeText = NULL;
FN_DrawThemeIcon CUIFTheme::s_fnDrawThemeIcon = NULL;
FN_GetThemeBackgroundExtent CUIFTheme::s_fnGetThemeBackgroundExtent = NULL;
FN_GetThemeBackgroundContentRect CUIFTheme::s_fnGetThemeBackgroundContentRect = NULL;
FN_GetThemeTextExtent CUIFTheme::s_fnGetThemeTextExtent = NULL;
FN_GetThemePartSize CUIFTheme::s_fnGetThemePartSize = NULL;
FN_DrawThemeEdge CUIFTheme::s_fnDrawThemeEdge = NULL;
FN_GetThemeColor CUIFTheme::s_fnGetThemeColor = NULL;
FN_GetThemeMargins CUIFTheme::s_fnGetThemeMargins = NULL;
FN_GetThemeFont CUIFTheme::s_fnGetThemeFont = NULL;
FN_GetThemeSysColor CUIFTheme::s_fnGetThemeSysColor = NULL;
FN_GetThemeSysSize CUIFTheme::s_fnGetThemeSysSize = NULL;
CUIFSystemInfo *CUIFSystemInfo::s_pSystemInfo = NULL;
CUIFColorTableSys *CUIFScheme::s_pColorTableSys = NULL;
CUIFColorTableOff10 *CUIFScheme::s_pColorTableOff10 = NULL;
/////////////////////////////////////////////////////////////////////////////
void CUIFSystemInfo::GetSystemMetrics()
{
HDC hDC = ::GetDC(NULL);
m_cBitsPixels = ::GetDeviceCaps(hDC, BITSPIXEL);
::ReleaseDC(NULL, hDC);
HIGHCONTRAST HighContrast = { sizeof(HighContrast) };
::SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(HighContrast), &HighContrast, 0);
m_bHighContrast1 = !!(HighContrast.dwFlags & HCF_HIGHCONTRASTON);
COLORREF rgbBtnText = ::GetSysColor(COLOR_BTNTEXT);
COLORREF rgbBtnFace = ::GetSysColor(COLOR_BTNFACE);
const COLORREF black = RGB(0, 0, 0), white = RGB(255, 255, 255);
m_bHighContrast2 = (m_bHighContrast1 ||
(rgbBtnText == black && rgbBtnFace == white) ||
(rgbBtnText == white && rgbBtnFace == black));
}
void CUIFSystemInfo::Initialize()
{
dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
::GetVersionEx(this);
GetSystemMetrics();
}
/////////////////////////////////////////////////////////////////////////////
// CUIFTheme
HRESULT CUIFTheme::InternalOpenThemeData(HWND hWnd)
{
if (!hWnd || !m_pszClassList)
return E_FAIL;
if (!cicGetFN(s_hUXTHEME, s_fnOpenThemeData, TEXT("uxtheme.dll"), "OpenThemeData"))
return E_FAIL;
m_hTheme = s_fnOpenThemeData(hWnd, m_pszClassList);
return (m_hTheme ? S_OK : E_FAIL);
}
HRESULT CUIFTheme::EnsureThemeData(HWND hWnd)
{
if (m_hTheme)
return S_OK;
return InternalOpenThemeData(hWnd);
}
HRESULT CUIFTheme::CloseThemeData()
{
if (!m_hTheme)
return S_OK;
if (!cicGetFN(s_hUXTHEME, s_fnCloseThemeData, TEXT("uxtheme.dll"), "CloseThemeData"))
return E_FAIL;
HRESULT hr = s_fnCloseThemeData(m_hTheme);
m_hTheme = NULL;
return hr;
}
STDMETHODIMP
CUIFTheme::DrawThemeBackground(HDC hDC, int iStateId, LPCRECT pRect, LPCRECT pClipRect)
{
if (!cicGetFN(s_hUXTHEME, s_fnDrawThemeBackground, TEXT("uxtheme.dll"), "DrawThemeBackground"))
return E_FAIL;
return s_fnDrawThemeBackground(m_hTheme, hDC, m_iPartId, iStateId, pRect, pClipRect);
}
STDMETHODIMP
CUIFTheme::DrawThemeParentBackground(HWND hwnd, HDC hDC, LPRECT prc)
{
if (!cicGetFN(s_hUXTHEME, s_fnDrawThemeParentBackground, TEXT("uxtheme.dll"), "DrawThemeParentBackground"))
return E_FAIL;
return s_fnDrawThemeParentBackground(hwnd, hDC, prc);
}
STDMETHODIMP
CUIFTheme::DrawThemeText(HDC hDC, int iStateId, LPCWSTR pszText, int cchText, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect)
{
if (!cicGetFN(s_hUXTHEME, s_fnDrawThemeText, TEXT("uxtheme.dll"), "DrawThemeText"))
return E_FAIL;
return s_fnDrawThemeText(m_hTheme, hDC, m_iPartId, iStateId, pszText, cchText, dwTextFlags, dwTextFlags2, pRect);
}
STDMETHODIMP
CUIFTheme::DrawThemeIcon(HDC hDC, int iStateId, LPCRECT pRect, HIMAGELIST himl, int iImageIndex)
{
if (!cicGetFN(s_hUXTHEME, s_fnDrawThemeIcon, TEXT("uxtheme.dll"), "DrawThemeIcon"))
return E_FAIL;
return s_fnDrawThemeIcon(m_hTheme, hDC, m_iPartId, iStateId, pRect, himl, iImageIndex);
}
STDMETHODIMP
CUIFTheme::GetThemeBackgroundExtent(HDC hDC, int iStateId, LPCRECT pContentRect, LPRECT pExtentRect)
{
if (!cicGetFN(s_hUXTHEME, s_fnGetThemeBackgroundExtent, TEXT("uxtheme.dll"), "GetThemeBackgroundExtent"))
return E_FAIL;
return s_fnGetThemeBackgroundExtent(m_hTheme, hDC, m_iPartId, iStateId, pContentRect, pExtentRect);
}
STDMETHODIMP
CUIFTheme::GetThemeBackgroundContentRect(HDC hDC, int iStateId, LPCRECT pBoundingRect, LPRECT pContentRect)
{
if (!cicGetFN(s_hUXTHEME, s_fnGetThemeBackgroundContentRect, TEXT("uxtheme.dll"), "GetThemeBackgroundContentRect"))
return E_FAIL;
return s_fnGetThemeBackgroundContentRect(m_hTheme, hDC, m_iPartId, iStateId, pBoundingRect, pContentRect);
}
STDMETHODIMP
CUIFTheme::GetThemeTextExtent(HDC hDC, int iStateId, LPCWSTR pszText, int cchCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect)
{
if (!cicGetFN(s_hUXTHEME, s_fnGetThemeTextExtent, TEXT("uxtheme.dll"), "GetThemeTextExtent"))
return E_FAIL;
return s_fnGetThemeTextExtent(m_hTheme, hDC, m_iPartId, iStateId, pszText, cchCharCount, dwTextFlags, pBoundingRect, pExtentRect);
}
STDMETHODIMP
CUIFTheme::GetThemePartSize(HDC hDC, int iStateId, LPRECT prc, THEMESIZE eSize, SIZE *psz)
{
if (!cicGetFN(s_hUXTHEME, s_fnGetThemePartSize, TEXT("uxtheme.dll"), "GetThemePartSize"))
return E_FAIL;
return s_fnGetThemePartSize(m_hTheme, hDC, m_iPartId, iStateId, prc, eSize, psz);
}
STDMETHODIMP
CUIFTheme::DrawThemeEdge(HDC hDC, int iStateId, LPCRECT pDestRect, UINT uEdge, UINT uFlags, LPRECT pContentRect)
{
if (!cicGetFN(s_hUXTHEME, s_fnDrawThemeEdge, TEXT("uxtheme.dll"), "DrawThemeEdge"))
return E_FAIL;
return s_fnDrawThemeEdge(m_hTheme, hDC, m_iPartId, iStateId, pDestRect, uEdge, uFlags, pContentRect);
}
STDMETHODIMP
CUIFTheme::GetThemeColor(int iStateId, int iPropId, COLORREF *pColor)
{
if (!cicGetFN(s_hUXTHEME, s_fnGetThemeColor, TEXT("uxtheme.dll"), "GetThemeColor"))
return E_FAIL;
return s_fnGetThemeColor(m_hTheme, m_iPartId, iStateId, iPropId, pColor);
}
STDMETHODIMP
CUIFTheme::GetThemeMargins(HDC hDC, int iStateId, int iPropId, LPRECT prc, MARGINS *pMargins)
{
if (!cicGetFN(s_hUXTHEME, s_fnGetThemeMargins, TEXT("uxtheme.dll"), "GetThemeMargins"))
return E_FAIL;
return s_fnGetThemeMargins(m_hTheme, hDC, m_iPartId, iStateId, iPropId, prc, pMargins);
}
STDMETHODIMP
CUIFTheme::GetThemeFont(HDC hDC, int iStateId, int iPropId, LOGFONTW *pFont)
{
if (!cicGetFN(s_hUXTHEME, s_fnGetThemeFont, TEXT("uxtheme.dll"), "GetThemeFont"))
return E_FAIL;
return s_fnGetThemeFont(m_hTheme, hDC, m_iPartId, iStateId, iPropId, pFont);
}
STDMETHODIMP_(COLORREF)
CUIFTheme::GetThemeSysColor(INT iColorId)
{
if (!cicGetFN(s_hUXTHEME, s_fnGetThemeSysColor, TEXT("uxtheme.dll"), "GetThemeSysColor"))
return RGB(0, 0, 0);
return s_fnGetThemeSysColor(m_hTheme, iColorId);
}
STDMETHODIMP_(int)
CUIFTheme::GetThemeSysSize(int iSizeId)
{
if (!cicGetFN(s_hUXTHEME, s_fnGetThemeSysSize, TEXT("uxtheme.dll"), "GetThemeSysSize"))
return 0;
return s_fnGetThemeSysSize(m_hTheme, iSizeId);
}
STDMETHODIMP_(void)
CUIFTheme::SetActiveTheme(LPCWSTR pszClassList, INT iPartId, INT iStateId)
{
m_iPartId = iPartId;
m_iStateId = iStateId;
m_pszClassList = pszClassList;
}
/////////////////////////////////////////////////////////////////////////////
// CUIFObject
/// @unimplemented
CUIFObject::CUIFObject(CUIFObject *pParent, DWORD nObjectID, LPCRECT prc, DWORD style)
{
m_pszClassList = NULL;
m_hTheme = NULL;
m_pParent = pParent;
m_nObjectID = nObjectID;
m_style = style;
if (prc)
m_rc = *prc;
else
m_rc = { 0, 0, 0, 0 };
if (m_pParent)
{
m_pWindow = m_pParent->m_pWindow;
m_pScheme = m_pParent->m_pScheme;
}
else
{
m_pWindow = NULL;
m_pScheme = NULL;
}
m_bEnable = m_bVisible = TRUE;
m_hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
m_bHasCustomFont = FALSE;
m_pszToolTip = NULL;
m_dwUnknown4[0] = -1; //FIXME: name
m_dwUnknown4[1] = -1; //FIXME: name
}
CUIFObject::~CUIFObject()
{
if (m_pWindow)
{
CUIFToolTip *pToolTip = m_pWindow->m_pToolTip;
if (pToolTip && pToolTip->m_pToolTipTarget == this)
pToolTip->m_pToolTipTarget = NULL;
}
if (m_pszToolTip)
{
delete[] m_pszToolTip;
m_pszToolTip = NULL;
}
for (size_t iObj = m_ObjectArray.size(); iObj > 0; )
{
--iObj;
delete m_ObjectArray[iObj];
}
m_ObjectArray.clear();
if (m_pWindow)
m_pWindow->RemoveUIObj(this);
CloseThemeData();
}
STDMETHODIMP_(void) CUIFObject::OnPaint(HDC hDC)
{
if (!(m_pWindow->m_style & UIF_WINDOW_ENABLETHEMED) || !OnPaintTheme(hDC))
OnPaintNoTheme(hDC);
}
STDMETHODIMP_(BOOL) CUIFObject::OnSetCursor(UINT uMsg, LONG x, LONG y)
{
return FALSE;
}
STDMETHODIMP_(void) CUIFObject::GetRect(LPRECT prc)
{
*prc = m_rc;
}
STDMETHODIMP_(BOOL) CUIFObject::PtInObject(POINT pt)
{
return m_bVisible && ::PtInRect(&m_rc, pt);
}
STDMETHODIMP_(void) CUIFObject::PaintObject(HDC hDC, LPCRECT prc)
{
if (!m_bVisible)
return;
if (!prc)
prc = &m_rc;
OnPaint(hDC);
for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
{
CUIFObject *pObject = m_ObjectArray[iItem];
RECT rc;
if (::IntersectRect(&rc, prc, &pObject->m_rc))
pObject->PaintObject(hDC, &rc);
}
}
STDMETHODIMP_(void) CUIFObject::CallOnPaint()
{
if (m_pWindow)
m_pWindow->UpdateUI(&m_rc);
}
STDMETHODIMP_(void) CUIFObject::Enable(BOOL bEnable)
{
if (m_bEnable == bEnable)
return;
m_bEnable = bEnable;
for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
m_ObjectArray[iItem]->Enable(bEnable);
CallOnPaint();
}
STDMETHODIMP_(void) CUIFObject::Show(BOOL bVisible)
{
if (m_bVisible == bVisible)
return;
m_bVisible = bVisible;
for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
m_ObjectArray[iItem]->Show(bVisible);
if (m_bVisible || m_pParent)
m_pParent->CallOnPaint();
}
STDMETHODIMP_(void) CUIFObject::SetFontToThis(HFONT hFont)
{
m_bHasCustomFont = !!hFont;
if (!hFont)
hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
m_hFont = hFont;
}
STDMETHODIMP_(void) CUIFObject::SetFont(HFONT hFont)
{
SetFontToThis(hFont);
for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
m_ObjectArray[iItem]->SetFont(hFont);
CallOnPaint();
}
STDMETHODIMP_(void) CUIFObject::SetStyle(DWORD style)
{
m_style = style;
}
STDMETHODIMP_(void) CUIFObject::AddUIObj(CUIFObject *pObject)
{
m_ObjectArray.Add(pObject);
CallOnPaint();
}
STDMETHODIMP_(void) CUIFObject::RemoveUIObj(CUIFObject *pObject)
{
if (m_ObjectArray.Remove(pObject))
CallOnPaint();
}
STDMETHODIMP_(LRESULT) CUIFObject::OnObjectNotify(CUIFObject *pObject, WPARAM wParam, LPARAM lParam)
{
if (m_pParent)
return m_pParent->OnObjectNotify(pObject, wParam, lParam);
return 0;
}
STDMETHODIMP_(void) CUIFObject::SetToolTip(LPCWSTR pszToolTip)
{
if (m_pszToolTip)
{
delete[] m_pszToolTip;
m_pszToolTip = NULL;
}
if (pszToolTip)
{
size_t cch = wcslen(pszToolTip);
m_pszToolTip = new(cicNoThrow) WCHAR[cch + 1];
if (m_pszToolTip)
lstrcpynW(m_pszToolTip, pszToolTip, cch + 1);
}
}
STDMETHODIMP_(void) CUIFObject::ClearWndObj()
{
m_pWindow = NULL;
for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
m_ObjectArray[iItem]->ClearWndObj();
}
STDMETHODIMP_(void) CUIFObject::ClearTheme()
{
CloseThemeData();
for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
m_ObjectArray[iItem]->ClearTheme();
}
void CUIFObject::StartCapture()
{
if (m_pWindow)
m_pWindow->SetCaptureObject(this);
}
void CUIFObject::EndCapture()
{
if (m_pWindow)
m_pWindow->SetCaptureObject(NULL);
}
BOOL CUIFObject::IsCapture()
{
return m_pWindow && (m_pWindow->m_pCaptured == this);
}
void CUIFObject::SetRect(LPCRECT prc)
{
m_rc = *prc;
if (m_pWindow)
m_pWindow->OnObjectMoved(this);
CallOnPaint();
}
LRESULT CUIFObject::NotifyCommand(WPARAM wParam, LPARAM lParam)
{
if (m_pParent)
return m_pParent->OnObjectNotify(this, wParam, lParam);
return 0;
}
void CUIFObject::DetachWndObj()
{
if (m_pWindow)
{
CUIFToolTip *pToolTip = m_pWindow->m_pToolTip;
if (pToolTip && pToolTip->m_pToolTipTarget == this)
pToolTip->m_pToolTipTarget = NULL;
m_pWindow->RemoveUIObj(this);
m_pWindow = NULL;
}
}
BOOL CUIFObject::IsRTL()
{
if (!m_pWindow)
return FALSE;
return !!(m_pWindow->m_style & UIF_WINDOW_LAYOUTRTL);
}
CUIFObject* CUIFObject::ObjectFromPoint(POINT pt)
{
if (!PtInObject(pt))
return NULL;
CUIFObject *pFound = this;
for (size_t i = 0; i < m_ObjectArray.size(); ++i)
{
CUIFObject *pObject = m_ObjectArray[i]->ObjectFromPoint(pt);
if (pObject)
pFound = pObject;
}
return pFound;
}
void CUIFObject::SetScheme(CUIFScheme *scheme)
{
m_pScheme = scheme;
for (size_t i = 0; i < m_ObjectArray.size(); ++i)
{
m_ObjectArray[i]->SetScheme(scheme);
}
}
void CUIFObject::StartTimer(WPARAM wParam)
{
if (m_pWindow)
m_pWindow->SetTimerObject(this, wParam);
}
void CUIFObject::EndTimer()
{
if (m_pWindow)
m_pWindow->SetTimerObject(NULL, 0);
}
/////////////////////////////////////////////////////////////////////////////
// CUIFColorTable...
STDMETHODIMP_(void) CUIFColorTableSys::InitColor()
{
m_rgbColors[0] = ::GetSysColor(COLOR_BTNFACE);
m_rgbColors[1] = ::GetSysColor(COLOR_BTNSHADOW);
m_rgbColors[2] = ::GetSysColor(COLOR_ACTIVEBORDER);
m_rgbColors[3] = ::GetSysColor(COLOR_ACTIVECAPTION);
m_rgbColors[4] = ::GetSysColor(COLOR_BTNFACE);
m_rgbColors[5] = ::GetSysColor(COLOR_BTNSHADOW);
m_rgbColors[6] = ::GetSysColor(COLOR_BTNTEXT);
m_rgbColors[7] = ::GetSysColor(COLOR_CAPTIONTEXT);
m_rgbColors[8] = ::GetSysColor(COLOR_GRAYTEXT);
m_rgbColors[9] = ::GetSysColor(COLOR_HIGHLIGHT);
m_rgbColors[10] = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
m_rgbColors[11] = ::GetSysColor(COLOR_INACTIVECAPTION);
m_rgbColors[12] = ::GetSysColor(COLOR_INACTIVECAPTIONTEXT);
m_rgbColors[13] = ::GetSysColor(COLOR_MENUTEXT);
m_rgbColors[14] = ::GetSysColor(COLOR_WINDOW);
m_rgbColors[15] = ::GetSysColor(COLOR_WINDOWTEXT);
}
STDMETHODIMP_(void) CUIFColorTableSys::InitBrush()
{
ZeroMemory(m_hBrushes, sizeof(m_hBrushes));
}
STDMETHODIMP_(void) CUIFColorTableSys::DoneBrush()
{
for (size_t i = 0; i < _countof(m_hBrushes); ++i)
{
if (m_hBrushes[i])
{
::DeleteObject(m_hBrushes[i]);
m_hBrushes[i] = NULL;
}
}
}
HBRUSH CUIFColorTableSys::GetBrush(INT iColor)
{
if (!m_hBrushes[iColor])
m_hBrushes[iColor] = ::CreateSolidBrush(m_rgbColors[iColor]);
return m_hBrushes[iColor];
}
HBRUSH CUIFColorTableOff10::GetBrush(INT iColor)
{
if (!m_hBrushes[iColor])
m_hBrushes[iColor] = ::CreateSolidBrush(m_rgbColors[iColor]);
return m_hBrushes[iColor];
}
/// @unimplemented
STDMETHODIMP_(void) CUIFColorTableOff10::InitColor()
{
m_rgbColors[0] = ::GetSysColor(COLOR_BTNFACE);
m_rgbColors[1] = ::GetSysColor(COLOR_WINDOW);
m_rgbColors[2] = ::GetSysColor(COLOR_WINDOW);
m_rgbColors[3] = ::GetSysColor(COLOR_BTNFACE);
m_rgbColors[4] = ::GetSysColor(COLOR_BTNSHADOW);
m_rgbColors[5] = ::GetSysColor(COLOR_WINDOW);
m_rgbColors[6] = ::GetSysColor(COLOR_HIGHLIGHT);
m_rgbColors[7] = ::GetSysColor(COLOR_WINDOWTEXT);
m_rgbColors[8] = ::GetSysColor(COLOR_HIGHLIGHT);
m_rgbColors[9] = ::GetSysColor(COLOR_HIGHLIGHT);
m_rgbColors[10] = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
m_rgbColors[11] = ::GetSysColor(COLOR_BTNFACE);
m_rgbColors[12] = ::GetSysColor(COLOR_BTNTEXT);
m_rgbColors[13] = ::GetSysColor(COLOR_BTNSHADOW);
m_rgbColors[14] = ::GetSysColor(COLOR_BTNFACE);
m_rgbColors[15] = ::GetSysColor(COLOR_WINDOW);
m_rgbColors[16] = ::GetSysColor(COLOR_HIGHLIGHT);
m_rgbColors[17] = ::GetSysColor(COLOR_BTNTEXT);
m_rgbColors[18] = ::GetSysColor(COLOR_WINDOW);
m_rgbColors[19] = ::GetSysColor(COLOR_BTNSHADOW);
m_rgbColors[20] = ::GetSysColor(COLOR_BTNFACE);
m_rgbColors[21] = ::GetSysColor(COLOR_BTNSHADOW);
m_rgbColors[22] = ::GetSysColor(COLOR_BTNFACE);
m_rgbColors[23] = ::GetSysColor(COLOR_BTNSHADOW);
m_rgbColors[24] = ::GetSysColor(COLOR_CAPTIONTEXT);
m_rgbColors[25] = ::GetSysColor(COLOR_HIGHLIGHT);
m_rgbColors[26] = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
m_rgbColors[27] = ::GetSysColor(COLOR_BTNFACE);
m_rgbColors[28] = ::GetSysColor(COLOR_BTNTEXT);
m_rgbColors[29] = ::GetSysColor(COLOR_BTNSHADOW);
m_rgbColors[30] = ::GetSysColor(COLOR_BTNTEXT);
m_rgbColors[31] = ::GetSysColor(COLOR_WINDOWTEXT);
}
STDMETHODIMP_(void) CUIFColorTableOff10::InitBrush()
{
ZeroMemory(m_hBrushes, sizeof(m_hBrushes));
}
STDMETHODIMP_(void) CUIFColorTableOff10::DoneBrush()
{
for (size_t i = 0; i < _countof(m_hBrushes); ++i)
{
if (m_hBrushes[i])
{
::DeleteObject(m_hBrushes[i]);
m_hBrushes[i] = NULL;
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CUIFScheme
/// @unimplemented
CUIFScheme *cicCreateUIFScheme(DWORD type)
{
#if 1
return new(cicNoThrow) CUIFSchemeDef(type);
#else
switch (type)
{
case 1: return new(cicNoThrow) CUIFSchemeOff10(1);
case 2: return new(cicNoThrow) CUIFSchemeOff10(2);
case 3: return new(cicNoThrow) CUIFSchemeOff10(3);
default: return new(cicNoThrow) CUIFSchemeDef(type);
}
#endif
}
STDMETHODIMP_(DWORD) CUIFSchemeDef::GetType()
{
return m_dwType;
}
STDMETHODIMP_(COLORREF) CUIFSchemeDef::GetColor(INT iColor)
{
return s_pColorTableSys->GetColor(iColor);
}
STDMETHODIMP_(HBRUSH) CUIFSchemeDef::GetBrush(INT iColor)
{
return s_pColorTableSys->GetBrush(iColor);
}
STDMETHODIMP_(INT) CUIFSchemeDef::CyMenuItem(INT cyText)
{
return cyText + 2;
}
STDMETHODIMP_(INT) CUIFSchemeDef::CxSizeFrame()
{
return ::GetSystemMetrics(SM_CXSIZEFRAME);
}
STDMETHODIMP_(INT) CUIFSchemeDef::CySizeFrame()
{
return ::GetSystemMetrics(SM_CYSIZEFRAME);
}
STDMETHODIMP_(void) CUIFScheme::FillRect(HDC hDC, LPCRECT prc, INT iColor)
{
::FillRect(hDC, prc, GetBrush(iColor));
}
STDMETHODIMP_(void) CUIFScheme::FrameRect(HDC hDC, LPCRECT prc, INT iColor)
{
::FrameRect(hDC, prc, GetBrush(iColor));
}
STDMETHODIMP_(void) CUIFSchemeDef::DrawSelectionRect(HDC hDC, LPCRECT prc, int)
{
::FillRect(hDC, prc, GetBrush(6));
}
STDMETHODIMP_(void)
CUIFSchemeDef::GetCtrlFaceOffset(DWORD dwUnknownFlags, DWORD dwDrawFlags, LPSIZE pSize)
{
if (!(dwDrawFlags & UIF_DRAW_PRESSED))
{
if (dwDrawFlags & 0x2)
{
if (dwUnknownFlags & 0x10)
{
pSize->cx = pSize->cy = -1;
return;
}
pSize->cx = pSize->cy = !!(dwUnknownFlags & 0x20);
}
else
{
if (!(dwDrawFlags & 0x1))
{
pSize->cx = pSize->cy = -((dwUnknownFlags & 1) != 0);
return;
}
if (dwUnknownFlags & 0x4)
{
pSize->cx = pSize->cy = -1;
return;
}
pSize->cx = pSize->cy = !!(dwUnknownFlags & 0x8);
}
return;
}
if (!(dwUnknownFlags & 0x40))
{
pSize->cx = pSize->cy = !!(dwUnknownFlags & 0x80);
return;
}
pSize->cx = pSize->cy = -1;
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawCtrlBkgd(HDC hDC, LPCRECT prc, DWORD dwUnknownFlags, DWORD dwDrawFlags)
{
::FillRect(hDC, prc, GetBrush(9));
if (!(dwDrawFlags & UIF_DRAW_PRESSED) && (dwDrawFlags & 0x2))
return;
HBRUSH hbrDither = cicCreateDitherBrush();
if (!hbrDither)
return;
COLORREF rgbOldText = ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNFACE));
COLORREF rgbOldBack = ::SetBkColor(hDC, ::GetSysColor(COLOR_BTNHIGHLIGHT));
RECT rc = *prc;
::InflateRect(&rc, -2, -2);
::FillRect(hDC, &rc, hbrDither);
::SetTextColor(hDC, rgbOldText);
::SetBkColor(hDC, rgbOldBack);
::DeleteObject(hbrDither);
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawCtrlEdge(
HDC hDC,
LPCRECT prc,
DWORD dwUnknownFlags,
DWORD dwDrawFlags)
{
UINT uEdge = BDR_RAISEDINNER;
if (dwDrawFlags & 0x10)
{
if (!(dwUnknownFlags & 0x40))
{
if (dwUnknownFlags & 0x80)
uEdge = BDR_SUNKENOUTER;
else
return;
}
}
else if (dwDrawFlags & 0x2)
{
if (!(dwUnknownFlags & 0x10))
{
if (dwUnknownFlags & 0x20)
uEdge = BDR_SUNKENOUTER;
else
return;
}
}
else if (dwDrawFlags & 0x1)
{
if (!(dwUnknownFlags & 0x4))
{
if (dwUnknownFlags & 0x8)
uEdge = BDR_SUNKENOUTER;
else
return;
}
}
else if (!(dwUnknownFlags & 0x1))
{
return;
}
RECT rc = *prc;
::DrawEdge(hDC, &rc, uEdge, BF_RECT);
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawCtrlText(
HDC hDC,
LPCRECT prc,
LPCWSTR pszText,
INT cchText,
DWORD dwDrawFlags,
BOOL bRight)
{
COLORREF rgbOldText = ::GetTextColor(hDC);
INT OldBkMode = ::SetBkMode(hDC, TRANSPARENT);
if (cchText == -1)
cchText = lstrlenW(pszText);
RECT rc = *prc;
if (dwDrawFlags & UIF_DRAW_DISABLED)
{
::OffsetRect(&rc, 1, 1);
::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHIGHLIGHT));
::ExtTextOutW(hDC, (bRight ? rc.right : rc.left), rc.top, ETO_CLIPPED, &rc,
pszText, cchText, NULL);
::OffsetRect(&rc, -1, -1);
}
::SetTextColor(hDC, ::GetSysColor(COLOR_BTNTEXT));
::ExtTextOutW(hDC, (bRight ? rc.right : rc.left), rc.top, ETO_CLIPPED, &rc,
pszText, cchText, NULL);
::SetTextColor(hDC, rgbOldText);
::SetBkMode(hDC, OldBkMode);
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawCtrlIcon(HDC hDC, LPCRECT prc, HICON hIcon, DWORD dwDrawFlags, LPSIZE pSize)
{
if (m_bMirroring)
{
HBITMAP hbm1, hbm2;
if (cicGetIconBitmaps(hIcon, &hbm1, &hbm2, pSize))
{
DrawCtrlBitmap(hDC, prc, hbm1, hbm2, dwDrawFlags);
::DeleteObject(hbm1);
::DeleteObject(hbm2);
}
}
else
{
UINT uFlags = DST_PREFIXTEXT | DST_TEXT;
if (dwDrawFlags & UIF_DRAW_DISABLED)
uFlags |= (DSS_MONO | DSS_DISABLED);
::DrawState(hDC, 0, 0, (LPARAM)hIcon, 0, prc->left, prc->top, 0, 0, uFlags);
}
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawCtrlBitmap(HDC hDC, LPCRECT prc, HBITMAP hbm1, HBITMAP hbm2, DWORD dwDrawFlags)
{
if (m_bMirroring)
{
hbm1 = cicMirrorBitmap(hbm1, GetBrush(9));
hbm2 = cicMirrorBitmap(hbm2, (HBRUSH)GetStockObject(BLACK_BRUSH));
}
HBRUSH hBrush = (HBRUSH)UlongToHandle(COLOR_BTNFACE + 1);
BOOL bBrushCreated = FALSE;
if (hbm2)
{
HBITMAP hBitmap = NULL;
if (dwDrawFlags & UIF_DRAW_DISABLED)
{
hBitmap = cicCreateDisabledBitmap(prc, hbm2, GetBrush(9), GetBrush(11), TRUE);
}
else
{
if ((dwDrawFlags & UIF_DRAW_PRESSED) && !(dwDrawFlags & 0x2))
{
hBrush = cicCreateDitherBrush();
bBrushCreated = TRUE;
}
COLORREF rgbFace = ::GetSysColor(COLOR_BTNFACE);
COLORREF rgbHighlight = ::GetSysColor(COLOR_BTNHIGHLIGHT);
hBitmap = cicCreateMaskBmp(prc, hbm1, hbm2, hBrush, rgbFace, rgbHighlight);
}
if (hBitmap)
{
::DrawState(hDC, NULL, NULL, (LPARAM)hBitmap, 0,
prc->left, prc->top,
prc->right - prc->left, prc->bottom - prc->top,
DST_BITMAP);
::DeleteObject(hBitmap);
}
}
else
{
UINT uFlags = DST_BITMAP;
if (dwDrawFlags & UIF_DRAW_DISABLED)
uFlags |= (DSS_MONO | DSS_DISABLED);
::DrawState(hDC, NULL, NULL, (LPARAM)hbm1, 0,
prc->left, prc->top,
prc->right - prc->left, prc->bottom - prc->top,
uFlags);
}
if (bBrushCreated)
::DeleteObject(hBrush);
if (m_bMirroring)
{
::DeleteObject(hbm1);
::DeleteObject(hbm2);
}
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawMenuBitmap(HDC hDC, LPCRECT prc, HBITMAP hbm1, HBITMAP hbm2, DWORD dwDrawFlags)
{
DrawCtrlBitmap(hDC, prc, hbm1, hbm2, dwDrawFlags);
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawMenuSeparator(HDC hDC, LPCRECT prc)
{
RECT rc = *prc;
rc.bottom = rc.top + (rc.bottom - rc.top) / 2;
::FillRect(hDC, &rc, (HBRUSH)UlongToHandle(COLOR_BTNSHADOW + 1));
rc = *prc;
rc.top += (rc.bottom - rc.top) / 2;
::FillRect(hDC, &rc, (HBRUSH)UlongToHandle(COLOR_BTNHIGHLIGHT + 1));
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawFrameCtrlBkgd(HDC hDC, LPCRECT prc, DWORD dwUnknownFlags, DWORD dwDrawFlags)
{
DrawCtrlBkgd(hDC, prc, dwUnknownFlags, dwDrawFlags);
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawFrameCtrlEdge(HDC hDC, LPCRECT prc, DWORD dwUnknownFlags, DWORD dwDrawFlags)
{
DrawCtrlEdge(hDC, prc, dwUnknownFlags, dwDrawFlags);
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawFrameCtrlIcon(HDC hDC, LPCRECT prc, HICON hIcon, DWORD dwDrawFlags, LPSIZE pSize)
{
DrawCtrlIcon(hDC, prc, hIcon, dwDrawFlags, pSize);
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawFrameCtrlBitmap(HDC hDC, LPCRECT prc, HBITMAP hbm1, HBITMAP hbm2, DWORD dwDrawFlags)
{
DrawCtrlBitmap(hDC, prc, hbm1, hbm2, dwDrawFlags);
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawWndFrame(HDC hDC, LPCRECT prc, DWORD type, DWORD unused1, DWORD unused2)
{
RECT rc = *prc;
if (type && type <= 2)
::DrawEdge(hDC, &rc, BDR_RAISED, BF_RECT);
else
FrameRect(hDC, &rc, 14);
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawDragHandle(HDC hDC, LPCRECT prc, BOOL bVertical)
{
RECT rc;
if (bVertical)
rc = { prc->left, prc->top + 1, prc->right, prc->top + 4 };
else
rc = { prc->left + 1, prc->top, prc->left + 4, prc->bottom };
::DrawEdge(hDC, &rc, BDR_RAISEDINNER, BF_RECT);
}
STDMETHODIMP_(void)
CUIFSchemeDef::DrawSeparator(HDC hDC, LPCRECT prc, BOOL bVertical)
{
HPEN hLightPen = ::CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNHIGHLIGHT));
if (!hLightPen)
return;
HPEN hShadowPen = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW));
if (!hShadowPen)
{
::DeleteObject(hLightPen);
return;
}
HGDIOBJ hPenOld = ::SelectObject(hDC, hShadowPen);
if (bVertical)
{
::MoveToEx(hDC, prc->left, prc->top + 1, NULL);
::LineTo(hDC, prc->right, prc->top + 1);
::SelectObject(hDC, hLightPen);
::MoveToEx(hDC, prc->left, prc->top + 2, NULL);
::LineTo(hDC, prc->right, prc->top + 2);
}
else
{
::MoveToEx(hDC, prc->left + 1, prc->top, NULL);
::LineTo(hDC, prc->left + 1, prc->bottom);
::SelectObject(hDC, hLightPen);
::MoveToEx(hDC, prc->left + 2, prc->top, NULL);
::LineTo(hDC, prc->left + 2, prc->bottom);
}
::SelectObject(hDC, hPenOld);
::DeleteObject(hShadowPen);
::DeleteObject(hLightPen);
}
/////////////////////////////////////////////////////////////////////////////
// CUIFIcon
HIMAGELIST CUIFIcon::GetImageList(BOOL bMirror)
{
if (!m_hImageList)
return NULL;
if (m_hIcon)
{
SIZE iconSize;
cicGetIconSize(m_hIcon, &iconSize);
UINT uFlags = ILC_COLOR32 | ILC_MASK;
if (bMirror)
uFlags |= ILC_MIRROR;
m_hImageList = ImageList_Create(iconSize.cx, iconSize.cy, uFlags, 1, 0);
if (m_hImageList)
ImageList_ReplaceIcon(m_hImageList, -1, m_hIcon);
return m_hImageList;
}
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CUIFBitmapDC
CUIFBitmapDC::CUIFBitmapDC(BOOL bMemory)
{
m_hBitmap = NULL;
m_hOldBitmap = NULL;
m_hOldObject = NULL;
if (bMemory)
m_hDC = ::CreateCompatibleDC(NULL);
else
m_hDC = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
}
CUIFBitmapDC::~CUIFBitmapDC()
{
Uninit();
::DeleteDC(m_hDC);
}
void CUIFBitmapDC::Uninit(BOOL bKeep)
{
if (m_hOldBitmap)
{
::SelectObject(m_hDC, m_hOldBitmap);
m_hOldBitmap = NULL;
}
if (m_hOldObject)
{
::SelectObject(m_hDC, m_hOldObject);
m_hOldObject = NULL;
}
if (!bKeep)
{
if (m_hBitmap)
{
::DeleteObject(m_hBitmap);
m_hBitmap = NULL;
}
}
}
BOOL CUIFBitmapDC::SetBitmap(HBITMAP hBitmap)
{
if (m_hDC)
m_hOldBitmap = ::SelectObject(m_hDC, hBitmap);
return TRUE;
}
BOOL CUIFBitmapDC::SetBitmap(LONG cx, LONG cy, WORD cPlanes, WORD cBitCount)
{
m_hBitmap = ::CreateBitmap(cx, cy, cPlanes, cBitCount, 0);
m_hOldBitmap = ::SelectObject(m_hDC, m_hBitmap);
return TRUE;
}
BOOL CUIFBitmapDC::SetDIB(LONG cx, LONG cy, WORD cPlanes, WORD cBitCount)
{
BITMAPINFO bmi;
ZeroMemory(&bmi, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = cx;
bmi.bmiHeader.biHeight = cy;
bmi.bmiHeader.biPlanes = cPlanes;
bmi.bmiHeader.biBitCount = cBitCount;
bmi.bmiHeader.biCompression = BI_RGB;
m_hBitmap = ::CreateDIBSection(m_hDC, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
m_hOldBitmap = ::SelectObject(m_hDC, m_hBitmap);
return TRUE;
}
void cicInitUIFUtil(void)
{
if (!CUIFBitmapDC::s_phdcSrc)
CUIFBitmapDC::s_phdcSrc = new(cicNoThrow) CUIFBitmapDC(TRUE);
if (!CUIFBitmapDC::s_phdcMask)
CUIFBitmapDC::s_phdcMask = new(cicNoThrow) CUIFBitmapDC(TRUE);
if (!CUIFBitmapDC::s_phdcDst)
CUIFBitmapDC::s_phdcDst = new(cicNoThrow) CUIFBitmapDC(TRUE);
if (CUIFBitmapDC::s_phdcSrc && CUIFBitmapDC::s_phdcMask && CUIFBitmapDC::s_phdcDst)
CUIFBitmapDC::s_fInitBitmapDCs = TRUE;
}
void cicDoneUIFUtil(void)
{
if (CUIFBitmapDC::s_phdcSrc)
{
delete CUIFBitmapDC::s_phdcSrc;
CUIFBitmapDC::s_phdcSrc = NULL;
}
if (CUIFBitmapDC::s_phdcMask)
{
delete CUIFBitmapDC::s_phdcMask;
CUIFBitmapDC::s_phdcMask = NULL;
}
if (CUIFBitmapDC::s_phdcDst)
{
delete CUIFBitmapDC::s_phdcDst;
CUIFBitmapDC::s_phdcDst = NULL;
}
CUIFBitmapDC::s_fInitBitmapDCs = FALSE;
}
HBITMAP cicMirrorBitmap(HBITMAP hBitmap, HBRUSH hbrBack)
{
BITMAP bm;
if (!CUIFBitmapDC::s_fInitBitmapDCs || !::GetObject(hBitmap, sizeof(bm), &bm))
return NULL;
CUIFBitmapDC::s_phdcSrc->SetBitmap(hBitmap);
CUIFBitmapDC::s_phdcDst->SetDIB(bm.bmWidth, bm.bmHeight, 1, 32);
CUIFBitmapDC::s_phdcMask->SetDIB(bm.bmWidth, bm.bmHeight, 1, 32);
RECT rc = { 0, 0, bm.bmWidth, bm.bmHeight };
FillRect(*CUIFBitmapDC::s_phdcDst, &rc, hbrBack);
::SetLayout(*CUIFBitmapDC::s_phdcMask, LAYOUT_RTL);
::BitBlt(*CUIFBitmapDC::s_phdcMask, 0, 0, bm.bmWidth, bm.bmHeight, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCCOPY);
::SetLayout(*CUIFBitmapDC::s_phdcMask, 0);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, bm.bmWidth, bm.bmHeight, *CUIFBitmapDC::s_phdcMask, 1, 0, SRCCOPY);
CUIFBitmapDC::s_phdcSrc->Uninit();
CUIFBitmapDC::s_phdcMask->Uninit();
CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
return CUIFBitmapDC::s_phdcDst->DetachBitmap();
}
HBRUSH cicCreateDitherBrush(VOID)
{
BYTE bytes[16];
ZeroMemory(&bytes, sizeof(bytes));
bytes[0] = bytes[4] = bytes[8] = bytes[12] = 0x55;
bytes[2] = bytes[6] = bytes[10] = bytes[14] = 0xAA;
HBITMAP hBitmap = ::CreateBitmap(8, 8, 1, 1, bytes);
if (!hBitmap)
return NULL;
LOGBRUSH lb;
lb.lbHatch = (ULONG_PTR)hBitmap;
lb.lbStyle = BS_PATTERN;
HBRUSH hbr = ::CreateBrushIndirect(&lb);
::DeleteObject(hBitmap);
return hbr;
}
HBITMAP
cicCreateDisabledBitmap(LPCRECT prc, HBITMAP hbmMask, HBRUSH hbr1, HBRUSH hbr2, BOOL bPressed)
{
if (!CUIFBitmapDC::s_fInitBitmapDCs)
return NULL;
LONG width = prc->right - prc->left, height = prc->bottom - prc->top;
CUIFBitmapDC::s_phdcDst->SetDIB(width, height, 1, 32);
CUIFBitmapDC::s_phdcMask->SetBitmap(hbmMask);
CUIFBitmapDC::s_phdcSrc->SetDIB(width, height, 1, 32);
RECT rc = { 0, 0, width, height };
::FillRect(*CUIFBitmapDC::s_phdcDst, &rc, hbr1);
HBRUSH hbrWhite = (HBRUSH)GetStockObject(WHITE_BRUSH);
::FillRect(*CUIFBitmapDC::s_phdcSrc, &rc, hbrWhite);
::BitBlt(*CUIFBitmapDC::s_phdcSrc, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCINVERT);
if (bPressed)
::BitBlt(*CUIFBitmapDC::s_phdcDst, 1, 1, width, height,
*CUIFBitmapDC::s_phdcSrc, 0, 0, SRCPAINT);
else
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height,
*CUIFBitmapDC::s_phdcSrc, 0, 0, SRCPAINT);
::FillRect(*CUIFBitmapDC::s_phdcSrc, &rc, hbr2);
::BitBlt(*CUIFBitmapDC::s_phdcSrc, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCPAINT);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCAND);
CUIFBitmapDC::s_phdcSrc->Uninit();
CUIFBitmapDC::s_phdcMask->Uninit();
CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
return CUIFBitmapDC::s_phdcDst->DetachBitmap();
}
HBITMAP
cicCreateShadowMaskBmp(LPRECT prc, HBITMAP hbm1, HBITMAP hbm2, HBRUSH hbr1, HBRUSH hbr2)
{
if (!CUIFBitmapDC::s_fInitBitmapDCs)
return NULL;
--prc->left;
--prc->top;
LONG width = prc->right - prc->left;
LONG height = prc->bottom - prc->top;
CUIFBitmapDC bitmapDC(TRUE);
CUIFBitmapDC::s_phdcDst->SetDIB(width, height, 1, 32);
CUIFBitmapDC::s_phdcSrc->SetBitmap(hbm1);
CUIFBitmapDC::s_phdcMask->SetBitmap(hbm2);
bitmapDC.SetDIB(width, height, 1, 32);
RECT rc = { 0, 0, width, height };
::FillRect(*CUIFBitmapDC::s_phdcDst, &rc, hbr1);
::FillRect(bitmapDC, &rc, hbr2);
::BitBlt(bitmapDC, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCPAINT);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 2, 2, width, height, bitmapDC, 0, 0, SRCAND);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCAND);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCINVERT);
CUIFBitmapDC::s_phdcSrc->Uninit();
CUIFBitmapDC::s_phdcMask->Uninit();
CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
return CUIFBitmapDC::s_phdcDst->DetachBitmap();
}
HBITMAP
cicChangeBitmapColor(LPCRECT prc, HBITMAP hbm, COLORREF rgbBack, COLORREF rgbFore)
{
if (!CUIFBitmapDC::s_fInitBitmapDCs)
return NULL;
INT width = prc->right - prc->left;
INT height = prc->bottom - prc->top;
CUIFSolidBrush brush(rgbFore);
CUIFBitmapDC::s_phdcDst->SetDIB(width, height, 1, 32);
CUIFBitmapDC::s_phdcSrc->SetBitmap(hbm);
CUIFBitmapDC::s_phdcMask->SetBitmap(width, height, 1, 1);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCCOPY);
::SelectObject(*CUIFBitmapDC::s_phdcDst, (HBRUSH)brush);
::SetBkColor(*CUIFBitmapDC::s_phdcDst, rgbBack);
::BitBlt(*CUIFBitmapDC::s_phdcMask, 0, 0, width, height, *CUIFBitmapDC::s_phdcDst, 0, 0, MERGECOPY);
::SetBkColor(*CUIFBitmapDC::s_phdcDst, RGB(255, 255, 255));
::SetTextColor(*CUIFBitmapDC::s_phdcDst, RGB(0, 0, 0));
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, 0xE20746u);
CUIFBitmapDC::s_phdcSrc->Uninit();
CUIFBitmapDC::s_phdcMask->Uninit();
CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
return CUIFBitmapDC::s_phdcDst->DetachBitmap();
}
HBITMAP
cicConvertBlackBKGBitmap(LPCRECT prc, HBITMAP hbm1, HBITMAP hbm2, HBRUSH hBrush)
{
if (!CUIFBitmapDC::s_fInitBitmapDCs)
return NULL;
if (IS_INTRESOURCE(hBrush))
hBrush = ::GetSysColorBrush(HandleToLong(hBrush) - 1);
LOGBRUSH lb;
::GetObject(hBrush, sizeof(lb), &lb);
if (lb.lbStyle || lb.lbColor)
return NULL;
INT width = prc->right - prc->left;
INT height = prc->bottom - prc->top;
HBITMAP hBitmap = cicChangeBitmapColor(prc, hbm1, 0, RGB(255, 255, 255));
if ( !hBitmap )
return NULL;
CUIFBitmapDC::s_phdcDst->SetDIB(width, height, 1, 32);
CUIFBitmapDC::s_phdcSrc->SetBitmap(hBitmap);
CUIFBitmapDC::s_phdcMask->SetBitmap(hbm2);
RECT rc = { 0, 0, width, height };
HBRUSH hbrWhite = (HBRUSH)GetStockObject(WHITE_BRUSH);
::FillRect(*CUIFBitmapDC::s_phdcDst, &rc, hbrWhite);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, 0x660046u);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcSrc, 0, 0, 0x8800C6u);
CUIFBitmapDC::s_phdcSrc->Uninit();
CUIFBitmapDC::s_phdcMask->Uninit();
CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
::DeleteObject(hBitmap);
return CUIFBitmapDC::s_phdcDst->DetachBitmap();
}
HBITMAP
cicCreateMaskBmp(LPCRECT prc, HBITMAP hbm1, HBITMAP hbm2,
HBRUSH hbr, COLORREF rgbColor, COLORREF rgbBack)
{
if (!CUIFBitmapDC::s_fInitBitmapDCs)
return NULL;
INT width = prc->right - prc->left;
INT height = prc->bottom - prc->top;
HBITMAP hBitmap = cicConvertBlackBKGBitmap(prc, hbm1, hbm2, hbr);
if (hBitmap)
return hBitmap;
CUIFBitmapDC::s_phdcDst->SetDIB(width, height, 1, 32);
CUIFBitmapDC::s_phdcSrc->SetBitmap(hbm1);
CUIFBitmapDC::s_phdcMask->SetBitmap(hbm2);
RECT rc = { 0, 0, width, height };
COLORREF OldTextColor = ::SetTextColor(*CUIFBitmapDC::s_phdcDst, rgbColor);
COLORREF OldBkColor = ::SetBkColor(*CUIFBitmapDC::s_phdcDst, rgbBack);
::FillRect(*CUIFBitmapDC::s_phdcDst, &rc, hbr);
::SetTextColor(*CUIFBitmapDC::s_phdcDst, OldTextColor);
::SetBkColor(*CUIFBitmapDC::s_phdcDst, OldBkColor);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCAND);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCINVERT);
CUIFBitmapDC::s_phdcSrc->Uninit();
CUIFBitmapDC::s_phdcMask->Uninit();
CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
return CUIFBitmapDC::s_phdcDst->DetachBitmap();
}
BOOL cicGetIconBitmaps(HICON hIcon, HBITMAP *hbm1, HBITMAP *hbm2, const SIZE *pSize)
{
if (!CUIFBitmapDC::s_fInitBitmapDCs)
return FALSE;
SIZE size;
if (pSize)
{
size = *pSize;
}
else
{
if (!cicGetIconSize(hIcon, &size))
return FALSE;
}
CUIFBitmapDC::s_phdcSrc->SetDIB(size.cx, size.cy, 1, 32);
CUIFBitmapDC::s_phdcMask->SetBitmap(size.cx, size.cy, 1, 1);
RECT rc = { 0, 0, size.cx, size.cy };
::FillRect(*CUIFBitmapDC::s_phdcSrc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
::DrawIconEx(*CUIFBitmapDC::s_phdcSrc, 0, 0, hIcon, size.cx, size.cy, 0, 0, DI_NORMAL);
::DrawIconEx(*CUIFBitmapDC::s_phdcMask, 0, 0, hIcon, size.cx, size.cy, 0, 0, DI_MASK);
CUIFBitmapDC::s_phdcSrc->Uninit(TRUE);
CUIFBitmapDC::s_phdcMask->Uninit(TRUE);
*hbm1 = CUIFBitmapDC::s_phdcSrc->DetachBitmap();
*hbm2 = CUIFBitmapDC::s_phdcMask->DetachBitmap();
return TRUE;
}
void cicDrawMaskBmpOnDC(HDC hDC, LPCRECT prc, HBITMAP hbmp, HBITMAP hbmpMask)
{
if (!CUIFBitmapDC::s_fInitBitmapDCs)
return;
LONG cx = prc->right - prc->left, cy = prc->bottom - prc->top;
CUIFBitmapDC::s_phdcDst->SetDIB(cx, cy, 1, 32);
CUIFBitmapDC::s_phdcSrc->SetBitmap(hbmp);
CUIFBitmapDC::s_phdcMask->SetBitmap(hbmpMask);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, cx, cy, hDC, prc->left, prc->top, SRCCOPY);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, cx, cy, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCAND);
::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, cx, cy, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCINVERT);
::BitBlt(hDC, prc->left, prc->top, cx, cy, *CUIFBitmapDC::s_phdcDst, 0, 0, SRCCOPY);
CUIFBitmapDC::s_phdcSrc->Uninit(FALSE);
CUIFBitmapDC::s_phdcMask->Uninit(FALSE);
CUIFBitmapDC::s_phdcDst->Uninit(FALSE);
}
/////////////////////////////////////////////////////////////////////////////
// CUIFWindow
CUIFWindow::CUIFWindow(HINSTANCE hInst, DWORD style)
: CUIFObject(NULL, 0, NULL, style)
{
m_hInst = hInst;
m_nLeft = 200;
m_nTop = 200;
m_nWidth = 200;
m_nHeight = 200;
m_hWnd = 0;
m_pWindow = this;
m_pCaptured = NULL;
m_pTimerObject = NULL;
m_pPointed = NULL;
m_bPointing = FALSE;
m_pToolTip = NULL;
m_pShadow = NULL;
m_bShowShadow = TRUE;
m_pBehindModal = NULL;
CUIFWindow::CreateScheme();
}
CUIFWindow::~CUIFWindow()
{
if (m_pToolTip)
{
delete m_pToolTip;
m_pToolTip = NULL;
}
if (m_pShadow)
{
delete m_pShadow;
m_pShadow = NULL;
}
for (size_t i = m_ObjectArray.size(); i > 0; )
{
--i;
CUIFObject *pObject = m_ObjectArray[i];
m_ObjectArray[i] = NULL;
m_ObjectArray.Remove(pObject);
delete pObject;
}
if (m_pScheme)
{
delete m_pScheme;
m_pScheme = NULL;
}
}
STDMETHODIMP_(BOOL)
CUIFWindow::Initialize()
{
LPCTSTR pszClass = GetClassName();
WNDCLASSEX wcx;
ZeroMemory(&wcx, sizeof(wcx));
wcx.cbSize = sizeof(WNDCLASSEXW);
if (!::GetClassInfoEx(m_hInst, pszClass, &wcx))
{
ZeroMemory(&wcx, sizeof(wcx));
wcx.cbSize = sizeof(wcx);
wcx.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcx.lpfnWndProc = CUIFWindow::WindowProcedure;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = sizeof(LONG_PTR) * 2;
wcx.hInstance = m_hInst;
wcx.hIcon = NULL;
wcx.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wcx.lpszClassName = pszClass;
wcx.hbrBackground = NULL;
wcx.lpszMenuName = NULL;
wcx.hIconSm = NULL;
::RegisterClassEx(&wcx);
}
cicUpdateUIFSys();
cicUpdateUIFScheme();
if (m_style & UIF_WINDOW_TOOLTIP)
{
DWORD style = (m_style & UIF_WINDOW_LAYOUTRTL) | UIF_WINDOW_TOPMOST | 0x10;
m_pToolTip = new(cicNoThrow) CUIFToolTip(m_hInst, style, this);
if (m_pToolTip)
m_pToolTip->Initialize();
}
if (m_style & UIF_WINDOW_SHADOW)
{
m_pShadow = new(cicNoThrow) CUIFShadow(m_hInst, UIF_WINDOW_TOPMOST, this);
if (m_pShadow)
m_pShadow->Initialize();
}
return CUIFObject::Initialize();
}
STDMETHODIMP_(LRESULT)
CUIFWindow::OnSettingChange(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
void CUIFWindow::UpdateUI(LPCRECT prc)
{
if (::IsWindow(m_hWnd))
::InvalidateRect(m_hWnd, prc, FALSE);
}
CUIFWindow*
CUIFWindow::GetThis(HWND hWnd)
{
return (CUIFWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
}
void
CUIFWindow::SetThis(HWND hWnd, LONG_PTR dwNewLong)
{
::SetWindowLongPtr(hWnd, GWLP_USERDATA, dwNewLong);
}
void CUIFWindow::CreateScheme()
{
if (m_pScheme)
{
delete m_pScheme;
m_pScheme = NULL;
}
INT iScheme = 0;
if (m_style & UIF_WINDOW_USESCHEME1)
iScheme = 1;
else if (m_style & UIF_WINDOW_USESCHEME2)
iScheme = 2;
else if (m_style & UIF_WINDOW_USESCHEME3)
iScheme = 3;
m_pScheme = cicCreateUIFScheme(iScheme);
SetScheme(m_pScheme);
}
STDMETHODIMP_(DWORD)
CUIFWindow::GetWndStyle()
{
DWORD ret;
if (m_style & UIF_WINDOW_CHILD)
ret = WS_CHILD | WS_CLIPSIBLINGS;
else
ret = WS_POPUP | WS_DISABLED;
if (m_style & UIF_WINDOW_USESCHEME1)
ret |= WS_BORDER;
else if (m_style & UIF_WINDOW_DLGFRAME)
ret |= WS_DLGFRAME;
else if ((m_style & UIF_WINDOW_USESCHEME2) || (m_style & 0x10))
ret |= WS_BORDER;
return ret;
}
STDMETHODIMP_(DWORD)
CUIFWindow::GetWndStyleEx()
{
DWORD ret = 0;
if (m_style & UIF_WINDOW_TOPMOST)
ret |= WS_EX_TOPMOST;
if (m_style & UIF_WINDOW_TOOLWINDOW)
ret |= WS_EX_TOOLWINDOW;
if (m_style & UIF_WINDOW_LAYOUTRTL)
ret |= WS_EX_LAYOUTRTL;
return ret;
}
STDMETHODIMP_(HWND)
CUIFWindow::CreateWnd(HWND hwndParent)
{
HWND hWnd = CreateWindowEx(GetWndStyleEx(), GetClassName(), GetWndTitle(), GetWndStyle(),
m_nLeft, m_nTop, m_nWidth, m_nHeight,
hwndParent, NULL, m_hInst, this);
if (m_pToolTip)
m_pToolTip->CreateWnd(hWnd);
if (m_pShadow)
m_pShadow->CreateWnd(hWnd);
return hWnd;
}
void CUIFWindow::Show(BOOL bVisible)
{
if (!IsWindow(m_hWnd))
return;
if (bVisible && (m_style & UIF_WINDOW_TOPMOST))
::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
m_bVisible = bVisible;
::ShowWindow(m_hWnd, (bVisible ? SW_SHOWNOACTIVATE : 0));
}
STDMETHODIMP_(BOOL)
CUIFWindow::AnimateWnd(DWORD dwTime, DWORD dwFlags)
{
if (!::IsWindow(m_hWnd))
return FALSE;
BOOL bVisible = !(dwFlags & 0x10000);
OnAnimationStart();
BOOL ret = ::AnimateWindow(m_hWnd, dwTime, dwFlags);
if (!ret)
m_bVisible = bVisible;
OnAnimationEnd();
return ret;
}
void CUIFWindow::SetCaptureObject(CUIFObject *pCaptured)
{
if (pCaptured)
{
m_pCaptured = pCaptured;
SetCapture(TRUE);
}
else
{
m_pCaptured = NULL;
SetCapture(FALSE);
}
}
STDMETHODIMP_(void)
CUIFWindow::SetCapture(BOOL bSet)
{
if (bSet)
::SetCapture(m_hWnd);
else
::ReleaseCapture();
}
void CUIFWindow::SetObjectPointed(CUIFObject *pPointed, POINT pt)
{
if (pPointed == m_pPointed)
return;
if (m_pCaptured)
{
if (m_pCaptured == m_pPointed && m_pPointed->m_bEnable)
m_pPointed->OnMouseOut(pt.x, pt.y);
}
else if (m_pPointed && m_pPointed->m_bEnable)
{
m_pPointed->OnMouseOut(pt.x, pt.y);
}
m_pPointed = pPointed;
if (m_pCaptured)
{
if (m_pCaptured == m_pPointed && m_pPointed->m_bEnable)
m_pPointed->OnMouseIn(pt.x, pt.y);
}
else if (m_pPointed && m_pPointed->m_bEnable)
{
m_pPointed->OnMouseIn(pt.x, pt.y);
}
}
STDMETHODIMP_(void)
CUIFWindow::OnObjectMoved(CUIFObject *pObject)
{
if (!::IsWindow(m_hWnd))
return;
POINT pt;
::GetCursorPos(&pt);
::ScreenToClient(m_hWnd, &pt);
POINT pt2 = pt;
CUIFObject *pFound = ObjectFromPoint(pt);
SetObjectPointed(pFound, pt2);
}
STDMETHODIMP_(void)
CUIFWindow::SetRect(LPCRECT prc)
{
RECT Rect = { 0, 0, 0, 0 };
if (::IsWindow(m_hWnd))
::GetClientRect(m_hWnd, &Rect);
CUIFObject::SetRect(&Rect);
}
STDMETHODIMP_(void)
CUIFWindow::ClientRectToWindowRect(LPRECT lpRect)
{
DWORD style, exstyle;
if (::IsWindow(m_hWnd))
{
style = ::GetWindowLongPtr(m_hWnd, GWL_STYLE);
exstyle = ::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
}
else
{
style = GetWndStyle();
exstyle = GetWndStyleEx();
}
::AdjustWindowRectEx(lpRect, style, FALSE, exstyle);
}
STDMETHODIMP_(void)
CUIFWindow::GetWindowFrameSize(LPSIZE pSize)
{
RECT rc = { 0, 0, 0, 0 };
ClientRectToWindowRect(&rc);
pSize->cx = (rc.right - rc.left) / 2;
pSize->cy = (rc.bottom - rc.top) / 2;
}
STDMETHODIMP_(void)
CUIFWindow::OnAnimationEnd()
{
if (m_pShadow && m_bShowShadow)
m_pShadow->Show(m_bVisible);
}
STDMETHODIMP_(void)
CUIFWindow::OnThemeChanged(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
ClearTheme();
}
LRESULT
CUIFWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_GETOBJECT:
return OnGetObject(hWnd, WM_GETOBJECT, wParam, lParam);
case WM_SYSCOLORCHANGE:
cicUpdateUIFScheme();
OnSysColorChange();
return 0;
case WM_ENDSESSION:
OnEndSession(hWnd, wParam, lParam);
return 0;
case WM_SHOWWINDOW:
if (m_pShadow && m_bShowShadow)
m_pShadow->Show(wParam);
return OnShowWindow(hWnd, WM_SHOWWINDOW, wParam, lParam);
case WM_SETTINGCHANGE:
cicUpdateUIFSys();
cicUpdateUIFScheme();
return OnSettingChange(hWnd, WM_SETTINGCHANGE, wParam, lParam);
case WM_SETCURSOR:
{
POINT Point;
::GetCursorPos(&Point);
::ScreenToClient(m_hWnd, &Point);
if (m_pBehindModal)
{
m_pBehindModal->ModalMouseNotify(HIWORD(lParam), Point.x, Point.y);
return TRUE;
}
if (!m_bPointing)
{
::SetTimer(m_hWnd, POINTING_TIMER_ID, 1000, NULL);
m_bPointing = TRUE;
}
if (m_pToolTip)
{
MSG msg = { m_hWnd, HIWORD(lParam), 0, MAKELPARAM(Point.x, Point.y) };
m_pToolTip->RelayEvent(&msg);
}
if (!(m_style & UIF_WINDOW_NOMOUSEMSG))
HandleMouseMsg(HIWORD(lParam), Point.x, Point.y);
return TRUE;
}
case WM_MOUSEACTIVATE:
return MA_NOACTIVATE;
case WM_ERASEBKGND:
return OnEraseBkGnd(hWnd, WM_ERASEBKGND, wParam, lParam);
case WM_CREATE:
SetRect(NULL);
OnCreate(hWnd);
return 0;
case WM_DESTROY:
if (m_pToolTip && ::IsWindow(*m_pToolTip))
::DestroyWindow(*m_pToolTip);
if (m_pShadow && ::IsWindow(*m_pShadow))
::DestroyWindow(*m_pShadow);
OnDestroy(hWnd);
return 0;
case WM_SIZE:
SetRect(NULL);
return 0;
case WM_ACTIVATE:
return OnActivate(hWnd, WM_ACTIVATE, wParam, lParam);
case WM_SETFOCUS:
OnSetFocus(hWnd);
return 0;
case WM_KILLFOCUS:
OnKillFocus(hWnd);
return 0;
case WM_PAINT:
{
PAINTSTRUCT Paint;
HDC hDC = ::BeginPaint(hWnd, &Paint);
PaintObject(hDC, &Paint.rcPaint);
::EndPaint(hWnd, &Paint);
return 0;
}
case WM_PRINTCLIENT:
{
PaintObject((HDC)wParam, NULL);
return 0;
}
case WM_THEMECHANGED:
{
OnThemeChanged(hWnd, wParam, lParam);
return 0;
}
case WM_COMMAND:
{
return 0;
}
case WM_TIMER:
{
switch (wParam)
{
case USER_TIMER_ID:
{
if (m_pTimerObject)
m_pTimerObject->OnTimer();
break;
}
case POINTING_TIMER_ID:
{
POINT pt;
::GetCursorPos(&pt);
POINT pt2 = pt;
::ScreenToClient(m_hWnd, &pt2);
RECT rc;
::GetWindowRect(m_hWnd, &rc);
if (::PtInRect(&rc, pt) && ::WindowFromPoint(pt) == m_hWnd)
{
m_pBehindModal->ModalMouseNotify(WM_MOUSEMOVE, pt2.x, pt2.y);
}
else
{
::KillTimer(m_hWnd, POINTING_TIMER_ID);
m_bPointing = FALSE;
SetObjectPointed(NULL, pt2);
OnMouseOutFromWindow(pt2.x, pt2.y);
}
if (m_pToolTip)
{
MSG msg = { m_hWnd, WM_MOUSEMOVE, 0, MAKELPARAM(pt2.x, pt2.y) };
m_pToolTip->RelayEvent(&msg);
}
break;
}
default:
{
OnTimer(wParam);
break;
}
}
break;
}
case WM_MOUSEMOVE:
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK:
case WM_MBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
case WM_RBUTTONUP:
{
if (m_pBehindModal)
m_pBehindModal->ModalMouseNotify(uMsg, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
else
HandleMouseMsg(uMsg, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
break;
}
case WM_KEYUP:
{
OnKeyUp(hWnd, wParam, lParam);
break;
}
case WM_WINDOWPOSCHANGING:
{
WINDOWPOS *pwp = (WINDOWPOS *)lParam;
if (m_pShadow && (pwp->flags & SWP_HIDEWINDOW))
m_pShadow->Show(FALSE);
if (!(pwp->flags & SWP_NOZORDER) && pwp->hwndInsertAfter == m_pShadow->m_hWnd)
pwp->flags |= SWP_NOZORDER;
m_pShadow->OnOwnerWndMoved(!(pwp->flags & SWP_NOSIZE));
return OnWindowPosChanging(hWnd, WM_WINDOWPOSCHANGING, wParam, lParam);
}
case WM_WINDOWPOSCHANGED:
{
WINDOWPOS *pwp = (WINDOWPOS *)lParam;
if (m_pShadow)
m_pShadow->OnOwnerWndMoved(!(pwp->flags & SWP_NOSIZE));
return OnWindowPosChanged(hWnd, WM_WINDOWPOSCHANGED, wParam, lParam);
}
case WM_NOTIFY:
OnNotify(hWnd, wParam, lParam);
return 0;
case WM_NOTIFYFORMAT:
return OnNotifyFormat(hWnd, wParam, lParam);
case WM_DISPLAYCHANGE:
cicUpdateUIFSys();
cicUpdateUIFScheme();
return OnDisplayChange(hWnd, WM_DISPLAYCHANGE, wParam, lParam);
case WM_NCDESTROY:
OnNCDestroy(hWnd);
return 0;
case WM_KEYDOWN:
OnKeyDown(hWnd, wParam, lParam);
return 0;
default:
{
if (uMsg >= WM_USER)
{
CUIFWindow *pThis = CUIFWindow::GetThis(hWnd);
pThis->OnUser(hWnd, uMsg, wParam, lParam);
break;
}
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
return 0;
}
LRESULT CALLBACK
CUIFWindow::WindowProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CUIFWindow *This;
if (uMsg == WM_NCCREATE)
{
This = (CUIFWindow*)((CREATESTRUCT*)lParam)->lpCreateParams;
CUIFWindow::SetThis(hWnd, (LONG_PTR)This);
This->m_hWnd = hWnd;
}
else
{
This = CUIFWindow::GetThis(hWnd);
}
if (uMsg == WM_GETMINMAXINFO)
{
if (This)
return This->WindowProc(hWnd, uMsg, wParam, lParam);
else
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
if (!This)
return 0;
if (uMsg == WM_NCDESTROY)
{
This->m_hWnd = NULL;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, 0);
}
return This->WindowProc(hWnd, uMsg, wParam, lParam);
}
BOOL
CUIFWindow::GetWorkArea(LPCRECT prcWnd, LPRECT prcWorkArea)
{
if (!(m_style & (UIF_WINDOW_WORKAREA | UIF_WINDOW_MONITOR)))
return FALSE;
HMONITOR hMon = ::MonitorFromRect(prcWnd, MONITOR_DEFAULTTONEAREST);
MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
if (!hMon || !::GetMonitorInfo(hMon, &mi))
{
if (m_style & UIF_WINDOW_WORKAREA)
return ::SystemParametersInfo(SPI_GETWORKAREA, 0, prcWorkArea, 0);
prcWorkArea->left = prcWorkArea->top = 0;
prcWorkArea->right = ::GetSystemMetrics(SM_CXSCREEN);
prcWorkArea->bottom = ::GetSystemMetrics(SM_CYSCREEN);
return TRUE;
}
if (m_style & UIF_WINDOW_WORKAREA)
{
*prcWorkArea = mi.rcWork;
return TRUE;
}
*prcWorkArea = mi.rcMonitor;
return TRUE;
}
void
CUIFWindow::AdjustWindowPosition()
{
RECT rc;
rc.left = m_nLeft;
rc.right = m_nLeft + m_nWidth;
rc.top = m_nTop;
rc.bottom = m_nTop + m_nHeight;
RECT rcWorkArea;
if (!GetWorkArea(&rc, &rcWorkArea))
return;
if (m_nLeft < rcWorkArea.left)
m_nLeft = rcWorkArea.left;
if (m_nTop < rcWorkArea.top)
m_nTop = rcWorkArea.top;
if (m_nLeft + m_nWidth >= rcWorkArea.right)
m_nLeft = rcWorkArea.right - m_nWidth;
if (m_nTop + m_nHeight >= rcWorkArea.bottom)
m_nTop = rcWorkArea.bottom - m_nHeight;
}
void CUIFWindow::SetBehindModal(CUIFWindow *pBehindModal)
{
m_pBehindModal = pBehindModal;
}
void CUIFWindow::SetTimerObject(CUIFObject *pTimerObject, UINT uElapse)
{
if (pTimerObject)
{
m_pTimerObject = pTimerObject;
::SetTimer(m_hWnd, USER_TIMER_ID, uElapse, NULL);
}
else
{
m_pTimerObject = NULL;
::KillTimer(m_hWnd, USER_TIMER_ID);
}
}
STDMETHODIMP_(void)
CUIFWindow::PaintObject(HDC hDC, LPCRECT prc)
{
BOOL bGotDC = FALSE;
if (!hDC)
{
hDC = ::GetDC(m_hWnd);
bGotDC = TRUE;
}
if (!prc)
prc = &m_rc;
HDC hMemDC = ::CreateCompatibleDC(hDC);
HBITMAP hbmMem = ::CreateCompatibleBitmap(hDC, prc->right - prc->left, prc->bottom - prc->top);
HGDIOBJ hbmOld = ::SelectObject(hMemDC, hbmMem);
::SetViewportOrgEx(hMemDC, -prc->left, -prc->top, NULL);
if (FAILED(EnsureThemeData(m_hWnd)) ||
((!(m_style & UIF_WINDOW_CHILD) || FAILED(DrawThemeParentBackground(m_hWnd, hMemDC, &m_rc))) &&
FAILED(DrawThemeBackground(hMemDC, m_iStateId, &m_rc, NULL))))
{
if (m_pScheme)
m_pScheme->FillRect(hMemDC, prc, 22);
}
CUIFObject::PaintObject(hMemDC, prc);
::BitBlt(hDC, prc->left, prc->top,
prc->right - prc->left, prc->bottom - prc->top,
hMemDC, prc->left, prc->top, SRCCOPY);
::SelectObject(hMemDC, hbmOld);
::DeleteObject(hbmMem);
::DeleteDC(hMemDC);
if (bGotDC)
::ReleaseDC(m_hWnd, hDC);
}
STDMETHODIMP_(void)
CUIFWindow::Move(INT x, INT y, INT nWidth, INT nHeight)
{
m_nLeft = x;
m_nTop = y;
if (nWidth >= 0)
m_nWidth = nWidth;
if (nHeight >= 0)
m_nHeight = nHeight;
if (::IsWindow(m_hWnd))
{
AdjustWindowPosition();
::MoveWindow(m_hWnd, m_nLeft, m_nTop, m_nWidth, m_nHeight, TRUE);
}
}
STDMETHODIMP_(void)
CUIFWindow::RemoveUIObj(CUIFObject *pRemove)
{
if (pRemove == m_pCaptured)
SetCaptureObject(NULL);
if (pRemove == m_pTimerObject)
{
m_pTimerObject = NULL;
::KillTimer(m_hWnd, USER_TIMER_ID);
}
if (pRemove == m_pPointed)
m_pPointed = NULL;
CUIFObject::RemoveUIObj(pRemove);
}
STDMETHODIMP_(void)
CUIFWindow::HandleMouseMsg(UINT uMsg, LONG x, LONG y)
{
POINT pt = { x, y };
CUIFObject *pFound = (CUIFWindow *)ObjectFromPoint(pt);
SetObjectPointed(pFound, pt);
if (m_pCaptured)
pFound = m_pCaptured;
if (!pFound || OnSetCursor(uMsg, pt.x, pt.y))
{
HCURSOR hCursor = ::LoadCursor(NULL, IDC_ARROW);
::SetCursor(hCursor);
}
if (pFound && pFound->m_bEnable)
{
switch (uMsg)
{
case WM_MOUSEMOVE:
pFound->OnMouseMove(pt.x, pt.y);
break;
case WM_LBUTTONDOWN:
pFound->OnLButtonDown(pt.x, pt.y);
break;
case WM_LBUTTONUP:
pFound->OnLButtonUp(pt.x, pt.y);
break;
case WM_RBUTTONDOWN:
pFound->OnRButtonDown(pt.x, pt.y);
break;
case WM_RBUTTONUP:
pFound->OnRButtonUp(pt.x, pt.y);
break;
case WM_MBUTTONDOWN:
pFound->OnMButtonDown(pt.x, pt.y);
break;
case WM_MBUTTONUP:
pFound->OnMButtonUp(pt.x, pt.y);
break;
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CUIFShadow
/// @unimplemented
CUIFShadow::CUIFShadow(HINSTANCE hInst, DWORD style, CUIFWindow *pShadowOwner)
: CUIFWindow(hInst, (style | UIF_WINDOW_TOOLWINDOW))
{
m_pShadowOwner = pShadowOwner;
m_rgbShadowColor = RGB(0, 0, 0);
m_dwUnknown11[0] = 0;
m_dwUnknown11[1] = 0;
m_xShadowDelta = m_yShadowDelta = 0;
m_bLayerAvailable = FALSE;
}
CUIFShadow::~CUIFShadow()
{
if (m_pShadowOwner)
m_pShadowOwner->m_pShadow = NULL;
}
/// @unimplemented
void CUIFShadow::InitSettings()
{
m_bLayerAvailable = FALSE;
m_rgbShadowColor = RGB(128, 128, 128);
m_xShadowDelta = m_yShadowDelta = 2;
}
/// @unimplemented
void CUIFShadow::InitShadow()
{
if (m_bLayerAvailable)
{
//FIXME
}
}
void CUIFShadow::AdjustWindowPos()
{
HWND hwndOwner = *m_pShadowOwner;
if (!::IsWindow(m_hWnd))
return;
RECT rc;
::GetWindowRect(hwndOwner, &rc);
::SetWindowPos(m_hWnd, hwndOwner,
rc.left + m_xShadowDelta,
rc.top + m_yShadowDelta,
rc.right - rc.left,
rc.bottom - rc.top,
SWP_NOOWNERZORDER | SWP_NOACTIVATE);
}
void CUIFShadow::OnOwnerWndMoved(BOOL bDoSize)
{
if (::IsWindow(m_hWnd) && ::IsWindowVisible(m_hWnd))
{
AdjustWindowPos();
if (bDoSize)
InitShadow();
}
}
STDMETHODIMP_(BOOL)
CUIFShadow::Initialize()
{
InitSettings();
return CUIFWindow::Initialize();
}
STDMETHODIMP_(DWORD)
CUIFShadow::GetWndStyleEx()
{
DWORD exstyle = CUIFWindow::GetWndStyleEx();
if (m_bLayerAvailable)
exstyle |= WS_EX_LAYERED;
return exstyle;
}
STDMETHODIMP_(void)
CUIFShadow::OnPaint(HDC hDC)
{
RECT rc = m_rc;
HBRUSH hBrush = ::CreateSolidBrush(m_rgbShadowColor);
::FillRect(hDC, &rc, hBrush);
::DeleteObject(hBrush);
}
STDMETHODIMP_(LRESULT)
CUIFShadow::OnWindowPosChanging(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
WINDOWPOS *wp = (WINDOWPOS *)lParam;
wp->hwndInsertAfter = *m_pShadowOwner;
return ::DefWindowProc(hWnd, Msg, wParam, lParam);
}
STDMETHODIMP_(LRESULT)
CUIFShadow::OnSettingChange(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
InitSettings();
DWORD exstyle;
if (m_bLayerAvailable)
exstyle = ::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED;
else
exstyle = ::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) & ~WS_EX_LAYERED;
::SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, exstyle);
AdjustWindowPos();
InitShadow();
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
STDMETHODIMP_(void)
CUIFShadow::Show(BOOL bVisible)
{
if (bVisible && ::IsWindow(m_hWnd) && !::IsWindowVisible(m_hWnd))
{
AdjustWindowPos();
InitShadow();
}
if (::IsWindow(m_hWnd))
{
m_bVisible = bVisible;
::ShowWindow(m_hWnd, (bVisible ? SW_SHOWNOACTIVATE : SW_HIDE));
}
}
/////////////////////////////////////////////////////////////////////////////
// CUIFToolTip
CUIFToolTip::CUIFToolTip(HINSTANCE hInst, DWORD style, CUIFWindow *pToolTipOwner)
: CUIFWindow(hInst, style)
{
m_pToolTipOwner = pToolTipOwner;
m_rcToolTipMargin.left = 2;
m_rcToolTipMargin.top = 2;
m_rcToolTipMargin.right = 2;
m_rcToolTipMargin.bottom = 2;
m_pToolTipTarget = NULL;
m_pszToolTipText = NULL;
m_dwUnknown10 = 0; //FIXME: name and type
m_nDelayTimeType2 = -1;
m_nDelayTimeType3 = -1;
m_nDelayTimeType1 = -1;
m_cxToolTipWidth = -1;
m_bToolTipHasBkColor = 0;
m_bToolTipHasTextColor = 0;
m_rgbToolTipBkColor = 0;
m_rgbToolTipTextColor = 0;
}
CUIFToolTip::~CUIFToolTip()
{
if (m_pToolTipOwner)
m_pToolTipOwner->m_pToolTip = NULL;
if (m_pszToolTipText)
delete[] m_pszToolTipText;
}
LONG
CUIFToolTip::GetDelayTime(UINT uType)
{
LONG nDelayTime;
switch (uType)
{
case 1:
{
nDelayTime = m_nDelayTimeType1;
if (nDelayTime == -1)
return ::GetDoubleClickTime() / 5;
return nDelayTime;
}
case 2:
{
nDelayTime = m_nDelayTimeType2;
if (nDelayTime == -1)
return 10 * ::GetDoubleClickTime();
return nDelayTime;
}
case 3:
{
nDelayTime = m_nDelayTimeType3;
if (nDelayTime == -1)
return ::GetDoubleClickTime();
return nDelayTime;
}
default:
{
return 0;
}
}
}
void CUIFToolTip::GetMargin(LPRECT prc)
{
if (prc)
*prc = m_rcToolTipMargin;
}
COLORREF
CUIFToolTip::GetTipBkColor()
{
if (m_bToolTipHasBkColor)
return m_rgbToolTipBkColor;
return ::GetSysColor(COLOR_INFOBK);
}
COLORREF
CUIFToolTip::GetTipTextColor()
{
if (m_bToolTipHasTextColor)
return m_rgbToolTipTextColor;
return ::GetSysColor(COLOR_INFOTEXT);
}
CUIFObject*
CUIFToolTip::FindObject(HWND hWnd, POINT pt)
{
if (hWnd == *m_pToolTipOwner)
return m_pToolTipOwner->ObjectFromPoint(pt);
return NULL;
}
void
CUIFToolTip::ShowTip()
{
::KillTimer(m_hWnd, TOOLTIP_TIMER_ID);
if (!m_pToolTipTarget)
return;
LPCWSTR pszText = m_pToolTipTarget->GetToolTip();
if (!pszText)
return;
if (!m_pToolTipTarget || m_pToolTipTarget->OnShowToolTip())
return;
POINT Point;
::GetCursorPos(&Point);
::ScreenToClient(*m_pToolTipTarget->m_pWindow, &Point);
RECT rc;
m_pToolTipTarget->GetRect(&rc);
if (!::PtInRect(&rc, Point))
return;
size_t cchText = wcslen(pszText);
m_pszToolTipText = new(cicNoThrow) WCHAR[cchText + 1];
if (!m_pszToolTipText)
return;
lstrcpynW(m_pszToolTipText, pszText, cchText + 1);
SIZE size;
GetTipWindowSize(&size);
RECT rc2 = rc;
::ClientToScreen(*m_pToolTipTarget->m_pWindow, (LPPOINT)&rc);
::ClientToScreen(*m_pToolTipTarget->m_pWindow, (LPPOINT)&rc.right);
GetTipWindowRect(&rc2, size, &rc);
m_bShowToolTip = TRUE;
Move(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
Show(TRUE);
}
void
CUIFToolTip::HideTip()
{
::KillTimer(m_hWnd, TOOLTIP_TIMER_ID);
m_bShowToolTip = FALSE;
if (m_pToolTipTarget)
m_pToolTipTarget->OnHideToolTip();
if (m_bVisible)
{
if (m_pszToolTipText)
{
delete[] m_pszToolTipText;
m_pszToolTipText = NULL;
}
Show(FALSE);
}
}
void
CUIFToolTip::GetTipWindowSize(LPSIZE pSize)
{
if (!m_pszToolTipText)
return;
HDC hDC = ::GetDC(m_hWnd);
HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
RECT rcText = { 0, 0, 0, 0 };
INT cyText;
if (m_cxToolTipWidth <= 0)
{
cyText = ::DrawTextW(hDC, m_pszToolTipText, -1, &rcText, DT_CALCRECT | DT_SINGLELINE);
}
else
{
rcText.right = m_cxToolTipWidth;
cyText = ::DrawTextW(hDC, m_pszToolTipText, -1, &rcText, DT_CALCRECT | DT_WORDBREAK);
}
RECT rcMargin;
GetMargin(&rcMargin);
RECT rc;
rc.left = rcText.left - rcMargin.left;
rc.top = rcText.top - rcMargin.top;
rc.right = rcText.right + rcMargin.right;
rc.bottom = rcText.top + cyText + rcMargin.bottom;
ClientRectToWindowRect(&rc);
pSize->cx = rc.right - rc.left;
pSize->cy = rc.bottom - rc.top;
::SelectObject(hDC, hFontOld);
::ReleaseDC(m_hWnd, hDC);
}
void
CUIFToolTip::GetTipWindowRect(LPRECT pRect, SIZE toolTipSize, LPCRECT prc)
{
POINT Point;
GetCursorPos(&Point);
HCURSOR hCursor = ::GetCursor();
ICONINFO IconInfo;
INT yHotspot = 0;
INT cyCursor = ::GetSystemMetrics(SM_CYCURSOR);
if (hCursor && ::GetIconInfo(hCursor, &IconInfo))
{
BITMAP bm;
::GetObject(IconInfo.hbmMask, sizeof(bm), &bm);
if (!IconInfo.fIcon)
{
cyCursor = bm.bmHeight;
yHotspot = IconInfo.yHotspot;
if (!IconInfo.hbmColor)
cyCursor = bm.bmHeight / 2;
}
if (IconInfo.hbmColor)
::DeleteObject(IconInfo.hbmColor);
if (IconInfo.hbmMask)
::DeleteObject(IconInfo.hbmMask);
}
RECT rcMonitor;
rcMonitor.left = 0;
rcMonitor.top = 0;
rcMonitor.right = GetSystemMetrics(SM_CXSCREEN);
rcMonitor.bottom = GetSystemMetrics(SM_CYSCREEN);
HMONITOR hMon = ::MonitorFromPoint(Point, MONITOR_DEFAULTTONEAREST);
MONITORINFO mi;
if (hMon)
{
mi.cbSize = sizeof(MONITORINFO);
if (::GetMonitorInfo(hMon, &mi))
rcMonitor = mi.rcMonitor;
}
pRect->left = Point.x;
pRect->right = pRect->left + toolTipSize.cx;
pRect->top = Point.y + cyCursor - yHotspot;
pRect->bottom = pRect->top + toolTipSize.cy;
if (rcMonitor.right < pRect->right)
{
pRect->left = rcMonitor.right - toolTipSize.cx;
pRect->right = rcMonitor.right;
}
if (pRect->left < rcMonitor.left)
{
pRect->left = rcMonitor.left;
pRect->right = rcMonitor.left + toolTipSize.cx;
}
if (rcMonitor.bottom < pRect->bottom)
{
pRect->top = rcMonitor.bottom - toolTipSize.cy;
pRect->bottom = rcMonitor.bottom;
}
if (pRect->top < rcMonitor.top)
{
pRect->top = rcMonitor.top;
pRect->bottom = rcMonitor.top + toolTipSize.cy;
}
}
void
CUIFToolTip::RelayEvent(LPMSG pMsg)
{
if (!pMsg)
return;
switch (pMsg->message)
{
case WM_MOUSEMOVE:
{
if (m_bEnable &&
::GetKeyState(VK_LBUTTON) >= 0 &&
::GetKeyState(VK_MBUTTON) >= 0 &&
::GetKeyState(VK_RBUTTON) >= 0)
{
POINT pt = { (SHORT)LOWORD(pMsg->lParam), (SHORT)HIWORD(pMsg->lParam) };
CUIFObject *pFound = CUIFToolTip::FindObject(pMsg->hwnd, pt);
if (pFound)
{
if (m_pToolTipTarget != pFound)
{
HideTip();
LONG DelayTime;
if (!m_bVisible)
DelayTime = GetDelayTime(3);
else
DelayTime = GetDelayTime(1);
::SetTimer(m_hWnd, TOOLTIP_TIMER_ID, DelayTime, NULL);
}
}
else
{
HideTip();
}
m_pToolTipTarget = pFound;
}
break;
}
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
{
HideTip();
break;
}
}
}
STDMETHODIMP_(void) CUIFToolTip::OnPaint(HDC hDC)
{
HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
INT iBkModeOld = ::SetBkMode(hDC, TRANSPARENT);
COLORREF rgbTextColor = GetTipTextColor();
COLORREF rgbOldTextColor = ::SetTextColor(hDC, rgbTextColor);
COLORREF rgbBkColor = GetTipBkColor();
HBRUSH hbrBack = ::CreateSolidBrush(rgbBkColor);
RECT rc = m_rc;
if (hbrBack)
{
::FillRect(hDC, &rc, hbrBack);
::DeleteObject(hbrBack);
}
RECT rcMargin;
GetMargin(&rcMargin);
rc.left += rcMargin.left;
rc.top += rcMargin.top;
rc.right -= rcMargin.right;
rc.bottom -= rcMargin.bottom;
if (m_cxToolTipWidth <= 0)
::DrawTextW(hDC, m_pszToolTipText, -1, &rc, DT_SINGLELINE);
else
::DrawTextW(hDC, m_pszToolTipText, -1, &rc, DT_WORDBREAK);
::SetTextColor(hDC, rgbOldTextColor);
::SetBkMode(hDC, iBkModeOld);
::SelectObject(hDC, hFontOld);
}
STDMETHODIMP_(void) CUIFToolTip::Enable(BOOL bEnable)
{
if (!bEnable)
HideTip();
CUIFObject::Enable(bEnable);
}
STDMETHODIMP_(void) CUIFToolTip::OnTimer(WPARAM wParam)
{
if (wParam == TOOLTIP_TIMER_ID)
ShowTip();
}
/////////////////////////////////////////////////////////////////////////////
// CUIFButton
CUIFButton::CUIFButton(
CUIFObject *pParent,
DWORD nObjectID,
LPCRECT prc,
DWORD style) : CUIFObject(pParent, nObjectID, prc, style)
{
m_ButtonIcon.m_hIcon = NULL;
m_ButtonIcon.m_hImageList = NULL;
m_dwUnknown9 = 0;
m_uButtonStatus = 0;
m_bPressed = FALSE;
m_hbmButton1 = NULL;
m_hbmButton2 = NULL;
m_pszButtonText = NULL;
}
CUIFButton::~CUIFButton()
{
if (m_pszButtonText)
{
delete[] m_pszButtonText;
m_pszButtonText = NULL;
}
if (m_ButtonIcon.m_hImageList)
ImageList_Destroy(m_ButtonIcon.m_hImageList);
}
void
CUIFButton::DrawBitmapProc(HDC hDC, LPCRECT prc, BOOL bPressed)
{
INT width = m_rc.right - m_rc.left;
INT height = m_rc.bottom - m_rc.top;
if (m_hbmButton2)
{
HBITMAP hbmMask = cicCreateMaskBmp(&m_rc, m_hbmButton1, m_hbmButton2,
(HBRUSH)UlongToHandle(COLOR_BTNFACE + 1), 0, 0);
::DrawState(hDC, NULL, NULL, (LPARAM)hbmMask, 0,
prc->left + bPressed, prc->top + bPressed,
width - bPressed, height - bPressed,
DST_BITMAP | (m_bEnable ? 0 : (DSS_MONO | DSS_DISABLED)));
::DeleteObject(hbmMask);
}
else
{
::DrawState(hDC, NULL, NULL, (LPARAM)m_hbmButton1, 0,
prc->left + bPressed, prc->top + bPressed,
width - bPressed, height - bPressed,
DST_BITMAP | (m_bEnable ? 0 : (DSS_MONO | DSS_DISABLED)));
}
}
void
CUIFButton::DrawEdgeProc(HDC hDC, LPCRECT prc, BOOL bPressed)
{
RECT rc = *prc;
if (bPressed)
::DrawEdge(hDC, &rc, BDR_SUNKENOUTER, BF_RECT);
else
::DrawEdge(hDC, &rc, BDR_RAISEDINNER, BF_RECT);
}
void CUIFButton::DrawIconProc(HDC hDC, LPRECT prc, BOOL bPressed)
{
INT width = prc->right - prc->left;
INT height = prc->bottom - prc->top;
RECT rc = { 0, 0, width, height };
HDC hMemDC = ::CreateCompatibleDC(hDC);
if (!hMemDC)
return;
HBITMAP hbmMem = ::CreateCompatibleBitmap(hDC, width, height);
if (!hbmMem)
{
::DeleteDC(hMemDC);
return;
}
HGDIOBJ hbmOld = ::SelectObject(hMemDC, hbmMem);
if (m_bEnable)
{
::BitBlt(hMemDC, rc.left, rc.top, width, height, hDC, prc->left, prc->top, SRCCOPY);
}
else
{
HBRUSH hbrWhite = (HBRUSH)::GetStockObject(WHITE_BRUSH);
::FillRect(hMemDC, &rc, hbrWhite);
}
if (m_style & UIF_BUTTON_LARGE_ICON)
{
::DrawIconEx(hMemDC,
2 + bPressed, 2 + bPressed,
m_ButtonIcon.m_hIcon,
width - 4, height - 4,
0, NULL, DI_NORMAL);
}
else
{
::DrawIconEx(hMemDC,
(width - 16) / 2 + bPressed,
(height - 16) / 2 + bPressed,
m_ButtonIcon.m_hIcon,
16, 16,
0, NULL, DI_NORMAL);
}
::SelectObject(hMemDC, hbmOld);
::DrawState(hDC, NULL, NULL, (LPARAM)hbmMem, 0,
prc->left, prc->top, width, height,
DST_BITMAP | (m_bEnable ? 0 : (DSS_MONO | DSS_DISABLED)));
::DeleteObject(hbmMem);
::DeleteDC(hMemDC);
}
void
CUIFButton::DrawTextProc(HDC hDC, LPCRECT prc, BOOL bPressed)
{
if (!m_pszButtonText)
return;
HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
INT cchText = lstrlenW(m_pszButtonText);
SIZE textSize;
::GetTextExtentPoint32W(hDC, m_pszButtonText, cchText, &textSize);
INT xText, yText;
if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_CENTER)
xText = (m_rc.right - m_rc.left - textSize.cx) / 2;
else if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_RIGHT)
xText = m_rc.right - m_rc.left - textSize.cx;
else
xText = 0;
if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_MIDDLE)
yText = (m_rc.bottom - m_rc.top - textSize.cy) / 2;
else if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_BOTTOM)
yText = m_rc.bottom - m_rc.top - textSize.cy;
else
yText = 0;
::SetBkMode(hDC, TRANSPARENT);
if (m_bEnable)
{
::SetTextColor(hDC, ::GetSysColor(COLOR_BTNTEXT));
::ExtTextOutW(hDC,
xText + prc->left + bPressed, yText + prc->top + bPressed,
ETO_CLIPPED, prc,
m_pszButtonText, cchText, NULL);
}
else
{
::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHILIGHT));
::ExtTextOutW(hDC,
xText + prc->left + bPressed + 1, yText + prc->top + bPressed + 1,
ETO_CLIPPED, prc,
m_pszButtonText, cchText, NULL);
::SetTextColor(hDC, ::GetSysColor(COLOR_BTNSHADOW));
::ExtTextOutW(hDC,
xText + prc->left + bPressed, yText + prc->top + bPressed,
ETO_CLIPPED, prc,
m_pszButtonText, cchText, NULL);
}
::SelectObject(hDC, hFontOld);
}
STDMETHODIMP_(void)
CUIFButton::Enable(BOOL bEnable)
{
CUIFObject::Enable(bEnable);
if (!m_bEnable)
{
SetStatus(0);
if (IsCapture())
CUIFObject::EndCapture();
}
}
void
CUIFButton::GetIconSize(HICON hIcon, LPSIZE pSize)
{
ICONINFO IconInfo;
if (::GetIconInfo(hIcon, &IconInfo))
{
BITMAP bm;
::GetObject(IconInfo.hbmColor, sizeof(bm), &bm);
::DeleteObject(IconInfo.hbmColor);
::DeleteObject(IconInfo.hbmMask);
pSize->cx = bm.bmWidth;
pSize->cy = bm.bmHeight;
}
else
{
pSize->cx = ::GetSystemMetrics(SM_CXSMICON);
pSize->cy = ::GetSystemMetrics(SM_CYSMICON);
}
}
void
CUIFButton::GetTextSize(LPCWSTR pszText, LPSIZE pSize)
{
HDC hDC = ::GetDC(NULL);
INT cchText = lstrlenW(pszText);
HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
if (!m_bHasCustomFont && SUCCEEDED(EnsureThemeData(*m_pWindow)))
{
RECT rc;
GetThemeTextExtent(hDC, 0, pszText, cchText, 0, NULL, &rc);
pSize->cx = rc.right;
pSize->cy = rc.bottom;
}
else
{
::GetTextExtentPoint32W(hDC, pszText, cchText, pSize);
}
if (m_style & UIF_BUTTON_VERTICAL)
{
INT tmp = pSize->cx;
pSize->cx = pSize->cy;
pSize->cy = tmp;
}
::SelectObject(hDC, hFontOld);
::ReleaseDC(NULL, hDC);
}
STDMETHODIMP_(void)
CUIFButton::OnLButtonDown(LONG x, LONG y)
{
SetStatus(1);
StartCapture();
if ((m_style & 0x30) == 0x20)
NotifyCommand(1, 0);
}
/// @unimplemented
STDMETHODIMP_(void)
CUIFButton::OnLButtonUp(LONG x, LONG y)
{
POINT pt = { x, y };
BOOL bCapture = IsCapture();
if (bCapture)
EndCapture();
BOOL bNotInObject = (m_style & 0x30) == 0x20;
if ((m_style & 0x30) != 0x10)
{
bNotInObject = !PtInObject(pt);
if (bNotInObject)
{
SetStatus(0);
return;
}
}
else
{
if (!bNotInObject)
{
bNotInObject = !PtInObject(pt);
if (!bNotInObject)
{
SetStatus(2);
NotifyCommand(1, 0);
return;
}
}
SetStatus(0);
return;
}
SetStatus(2);
if (bCapture)
{
m_bPressed = !m_bPressed;
NotifyCommand(1, 0);
}
}
void CUIFButton::OnMouseIn(LONG x, LONG y)
{
if ((m_style & 0x30) == 0x20)
{
if (IsCapture())
SetStatus(0);
else
SetStatus(2);
}
else
{
if (IsCapture())
SetStatus(1);
else
SetStatus(2);
}
}
void CUIFButton::OnMouseOut(LONG x, LONG y)
{
if ((m_style & 0x30) == 0x20)
SetStatus(0);
else if (IsCapture())
SetStatus(3);
else
SetStatus(0);
}
STDMETHODIMP_(void)
CUIFButton::OnPaintNoTheme(HDC hDC)
{
::FillRect(hDC, &m_rc, (HBRUSH)UlongToHandle(COLOR_BTNFACE + 1));
if (m_bPressed && ((m_uButtonStatus == 0) || (m_uButtonStatus == 3)))
{
HBRUSH hbr = cicCreateDitherBrush();
if (hbr)
{
COLORREF OldTextColor = ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNFACE));
COLORREF OldBkColor = ::SetBkColor(hDC, ::GetSysColor(COLOR_BTNHIGHLIGHT));
RECT rc = m_rc;
::InflateRect(&rc, -2, -2);
::FillRect(hDC, &rc, hbr);
::SetTextColor(hDC, OldTextColor);
::SetBkColor(hDC, OldBkColor);
::DeleteObject(hbr);
}
}
BOOL bPressed = (m_bPressed || (m_uButtonStatus == 1));
if (m_hbmButton1)
DrawBitmapProc(hDC, &m_rc, bPressed);
else if (m_ButtonIcon.m_hIcon)
DrawIconProc(hDC, &m_rc, bPressed);
else
DrawTextProc(hDC, &m_rc, bPressed);
if (m_bPressed || (m_uButtonStatus == 1))
DrawEdgeProc(hDC, &m_rc, TRUE);
else if (2 <= m_uButtonStatus && m_uButtonStatus <= 3)
DrawEdgeProc(hDC, &m_rc, FALSE);
}
void CUIFButton::SetIcon(HICON hIcon)
{
m_ButtonIcon = hIcon;
if (m_ButtonIcon.m_hIcon)
GetIconSize(m_ButtonIcon.m_hIcon, &m_IconSize);
else
m_IconSize.cx = m_IconSize.cy = 0;
CallOnPaint();
}
void CUIFButton::SetStatus(UINT uStatus)
{
if (uStatus != m_uButtonStatus)
{
m_uButtonStatus = uStatus;
CallOnPaint();
}
}
void CUIFButton::SetText(LPCWSTR pszText)
{
if (m_pszButtonText)
{
delete[] m_pszButtonText;
m_pszButtonText = NULL;
}
m_TextSize.cx = m_TextSize.cy = 0;
if (pszText)
{
INT cch = lstrlenW(pszText);
m_pszButtonText = new(cicNoThrow) WCHAR[cch + 1];
if (!m_pszButtonText)
return;
lstrcpynW(m_pszButtonText, pszText, cch + 1);
GetTextSize(m_pszButtonText, &m_TextSize);
}
CallOnPaint();
}
/////////////////////////////////////////////////////////////////////////////
// CUIFButton2
CUIFButton2::CUIFButton2(
CUIFObject *pParent,
DWORD nObjectID,
LPCRECT prc,
DWORD style) : CUIFButton(pParent, nObjectID, prc, style)
{
m_iStateId = 0;
m_iPartId = BP_PUSHBUTTON;
m_pszClassList = L"TOOLBAR";
}
CUIFButton2::~CUIFButton2()
{
CloseThemeData();
}
DWORD CUIFButton2::MakeDrawFlag()
{
DWORD dwDrawFlags = 0;
if (m_bPressed)
dwDrawFlags |= UIF_DRAW_PRESSED;
if (m_uButtonStatus == 1)
dwDrawFlags |= 0x2;
else if (2 <= m_uButtonStatus && m_uButtonStatus <= 3)
dwDrawFlags |= 0x1;
if (!m_bEnable)
dwDrawFlags |= UIF_DRAW_DISABLED;
return dwDrawFlags;
}
/// @unimplemented
STDMETHODIMP_(BOOL)
CUIFButton2::OnPaintTheme(HDC hDC)
{
//FIXME
return FALSE;
}
STDMETHODIMP_(void)
CUIFButton2::OnPaintNoTheme(HDC hDC)
{
if (!m_pScheme)
return;
INT width = m_rc.right - m_rc.left;
INT height = m_rc.bottom - m_rc.top;
HDC hdcMem = ::CreateCompatibleDC(hDC);
if (!hdcMem)
return;
HBITMAP hbmMem = ::CreateCompatibleBitmap(hDC, width, height);
if ( !hbmMem )
{
::DeleteDC(hdcMem);
return;
}
HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbmMem);
HGDIOBJ hFontOld = ::SelectObject(hdcMem, m_hFont);
RECT rcBack = { 0, 0, width, height };
INT cxText = 0, cyText = 0, cxContent = 0, cyContent = 0;
INT cxyBorders, cxButton, cyButton;
if (m_pszButtonText)
{
cxText = m_TextSize.cx;
cyText = m_TextSize.cy;
}
if (m_ButtonIcon.m_hIcon)
{
cxContent = m_IconSize.cx;
cyContent = m_IconSize.cy;
}
else if (m_hbmButton1)
{
cxContent = m_BitmapSize.cx;
cyContent = m_BitmapSize.cy;
}
if (m_style & UIF_BUTTON_VERTICAL)
{
cxyBorders = ((cyText && cyContent) ? 2 : 0);
cxButton = cxContent;
cyButton = cyText + cyContent + cxyBorders;
if (cxText > cxContent)
cxButton = cxText;
}
else
{
cxyBorders = ((cxText && cxContent) ? 2 : 0);
cxButton = cxText + cxContent + cxyBorders;
cyButton = cyContent;
if (cyText > cyButton)
cyButton = cyText;
}
INT xOffset, yOffset;
if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_CENTER)
xOffset = (rcBack.left + rcBack.right - cxButton) / 2;
else if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_RIGHT)
xOffset = rcBack.right - cxText - 2;
else
xOffset = rcBack.left + 2;
if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_MIDDLE)
yOffset = (rcBack.top + rcBack.bottom - cyButton) / 2;
else if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_BOTTOM)
yOffset = rcBack.bottom - cyButton - 2;
else
yOffset = rcBack.top + 2;
RECT rc = { xOffset, yOffset, xOffset + cxButton, cyButton + yOffset };
SIZE offsetSize = { 0, 0 };
DWORD dwDrawFlags = MakeDrawFlag();
m_pScheme->GetCtrlFaceOffset(((m_style & 0x200) ? 0xA5 : 0x54),
dwDrawFlags,
&offsetSize);
::OffsetRect(&rc, offsetSize.cx, offsetSize.cy);
RECT rcImage, rcText;
if (m_style & UIF_BUTTON_VERTICAL)
{
rcImage.left = (rc.left + rc.right - cxContent) / 2;
rcImage.top = rc.top;
rcImage.right = rcImage.left + cxContent;
rcImage.bottom = rc.top + cyContent;
rcText.left = (rc.left + rc.right - cxText) / 2;
rcText.top = rc.bottom - cyText;
rcText.right = rcText.left + cxText;
rcText.bottom = rc.bottom;
}
else
{
rcImage.left = rc.left;
rcImage.top = (rc.top + rc.bottom - cyContent) / 2;
rcImage.bottom = rcImage.top + cyContent;
rcImage.right = rc.left + cxContent;
rcText.left = rc.right - cxText;
rcText.top = (rc.top + rc.bottom - cyText) / 2;
rcText.right = rc.right;
rcText.bottom = rcText.top + cyText;
}
if (IsRTL())
m_pScheme->m_bMirroring = TRUE;
m_pScheme->DrawCtrlBkgd(hdcMem,
&rcBack,
((m_style & 0x200) ? 0xA5 : 0x54),
dwDrawFlags);
if (m_pszButtonText)
{
m_pScheme->DrawCtrlText(hdcMem, &rcText, m_pszButtonText, -1, dwDrawFlags,
!!(m_style & UIF_BUTTON_VERTICAL));
}
if (m_ButtonIcon.m_hIcon)
m_pScheme->DrawCtrlIcon(hdcMem, &rcImage, m_ButtonIcon.m_hIcon, dwDrawFlags, &m_IconSize);
else if (m_hbmButton1)
m_pScheme->DrawCtrlBitmap(hdcMem, &rcImage, m_hbmButton1, m_hbmButton2, dwDrawFlags);
if (IsRTL())
m_pScheme->m_bMirroring = FALSE;
m_pScheme->DrawCtrlEdge(hdcMem,
&rcBack,
((m_style & 0x200) ? 0xA5 : 0x54),
dwDrawFlags);
::BitBlt(hDC, m_rc.left, m_rc.top, width, height, hdcMem, 0, 0, SRCCOPY);
::SelectObject(hdcMem, hFontOld);
::SelectObject(hdcMem, hbmOld);
::DeleteObject(hbmMem);
}
/////////////////////////////////////////////////////////////////////////////
// CUIFGripper
CUIFGripper::CUIFGripper(CUIFObject *pParent, LPCRECT prc, DWORD style)
: CUIFObject(pParent, 0, prc, style)
{
m_iStateId = 0;
m_pszClassList = L"REBAR";
if (m_style & UIF_GRIPPER_VERTICAL)
m_iPartId = RP_GRIPPERVERT;
else
m_iPartId = RP_GRIPPER;
}
CUIFGripper::~CUIFGripper()
{
}
STDMETHODIMP_(void)
CUIFGripper::OnMouseMove(LONG x, LONG y)
{
if (IsCapture())
{
POINT pt;
::GetCursorPos(&pt);
m_pWindow->Move(pt.x - m_ptGripper.x, pt.y - m_ptGripper.y, -1, -1);
}
}
STDMETHODIMP_(void)
CUIFGripper::OnLButtonDown(LONG x, LONG y)
{
StartCapture();
m_ptGripper.x = x;
m_ptGripper.y = y;
::ScreenToClient(*m_pWindow, &m_ptGripper);
RECT rc;
::GetWindowRect(*m_pWindow, &rc);
m_ptGripper.x -= rc.left;
m_ptGripper.y -= rc.top;
}
STDMETHODIMP_(void)
CUIFGripper::OnLButtonUp(LONG x, LONG y)
{
if (IsCapture())
EndCapture();
}
STDMETHODIMP_(BOOL)
CUIFGripper::OnPaintTheme(HDC hDC)
{
if (FAILED(EnsureThemeData(*m_pWindow)))
return FALSE;
if (m_style & UIF_GRIPPER_VERTICAL)
{
m_rc.top += 2;
m_rc.bottom -= 2;
}
else
{
m_rc.left += 2;
m_rc.right -= 2;
}
if (FAILED(DrawThemeBackground(hDC, 1, &m_rc, 0)))
return FALSE;
return TRUE;
}
STDMETHODIMP_(void)
CUIFGripper::OnPaintNoTheme(HDC hDC)
{
if (m_pScheme)
{
m_pScheme->DrawDragHandle(hDC, &m_rc, !!(m_style & UIF_GRIPPER_VERTICAL));
return;
}
RECT rc;
if (m_style & UIF_GRIPPER_VERTICAL)
rc = { m_rc.left, m_rc.top + 1, m_rc.right, m_rc.top + 4 };
else
rc = { m_rc.left + 1, m_rc.top, m_rc.left + 4, m_rc.bottom };
::DrawEdge(hDC, &rc, BDR_RAISEDINNER, BF_RECT);
}
STDMETHODIMP_(BOOL)
CUIFGripper::OnSetCursor(UINT uMsg, LONG x, LONG y)
{
HCURSOR hCursor = ::LoadCursor(NULL, IDC_SIZEALL);
::SetCursor(hCursor);
return TRUE;
}
STDMETHODIMP_(void)
CUIFGripper::SetStyle(DWORD style)
{
m_style = style;
if (m_style & UIF_GRIPPER_VERTICAL)
SetActiveTheme(L"REBAR", RP_GRIPPERVERT, 0);
else
SetActiveTheme(L"REBAR", RP_GRIPPER, 0);
}
/////////////////////////////////////////////////////////////////////////////
// CUIFToolbarMenuButton
CUIFToolbarMenuButton::CUIFToolbarMenuButton(
CUIFToolbarButton *pParent,
DWORD nObjectID,
LPCRECT prc,
DWORD style) : CUIFButton2(pParent, nObjectID, prc, style)
{
m_pToolbarButton = pParent;
HFONT hFont = ::CreateFontW(8, 8, 0, 0, FW_NORMAL, 0, 0, 0, SYMBOL_CHARSET,
0, 0, 0, 0, L"Marlett");
SetFont(hFont);
SetText(L"u"); // downward triangle
}
CUIFToolbarMenuButton::~CUIFToolbarMenuButton()
{
::DeleteObject(m_hFont);
SetFont(NULL);
}
STDMETHODIMP_(void)
CUIFToolbarMenuButton::OnLButtonUp(LONG x, LONG y)
{
CUIFButton::OnLButtonUp(x, y);
m_pToolbarButton->OnUnknownMouse0();
}
STDMETHODIMP_(BOOL)
CUIFToolbarMenuButton::OnSetCursor(UINT uMsg, LONG x, LONG y)
{
m_pToolbarButton->OnSetCursor(uMsg, x, y);
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CUIFToolbarButtonElement
CUIFToolbarButtonElement::CUIFToolbarButtonElement(
CUIFToolbarButton *pParent,
DWORD nObjectID,
LPCRECT prc,
DWORD style) : CUIFButton2(pParent, nObjectID, prc, style)
{
m_pToolbarButton = pParent;
}
STDMETHODIMP_(LPCWSTR)
CUIFToolbarButtonElement::GetToolTip()
{
if (m_pToolbarButton)
return m_pToolbarButton->GetToolTip();
return NULL;
}
STDMETHODIMP_(void)
CUIFToolbarButtonElement::OnLButtonUp(LONG x, LONG y)
{
CUIFButton::OnLButtonUp(x, y);
if ((m_pToolbarButton->m_dwToolbarButtonFlags & 0x30000) == 0x20000)
m_pToolbarButton->OnUnknownMouse0();
else
m_pToolbarButton->OnLeftClick();
}
STDMETHODIMP_(void)
CUIFToolbarButtonElement::OnRButtonUp(LONG x, LONG y)
{
if ((m_pToolbarButton->m_dwToolbarButtonFlags & 0x30000) != 0x20000)
m_pToolbarButton->OnRightClick();
}
/////////////////////////////////////////////////////////////////////////////
// CUIFToolbarButton
CUIFToolbarButton::CUIFToolbarButton(
CUIFObject *pParent,
DWORD nObjectID,
LPCRECT prc,
DWORD style,
DWORD dwToolbarButtonFlags,
LPCWSTR pszUnknownText) : CUIFObject(pParent, nObjectID, prc, style)
{
m_dwToolbarButtonFlags = dwToolbarButtonFlags;
m_pszUnknownText = pszUnknownText;
}
BOOL CUIFToolbarButton::Init()
{
RECT rc1, rc2;
rc1 = rc2 = m_rc;
if ((m_dwToolbarButtonFlags & 0x30000) == 0x30000)
{
rc1.right -= 12;
rc2.left = rc1.right + 1;
}
DWORD style = UIF_BUTTON_LARGE_ICON | UIF_BUTTON_V_ALIGN_MIDDLE | UIF_BUTTON_H_ALIGN_CENTER;
if (m_dwToolbarButtonFlags & 0x2000)
style |= 0x10;
if (m_dwToolbarButtonFlags & 0x80000)
style |= UIF_BUTTON_VERTICAL;
m_pToolbarButtonElement = new(cicNoThrow) CUIFToolbarButtonElement(this, m_nObjectID, &rc1, style);
if (!m_pToolbarButtonElement)
return FALSE;
m_pToolbarButtonElement->Initialize();
AddUIObj(m_pToolbarButtonElement);
if (!m_bEnable)
m_pToolbarButtonElement->Enable(FALSE);
if ((m_dwToolbarButtonFlags & 0x30000) == 0x30000)
{
style = UIF_BUTTON_LARGE_ICON | UIF_BUTTON_H_ALIGN_CENTER;
if (m_dwToolbarButtonFlags & 0x80000)
style |= UIF_BUTTON_VERTICAL;
m_pToolbarMenuButton = new(cicNoThrow) CUIFToolbarMenuButton(this, 0, &rc2, style);
if (!m_pToolbarMenuButton)
return FALSE;
m_pToolbarMenuButton->Initialize();
AddUIObj(m_pToolbarMenuButton);
if (!m_bEnable)
m_pToolbarMenuButton->Enable(FALSE);
}
return TRUE;
}
HICON CUIFToolbarButton::GetIcon()
{
return m_pToolbarButtonElement->m_ButtonIcon.m_hIcon;
}
void CUIFToolbarButton::SetIcon(HICON hIcon)
{
m_pToolbarButtonElement->SetIcon(hIcon);
}
STDMETHODIMP_(void)
CUIFToolbarButton::ClearWndObj()
{
if (m_pToolbarButtonElement)
m_pToolbarButtonElement->ClearWndObj();
if (m_pToolbarMenuButton)
m_pToolbarMenuButton->ClearWndObj();
CUIFObject::ClearWndObj();
}
STDMETHODIMP_(void)
CUIFToolbarButton::DetachWndObj()
{
if (m_pToolbarButtonElement)
m_pToolbarButtonElement->DetachWndObj();
if (m_pToolbarMenuButton)
m_pToolbarMenuButton->DetachWndObj();
CUIFObject::DetachWndObj();
}
STDMETHODIMP_(void)
CUIFToolbarButton::Enable(BOOL bEnable)
{
CUIFObject::Enable(bEnable);
if (m_pToolbarButtonElement)
m_pToolbarButtonElement->Enable(bEnable);
if (m_pToolbarMenuButton)
m_pToolbarMenuButton->Enable(bEnable);
}
STDMETHODIMP_(LPCWSTR)
CUIFToolbarButton::GetToolTip()
{
return CUIFObject::GetToolTip();
}
STDMETHODIMP_(void)
CUIFToolbarButton::SetActiveTheme(LPCWSTR pszClassList, INT iPartId, INT iStateId)
{
if (m_pToolbarButtonElement)
m_pToolbarButtonElement->SetActiveTheme(pszClassList, iPartId, iStateId);
if (m_pToolbarMenuButton)
m_pToolbarMenuButton->SetActiveTheme(pszClassList, iPartId, iStateId);
m_pszClassList = pszClassList;
m_iPartId = iPartId;
m_iStateId = iStateId;
}
STDMETHODIMP_(void)
CUIFToolbarButton::SetFont(HFONT hFont)
{
m_pToolbarButtonElement->SetFont(hFont);
}
STDMETHODIMP_(void)
CUIFToolbarButton::SetRect(LPCRECT prc)
{
CUIFObject::SetRect(prc);
RECT rc1, rc2;
rc1 = rc2 = m_rc;
if ((m_dwToolbarButtonFlags & 0x30000) == 0x30000)
{
rc1.right -= 12;
rc2.left = rc1.right + 1;
}
if (m_pToolbarButtonElement)
m_pToolbarButtonElement->SetRect(&rc1);
if (m_pToolbarMenuButton)
m_pToolbarMenuButton->SetRect(&rc2);
}
STDMETHODIMP_(void)
CUIFToolbarButton::SetToolTip(LPCWSTR pszToolTip)
{
CUIFObject::SetToolTip(pszToolTip);
if (m_pToolbarButtonElement)
m_pToolbarButtonElement->SetToolTip(pszToolTip);
if (m_pToolbarMenuButton)
m_pToolbarMenuButton->SetToolTip(pszToolTip);
}
/////////////////////////////////////////////////////////////////////////////
// CUIFWndFrame
CUIFWndFrame::CUIFWndFrame(
CUIFObject *pParent,
LPCRECT prc,
DWORD style) : CUIFObject(pParent, 0, prc, style)
{
m_iPartId = 7;
m_iStateId = 0;
m_pszClassList = L"WINDOW";
m_dwHitTest = 0;
m_cxFrame = m_cyFrame = 0;
if (m_pScheme)
{
if ((m_style & 0xF) && (m_style & 0xF) <= 2)
{
m_cxFrame = m_pScheme->CxSizeFrame();
m_cyFrame = m_pScheme->CySizeFrame();
}
else
{
m_cxFrame = m_pScheme->CxWndBorder();
m_cyFrame = m_pScheme->CyWndBorder();
}
}
m_cxMin = GetSystemMetrics(SM_CXMIN);
m_cyMin = GetSystemMetrics(SM_CYMIN);
}
void CUIFWndFrame::GetFrameSize(LPSIZE pSize)
{
pSize->cx = m_cxFrame;
pSize->cy = m_cyFrame;
}
DWORD CUIFWndFrame::HitTest(LONG x, LONG y)
{
DWORD dwFlags = 0;
if ( m_rc.left <= x && x < m_rc.left + m_cxFrame)
dwFlags |= 0x10;
if (m_rc.top <= y && y < m_rc.top + m_cyFrame )
dwFlags |= 0x20;
if (m_rc.right - m_cxFrame <= x && x < m_rc.right)
dwFlags |= 0x40;
if (m_rc.bottom - m_cyFrame <= y && y < m_rc.bottom)
dwFlags |= 0x80;
return dwFlags;
}
STDMETHODIMP_(void)
CUIFWndFrame::OnMouseMove(LONG x, LONG y)
{
if (!IsCapture())
return;
POINT Point;
::ClientToScreen(*m_pWindow, &Point);
RECT rc = m_rcWnd;
if (m_dwHitTest & 0x10)
rc.left = Point.x + m_rcWnd.left - m_ptHit.x;
if (m_dwHitTest & 0x20)
rc.top = Point.y + m_rcWnd.top - m_ptHit.y;
if (m_dwHitTest & 0x40)
{
rc.right = Point.x + m_rcWnd.right - m_ptHit.x;
if (rc.right <= rc.left + m_cxMin)
rc.right = rc.left + m_cxMin;
}
if (m_dwHitTest & 0x80)
{
rc.bottom = Point.y + m_rcWnd.bottom - m_ptHit.y;
if (rc.bottom <= rc.top + m_cyMin)
rc.bottom = rc.top + m_cyMin;
}
m_pWindow->Move(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
}
STDMETHODIMP_(void)
CUIFWndFrame::OnLButtonDown(LONG x, LONG y)
{
POINT Point = { x, y };
DWORD hitTest = m_style & HitTest(x, y);
if (!hitTest)
return;
::ClientToScreen(*m_pWindow, &Point);
m_ptHit = Point;
m_pWindow = m_pWindow;
m_dwHitTest = hitTest;
::GetWindowRect(*m_pWindow, &m_rcWnd);
StartCapture();
}
STDMETHODIMP_(void)
CUIFWndFrame::OnLButtonUp(LONG x, LONG y)
{
if (IsCapture())
EndCapture();
}
STDMETHODIMP_(BOOL)
CUIFWndFrame::OnPaintTheme(HDC hDC)
{
if (FAILED(EnsureThemeData(*m_pWindow)))
return FALSE;
RECT rc = m_rc;
rc.right = m_cxFrame;
if (FAILED(DrawThemeEdge(hDC, 0, &rc, 5, 1, NULL)))
return FALSE;
rc = m_rc;
rc.left = rc.right - m_cxFrame;
if (FAILED(DrawThemeEdge(hDC, 0, &rc, 10, 4, NULL)))
return FALSE;
rc = m_rc;
rc.bottom = m_cyFrame;
if (FAILED(DrawThemeEdge(hDC, 0, &rc, 5, 2, NULL)))
return FALSE;
rc = m_rc;
rc.top = rc.bottom - m_cyFrame;
if (FAILED(DrawThemeEdge(hDC, 0, &rc, 10, 8, NULL)))
return FALSE;
return TRUE;
}
STDMETHODIMP_(void)
CUIFWndFrame::OnPaintNoTheme(HDC hDC)
{
if (!m_pScheme)
return;
DWORD type = 0;
if ((m_style & 0xF) == 1)
type = 1;
else if ( (m_style & 0xF) == 2 )
type = 2;
m_pScheme->DrawWndFrame(hDC, &m_rc, type, m_cxFrame, m_cyFrame);
}
STDMETHODIMP_(BOOL)
CUIFWndFrame::OnSetCursor(UINT uMsg, LONG x, LONG y)
{
DWORD dwHitTest = m_dwHitTest;
if (!IsCapture())
dwHitTest = m_style & HitTest(x, y);
LPTSTR pszCursor = NULL;
switch (dwHitTest)
{
case 0x30:
case 0xC0:
pszCursor = IDC_SIZENWSE;
break;
case 0x90:
case 0x60:
pszCursor = IDC_SIZENESW;
break;
case 0x10:
case 0x40:
pszCursor = IDC_SIZEWE;
break;
case 0x20:
case 0x80:
pszCursor = IDC_SIZENS;
break;
default:
return FALSE;
}
HCURSOR hCursor = ::LoadCursor(NULL, pszCursor);
::SetCursor(hCursor);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CUIFBalloonButton
CUIFBalloonButton::CUIFBalloonButton(
CUIFObject *pParent,
DWORD nObjectID,
LPCRECT prc,
DWORD style) : CUIFButton(pParent, nObjectID, prc, style)
{
m_nCommandID = 0;
}
STDMETHODIMP_(void)
CUIFBalloonButton::OnPaint(HDC hDC)
{
RECT rc = m_rc;
::OffsetRect(&rc, -rc.left, -rc.top);
HDC hMemDC = ::CreateCompatibleDC(hDC);
HBITMAP hbmMem = ::CreateCompatibleBitmap(hDC, rc.right, rc.bottom);
HGDIOBJ hbmOld = ::SelectObject(hMemDC, hbmMem);
BOOL bPressed;
COLORREF rgbShadow, rgbBorder;
if (m_uButtonStatus == 1)
{
bPressed = TRUE;
rgbShadow = ::GetSysColor(COLOR_BTNSHADOW);
rgbBorder = ::GetSysColor(COLOR_BTNHIGHLIGHT);
}
else
{
bPressed = FALSE;
if (m_uButtonStatus < 4)
{
rgbShadow = ::GetSysColor(COLOR_BTNHIGHLIGHT);
rgbBorder = ::GetSysColor(COLOR_BTNSHADOW);
}
else
{
rgbShadow = ::GetSysColor(COLOR_INFOBK);
rgbBorder = ::GetSysColor(COLOR_INFOBK);
}
}
COLORREF rgbInfoBk = ::GetSysColor(COLOR_INFOBK);
HBRUSH hbrBack = ::CreateSolidBrush(rgbInfoBk);
::FillRect(hMemDC, &rc, hbrBack);
::DeleteObject(hbrBack);
DrawTextProc(hMemDC, &rc, bPressed);
HBRUSH hNullBrush = (HBRUSH)::GetStockObject(NULL_BRUSH);
HGDIOBJ hbrOld = ::SelectObject(hMemDC, hNullBrush);
HPEN hPen = ::CreatePen(PS_SOLID, 0, rgbShadow);
HGDIOBJ hPenOld = ::SelectObject(hMemDC, hPen);
::RoundRect(hMemDC, rc.left, rc.top, rc.right - 1, rc.bottom - 1, 6, 6);
::SelectObject(hMemDC, hPenOld);
::DeleteObject(hPen);
hPen = ::CreatePen(PS_SOLID, 0, rgbBorder);
hPenOld = ::SelectObject(hMemDC, hPen);
::RoundRect(hMemDC, rc.left + 1, rc.top + 1, rc.right, rc.bottom, 6, 6);
::SelectObject(hMemDC, hPenOld);
::DeleteObject(hPen);
hPen = ::CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNFACE));
hPenOld = ::SelectObject(hMemDC, hPen);
::RoundRect(hMemDC, rc.left + 1, rc.top + 1, rc.right - 1, rc.bottom - 1, 6, 6);
::SelectObject(hMemDC, hPenOld);
::DeleteObject(hPen);
::SelectObject(hMemDC, hbrOld);
::BitBlt(hDC, m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - m_rc.top,
hMemDC, rc.left, rc.top, SRCCOPY);
::SelectObject(hMemDC, hbmOld);
::DeleteObject(hbmMem);
::DeleteDC(hMemDC);
}
void
CUIFBalloonButton::DrawTextProc(HDC hDC, LPCRECT prc, BOOL bPressed)
{
if (!m_pszButtonText)
return;
UINT uFlags = DT_SINGLELINE;
if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_CENTER)
uFlags |= DT_CENTER;
else if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_RIGHT)
uFlags |= DT_RIGHT;
if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_MIDDLE)
uFlags |= DT_VCENTER;
else if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_BOTTOM)
uFlags |= DT_BOTTOM;
COLORREF rgbOldColor = ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNTEXT));
INT nOldBkMode = ::SetBkMode(hDC, TRANSPARENT);
RECT rc = *prc;
if (bPressed)
::OffsetRect(&rc, 1, 1);
HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
::DrawTextW(hDC, m_pszButtonText, -1, &rc, uFlags);
::SelectObject(hDC, hFontOld);
::SetBkMode(hDC, nOldBkMode);
::SetTextColor(hDC, rgbOldColor);
}
/////////////////////////////////////////////////////////////////////////////
// CUIFBalloonWindow
CUIFBalloonWindow::CUIFBalloonWindow(HINSTANCE hInst, DWORD style) : CUIFWindow(hInst, style)
{
m_dwUnknown6 = -1;
m_nActionID = -1;
m_hRgn = NULL;
m_pszBalloonText = NULL;
m_bHasBkColor = m_bHasTextColor = FALSE;
m_rgbBkColor = 0;
m_rgbTextColor = 0;
m_ptTarget.x = m_ptTarget.y = 0;
ZeroMemory(&m_rcExclude, sizeof(m_rcExclude));
m_dwUnknown7 = 0;
m_nBalloonType = 0;
m_dwUnknown8[0] = 0;
m_dwUnknown8[1] = 0;
m_ptBalloon.x = m_ptBalloon.y = 0;
m_cButtons = 0;
m_hwndNotif = NULL;
m_uNotifMsg = 0;
m_rcMargin.left = 8;
m_rcMargin.top = 8;
m_rcMargin.right = 8;
m_rcMargin.bottom = 8;
}
CUIFBalloonWindow::~CUIFBalloonWindow()
{
if (m_pszBalloonText)
{
delete[] m_pszBalloonText;
m_pszBalloonText = NULL;
}
}
STDMETHODIMP_(BOOL)
CUIFBalloonWindow::Initialize()
{
CUIFWindow::Initialize();
if ((m_style & UIF_BALLOON_WINDOW_TYPE_MASK) == UIF_BALLOON_WINDOW_OK)
{
AddButton(IDOK);
}
else if ((m_style & UIF_BALLOON_WINDOW_TYPE_MASK) == UIF_BALLOON_WINDOW_YESNO)
{
AddButton(IDYES);
AddButton(IDNO);
}
return TRUE;
}
STDMETHODIMP_(void)
CUIFBalloonWindow::OnCreate(HWND hWnd)
{
m_nActionID = -1;
AdjustPos();
}
STDMETHODIMP_(void)
CUIFBalloonWindow::OnDestroy(HWND hWnd)
{
SendNotification(m_nActionID);
DoneWindowRegion();
}
STDMETHODIMP_(void)
CUIFBalloonWindow::OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
CUIFBalloonButton *pButton = NULL;
switch (wParam)
{
case VK_RETURN:
pButton = (CUIFBalloonButton *)FindUIObject(0);
break;
case VK_ESCAPE:
m_nActionID = -1;
::DestroyWindow(m_hWnd);
return;
case TEXT('Y'):
pButton = FindButton(IDYES);
break;
case TEXT('N'):
pButton = FindButton(IDNO);
break;
}
if (!pButton)
return;
m_nActionID = pButton->m_nCommandID;
::DestroyWindow(m_hWnd);
}
STDMETHODIMP_(LRESULT)
CUIFBalloonWindow::OnObjectNotify(CUIFObject *pObject, WPARAM wParam, LPARAM lParam)
{
CUIFBalloonButton *pButton = (CUIFBalloonButton *)pObject;
m_nActionID = pButton->m_nCommandID;
::DestroyWindow(m_hWnd);
return 0;
}
STDMETHODIMP_(void)
CUIFBalloonWindow::OnPaint(HDC hDC)
{
RECT rc;
GetRect(&rc);
PaintFrameProc(hDC, &rc);
switch (m_nBalloonType)
{
case 1:
rc.top += 16;
break;
case 2:
rc.right -= 16;
break;
case 3:
rc.left += 16;
break;
default:
rc.bottom -= 16;
break;
}
RECT rcMargin;
GetMargin(&rcMargin);
rc.left += rcMargin.left;
rc.top += rcMargin.top;
rc.right -= rcMargin.right;
rc.bottom -= rcMargin.bottom;
PaintMessageProc(hDC, &rc, m_pszBalloonText);
}
void
CUIFBalloonWindow::AddButton(UINT nCommandId)
{
RECT rc = { 0, 0, 0, 0 };
if (!((IDOK <= nCommandId) && (nCommandId <= IDNO)))
return;
CUIFBalloonButton *pButton = new(cicNoThrow) CUIFBalloonButton(this, m_cButtons, &rc, 5);
if (!pButton)
return;
pButton->Initialize();
pButton->m_nCommandID = nCommandId;
LPCWSTR pszText;
#ifdef IDS_OK
extern HINSTANCE g_hInst;
WCHAR szText[64];
::LoadStringW(g_hInst, IDS_OK + (nCommandId - IDOK), szText, _countof(szText));
pszText = szText;
#else
switch (nCommandId)
{
case IDOK: pszText = L"OK"; break;
case IDCANCEL: pszText = L"Cancel"; break;
case IDABORT: pszText = L"&Abort"; break;
case IDRETRY: pszText = L"&Retry"; break;
case IDIGNORE: pszText = L"&Ignore"; break;
case IDYES: pszText = L"&Yes"; break;
default: pszText = L"&No"; break;
}
#endif
pButton->SetText(pszText);
AddUIObj(pButton);
++m_cButtons;
}
/// @unimplemented
void
CUIFBalloonWindow::AdjustPos()
{
//FIXME
}
HRGN
CUIFBalloonWindow::CreateRegion(LPCRECT prc)
{
POINT Points[4];
HRGN hRgn;
BOOL bFlag = FALSE;
LONG x, y;
switch (m_nBalloonType)
{
case 1:
hRgn = ::CreateRoundRectRgn(prc->left, prc->top + 16, prc->right, prc->bottom, 16, 16);
y = prc->top + 16;
bFlag = TRUE;
break;
case 2:
hRgn = ::CreateRoundRectRgn(prc->left, prc->top, prc->right - 16, prc->bottom, 16, 16);
x = prc->right - 17;
break;
case 3:
hRgn = ::CreateRoundRectRgn(prc->left + 16, prc->top, prc->right, prc->bottom, 16, 16);
x = prc->left + 16;
break;
default:
hRgn = ::CreateRoundRectRgn(prc->left, prc->top, prc->right, prc->bottom - 16, 16, 16);
y = prc->bottom - 17;
bFlag = TRUE;
break;
}
if (bFlag)
{
x = Points[1].x = m_ptBalloon.x;
Points[1].y = m_ptBalloon.y;
Points[0].y = Points[2].y = Points[3].y = y;
Points[2].x = x + 10 * (2 * (m_dwUnknown8[0] == 0) - 1);
}
else
{
Points[2].x = x;
y = Points[0].y = Points[1].y = Points[3].y = m_ptBalloon.y;
Points[1].x = m_ptBalloon.x;
Points[2].y = y + 10 * (2 * (m_dwUnknown8[0] == 2) - 1);
}
Points[0].x = Points[3].x = x;
HRGN hPolygonRgn = ::CreatePolygonRgn(Points, _countof(Points), WINDING);
::CombineRgn(hRgn, hRgn, hPolygonRgn, RGN_OR);
::DeleteObject(hPolygonRgn);
return hRgn;
}
void
CUIFBalloonWindow::DoneWindowRegion()
{
if (m_hRgn)
{
::SetWindowRgn(m_hWnd, NULL, TRUE);
::DeleteObject(m_hRgn);
m_hRgn = NULL;
}
}
CUIFBalloonButton *
CUIFBalloonWindow::FindButton(UINT nCommandID)
{
for (UINT iButton = 0; iButton < m_cButtons; ++iButton)
{
CUIFBalloonButton *pButton = (CUIFBalloonButton *)FindUIObject(iButton);
if (pButton && (pButton->m_nCommandID == nCommandID))
return pButton;
}
return NULL;
}
CUIFObject *
CUIFBalloonWindow::FindUIObject(UINT nObjectID)
{
for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
{
CUIFObject *pObject = m_ObjectArray[iItem];
if (pObject->m_nObjectID == nObjectID)
return pObject;
}
return NULL;
}
COLORREF
CUIFBalloonWindow::GetBalloonBkColor()
{
if (m_bHasBkColor)
return m_rgbBkColor;
else
return ::GetSysColor(COLOR_INFOBK);
}
COLORREF
CUIFBalloonWindow::GetBalloonTextColor()
{
if (m_bHasTextColor)
return m_rgbTextColor;
else
return ::GetSysColor(COLOR_INFOTEXT);
}
void
CUIFBalloonWindow::GetButtonSize(LPSIZE pSize)
{
HDC hDisplayDC = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
TEXTMETRIC tm;
HGDIOBJ hFontOld = ::SelectObject(hDisplayDC, m_hFont);
::GetTextMetrics(hDisplayDC, &tm);
::SelectObject(hDisplayDC, hFontOld);
::DeleteDC(hDisplayDC);
pSize->cx = 16 * tm.tmAveCharWidth;
pSize->cy = tm.tmHeight + 10;
}
void
CUIFBalloonWindow::GetMargin(LPRECT prcMargin)
{
if (prcMargin)
*prcMargin = m_rcMargin;
}
void
CUIFBalloonWindow::SetExcludeRect(LPCRECT prcExclude)
{
m_rcExclude = *prcExclude;
AdjustPos();
}
void
CUIFBalloonWindow::SetTargetPos(POINT ptTarget)
{
m_ptTarget = ptTarget;
AdjustPos();
}
void
CUIFBalloonWindow::SetText(LPCWSTR pszText)
{
if (m_pszBalloonText)
{
delete[] m_pszBalloonText;
m_pszBalloonText = NULL;
}
if (pszText == NULL)
pszText = L"";
size_t cch = wcslen(pszText);
m_pszBalloonText = new(cicNoThrow) WCHAR[cch + 1];
if (m_pszBalloonText)
lstrcpynW(m_pszBalloonText, pszText, cch + 1);
AdjustPos();
}
void
CUIFBalloonWindow::InitWindowRegion()
{
RECT rc;
GetRect(&rc);
m_hRgn = CreateRegion(&rc);
if (m_hRgn)
::SetWindowRgn(m_hWnd, m_hRgn, TRUE);
}
void
CUIFBalloonWindow::LayoutObject()
{
SIZE size;
GetButtonSize(&size);
RECT rc;
GetRect(&rc);
switch (m_nBalloonType)
{
case 1:
rc.top += 16;
break;
case 2:
rc.right -= 16;
break;
case 3:
rc.left += 16;
break;
default:
rc.bottom -= 16;
break;
}
RECT rcMargin;
GetMargin(&rcMargin);
rc.left += rcMargin.left;
rc.top += rcMargin.top;
rc.right -= rcMargin.right;
rc.bottom -= rcMargin.bottom;
LONG xLeft = (rc.left + rc.right - size.cx * (((m_cButtons - 1) / 2) - m_cButtons)) / 2;
for (UINT iButton = 0; iButton < m_cButtons; ++iButton)
{
CUIFObject *UIObject = FindUIObject(iButton);
if (!UIObject)
continue;
rcMargin.left = xLeft + iButton * (size.cx * 3 / 2);
rcMargin.top = rc.bottom - size.cy;
rcMargin.right = rcMargin.left + size.cx;
rcMargin.bottom = rc.bottom;
UIObject->SetRect(&rcMargin);
UIObject->Show(TRUE);
}
}
void
CUIFBalloonWindow::PaintFrameProc(HDC hDC, LPCRECT prc)
{
HRGN hRgn = CreateRegion(prc);
HBRUSH hbrBack = ::CreateSolidBrush(GetBalloonBkColor());
HBRUSH hbrFrame = ::CreateSolidBrush(::GetSysColor(COLOR_WINDOWFRAME));
::FillRgn(hDC, hRgn, hbrBack);
::FrameRgn(hDC, hRgn, hbrFrame, 1, 1);
::DeleteObject(hbrBack);
::DeleteObject(hbrFrame);
::DeleteObject(hRgn);
}
void
CUIFBalloonWindow::PaintMessageProc(HDC hDC, LPRECT prc, LPCWSTR pszText)
{
HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
COLORREF rgbOldColor = ::SetTextColor(hDC, GetBalloonTextColor());
INT nOldBkMode = ::SetBkMode(hDC, TRANSPARENT);
::DrawTextW(hDC, pszText, -1, prc, DT_WORDBREAK);
::SelectObject(hDC, hFontOld);
::SetTextColor(hDC, rgbOldColor);
::SetBkMode(hDC, nOldBkMode);
}
void
CUIFBalloonWindow::SendNotification(WPARAM wParam)
{
if (m_hwndNotif)
::PostMessage(m_hwndNotif, m_uNotifMsg, wParam, 0);
}
/////////////////////////////////////////////////////////////////////////////
// CUIFMenu
CUIFMenu::CUIFMenu(
HINSTANCE hInst,
DWORD style,
DWORD dwUnknown14) : CUIFWindow(hInst, style)
{
m_nSelectedID = -1;
m_dwUnknown14 = dwUnknown14;
SetMenuFont();
}
CUIFMenu::~CUIFMenu()
{
for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
delete m_MenuItems[iItem];
::DeleteObject(m_hMenuFont);
ClearMenuFont();
}
void CUIFMenu::CancelMenu()
{
if (m_pVisibleSubMenu)
{
UninitShow();
}
else if (m_bModal)
{
SetSelectedId(0xFFFFFFFF);
::PostMessage(m_hWnd, WM_NULL, 0, 0);
}
}
void CUIFMenu::ClearMenuFont()
{
SetFont(NULL);
::DeleteObject(m_hFont);
}
CUIFMenuItem*
CUIFMenu::GetNextItem(CUIFMenuItem *pItem)
{
size_t iItem, cItems = m_MenuItems.size();
if (cItems == 0)
return NULL;
if (!m_pSelectedItem)
return m_MenuItems[0];
for (iItem = 0; iItem < cItems; )
{
if (m_MenuItems[iItem++] == pItem)
break;
}
for (;;)
{
if (iItem == cItems)
iItem = 0;
if (!m_MenuItems[iItem] || !m_MenuItems[iItem]->m_bMenuItemDisabled)
break;
++iItem;
}
return m_MenuItems[iItem];
}
CUIFMenuItem*
CUIFMenu::GetPrevItem(CUIFMenuItem *pItem)
{
ptrdiff_t iItem, cItems = m_MenuItems.size();
if (cItems == 0)
return NULL;
if (!m_pSelectedItem)
return m_MenuItems[cItems - 1];
for (iItem = cItems - 1; iItem >= 0; )
{
if (m_MenuItems[iItem--] == pItem)
break;
}
for (;;)
{
if (iItem < 0)
iItem = cItems - 1;
if (!m_MenuItems[iItem] || !m_MenuItems[iItem]->m_bMenuItemDisabled)
break;
--iItem;
}
return m_MenuItems[iItem];
}
CUIFMenu*
CUIFMenu::GetTopSubMenu()
{
CUIFMenu *pMenu;
for (pMenu = this; pMenu->m_pParentMenu; pMenu = pMenu->m_pParentMenu)
;
return pMenu;
}
void CUIFMenu::HandleMouseMsg(UINT uMsg, LONG x, LONG y)
{
POINT pt = { x, y };
if (!::PtInRect(&m_rc, pt) &&
(uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP))
{
SetSelectedId(-1);
PostMessage(m_hWnd, WM_NULL, 0, 0);
}
CUIFWindow::HandleMouseMsg(uMsg, x, y);
}
STDMETHODIMP_(BOOL)
CUIFMenu::InitShow(CUIFWindow *pWindow, LPCRECT prc, BOOL bFlag, BOOL bDoAnimation)
{
HWND hWnd = NULL;
if (pWindow)
hWnd = *pWindow;
CreateWnd(hWnd);
m_bHasMargin = FALSE;
for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
{
if (m_MenuItems[iItem])
m_MenuItems[iItem]->InitMenuExtent();
}
INT cxMax = 0;
m_cxMenuExtent = 0;
for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
{
CUIFMenuItem *pItem = m_MenuItems[iItem];
if (!pItem)
continue;
INT cxItem = m_cxyMargin + pItem->m_MenuLeftExtent.cx;
if (cxMax < cxItem)
cxMax = cxItem;
m_cxMenuExtent = max(m_cxMenuExtent, pItem->m_MenuRightExtent.cx);
if (!m_bHasMargin && pItem->m_hbmColor && pItem->IsCheck())
m_bHasMargin = TRUE;
}
RECT rcItem = { 0, 0, 0, 0 };
for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
{
CUIFMenuItem *pItem = m_MenuItems[iItem];
if (!pItem)
continue;
INT cyItem = pItem->m_MenuLeftExtent.cy;
rcItem.right = rcItem.left + cxMax + m_cxMenuExtent;
rcItem.bottom = rcItem.top + cyItem;
pItem->SetRect(&rcItem);
rcItem.top += cyItem;
AddUIObj(pItem);
}
rcItem.top = 0;
DWORD style = ::GetWindowLongPtr(hWnd, GWL_STYLE);
cxMax = rcItem.right;
INT cyMax = rcItem.bottom;
if (style & WS_DLGFRAME)
{
cxMax = rcItem.right + 2 * ::GetSystemMetrics(SM_CXDLGFRAME);
cyMax += 2 * ::GetSystemMetrics(SM_CYDLGFRAME);
}
else if (style & WS_BORDER)
{
cxMax = rcItem.right + 2 * ::GetSystemMetrics(SM_CXBORDER);
cyMax += 2 * ::GetSystemMetrics(SM_CYBORDER);
}
RECT rc = { 0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN) };
RECT rc3 = *prc;
HMONITOR hMon = ::MonitorFromRect(&rc3, MONITOR_DEFAULTTONEAREST);
if (hMon)
{
MONITORINFO mi = { sizeof(mi) };
if (::GetMonitorInfo(hMon, &mi))
rc = mi.rcMonitor;
}
if (m_style & 0x200)
rcItem.left -= cxMax;
INT x, y;
DWORD dwFlags2 = 0;
if (bFlag)
{
INT bottom = prc->bottom;
x = rcItem.left + prc->left;
if (rcItem.top + bottom + cyMax > rc.bottom)
{
bottom = prc->top - cyMax;
dwFlags2 = 8;
}
else
{
dwFlags2 = 4;
}
y = rcItem.top + bottom;
if (rcItem.left + cxMax + prc->right > rc.right)
x = rc.right - cxMax;
}
else
{
y = rcItem.top + prc->top;
if (rcItem.left + prc->right + cxMax > rc.right)
{
x = rcItem.left + prc->left - cxMax;
dwFlags2 = 2;
}
else
{
x = rcItem.left + prc->right;
dwFlags2 = 1;
}
if (rcItem.top + cyMax + prc->bottom > rc.bottom)
y = rc.bottom - cyMax;
}
if (x > rc.right - cxMax)
x = rc.right - cxMax;
if (x < rc.left)
x = rc.left;
if (y > rc.bottom - cyMax)
y = rc.bottom - cyMax;
if (y < rc.top)
y = rc.top;
Move(x, y, cxMax, -1);
SetRect(NULL);
BOOL bAnimation = FALSE;
if (bDoAnimation &&
::SystemParametersInfo(SPI_GETMENUANIMATION, 0, &bAnimation, 0) && bAnimation)
{
BOOL bMenuFade = FALSE;
if (!::SystemParametersInfoA(SPI_GETMENUFADE, 0, &bMenuFade, 0))
bMenuFade = FALSE;
DWORD dwFlags = (bMenuFade ? 0x80000 : dwFlags2) | 0x40000;
if (!AnimateWnd(200, dwFlags))
Show(TRUE);
}
else
{
Show(TRUE);
}
if (m_pVisibleSubMenu)
m_pVisibleSubMenu->m_pParentMenu = this;
return TRUE;
}
BOOL CUIFMenu::InsertItem(CUIFMenuItem *pItem)
{
if (!m_MenuItems.Add(pItem))
return FALSE;
pItem->SetFont(m_hFont);
return TRUE;
}
BOOL CUIFMenu::InsertSeparator()
{
CUIFMenuItemSeparator *pSep = new(cicNoThrow) CUIFMenuItemSeparator(this);
if (!pSep)
return FALSE;
if (!m_MenuItems.Add(pSep))
{
delete pSep;
return FALSE;
}
pSep->Initialize();
return TRUE;
}
STDMETHODIMP_(void)
CUIFMenu::ModalMessageLoop()
{
MSG msg;
while (::GetMessage(&msg, 0, 0, 0) && msg.message != WM_NULL &&
(msg.hwnd == m_hWnd || msg.message <= WM_MOUSEFIRST || WM_MOUSELAST <= msg.message))
{
if (!msg.hwnd && WM_KEYFIRST <= msg.message && msg.message <= WM_KEYLAST)
msg.hwnd = GetTopSubMenu()->m_hWnd;
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
STDMETHODIMP_(void)
CUIFMenu::ModalMouseNotify(UINT uMsg, LONG x, LONG y)
{
if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN)
CancelMenu();
}
STDMETHODIMP_(void)
CUIFMenu::OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
CUIFMenuItem *pTargetItem;
BYTE vKey = (BYTE)wParam;
switch (vKey)
{
case VK_ESCAPE:
CancelMenu();
return;
case VK_LEFT:
if (!m_pVisibleSubMenu)
return;
CancelMenu();
return;
case VK_RIGHT:
if (m_pSelectedItem && m_pSelectedItem->m_pSubMenu)
{
m_pSelectedItem->ShowSubPopup();
CUIFMenu *pSubMenu = m_pSelectedItem->m_pSubMenu;
pTargetItem = pSubMenu->GetNextItem(NULL);
pSubMenu->SetSelectedItem(pTargetItem);
}
return;
case VK_UP:
pTargetItem = GetPrevItem(m_pSelectedItem);
SetSelectedItem(pTargetItem);
return;
case VK_DOWN:
pTargetItem = GetNextItem(m_pSelectedItem);
SetSelectedItem(pTargetItem);
return;
case VK_RETURN:
break;
default:
{
if (!(('A' <= vKey && vKey <= 'Z') || ('0' <= vKey && vKey <= '9')))
return;
size_t iItem;
for (iItem = 0; iItem < m_MenuItems.size(); ++iItem)
{
CUIFMenuItem *pItem = m_MenuItems[iItem];
if (pItem->m_nMenuItemVKey == vKey)
{
SetSelectedItem(pItem);
break;
}
}
if (iItem == m_MenuItems.size())
return;
}
}
if (m_pSelectedItem && !m_pSelectedItem->m_bMenuItemGrayed)
{
CUIFMenu *pSubMenu = m_pSelectedItem->m_pSubMenu;
if (pSubMenu)
{
m_pSelectedItem->ShowSubPopup();
pTargetItem = pSubMenu->GetNextItem(NULL);
pSubMenu->SetSelectedItem(pTargetItem);
}
else
{
SetSelectedId(m_pSelectedItem->m_nMenuItemID);
::PostMessage(m_hWnd, WM_NULL, 0, 0);
}
}
}
void CUIFMenu::PostKey(BOOL bUp, WPARAM wParam, LPARAM lParam)
{
if (m_bModal)
{
// NOTE: hWnd parameter will be populated in CUIFMenu::ModalMessageLoop.
if (bUp)
::PostMessage(NULL, WM_KEYUP, wParam, lParam);
else
::PostMessage(NULL, WM_KEYDOWN, wParam, lParam);
}
}
void CUIFMenu::SetMenuFont()
{
LONG height = 14;
NONCLIENTMETRICS ncm = { sizeof(ncm) };
if (::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
{
HFONT hFont = ::CreateFontIndirect(&ncm.lfMenuFont);
SetFont(hFont);
LONG lfHeight = ncm.lfMenuFont.lfHeight;
if (lfHeight < 0)
lfHeight = -lfHeight;
height = (ncm.iMenuHeight + lfHeight) / 2;
}
m_hMenuFont = ::CreateFontW(height, 0, 0, 0, FW_NORMAL, 0, 0, 0, SYMBOL_CHARSET,
0, 0, 0, 0, L"Marlett");
INT cxSmallIcon = ::GetSystemMetrics(SM_CXSMICON);
m_cxyMargin = max(height, cxSmallIcon) + 2;
}
void CUIFMenu::SetSelectedId(UINT nSelectID)
{
CUIFMenu *pMenu = this;
while (pMenu->m_pVisibleSubMenu)
pMenu = pMenu->m_pVisibleSubMenu;
pMenu->m_nSelectedID = nSelectID;
}
void CUIFMenu::SetSelectedItem(CUIFMenuItem *pItem)
{
CUIFMenuItem *pOldItem = m_pSelectedItem;
if (pOldItem == pItem)
return;
m_pSelectedItem = pItem;
if (pOldItem)
pOldItem->CallOnPaint();
if (m_pSelectedItem)
m_pSelectedItem->CallOnPaint();
}
UINT CUIFMenu::ShowModalPopup(CUIFWindow *pWindow, LPCRECT prc, BOOL bFlag)
{
CUIFObject *pCaptured = NULL;
if (pWindow)
{
pCaptured = pWindow->m_pCaptured;
CUIFWindow::SetCaptureObject(NULL);
}
UINT nSelectedID = -1;
if (InitShow(pWindow, prc, bFlag, TRUE))
{
m_bModal = TRUE;
pWindow->SetBehindModal(this);
ModalMessageLoop();
nSelectedID = m_nSelectedID;
pWindow->SetBehindModal(NULL);
m_bModal = FALSE;
}
UninitShow();
if (pWindow)
pWindow->SetCaptureObject(pCaptured);
return nSelectedID;
}
void CUIFMenu::ShowSubPopup(CUIFMenu *pSubMenu, LPCRECT prc, BOOL bFlag)
{
m_pVisibleSubMenu = pSubMenu;
InitShow(pSubMenu, prc, bFlag, TRUE);
}
STDMETHODIMP_(BOOL)
CUIFMenu::UninitShow()
{
if (m_pParentMenu)
m_pParentMenu->UninitShow();
Show(FALSE);
if (m_pVisibleSubMenu)
m_pVisibleSubMenu->m_pParentMenu = NULL;
for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
RemoveUIObj(m_MenuItems[iItem]);
::DestroyWindow(m_hWnd);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CUIFMenuItem
CUIFMenuItem::CUIFMenuItem(
CUIFMenu *pMenu,
BOOL bDisabled) : CUIFObject(pMenu, 0, NULL, 0)
{
m_ichMenuItemPrefix = -1;
m_nMenuItemID = 0;
m_pszMenuItemLeft = m_pszMenuItemRight = NULL;
m_cchMenuItemLeft = m_cchMenuItemRight = 0;
m_nMenuItemVKey = 0;
m_hbmColor = m_hbmMask = NULL;
m_bMenuItemChecked = m_bMenuItemGrayed = FALSE;
m_bMenuItemDisabled = bDisabled;
m_pMenu = pMenu;
}
CUIFMenuItem::~CUIFMenuItem()
{
if (m_pszMenuItemLeft)
{
delete[] m_pszMenuItemLeft;
m_pszMenuItemLeft = NULL;
}
if (m_pszMenuItemRight)
{
delete[] m_pszMenuItemRight;
m_pszMenuItemRight = NULL;
}
if (m_pSubMenu)
{
delete m_pSubMenu;
m_pSubMenu = NULL;
}
}
BOOL CUIFMenuItem::Init(UINT nMenuItemID, LPCWSTR pszText)
{
m_nMenuItemID = nMenuItemID;
if (!pszText)
{
m_pszMenuItemLeft = NULL;
m_cchMenuItemLeft = 0;
return TRUE;
}
INT cch = lstrlenW(pszText);
m_pszMenuItemLeft = new(cicNoThrow) WCHAR[cch + 1];
if (!m_pszMenuItemLeft)
return FALSE;
const WCHAR *pch0 = pszText;
INT ich1, ich2;
for (ich1 = 0; *pch0 && *pch0 != L'\t'; ++ich1, ++pch0)
{
if (*pch0 == L'&' && *++pch0 != L'&')
{
m_nMenuItemVKey = ::VkKeyScanW(*pch0);
if (!m_nMenuItemVKey)
m_nMenuItemVKey = (BYTE)VkKeyScanA(*(BYTE*)pch0);
m_ichMenuItemPrefix = ich1;
}
m_pszMenuItemLeft[ich1] = *pch0;
}
m_pszMenuItemLeft[ich1] = 0;
m_cchMenuItemLeft = lstrlenW(m_pszMenuItemLeft);
if (*pch0 == L'\t')
{
m_cchMenuItemRight = 0;
m_pszMenuItemRight = new(cicNoThrow) WCHAR[cch + 1];
if (m_pszMenuItemRight)
{
++pch0;
WCHAR wch = *pch0;
for (ich2 = 0; *pch0; ++ich2)
{
m_pszMenuItemRight[ich2] = wch;
wch = *++pch0;
}
m_pszMenuItemRight[ich2] = 0;
m_cchMenuItemRight = lstrlenW(m_pszMenuItemRight);
}
}
return TRUE;
}
STDMETHODIMP_(void)
CUIFMenuItem::InitMenuExtent()
{
if (!m_pszMenuItemLeft)
{
if (m_hbmColor)
{
BITMAP bm;
::GetObject(m_hbmColor, sizeof(bm), &bm);
m_MenuLeftExtent.cx = bm.bmWidth + 2;
m_MenuLeftExtent.cy = bm.bmHeight + 4;
}
else
{
m_MenuLeftExtent.cx = m_MenuLeftExtent.cy = 0;
}
return;
}
HDC hDC = ::GetDC(*m_pWindow);
HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
::GetTextExtentPoint32W(hDC, m_pszMenuItemLeft, m_cchMenuItemLeft, &m_MenuLeftExtent);
m_MenuLeftExtent.cx += 16;
m_MenuLeftExtent.cy += 8;
if (m_pszMenuItemRight)
{
::GetTextExtentPoint32W(hDC, m_pszMenuItemRight, m_cchMenuItemRight, &m_MenuRightExtent);
m_MenuRightExtent.cy += 8;
}
::SelectObject(hDC, hFontOld);
if (m_pSubMenu)
m_MenuLeftExtent.cx += m_MenuLeftExtent.cy + 2;
if (m_pMenu->m_style & UIF_MENU_USE_OFF10)
m_MenuLeftExtent.cx += 24;
::ReleaseDC(*m_pWindow, hDC);
}
BOOL CUIFMenuItem::IsCheck()
{
return m_bMenuItemChecked || m_bMenuItemForceChecked;
}
void CUIFMenuItem::DrawArrow(HDC hDC, INT xLeft, INT yTop)
{
if (!m_pSubMenu)
return;
HGDIOBJ hFontOld = ::SelectObject(hDC, m_pMenu->m_hMenuFont);
::TextOutW(hDC, xLeft, yTop, L"4", 1); // rightward triangle
::SelectObject(hDC, hFontOld);
}
void CUIFMenuItem::DrawBitmapProc(HDC hDC, INT xLeft, INT yTop)
{
if (!m_pScheme || !m_hbmColor)
return;
BITMAP bm;
::GetObject(m_hbmColor, sizeof(bm), &bm);
INT width = m_pMenu->m_cxyMargin, height = m_rc.bottom - m_rc.top;
if (width > bm.bmWidth)
{
width = bm.bmWidth;
xLeft += (width - bm.bmWidth) / 2;
}
if (height > bm.bmHeight)
{
height = bm.bmHeight;
yTop += (height - bm.bmHeight) / 2;
}
RECT rc = { xLeft, yTop, xLeft + width, yTop + height };
if (IsRTL())
m_pScheme->m_bMirroring = TRUE;
if (m_pMenu->m_pSelectedItem != this || m_bMenuItemDisabled)
m_pScheme->DrawFrameCtrlBitmap(hDC, &rc, m_hbmColor, m_hbmMask, 0);
else
m_pScheme->DrawFrameCtrlBitmap(hDC, &rc, m_hbmColor, m_hbmMask, UIF_DRAW_PRESSED);
if (IsRTL())
m_pScheme->m_bMirroring = FALSE;
}
void CUIFMenuItem::DrawCheck(HDC hDC, INT xLeft, INT yTop)
{
if (!IsCheck())
return;
HGDIOBJ hFontOld = ::SelectObject(hDC, m_pMenu->m_hMenuFont);
WCHAR wch = (m_bMenuItemChecked ? L'a' : L'h'); // checkmark or bullet
::TextOutW(hDC, xLeft, yTop, &wch, 1);
::SelectObject(hDC, hFontOld);
}
void
CUIFMenuItem::DrawUnderline(HDC hDC, INT xText, INT yText, HBRUSH hbr)
{
if (m_ichMenuItemPrefix > m_cchMenuItemLeft)
return;
SIZE PrePrefixSize, PostPrefixSize;
::GetTextExtentPoint32W(hDC, m_pszMenuItemLeft, m_ichMenuItemPrefix, &PrePrefixSize);
::GetTextExtentPoint32W(hDC, m_pszMenuItemLeft, m_ichMenuItemPrefix + 1, &PostPrefixSize);
BOOL bHeadPrefix = (m_ichMenuItemPrefix == 0);
RECT rc;
rc.left = xText + PrePrefixSize.cx + !bHeadPrefix;
rc.right = xText + PostPrefixSize.cx;
rc.top = (yText + PostPrefixSize.cy) - 1;
rc.bottom = yText + PostPrefixSize.cy;
::FillRect(hDC, &rc, hbr);
}
STDMETHODIMP_(void)
CUIFMenuItem::OnLButtonUp(LONG x, LONG y)
{
if (!m_bMenuItemGrayed && !m_bMenuItemDisabled && !m_pSubMenu)
{
m_pMenu->SetSelectedId(m_nMenuItemID);
::PostMessage(*m_pWindow, WM_NULL, 0, 0);
}
}
STDMETHODIMP_(void)
CUIFMenuItem::OnMouseIn(LONG x, LONG y)
{
if (m_pMenu->m_pParentMenu)
m_pMenu->m_pParentMenu->CancelMenu();
if (m_pSubMenu)
{
DWORD Delay;
if (!::SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &Delay, 0))
Delay = 300;
CUIFObject::StartTimer(Delay);
}
m_pMenu->SetSelectedItem(this);
}
STDMETHODIMP_(void)
CUIFMenuItem::OnPaint(HDC hDC)
{
if (m_pMenu->m_style & UIF_MENU_USE_OFF10)
OnPaintO10(hDC);
else
OnPaintDef(hDC);
}
STDMETHODIMP_(void)
CUIFMenuItem::OnPaintO10(HDC hDC)
{
if (!m_pScheme)
return;
HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
SIZE textSize;
::GetTextExtentPoint32W(hDC, m_pszMenuItemLeft, m_cchMenuItemLeft, &textSize);
LONG cySpace = m_rc.bottom - m_rc.top - textSize.cy;
LONG xCheck = m_rc.left, yCheck = m_rc.top + cySpace / 2;
LONG cxyMargin = (m_pMenu->m_bHasMargin ? m_pMenu->m_cxyMargin : 0);
LONG xBitmap = m_rc.left + cxyMargin, yBitmap = m_rc.top;
LONG xText = m_rc.left + m_pMenu->m_cxyMargin + cxyMargin + 8;
LONG yText = m_rc.top + cySpace / 2;
LONG xArrow = m_rc.left - textSize.cy + m_rc.right - 2;
LONG xRightText = m_rc.right - m_pMenu->m_cxMenuExtent - 8;
RECT rc;
GetRect(&rc);
if (m_bMenuItemDisabled || m_pMenu->m_pSelectedItem != this)
{
rc.right = m_pMenu->m_cxyMargin + rc.left + 2;
if (m_pMenu->m_bHasMargin)
rc.right += m_pMenu->m_cxyMargin;
::FillRect(hDC, &rc, m_pScheme->GetBrush(9));
}
else
{
m_pScheme->DrawCtrlBkgd(hDC, &rc, 0, UIF_DRAW_PRESSED);
m_pScheme->DrawCtrlEdge(hDC, &rc, 0, UIF_DRAW_PRESSED);
}
::SetBkMode(hDC, TRANSPARENT);
if (m_bMenuItemGrayed)
{
::SetTextColor(hDC, m_pScheme->GetColor(11));
::ExtTextOutW(hDC, xText, yText, ETO_CLIPPED, &m_rc, m_pszMenuItemLeft,
m_cchMenuItemLeft, NULL);
}
else if (m_bMenuItemDisabled || m_pMenu->m_pSelectedItem != this)
{
::SetTextColor(hDC, m_pScheme->GetColor(10));
::ExtTextOutW(hDC, xText, yText, ETO_CLIPPED, &m_rc, m_pszMenuItemLeft,
m_cchMenuItemLeft, NULL);
}
else
{
::SetTextColor(hDC, m_pScheme->GetColor(5));
::ExtTextOutW(hDC, xText, yText, ETO_CLIPPED, &m_rc, m_pszMenuItemLeft,
m_cchMenuItemLeft, NULL);
}
DrawUnderline(hDC, xText, yText, m_pScheme->GetBrush(5));
if (m_pszMenuItemRight)
{
::ExtTextOutW(hDC, xRightText, yText, ETO_CLIPPED, &m_rc, m_pszMenuItemRight,
m_cchMenuItemRight, NULL);
}
DrawCheck(hDC, xCheck, yCheck);
DrawBitmapProc(hDC, xBitmap, yBitmap);
DrawArrow(hDC, xArrow, yText);
::SelectObject(hDC, hFontOld);
}
STDMETHODIMP_(void)
CUIFMenuItem::OnPaintDef(HDC hDC)
{
HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
SIZE textSize;
::GetTextExtentPoint32W(hDC, m_pszMenuItemLeft, m_cchMenuItemLeft, &textSize);
LONG cxyMargin = (m_pMenu->m_bHasMargin ? m_pMenu->m_cxyMargin : 0);
LONG cySpace = m_rc.bottom - m_rc.top - textSize.cy;
LONG xCheck = m_rc.left, yCheck = m_rc.top + cySpace / 2;
LONG xBitmap = m_rc.left + cxyMargin, yBitmap = m_rc.top;
LONG xText = m_rc.left + cxyMargin + m_pMenu->m_cxyMargin + 2;
LONG yText = m_rc.top + cySpace / 2;
LONG xArrow = m_rc.right + m_rc.left - 10;
::SetBkMode(hDC, TRANSPARENT);
if (m_bMenuItemGrayed)
{
UINT uOptions = ETO_CLIPPED;
if (m_bMenuItemDisabled || m_pMenu->m_pSelectedItem != this)
{
::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHIGHLIGHT));
::ExtTextOutW(hDC, xText + 1, yText + 1, ETO_CLIPPED, &m_rc, m_pszMenuItemLeft,
m_cchMenuItemLeft, NULL);
DrawCheck(hDC, xCheck + 1, yCheck + 1);
DrawBitmapProc(hDC, xBitmap + 1, yBitmap + 1);
DrawArrow(hDC, xArrow + 1, yText + 1);
}
else
{
::SetBkColor(hDC, ::GetSysColor(COLOR_HIGHLIGHT));
uOptions = ETO_CLIPPED | ETO_OPAQUE;
}
::SetTextColor(hDC, ::GetSysColor(COLOR_BTNSHADOW));
::ExtTextOutW(hDC, xText, yText, uOptions, &m_rc, m_pszMenuItemLeft,
m_cchMenuItemLeft, NULL);
DrawUnderline(hDC, xText, yText, (HBRUSH)UlongToHandle(COLOR_BTNSHADOW + 1));
}
else if (m_bMenuItemDisabled || m_pMenu->m_pSelectedItem != this)
{
::SetTextColor(hDC, ::GetSysColor(COLOR_MENUTEXT));
::ExtTextOutW(hDC, xText, yText, ETO_CLIPPED, &m_rc, m_pszMenuItemLeft,
m_cchMenuItemLeft, NULL);
DrawUnderline(hDC, xText, yText, (HBRUSH)UlongToHandle(COLOR_MENUTEXT + 1));
}
else
{
::SetTextColor(hDC, ::GetSysColor(COLOR_HIGHLIGHTTEXT));
::SetBkColor(hDC, ::GetSysColor(COLOR_HIGHLIGHT));
::ExtTextOutW(hDC, xText, yText, ETO_CLIPPED | ETO_OPAQUE, &m_rc,
m_pszMenuItemLeft, m_cchMenuItemLeft, NULL);
DrawUnderline(hDC, xText, yText, (HBRUSH)UlongToHandle(COLOR_HIGHLIGHTTEXT + 1));
}
DrawCheck(hDC, xCheck, yCheck);
DrawBitmapProc(hDC, xBitmap, yBitmap);
DrawArrow(hDC, xArrow, yText);
::SelectObject(hDC, hFontOld);
}
STDMETHODIMP_(void)
CUIFMenuItem::OnTimer()
{
CUIFObject::EndTimer();
if (m_pMenu->m_pPointed == this)
ShowSubPopup();
}
void CUIFMenuItem::SetBitmapMask(HBITMAP hbmMask)
{
m_hbmMask = hbmMask;
CallOnPaint();
}
void CUIFMenuItem::ShowSubPopup()
{
RECT rc = m_rc;
::ClientToScreen(*m_pWindow, (LPPOINT)&rc);
::ClientToScreen(*m_pWindow, (LPPOINT)&rc.right);
m_pSubMenu->ShowSubPopup(m_pMenu, &rc, FALSE);
}
/////////////////////////////////////////////////////////////////////////////
// CUIFMenuItemSeparator
CUIFMenuItemSeparator::CUIFMenuItemSeparator(CUIFMenu *pMenu) : CUIFMenuItem(pMenu, TRUE)
{
m_nMenuItemID = -1;
}
STDMETHODIMP_(void)
CUIFMenuItemSeparator::InitMenuExtent()
{
m_MenuLeftExtent.cx = 0;
m_MenuLeftExtent.cy = 6;
}
STDMETHODIMP_(void)
CUIFMenuItemSeparator::OnPaintDef(HDC hDC)
{
if (!m_pScheme)
return;
RECT rc;
rc.left = m_rc.left + 2;
rc.top = m_rc.top + (m_rc.bottom - m_rc.top - 2) / 2;
rc.right = m_rc.right - 2;
rc.bottom = rc.top + 2;
m_pScheme->DrawMenuSeparator(hDC, &rc);
}
STDMETHODIMP_(void)
CUIFMenuItemSeparator::OnPaintO10(HDC hDC)
{
if (!m_pScheme)
return;
LONG cx = m_rc.right - m_rc.left - 4;
LONG cy = (m_rc.bottom - m_rc.top - 2) / 2;
RECT rc;
GetRect(&rc);
rc.right = rc.left + m_pMenu->m_cxyMargin + 2;
if (m_pMenu->m_bHasMargin)
rc.right += m_pMenu->m_cxyMargin;
HBRUSH hBrush = m_pScheme->GetBrush(9);
::FillRect(hDC, &rc, hBrush);
rc = {
m_rc.left + m_pMenu->m_cxyMargin + 4,
m_rc.top + cy,
m_rc.left + cx + 2,
m_rc.top + cy + 1
};
m_pScheme->DrawMenuSeparator(hDC, &rc);
}
/////////////////////////////////////////////////////////////////////////////
void cicGetWorkAreaRect(POINT pt, LPRECT prc)
{
::SystemParametersInfo(SPI_GETWORKAREA, 0, prc, 0);
HMONITOR hMon = ::MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
if (hMon)
{
MONITORINFO mi = { sizeof(mi) };
if (::GetMonitorInfo(hMon, &mi))
*prc = mi.rcWork;
}
}
void cicGetScreenRect(POINT pt, LPRECT prc)
{
*prc = { 0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN) };
HMONITOR hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
if (hMon)
{
MONITORINFO mi = { sizeof(mi) };
GetMonitorInfo(hMon, &mi);
*prc = mi.rcMonitor;
}
}
BOOL cicIsFullScreenSize(HWND hWnd)
{
RECT rc;
::GetWindowRect(hWnd, &rc);
return (rc.left <= 0) && (rc.top <= 0) &&
(rc.right >= GetSystemMetrics(SM_CXFULLSCREEN)) &&
(rc.bottom >= GetSystemMetrics(SM_CYFULLSCREEN));
}
BOOL cicGetIconSize(HICON hIcon, LPSIZE pSize)
{
ICONINFO IconInfo;
if (!GetIconInfo(hIcon, &IconInfo))
return FALSE;
BITMAP bm;
::GetObject(IconInfo.hbmColor, sizeof(bm), &bm);
::DeleteObject(IconInfo.hbmColor);
::DeleteObject(IconInfo.hbmMask);
pSize->cx = bm.bmWidth;
pSize->cy = bm.bmHeight;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
void cicInitUIFSys(void)
{
CUIFSystemInfo::s_pSystemInfo = new(cicNoThrow) CUIFSystemInfo();
if (CUIFSystemInfo::s_pSystemInfo)
CUIFSystemInfo::s_pSystemInfo->Initialize();
}
void cicDoneUIFSys(void)
{
if (CUIFSystemInfo::s_pSystemInfo)
{
delete CUIFSystemInfo::s_pSystemInfo;
CUIFSystemInfo::s_pSystemInfo = NULL;
}
}
void cicUpdateUIFSys(void)
{
if (CUIFSystemInfo::s_pSystemInfo)
CUIFSystemInfo::s_pSystemInfo->GetSystemMetrics();
}
/////////////////////////////////////////////////////////////////////////////
void cicInitUIFScheme(void)
{
CUIFColorTable *pColorTable;
pColorTable = CUIFScheme::s_pColorTableSys = new(cicNoThrow) CUIFColorTableSys();
if (pColorTable)
{
pColorTable->InitColor();
pColorTable->InitBrush();
}
pColorTable = CUIFScheme::s_pColorTableOff10 = new(cicNoThrow) CUIFColorTableOff10();
if (pColorTable)
{
pColorTable->InitColor();
pColorTable->InitBrush();
}
}
void cicUpdateUIFScheme(void)
{
if (CUIFScheme::s_pColorTableSys)
CUIFScheme::s_pColorTableSys->Update();
if (CUIFScheme::s_pColorTableOff10)
CUIFScheme::s_pColorTableOff10->Update();
}
void cicDoneUIFScheme(void)
{
if (CUIFScheme::s_pColorTableSys)
{
delete CUIFScheme::s_pColorTableSys;
CUIFScheme::s_pColorTableSys = NULL;
}
if (CUIFScheme::s_pColorTableOff10)
{
delete CUIFScheme::s_pColorTableOff10;
CUIFScheme::s_pColorTableOff10 = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////
void cicInitUIFLib(void)
{
cicInitUIFSys();
cicInitUIFScheme();
cicInitUIFUtil();
}
void cicDoneUIFLib(void)
{
cicDoneUIFScheme();
cicDoneUIFSys();
cicDoneUIFUtil();
}
/////////////////////////////////////////////////////////////////////////////