1 /*
2 * PROJECT: ReactOS Cicero
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Cicero UIF Library
5 * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8 #include "precomp.h"
9 #include "cicuif.h"
10
11 /////////////////////////////////////////////////////////////////////////////
12 // static members
13
14 HINSTANCE CUIFTheme::s_hUXTHEME = NULL;
15 FN_OpenThemeData CUIFTheme::s_fnOpenThemeData = NULL;
16 FN_CloseThemeData CUIFTheme::s_fnCloseThemeData = NULL;
17 FN_DrawThemeBackground CUIFTheme::s_fnDrawThemeBackground = NULL;
18 FN_DrawThemeParentBackground CUIFTheme::s_fnDrawThemeParentBackground = NULL;
19 FN_DrawThemeText CUIFTheme::s_fnDrawThemeText = NULL;
20 FN_DrawThemeIcon CUIFTheme::s_fnDrawThemeIcon = NULL;
21 FN_GetThemeBackgroundExtent CUIFTheme::s_fnGetThemeBackgroundExtent = NULL;
22 FN_GetThemeBackgroundContentRect CUIFTheme::s_fnGetThemeBackgroundContentRect = NULL;
23 FN_GetThemeTextExtent CUIFTheme::s_fnGetThemeTextExtent = NULL;
24 FN_GetThemePartSize CUIFTheme::s_fnGetThemePartSize = NULL;
25 FN_DrawThemeEdge CUIFTheme::s_fnDrawThemeEdge = NULL;
26 FN_GetThemeColor CUIFTheme::s_fnGetThemeColor = NULL;
27 FN_GetThemeMargins CUIFTheme::s_fnGetThemeMargins = NULL;
28 FN_GetThemeFont CUIFTheme::s_fnGetThemeFont = NULL;
29 FN_GetThemeSysColor CUIFTheme::s_fnGetThemeSysColor = NULL;
30 FN_GetThemeSysSize CUIFTheme::s_fnGetThemeSysSize = NULL;
31
32 CUIFSystemInfo *CUIFSystemInfo::s_pSystemInfo = NULL;
33
34 CUIFColorTableSys *CUIFScheme::s_pColorTableSys = NULL;
35 CUIFColorTableOff10 *CUIFScheme::s_pColorTableOff10 = NULL;
36
37 /////////////////////////////////////////////////////////////////////////////
38
GetSystemMetrics()39 void CUIFSystemInfo::GetSystemMetrics()
40 {
41 HDC hDC = ::GetDC(NULL);
42 m_cBitsPixels = ::GetDeviceCaps(hDC, BITSPIXEL);
43 ::ReleaseDC(NULL, hDC);
44
45 HIGHCONTRAST HighContrast = { sizeof(HighContrast) };
46 ::SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(HighContrast), &HighContrast, 0);
47 m_bHighContrast1 = !!(HighContrast.dwFlags & HCF_HIGHCONTRASTON);
48 COLORREF rgbBtnText = ::GetSysColor(COLOR_BTNTEXT);
49 COLORREF rgbBtnFace = ::GetSysColor(COLOR_BTNFACE);
50 const COLORREF black = RGB(0, 0, 0), white = RGB(255, 255, 255);
51 m_bHighContrast2 = (m_bHighContrast1 ||
52 (rgbBtnText == black && rgbBtnFace == white) ||
53 (rgbBtnText == white && rgbBtnFace == black));
54 }
55
Initialize()56 void CUIFSystemInfo::Initialize()
57 {
58 dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
59 ::GetVersionEx(this);
60 GetSystemMetrics();
61 }
62
63 /////////////////////////////////////////////////////////////////////////////
64 // CUIFTheme
65
InternalOpenThemeData(HWND hWnd)66 HRESULT CUIFTheme::InternalOpenThemeData(HWND hWnd)
67 {
68 if (!hWnd || !m_pszClassList)
69 return E_FAIL;
70
71 if (!cicGetFN(s_hUXTHEME, s_fnOpenThemeData, TEXT("uxtheme.dll"), "OpenThemeData"))
72 return E_FAIL;
73 m_hTheme = s_fnOpenThemeData(hWnd, m_pszClassList);
74 return (m_hTheme ? S_OK : E_FAIL);
75 }
76
EnsureThemeData(HWND hWnd)77 HRESULT CUIFTheme::EnsureThemeData(HWND hWnd)
78 {
79 if (m_hTheme)
80 return S_OK;
81 return InternalOpenThemeData(hWnd);
82 }
83
CloseThemeData()84 HRESULT CUIFTheme::CloseThemeData()
85 {
86 if (!m_hTheme)
87 return S_OK;
88
89 if (!cicGetFN(s_hUXTHEME, s_fnCloseThemeData, TEXT("uxtheme.dll"), "CloseThemeData"))
90 return E_FAIL;
91
92 HRESULT hr = s_fnCloseThemeData(m_hTheme);
93 m_hTheme = NULL;
94 return hr;
95 }
96
97 STDMETHODIMP
DrawThemeBackground(HDC hDC,int iStateId,LPCRECT pRect,LPCRECT pClipRect)98 CUIFTheme::DrawThemeBackground(HDC hDC, int iStateId, LPCRECT pRect, LPCRECT pClipRect)
99 {
100 if (!cicGetFN(s_hUXTHEME, s_fnDrawThemeBackground, TEXT("uxtheme.dll"), "DrawThemeBackground"))
101 return E_FAIL;
102 return s_fnDrawThemeBackground(m_hTheme, hDC, m_iPartId, iStateId, pRect, pClipRect);
103 }
104
105 STDMETHODIMP
DrawThemeParentBackground(HWND hwnd,HDC hDC,LPRECT prc)106 CUIFTheme::DrawThemeParentBackground(HWND hwnd, HDC hDC, LPRECT prc)
107 {
108 if (!cicGetFN(s_hUXTHEME, s_fnDrawThemeParentBackground, TEXT("uxtheme.dll"), "DrawThemeParentBackground"))
109 return E_FAIL;
110 return s_fnDrawThemeParentBackground(hwnd, hDC, prc);
111 }
112
113 STDMETHODIMP
DrawThemeText(HDC hDC,int iStateId,LPCWSTR pszText,int cchText,DWORD dwTextFlags,DWORD dwTextFlags2,LPCRECT pRect)114 CUIFTheme::DrawThemeText(HDC hDC, int iStateId, LPCWSTR pszText, int cchText, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect)
115 {
116 if (!cicGetFN(s_hUXTHEME, s_fnDrawThemeText, TEXT("uxtheme.dll"), "DrawThemeText"))
117 return E_FAIL;
118 return s_fnDrawThemeText(m_hTheme, hDC, m_iPartId, iStateId, pszText, cchText, dwTextFlags, dwTextFlags2, pRect);
119 }
120
121 STDMETHODIMP
DrawThemeIcon(HDC hDC,int iStateId,LPCRECT pRect,HIMAGELIST himl,int iImageIndex)122 CUIFTheme::DrawThemeIcon(HDC hDC, int iStateId, LPCRECT pRect, HIMAGELIST himl, int iImageIndex)
123 {
124 if (!cicGetFN(s_hUXTHEME, s_fnDrawThemeIcon, TEXT("uxtheme.dll"), "DrawThemeIcon"))
125 return E_FAIL;
126 return s_fnDrawThemeIcon(m_hTheme, hDC, m_iPartId, iStateId, pRect, himl, iImageIndex);
127 }
128
129 STDMETHODIMP
GetThemeBackgroundExtent(HDC hDC,int iStateId,LPCRECT pContentRect,LPRECT pExtentRect)130 CUIFTheme::GetThemeBackgroundExtent(HDC hDC, int iStateId, LPCRECT pContentRect, LPRECT pExtentRect)
131 {
132 if (!cicGetFN(s_hUXTHEME, s_fnGetThemeBackgroundExtent, TEXT("uxtheme.dll"), "GetThemeBackgroundExtent"))
133 return E_FAIL;
134 return s_fnGetThemeBackgroundExtent(m_hTheme, hDC, m_iPartId, iStateId, pContentRect, pExtentRect);
135 }
136
137 STDMETHODIMP
GetThemeBackgroundContentRect(HDC hDC,int iStateId,LPCRECT pBoundingRect,LPRECT pContentRect)138 CUIFTheme::GetThemeBackgroundContentRect(HDC hDC, int iStateId, LPCRECT pBoundingRect, LPRECT pContentRect)
139 {
140 if (!cicGetFN(s_hUXTHEME, s_fnGetThemeBackgroundContentRect, TEXT("uxtheme.dll"), "GetThemeBackgroundContentRect"))
141 return E_FAIL;
142 return s_fnGetThemeBackgroundContentRect(m_hTheme, hDC, m_iPartId, iStateId, pBoundingRect, pContentRect);
143 }
144
145 STDMETHODIMP
GetThemeTextExtent(HDC hDC,int iStateId,LPCWSTR pszText,int cchCharCount,DWORD dwTextFlags,LPCRECT pBoundingRect,LPRECT pExtentRect)146 CUIFTheme::GetThemeTextExtent(HDC hDC, int iStateId, LPCWSTR pszText, int cchCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect)
147 {
148 if (!cicGetFN(s_hUXTHEME, s_fnGetThemeTextExtent, TEXT("uxtheme.dll"), "GetThemeTextExtent"))
149 return E_FAIL;
150 return s_fnGetThemeTextExtent(m_hTheme, hDC, m_iPartId, iStateId, pszText, cchCharCount, dwTextFlags, pBoundingRect, pExtentRect);
151 }
152
153 STDMETHODIMP
GetThemePartSize(HDC hDC,int iStateId,LPRECT prc,THEMESIZE eSize,SIZE * psz)154 CUIFTheme::GetThemePartSize(HDC hDC, int iStateId, LPRECT prc, THEMESIZE eSize, SIZE *psz)
155 {
156 if (!cicGetFN(s_hUXTHEME, s_fnGetThemePartSize, TEXT("uxtheme.dll"), "GetThemePartSize"))
157 return E_FAIL;
158 return s_fnGetThemePartSize(m_hTheme, hDC, m_iPartId, iStateId, prc, eSize, psz);
159 }
160
161 STDMETHODIMP
DrawThemeEdge(HDC hDC,int iStateId,LPCRECT pDestRect,UINT uEdge,UINT uFlags,LPRECT pContentRect)162 CUIFTheme::DrawThemeEdge(HDC hDC, int iStateId, LPCRECT pDestRect, UINT uEdge, UINT uFlags, LPRECT pContentRect)
163 {
164 if (!cicGetFN(s_hUXTHEME, s_fnDrawThemeEdge, TEXT("uxtheme.dll"), "DrawThemeEdge"))
165 return E_FAIL;
166 return s_fnDrawThemeEdge(m_hTheme, hDC, m_iPartId, iStateId, pDestRect, uEdge, uFlags, pContentRect);
167 }
168
169 STDMETHODIMP
GetThemeColor(int iStateId,int iPropId,COLORREF * pColor)170 CUIFTheme::GetThemeColor(int iStateId, int iPropId, COLORREF *pColor)
171 {
172 if (!cicGetFN(s_hUXTHEME, s_fnGetThemeColor, TEXT("uxtheme.dll"), "GetThemeColor"))
173 return E_FAIL;
174 return s_fnGetThemeColor(m_hTheme, m_iPartId, iStateId, iPropId, pColor);
175 }
176
177 STDMETHODIMP
GetThemeMargins(HDC hDC,int iStateId,int iPropId,LPRECT prc,MARGINS * pMargins)178 CUIFTheme::GetThemeMargins(HDC hDC, int iStateId, int iPropId, LPRECT prc, MARGINS *pMargins)
179 {
180 if (!cicGetFN(s_hUXTHEME, s_fnGetThemeMargins, TEXT("uxtheme.dll"), "GetThemeMargins"))
181 return E_FAIL;
182 return s_fnGetThemeMargins(m_hTheme, hDC, m_iPartId, iStateId, iPropId, prc, pMargins);
183 }
184
185 STDMETHODIMP
GetThemeFont(HDC hDC,int iStateId,int iPropId,LOGFONTW * pFont)186 CUIFTheme::GetThemeFont(HDC hDC, int iStateId, int iPropId, LOGFONTW *pFont)
187 {
188 if (!cicGetFN(s_hUXTHEME, s_fnGetThemeFont, TEXT("uxtheme.dll"), "GetThemeFont"))
189 return E_FAIL;
190 return s_fnGetThemeFont(m_hTheme, hDC, m_iPartId, iStateId, iPropId, pFont);
191 }
192
STDMETHODIMP_(COLORREF)193 STDMETHODIMP_(COLORREF)
194 CUIFTheme::GetThemeSysColor(INT iColorId)
195 {
196 if (!cicGetFN(s_hUXTHEME, s_fnGetThemeSysColor, TEXT("uxtheme.dll"), "GetThemeSysColor"))
197 return RGB(0, 0, 0);
198 return s_fnGetThemeSysColor(m_hTheme, iColorId);
199 }
200
STDMETHODIMP_(int)201 STDMETHODIMP_(int)
202 CUIFTheme::GetThemeSysSize(int iSizeId)
203 {
204 if (!cicGetFN(s_hUXTHEME, s_fnGetThemeSysSize, TEXT("uxtheme.dll"), "GetThemeSysSize"))
205 return 0;
206 return s_fnGetThemeSysSize(m_hTheme, iSizeId);
207 }
208
STDMETHODIMP_(void)209 STDMETHODIMP_(void)
210 CUIFTheme::SetActiveTheme(LPCWSTR pszClassList, INT iPartId, INT iStateId)
211 {
212 m_iPartId = iPartId;
213 m_iStateId = iStateId;
214 m_pszClassList = pszClassList;
215 }
216
217 /////////////////////////////////////////////////////////////////////////////
218 // CUIFObject
219
220 /// @unimplemented
CUIFObject(CUIFObject * pParent,DWORD nObjectID,LPCRECT prc,DWORD style)221 CUIFObject::CUIFObject(CUIFObject *pParent, DWORD nObjectID, LPCRECT prc, DWORD style)
222 {
223 m_pszClassList = NULL;
224 m_hTheme = NULL;
225 m_pParent = pParent;
226 m_nObjectID = nObjectID;
227 m_style = style;
228
229 if (prc)
230 m_rc = *prc;
231 else
232 m_rc = { 0, 0, 0, 0 };
233
234 if (m_pParent)
235 {
236 m_pWindow = m_pParent->m_pWindow;
237 m_pScheme = m_pParent->m_pScheme;
238 }
239 else
240 {
241 m_pWindow = NULL;
242 m_pScheme = NULL;
243 }
244
245 m_bEnable = m_bVisible = TRUE;
246
247 m_hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
248 m_bHasCustomFont = FALSE;
249
250 m_pszToolTip = NULL;
251
252 m_dwUnknown4[0] = -1; //FIXME: name
253 m_dwUnknown4[1] = -1; //FIXME: name
254 }
255
~CUIFObject()256 CUIFObject::~CUIFObject()
257 {
258 if (m_pWindow)
259 {
260 CUIFToolTip *pToolTip = m_pWindow->m_pToolTip;
261 if (pToolTip && pToolTip->m_pToolTipTarget == this)
262 pToolTip->m_pToolTipTarget = NULL;
263 }
264
265 if (m_pszToolTip)
266 {
267 delete[] m_pszToolTip;
268 m_pszToolTip = NULL;
269 }
270
271 for (size_t iObj = m_ObjectArray.size(); iObj > 0; )
272 {
273 --iObj;
274 delete m_ObjectArray[iObj];
275 }
276 m_ObjectArray.clear();
277
278 if (m_pWindow)
279 m_pWindow->RemoveUIObj(this);
280
281 CloseThemeData();
282 }
283
STDMETHODIMP_(void)284 STDMETHODIMP_(void) CUIFObject::OnPaint(HDC hDC)
285 {
286 if (!(m_pWindow->m_style & UIF_WINDOW_ENABLETHEMED) || !OnPaintTheme(hDC))
287 OnPaintNoTheme(hDC);
288 }
289
STDMETHODIMP_(BOOL)290 STDMETHODIMP_(BOOL) CUIFObject::OnSetCursor(UINT uMsg, LONG x, LONG y)
291 {
292 return FALSE;
293 }
294
STDMETHODIMP_(void)295 STDMETHODIMP_(void) CUIFObject::GetRect(LPRECT prc)
296 {
297 *prc = m_rc;
298 }
299
STDMETHODIMP_(BOOL)300 STDMETHODIMP_(BOOL) CUIFObject::PtInObject(POINT pt)
301 {
302 return m_bVisible && ::PtInRect(&m_rc, pt);
303 }
304
STDMETHODIMP_(void)305 STDMETHODIMP_(void) CUIFObject::PaintObject(HDC hDC, LPCRECT prc)
306 {
307 if (!m_bVisible)
308 return;
309
310 if (!prc)
311 prc = &m_rc;
312
313 OnPaint(hDC);
314
315 for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
316 {
317 CUIFObject *pObject = m_ObjectArray[iItem];
318 RECT rc;
319 if (::IntersectRect(&rc, prc, &pObject->m_rc))
320 pObject->PaintObject(hDC, &rc);
321 }
322 }
323
STDMETHODIMP_(void)324 STDMETHODIMP_(void) CUIFObject::CallOnPaint()
325 {
326 if (m_pWindow)
327 m_pWindow->UpdateUI(&m_rc);
328 }
329
STDMETHODIMP_(void)330 STDMETHODIMP_(void) CUIFObject::Enable(BOOL bEnable)
331 {
332 if (m_bEnable == bEnable)
333 return;
334
335 m_bEnable = bEnable;
336 for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
337 m_ObjectArray[iItem]->Enable(bEnable);
338
339 CallOnPaint();
340 }
341
STDMETHODIMP_(void)342 STDMETHODIMP_(void) CUIFObject::Show(BOOL bVisible)
343 {
344 if (m_bVisible == bVisible)
345 return;
346
347 m_bVisible = bVisible;
348 for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
349 m_ObjectArray[iItem]->Show(bVisible);
350
351 if (m_bVisible || m_pParent)
352 m_pParent->CallOnPaint();
353 }
354
STDMETHODIMP_(void)355 STDMETHODIMP_(void) CUIFObject::SetFontToThis(HFONT hFont)
356 {
357 m_bHasCustomFont = !!hFont;
358 if (!hFont)
359 hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
360 m_hFont = hFont;
361 }
362
STDMETHODIMP_(void)363 STDMETHODIMP_(void) CUIFObject::SetFont(HFONT hFont)
364 {
365 SetFontToThis(hFont);
366
367 for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
368 m_ObjectArray[iItem]->SetFont(hFont);
369
370 CallOnPaint();
371 }
372
STDMETHODIMP_(void)373 STDMETHODIMP_(void) CUIFObject::SetStyle(DWORD style)
374 {
375 m_style = style;
376 }
377
STDMETHODIMP_(void)378 STDMETHODIMP_(void) CUIFObject::AddUIObj(CUIFObject *pObject)
379 {
380 m_ObjectArray.Add(pObject);
381 CallOnPaint();
382 }
383
STDMETHODIMP_(void)384 STDMETHODIMP_(void) CUIFObject::RemoveUIObj(CUIFObject *pObject)
385 {
386 if (m_ObjectArray.Remove(pObject))
387 CallOnPaint();
388 }
389
STDMETHODIMP_(LRESULT)390 STDMETHODIMP_(LRESULT) CUIFObject::OnObjectNotify(CUIFObject *pObject, WPARAM wParam, LPARAM lParam)
391 {
392 if (m_pParent)
393 return m_pParent->OnObjectNotify(pObject, wParam, lParam);
394 return 0;
395 }
396
STDMETHODIMP_(void)397 STDMETHODIMP_(void) CUIFObject::SetToolTip(LPCWSTR pszToolTip)
398 {
399 if (m_pszToolTip)
400 {
401 delete[] m_pszToolTip;
402 m_pszToolTip = NULL;
403 }
404
405 if (pszToolTip)
406 {
407 size_t cch = wcslen(pszToolTip);
408 m_pszToolTip = new(cicNoThrow) WCHAR[cch + 1];
409 if (m_pszToolTip)
410 lstrcpynW(m_pszToolTip, pszToolTip, cch + 1);
411 }
412 }
413
STDMETHODIMP_(void)414 STDMETHODIMP_(void) CUIFObject::ClearWndObj()
415 {
416 m_pWindow = NULL;
417 for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
418 m_ObjectArray[iItem]->ClearWndObj();
419 }
420
STDMETHODIMP_(void)421 STDMETHODIMP_(void) CUIFObject::ClearTheme()
422 {
423 CloseThemeData();
424 for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
425 m_ObjectArray[iItem]->ClearTheme();
426 }
427
StartCapture()428 void CUIFObject::StartCapture()
429 {
430 if (m_pWindow)
431 m_pWindow->SetCaptureObject(this);
432 }
433
EndCapture()434 void CUIFObject::EndCapture()
435 {
436 if (m_pWindow)
437 m_pWindow->SetCaptureObject(NULL);
438 }
439
IsCapture()440 BOOL CUIFObject::IsCapture()
441 {
442 return m_pWindow && (m_pWindow->m_pCaptured == this);
443 }
444
SetRect(LPCRECT prc)445 void CUIFObject::SetRect(LPCRECT prc)
446 {
447 m_rc = *prc;
448 if (m_pWindow)
449 m_pWindow->OnObjectMoved(this);
450 CallOnPaint();
451 }
452
NotifyCommand(WPARAM wParam,LPARAM lParam)453 LRESULT CUIFObject::NotifyCommand(WPARAM wParam, LPARAM lParam)
454 {
455 if (m_pParent)
456 return m_pParent->OnObjectNotify(this, wParam, lParam);
457 return 0;
458 }
459
DetachWndObj()460 void CUIFObject::DetachWndObj()
461 {
462 if (m_pWindow)
463 {
464 CUIFToolTip *pToolTip = m_pWindow->m_pToolTip;
465 if (pToolTip && pToolTip->m_pToolTipTarget == this)
466 pToolTip->m_pToolTipTarget = NULL;
467
468 m_pWindow->RemoveUIObj(this);
469 m_pWindow = NULL;
470 }
471 }
472
IsRTL()473 BOOL CUIFObject::IsRTL()
474 {
475 if (!m_pWindow)
476 return FALSE;
477 return !!(m_pWindow->m_style & UIF_WINDOW_LAYOUTRTL);
478 }
479
ObjectFromPoint(POINT pt)480 CUIFObject* CUIFObject::ObjectFromPoint(POINT pt)
481 {
482 if (!PtInObject(pt))
483 return NULL;
484
485 CUIFObject *pFound = this;
486 for (size_t i = 0; i < m_ObjectArray.size(); ++i)
487 {
488 CUIFObject *pObject = m_ObjectArray[i]->ObjectFromPoint(pt);
489 if (pObject)
490 pFound = pObject;
491 }
492 return pFound;
493 }
494
SetScheme(CUIFScheme * scheme)495 void CUIFObject::SetScheme(CUIFScheme *scheme)
496 {
497 m_pScheme = scheme;
498 for (size_t i = 0; i < m_ObjectArray.size(); ++i)
499 {
500 m_ObjectArray[i]->SetScheme(scheme);
501 }
502 }
503
StartTimer(WPARAM wParam)504 void CUIFObject::StartTimer(WPARAM wParam)
505 {
506 if (m_pWindow)
507 m_pWindow->SetTimerObject(this, wParam);
508 }
509
EndTimer()510 void CUIFObject::EndTimer()
511 {
512 if (m_pWindow)
513 m_pWindow->SetTimerObject(NULL, 0);
514 }
515
516 /////////////////////////////////////////////////////////////////////////////
517 // CUIFColorTable...
518
STDMETHODIMP_(void)519 STDMETHODIMP_(void) CUIFColorTableSys::InitColor()
520 {
521 m_rgbColors[0] = ::GetSysColor(COLOR_BTNFACE);
522 m_rgbColors[1] = ::GetSysColor(COLOR_BTNSHADOW);
523 m_rgbColors[2] = ::GetSysColor(COLOR_ACTIVEBORDER);
524 m_rgbColors[3] = ::GetSysColor(COLOR_ACTIVECAPTION);
525 m_rgbColors[4] = ::GetSysColor(COLOR_BTNFACE);
526 m_rgbColors[5] = ::GetSysColor(COLOR_BTNSHADOW);
527 m_rgbColors[6] = ::GetSysColor(COLOR_BTNTEXT);
528 m_rgbColors[7] = ::GetSysColor(COLOR_CAPTIONTEXT);
529 m_rgbColors[8] = ::GetSysColor(COLOR_GRAYTEXT);
530 m_rgbColors[9] = ::GetSysColor(COLOR_HIGHLIGHT);
531 m_rgbColors[10] = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
532 m_rgbColors[11] = ::GetSysColor(COLOR_INACTIVECAPTION);
533 m_rgbColors[12] = ::GetSysColor(COLOR_INACTIVECAPTIONTEXT);
534 m_rgbColors[13] = ::GetSysColor(COLOR_MENUTEXT);
535 m_rgbColors[14] = ::GetSysColor(COLOR_WINDOW);
536 m_rgbColors[15] = ::GetSysColor(COLOR_WINDOWTEXT);
537 }
538
STDMETHODIMP_(void)539 STDMETHODIMP_(void) CUIFColorTableSys::InitBrush()
540 {
541 ZeroMemory(m_hBrushes, sizeof(m_hBrushes));
542 }
543
STDMETHODIMP_(void)544 STDMETHODIMP_(void) CUIFColorTableSys::DoneBrush()
545 {
546 for (size_t i = 0; i < _countof(m_hBrushes); ++i)
547 {
548 if (m_hBrushes[i])
549 {
550 ::DeleteObject(m_hBrushes[i]);
551 m_hBrushes[i] = NULL;
552 }
553 }
554 }
555
GetBrush(INT iColor)556 HBRUSH CUIFColorTableSys::GetBrush(INT iColor)
557 {
558 if (!m_hBrushes[iColor])
559 m_hBrushes[iColor] = ::CreateSolidBrush(m_rgbColors[iColor]);
560 return m_hBrushes[iColor];
561 }
562
GetBrush(INT iColor)563 HBRUSH CUIFColorTableOff10::GetBrush(INT iColor)
564 {
565 if (!m_hBrushes[iColor])
566 m_hBrushes[iColor] = ::CreateSolidBrush(m_rgbColors[iColor]);
567 return m_hBrushes[iColor];
568 }
569
570 /// @unimplemented
STDMETHODIMP_(void)571 STDMETHODIMP_(void) CUIFColorTableOff10::InitColor()
572 {
573 m_rgbColors[0] = ::GetSysColor(COLOR_BTNFACE);
574 m_rgbColors[1] = ::GetSysColor(COLOR_WINDOW);
575 m_rgbColors[2] = ::GetSysColor(COLOR_WINDOW);
576 m_rgbColors[3] = ::GetSysColor(COLOR_BTNFACE);
577 m_rgbColors[4] = ::GetSysColor(COLOR_BTNSHADOW);
578 m_rgbColors[5] = ::GetSysColor(COLOR_WINDOW);
579 m_rgbColors[6] = ::GetSysColor(COLOR_HIGHLIGHT);
580 m_rgbColors[7] = ::GetSysColor(COLOR_WINDOWTEXT);
581 m_rgbColors[8] = ::GetSysColor(COLOR_HIGHLIGHT);
582 m_rgbColors[9] = ::GetSysColor(COLOR_HIGHLIGHT);
583 m_rgbColors[10] = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
584 m_rgbColors[11] = ::GetSysColor(COLOR_BTNFACE);
585 m_rgbColors[12] = ::GetSysColor(COLOR_BTNTEXT);
586 m_rgbColors[13] = ::GetSysColor(COLOR_BTNSHADOW);
587 m_rgbColors[14] = ::GetSysColor(COLOR_BTNFACE);
588 m_rgbColors[15] = ::GetSysColor(COLOR_WINDOW);
589 m_rgbColors[16] = ::GetSysColor(COLOR_HIGHLIGHT);
590 m_rgbColors[17] = ::GetSysColor(COLOR_BTNTEXT);
591 m_rgbColors[18] = ::GetSysColor(COLOR_WINDOW);
592 m_rgbColors[19] = ::GetSysColor(COLOR_BTNSHADOW);
593 m_rgbColors[20] = ::GetSysColor(COLOR_BTNFACE);
594 m_rgbColors[21] = ::GetSysColor(COLOR_BTNSHADOW);
595 m_rgbColors[22] = ::GetSysColor(COLOR_BTNFACE);
596 m_rgbColors[23] = ::GetSysColor(COLOR_BTNSHADOW);
597 m_rgbColors[24] = ::GetSysColor(COLOR_CAPTIONTEXT);
598 m_rgbColors[25] = ::GetSysColor(COLOR_HIGHLIGHT);
599 m_rgbColors[26] = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
600 m_rgbColors[27] = ::GetSysColor(COLOR_BTNFACE);
601 m_rgbColors[28] = ::GetSysColor(COLOR_BTNTEXT);
602 m_rgbColors[29] = ::GetSysColor(COLOR_BTNSHADOW);
603 m_rgbColors[30] = ::GetSysColor(COLOR_BTNTEXT);
604 m_rgbColors[31] = ::GetSysColor(COLOR_WINDOWTEXT);
605 }
606
STDMETHODIMP_(void)607 STDMETHODIMP_(void) CUIFColorTableOff10::InitBrush()
608 {
609 ZeroMemory(m_hBrushes, sizeof(m_hBrushes));
610 }
611
STDMETHODIMP_(void)612 STDMETHODIMP_(void) CUIFColorTableOff10::DoneBrush()
613 {
614 for (size_t i = 0; i < _countof(m_hBrushes); ++i)
615 {
616 if (m_hBrushes[i])
617 {
618 ::DeleteObject(m_hBrushes[i]);
619 m_hBrushes[i] = NULL;
620 }
621 }
622 }
623
624 /////////////////////////////////////////////////////////////////////////////
625 // CUIFScheme
626
627 /// @unimplemented
cicCreateUIFScheme(DWORD type)628 CUIFScheme *cicCreateUIFScheme(DWORD type)
629 {
630 #if 1
631 return new(cicNoThrow) CUIFSchemeDef(type);
632 #else
633 switch (type)
634 {
635 case 1: return new(cicNoThrow) CUIFSchemeOff10(1);
636 case 2: return new(cicNoThrow) CUIFSchemeOff10(2);
637 case 3: return new(cicNoThrow) CUIFSchemeOff10(3);
638 default: return new(cicNoThrow) CUIFSchemeDef(type);
639 }
640 #endif
641 }
642
STDMETHODIMP_(DWORD)643 STDMETHODIMP_(DWORD) CUIFSchemeDef::GetType()
644 {
645 return m_dwType;
646 }
647
STDMETHODIMP_(COLORREF)648 STDMETHODIMP_(COLORREF) CUIFSchemeDef::GetColor(INT iColor)
649 {
650 return s_pColorTableSys->GetColor(iColor);
651 }
652
STDMETHODIMP_(HBRUSH)653 STDMETHODIMP_(HBRUSH) CUIFSchemeDef::GetBrush(INT iColor)
654 {
655 return s_pColorTableSys->GetBrush(iColor);
656 }
657
STDMETHODIMP_(INT)658 STDMETHODIMP_(INT) CUIFSchemeDef::CyMenuItem(INT cyText)
659 {
660 return cyText + 2;
661 }
662
STDMETHODIMP_(INT)663 STDMETHODIMP_(INT) CUIFSchemeDef::CxSizeFrame()
664 {
665 return ::GetSystemMetrics(SM_CXSIZEFRAME);
666 }
667
STDMETHODIMP_(INT)668 STDMETHODIMP_(INT) CUIFSchemeDef::CySizeFrame()
669 {
670 return ::GetSystemMetrics(SM_CYSIZEFRAME);
671 }
672
STDMETHODIMP_(void)673 STDMETHODIMP_(void) CUIFScheme::FillRect(HDC hDC, LPCRECT prc, INT iColor)
674 {
675 ::FillRect(hDC, prc, GetBrush(iColor));
676 }
677
STDMETHODIMP_(void)678 STDMETHODIMP_(void) CUIFScheme::FrameRect(HDC hDC, LPCRECT prc, INT iColor)
679 {
680 ::FrameRect(hDC, prc, GetBrush(iColor));
681 }
682
STDMETHODIMP_(void)683 STDMETHODIMP_(void) CUIFSchemeDef::DrawSelectionRect(HDC hDC, LPCRECT prc, int)
684 {
685 ::FillRect(hDC, prc, GetBrush(6));
686 }
687
STDMETHODIMP_(void)688 STDMETHODIMP_(void)
689 CUIFSchemeDef::GetCtrlFaceOffset(DWORD dwUnknownFlags, DWORD dwDrawFlags, LPSIZE pSize)
690 {
691 if (!(dwDrawFlags & UIF_DRAW_PRESSED))
692 {
693 if (dwDrawFlags & 0x2)
694 {
695 if (dwUnknownFlags & 0x10)
696 {
697 pSize->cx = pSize->cy = -1;
698 return;
699 }
700 pSize->cx = pSize->cy = !!(dwUnknownFlags & 0x20);
701 }
702 else
703 {
704 if (!(dwDrawFlags & 0x1))
705 {
706 pSize->cx = pSize->cy = -((dwUnknownFlags & 1) != 0);
707 return;
708 }
709 if (dwUnknownFlags & 0x4)
710 {
711 pSize->cx = pSize->cy = -1;
712 return;
713 }
714 pSize->cx = pSize->cy = !!(dwUnknownFlags & 0x8);
715 }
716 return;
717 }
718
719 if (!(dwUnknownFlags & 0x40))
720 {
721 pSize->cx = pSize->cy = !!(dwUnknownFlags & 0x80);
722 return;
723 }
724
725 pSize->cx = pSize->cy = -1;
726 }
727
STDMETHODIMP_(void)728 STDMETHODIMP_(void)
729 CUIFSchemeDef::DrawCtrlBkgd(HDC hDC, LPCRECT prc, DWORD dwUnknownFlags, DWORD dwDrawFlags)
730 {
731 ::FillRect(hDC, prc, GetBrush(9));
732
733 if (!(dwDrawFlags & UIF_DRAW_PRESSED) && (dwDrawFlags & 0x2))
734 return;
735
736 HBRUSH hbrDither = cicCreateDitherBrush();
737 if (!hbrDither)
738 return;
739
740 COLORREF rgbOldText = ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNFACE));
741 COLORREF rgbOldBack = ::SetBkColor(hDC, ::GetSysColor(COLOR_BTNHIGHLIGHT));
742
743 RECT rc = *prc;
744 ::InflateRect(&rc, -2, -2);
745 ::FillRect(hDC, &rc, hbrDither);
746 ::SetTextColor(hDC, rgbOldText);
747 ::SetBkColor(hDC, rgbOldBack);
748 ::DeleteObject(hbrDither);
749 }
750
STDMETHODIMP_(void)751 STDMETHODIMP_(void)
752 CUIFSchemeDef::DrawCtrlEdge(
753 HDC hDC,
754 LPCRECT prc,
755 DWORD dwUnknownFlags,
756 DWORD dwDrawFlags)
757 {
758 UINT uEdge = BDR_RAISEDINNER;
759
760 if (dwDrawFlags & 0x10)
761 {
762 if (!(dwUnknownFlags & 0x40))
763 {
764 if (dwUnknownFlags & 0x80)
765 uEdge = BDR_SUNKENOUTER;
766 else
767 return;
768 }
769 }
770 else if (dwDrawFlags & 0x2)
771 {
772 if (!(dwUnknownFlags & 0x10))
773 {
774 if (dwUnknownFlags & 0x20)
775 uEdge = BDR_SUNKENOUTER;
776 else
777 return;
778 }
779 }
780 else if (dwDrawFlags & 0x1)
781 {
782 if (!(dwUnknownFlags & 0x4))
783 {
784 if (dwUnknownFlags & 0x8)
785 uEdge = BDR_SUNKENOUTER;
786 else
787 return;
788 }
789 }
790 else if (!(dwUnknownFlags & 0x1))
791 {
792 return;
793 }
794
795 RECT rc = *prc;
796 ::DrawEdge(hDC, &rc, uEdge, BF_RECT);
797 }
798
STDMETHODIMP_(void)799 STDMETHODIMP_(void)
800 CUIFSchemeDef::DrawCtrlText(
801 HDC hDC,
802 LPCRECT prc,
803 LPCWSTR pszText,
804 INT cchText,
805 DWORD dwDrawFlags,
806 BOOL bRight)
807 {
808 COLORREF rgbOldText = ::GetTextColor(hDC);
809 INT OldBkMode = ::SetBkMode(hDC, TRANSPARENT);
810
811 if (cchText == -1)
812 cchText = lstrlenW(pszText);
813
814 RECT rc = *prc;
815 if (dwDrawFlags & UIF_DRAW_DISABLED)
816 {
817 ::OffsetRect(&rc, 1, 1);
818 ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHIGHLIGHT));
819 ::ExtTextOutW(hDC, (bRight ? rc.right : rc.left), rc.top, ETO_CLIPPED, &rc,
820 pszText, cchText, NULL);
821 ::OffsetRect(&rc, -1, -1);
822 }
823
824 ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNTEXT));
825 ::ExtTextOutW(hDC, (bRight ? rc.right : rc.left), rc.top, ETO_CLIPPED, &rc,
826 pszText, cchText, NULL);
827
828 ::SetTextColor(hDC, rgbOldText);
829 ::SetBkMode(hDC, OldBkMode);
830 }
831
STDMETHODIMP_(void)832 STDMETHODIMP_(void)
833 CUIFSchemeDef::DrawCtrlIcon(HDC hDC, LPCRECT prc, HICON hIcon, DWORD dwDrawFlags, LPSIZE pSize)
834 {
835 if (m_bMirroring)
836 {
837 HBITMAP hbm1, hbm2;
838 if (cicGetIconBitmaps(hIcon, &hbm1, &hbm2, pSize))
839 {
840 DrawCtrlBitmap(hDC, prc, hbm1, hbm2, dwDrawFlags);
841 ::DeleteObject(hbm1);
842 ::DeleteObject(hbm2);
843 }
844 }
845 else
846 {
847 UINT uFlags = DST_PREFIXTEXT | DST_TEXT;
848 if (dwDrawFlags & UIF_DRAW_DISABLED)
849 uFlags |= (DSS_MONO | DSS_DISABLED);
850 ::DrawState(hDC, 0, 0, (LPARAM)hIcon, 0, prc->left, prc->top, 0, 0, uFlags);
851 }
852 }
853
STDMETHODIMP_(void)854 STDMETHODIMP_(void)
855 CUIFSchemeDef::DrawCtrlBitmap(HDC hDC, LPCRECT prc, HBITMAP hbm1, HBITMAP hbm2, DWORD dwDrawFlags)
856 {
857 if (m_bMirroring)
858 {
859 hbm1 = cicMirrorBitmap(hbm1, GetBrush(9));
860 hbm2 = cicMirrorBitmap(hbm2, (HBRUSH)GetStockObject(BLACK_BRUSH));
861 }
862
863 HBRUSH hBrush = (HBRUSH)UlongToHandle(COLOR_BTNFACE + 1);
864 BOOL bBrushCreated = FALSE;
865 if (hbm2)
866 {
867 HBITMAP hBitmap = NULL;
868 if (dwDrawFlags & UIF_DRAW_DISABLED)
869 {
870 hBitmap = cicCreateDisabledBitmap(prc, hbm2, GetBrush(9), GetBrush(11), TRUE);
871 }
872 else
873 {
874 if ((dwDrawFlags & UIF_DRAW_PRESSED) && !(dwDrawFlags & 0x2))
875 {
876 hBrush = cicCreateDitherBrush();
877 bBrushCreated = TRUE;
878 }
879
880 COLORREF rgbFace = ::GetSysColor(COLOR_BTNFACE);
881 COLORREF rgbHighlight = ::GetSysColor(COLOR_BTNHIGHLIGHT);
882 hBitmap = cicCreateMaskBmp(prc, hbm1, hbm2, hBrush, rgbFace, rgbHighlight);
883 }
884
885 if (hBitmap)
886 {
887 ::DrawState(hDC, NULL, NULL, (LPARAM)hBitmap, 0,
888 prc->left, prc->top,
889 prc->right - prc->left, prc->bottom - prc->top,
890 DST_BITMAP);
891 ::DeleteObject(hBitmap);
892 }
893 }
894 else
895 {
896 UINT uFlags = DST_BITMAP;
897 if (dwDrawFlags & UIF_DRAW_DISABLED)
898 uFlags |= (DSS_MONO | DSS_DISABLED);
899
900 ::DrawState(hDC, NULL, NULL, (LPARAM)hbm1, 0,
901 prc->left, prc->top,
902 prc->right - prc->left, prc->bottom - prc->top,
903 uFlags);
904 }
905
906 if (bBrushCreated)
907 ::DeleteObject(hBrush);
908
909 if (m_bMirroring)
910 {
911 ::DeleteObject(hbm1);
912 ::DeleteObject(hbm2);
913 }
914 }
915
STDMETHODIMP_(void)916 STDMETHODIMP_(void)
917 CUIFSchemeDef::DrawMenuBitmap(HDC hDC, LPCRECT prc, HBITMAP hbm1, HBITMAP hbm2, DWORD dwDrawFlags)
918 {
919 DrawCtrlBitmap(hDC, prc, hbm1, hbm2, dwDrawFlags);
920 }
921
STDMETHODIMP_(void)922 STDMETHODIMP_(void)
923 CUIFSchemeDef::DrawMenuSeparator(HDC hDC, LPCRECT prc)
924 {
925 RECT rc = *prc;
926 rc.bottom = rc.top + (rc.bottom - rc.top) / 2;
927 ::FillRect(hDC, &rc, (HBRUSH)UlongToHandle(COLOR_BTNSHADOW + 1));
928
929 rc = *prc;
930 rc.top += (rc.bottom - rc.top) / 2;
931 ::FillRect(hDC, &rc, (HBRUSH)UlongToHandle(COLOR_BTNHIGHLIGHT + 1));
932 }
933
STDMETHODIMP_(void)934 STDMETHODIMP_(void)
935 CUIFSchemeDef::DrawFrameCtrlBkgd(HDC hDC, LPCRECT prc, DWORD dwUnknownFlags, DWORD dwDrawFlags)
936 {
937 DrawCtrlBkgd(hDC, prc, dwUnknownFlags, dwDrawFlags);
938 }
939
STDMETHODIMP_(void)940 STDMETHODIMP_(void)
941 CUIFSchemeDef::DrawFrameCtrlEdge(HDC hDC, LPCRECT prc, DWORD dwUnknownFlags, DWORD dwDrawFlags)
942 {
943 DrawCtrlEdge(hDC, prc, dwUnknownFlags, dwDrawFlags);
944 }
945
STDMETHODIMP_(void)946 STDMETHODIMP_(void)
947 CUIFSchemeDef::DrawFrameCtrlIcon(HDC hDC, LPCRECT prc, HICON hIcon, DWORD dwDrawFlags, LPSIZE pSize)
948 {
949 DrawCtrlIcon(hDC, prc, hIcon, dwDrawFlags, pSize);
950 }
951
STDMETHODIMP_(void)952 STDMETHODIMP_(void)
953 CUIFSchemeDef::DrawFrameCtrlBitmap(HDC hDC, LPCRECT prc, HBITMAP hbm1, HBITMAP hbm2, DWORD dwDrawFlags)
954 {
955 DrawCtrlBitmap(hDC, prc, hbm1, hbm2, dwDrawFlags);
956 }
957
STDMETHODIMP_(void)958 STDMETHODIMP_(void)
959 CUIFSchemeDef::DrawWndFrame(HDC hDC, LPCRECT prc, DWORD type, DWORD unused1, DWORD unused2)
960 {
961 RECT rc = *prc;
962 if (type && type <= 2)
963 ::DrawEdge(hDC, &rc, BDR_RAISED, BF_RECT);
964 else
965 FrameRect(hDC, &rc, 14);
966 }
967
STDMETHODIMP_(void)968 STDMETHODIMP_(void)
969 CUIFSchemeDef::DrawDragHandle(HDC hDC, LPCRECT prc, BOOL bVertical)
970 {
971 RECT rc;
972 if (bVertical)
973 rc = { prc->left, prc->top + 1, prc->right, prc->top + 4 };
974 else
975 rc = { prc->left + 1, prc->top, prc->left + 4, prc->bottom };
976 ::DrawEdge(hDC, &rc, BDR_RAISEDINNER, BF_RECT);
977 }
978
STDMETHODIMP_(void)979 STDMETHODIMP_(void)
980 CUIFSchemeDef::DrawSeparator(HDC hDC, LPCRECT prc, BOOL bVertical)
981 {
982 HPEN hLightPen = ::CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNHIGHLIGHT));
983 if (!hLightPen)
984 return;
985
986 HPEN hShadowPen = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW));
987 if (!hShadowPen)
988 {
989 ::DeleteObject(hLightPen);
990 return;
991 }
992
993 HGDIOBJ hPenOld = ::SelectObject(hDC, hShadowPen);
994 if (bVertical)
995 {
996 ::MoveToEx(hDC, prc->left, prc->top + 1, NULL);
997 ::LineTo(hDC, prc->right, prc->top + 1);
998 ::SelectObject(hDC, hLightPen);
999 ::MoveToEx(hDC, prc->left, prc->top + 2, NULL);
1000 ::LineTo(hDC, prc->right, prc->top + 2);
1001 }
1002 else
1003 {
1004 ::MoveToEx(hDC, prc->left + 1, prc->top, NULL);
1005 ::LineTo(hDC, prc->left + 1, prc->bottom);
1006 ::SelectObject(hDC, hLightPen);
1007 ::MoveToEx(hDC, prc->left + 2, prc->top, NULL);
1008 ::LineTo(hDC, prc->left + 2, prc->bottom);
1009 }
1010 ::SelectObject(hDC, hPenOld);
1011
1012 ::DeleteObject(hShadowPen);
1013 ::DeleteObject(hLightPen);
1014 }
1015
1016 /////////////////////////////////////////////////////////////////////////////
1017 // CUIFIcon
1018
GetImageList(BOOL bMirror)1019 HIMAGELIST CUIFIcon::GetImageList(BOOL bMirror)
1020 {
1021 if (!m_hImageList)
1022 return NULL;
1023
1024 if (m_hIcon)
1025 {
1026 SIZE iconSize;
1027 cicGetIconSize(m_hIcon, &iconSize);
1028
1029 UINT uFlags = ILC_COLOR32 | ILC_MASK;
1030 if (bMirror)
1031 uFlags |= ILC_MIRROR;
1032
1033 m_hImageList = ImageList_Create(iconSize.cx, iconSize.cy, uFlags, 1, 0);
1034 if (m_hImageList)
1035 ImageList_ReplaceIcon(m_hImageList, -1, m_hIcon);
1036
1037 return m_hImageList;
1038 }
1039
1040 return NULL;
1041 }
1042
1043 /////////////////////////////////////////////////////////////////////////////
1044 // CUIFBitmapDC
1045
CUIFBitmapDC(BOOL bMemory)1046 CUIFBitmapDC::CUIFBitmapDC(BOOL bMemory)
1047 {
1048 m_hBitmap = NULL;
1049 m_hOldBitmap = NULL;
1050 m_hOldObject = NULL;
1051 if (bMemory)
1052 m_hDC = ::CreateCompatibleDC(NULL);
1053 else
1054 m_hDC = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
1055 }
1056
~CUIFBitmapDC()1057 CUIFBitmapDC::~CUIFBitmapDC()
1058 {
1059 Uninit();
1060 ::DeleteDC(m_hDC);
1061 }
1062
Uninit(BOOL bKeep)1063 void CUIFBitmapDC::Uninit(BOOL bKeep)
1064 {
1065 if (m_hOldBitmap)
1066 {
1067 ::SelectObject(m_hDC, m_hOldBitmap);
1068 m_hOldBitmap = NULL;
1069 }
1070
1071 if (m_hOldObject)
1072 {
1073 ::SelectObject(m_hDC, m_hOldObject);
1074 m_hOldObject = NULL;
1075 }
1076
1077 if (!bKeep)
1078 {
1079 if (m_hBitmap)
1080 {
1081 ::DeleteObject(m_hBitmap);
1082 m_hBitmap = NULL;
1083 }
1084 }
1085 }
1086
SetBitmap(HBITMAP hBitmap)1087 BOOL CUIFBitmapDC::SetBitmap(HBITMAP hBitmap)
1088 {
1089 if (m_hDC)
1090 m_hOldBitmap = ::SelectObject(m_hDC, hBitmap);
1091 return TRUE;
1092 }
1093
SetBitmap(LONG cx,LONG cy,WORD cPlanes,WORD cBitCount)1094 BOOL CUIFBitmapDC::SetBitmap(LONG cx, LONG cy, WORD cPlanes, WORD cBitCount)
1095 {
1096 m_hBitmap = ::CreateBitmap(cx, cy, cPlanes, cBitCount, 0);
1097 m_hOldBitmap = ::SelectObject(m_hDC, m_hBitmap);
1098 return TRUE;
1099 }
1100
SetDIB(LONG cx,LONG cy,WORD cPlanes,WORD cBitCount)1101 BOOL CUIFBitmapDC::SetDIB(LONG cx, LONG cy, WORD cPlanes, WORD cBitCount)
1102 {
1103 BITMAPINFO bmi;
1104 ZeroMemory(&bmi, sizeof(bmi));
1105 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
1106 bmi.bmiHeader.biWidth = cx;
1107 bmi.bmiHeader.biHeight = cy;
1108 bmi.bmiHeader.biPlanes = cPlanes;
1109 bmi.bmiHeader.biBitCount = cBitCount;
1110 bmi.bmiHeader.biCompression = BI_RGB;
1111 m_hBitmap = ::CreateDIBSection(m_hDC, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
1112 m_hOldBitmap = ::SelectObject(m_hDC, m_hBitmap);
1113 return TRUE;
1114 }
1115
cicInitUIFUtil(void)1116 void cicInitUIFUtil(void)
1117 {
1118 if (!CUIFBitmapDC::s_phdcSrc)
1119 CUIFBitmapDC::s_phdcSrc = new(cicNoThrow) CUIFBitmapDC(TRUE);
1120
1121 if (!CUIFBitmapDC::s_phdcMask)
1122 CUIFBitmapDC::s_phdcMask = new(cicNoThrow) CUIFBitmapDC(TRUE);
1123
1124 if (!CUIFBitmapDC::s_phdcDst)
1125 CUIFBitmapDC::s_phdcDst = new(cicNoThrow) CUIFBitmapDC(TRUE);
1126
1127 if (CUIFBitmapDC::s_phdcSrc && CUIFBitmapDC::s_phdcMask && CUIFBitmapDC::s_phdcDst)
1128 CUIFBitmapDC::s_fInitBitmapDCs = TRUE;
1129 }
1130
cicDoneUIFUtil(void)1131 void cicDoneUIFUtil(void)
1132 {
1133 if (CUIFBitmapDC::s_phdcSrc)
1134 {
1135 delete CUIFBitmapDC::s_phdcSrc;
1136 CUIFBitmapDC::s_phdcSrc = NULL;
1137 }
1138
1139 if (CUIFBitmapDC::s_phdcMask)
1140 {
1141 delete CUIFBitmapDC::s_phdcMask;
1142 CUIFBitmapDC::s_phdcMask = NULL;
1143 }
1144
1145 if (CUIFBitmapDC::s_phdcDst)
1146 {
1147 delete CUIFBitmapDC::s_phdcDst;
1148 CUIFBitmapDC::s_phdcDst = NULL;
1149 }
1150
1151 CUIFBitmapDC::s_fInitBitmapDCs = FALSE;
1152 }
1153
cicMirrorBitmap(HBITMAP hBitmap,HBRUSH hbrBack)1154 HBITMAP cicMirrorBitmap(HBITMAP hBitmap, HBRUSH hbrBack)
1155 {
1156 BITMAP bm;
1157 if (!CUIFBitmapDC::s_fInitBitmapDCs || !::GetObject(hBitmap, sizeof(bm), &bm))
1158 return NULL;
1159
1160 CUIFBitmapDC::s_phdcSrc->SetBitmap(hBitmap);
1161 CUIFBitmapDC::s_phdcDst->SetDIB(bm.bmWidth, bm.bmHeight, 1, 32);
1162 CUIFBitmapDC::s_phdcMask->SetDIB(bm.bmWidth, bm.bmHeight, 1, 32);
1163
1164 RECT rc = { 0, 0, bm.bmWidth, bm.bmHeight };
1165 FillRect(*CUIFBitmapDC::s_phdcDst, &rc, hbrBack);
1166
1167 ::SetLayout(*CUIFBitmapDC::s_phdcMask, LAYOUT_RTL);
1168
1169 ::BitBlt(*CUIFBitmapDC::s_phdcMask, 0, 0, bm.bmWidth, bm.bmHeight, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCCOPY);
1170
1171 ::SetLayout(*CUIFBitmapDC::s_phdcMask, 0);
1172
1173 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, bm.bmWidth, bm.bmHeight, *CUIFBitmapDC::s_phdcMask, 1, 0, SRCCOPY);
1174
1175 CUIFBitmapDC::s_phdcSrc->Uninit();
1176 CUIFBitmapDC::s_phdcMask->Uninit();
1177 CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
1178 return CUIFBitmapDC::s_phdcDst->DetachBitmap();
1179 }
1180
cicCreateDitherBrush(VOID)1181 HBRUSH cicCreateDitherBrush(VOID)
1182 {
1183 BYTE bytes[16];
1184 ZeroMemory(&bytes, sizeof(bytes));
1185 bytes[0] = bytes[4] = bytes[8] = bytes[12] = 0x55;
1186 bytes[2] = bytes[6] = bytes[10] = bytes[14] = 0xAA;
1187 HBITMAP hBitmap = ::CreateBitmap(8, 8, 1, 1, bytes);
1188 if (!hBitmap)
1189 return NULL;
1190
1191 LOGBRUSH lb;
1192 lb.lbHatch = (ULONG_PTR)hBitmap;
1193 lb.lbStyle = BS_PATTERN;
1194 HBRUSH hbr = ::CreateBrushIndirect(&lb);
1195 ::DeleteObject(hBitmap);
1196 return hbr;
1197 }
1198
1199 HBITMAP
cicCreateDisabledBitmap(LPCRECT prc,HBITMAP hbmMask,HBRUSH hbr1,HBRUSH hbr2,BOOL bPressed)1200 cicCreateDisabledBitmap(LPCRECT prc, HBITMAP hbmMask, HBRUSH hbr1, HBRUSH hbr2, BOOL bPressed)
1201 {
1202 if (!CUIFBitmapDC::s_fInitBitmapDCs)
1203 return NULL;
1204
1205 LONG width = prc->right - prc->left, height = prc->bottom - prc->top;
1206
1207 CUIFBitmapDC::s_phdcDst->SetDIB(width, height, 1, 32);
1208 CUIFBitmapDC::s_phdcMask->SetBitmap(hbmMask);
1209 CUIFBitmapDC::s_phdcSrc->SetDIB(width, height, 1, 32);
1210
1211 RECT rc = { 0, 0, width, height };
1212 ::FillRect(*CUIFBitmapDC::s_phdcDst, &rc, hbr1);
1213
1214 HBRUSH hbrWhite = (HBRUSH)GetStockObject(WHITE_BRUSH);
1215 ::FillRect(*CUIFBitmapDC::s_phdcSrc, &rc, hbrWhite);
1216
1217 ::BitBlt(*CUIFBitmapDC::s_phdcSrc, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCINVERT);
1218 if (bPressed)
1219 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 1, 1, width, height,
1220 *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCPAINT);
1221 else
1222 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height,
1223 *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCPAINT);
1224
1225 ::FillRect(*CUIFBitmapDC::s_phdcSrc, &rc, hbr2);
1226
1227 ::BitBlt(*CUIFBitmapDC::s_phdcSrc, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCPAINT);
1228 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCAND);
1229
1230 CUIFBitmapDC::s_phdcSrc->Uninit();
1231 CUIFBitmapDC::s_phdcMask->Uninit();
1232 CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
1233 return CUIFBitmapDC::s_phdcDst->DetachBitmap();
1234 }
1235
1236 HBITMAP
cicCreateShadowMaskBmp(LPRECT prc,HBITMAP hbm1,HBITMAP hbm2,HBRUSH hbr1,HBRUSH hbr2)1237 cicCreateShadowMaskBmp(LPRECT prc, HBITMAP hbm1, HBITMAP hbm2, HBRUSH hbr1, HBRUSH hbr2)
1238 {
1239 if (!CUIFBitmapDC::s_fInitBitmapDCs)
1240 return NULL;
1241
1242 --prc->left;
1243 --prc->top;
1244
1245 LONG width = prc->right - prc->left;
1246 LONG height = prc->bottom - prc->top;
1247
1248 CUIFBitmapDC bitmapDC(TRUE);
1249
1250 CUIFBitmapDC::s_phdcDst->SetDIB(width, height, 1, 32);
1251 CUIFBitmapDC::s_phdcSrc->SetBitmap(hbm1);
1252 CUIFBitmapDC::s_phdcMask->SetBitmap(hbm2);
1253 bitmapDC.SetDIB(width, height, 1, 32);
1254
1255 RECT rc = { 0, 0, width, height };
1256
1257 ::FillRect(*CUIFBitmapDC::s_phdcDst, &rc, hbr1);
1258 ::FillRect(bitmapDC, &rc, hbr2);
1259
1260 ::BitBlt(bitmapDC, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCPAINT);
1261 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 2, 2, width, height, bitmapDC, 0, 0, SRCAND);
1262 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCAND);
1263 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCINVERT);
1264
1265 CUIFBitmapDC::s_phdcSrc->Uninit();
1266 CUIFBitmapDC::s_phdcMask->Uninit();
1267 CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
1268 return CUIFBitmapDC::s_phdcDst->DetachBitmap();
1269 }
1270
1271 HBITMAP
cicChangeBitmapColor(LPCRECT prc,HBITMAP hbm,COLORREF rgbBack,COLORREF rgbFore)1272 cicChangeBitmapColor(LPCRECT prc, HBITMAP hbm, COLORREF rgbBack, COLORREF rgbFore)
1273 {
1274 if (!CUIFBitmapDC::s_fInitBitmapDCs)
1275 return NULL;
1276
1277 INT width = prc->right - prc->left;
1278 INT height = prc->bottom - prc->top;
1279
1280 CUIFSolidBrush brush(rgbFore);
1281
1282 CUIFBitmapDC::s_phdcDst->SetDIB(width, height, 1, 32);
1283 CUIFBitmapDC::s_phdcSrc->SetBitmap(hbm);
1284 CUIFBitmapDC::s_phdcMask->SetBitmap(width, height, 1, 1);
1285
1286 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCCOPY);
1287 ::SelectObject(*CUIFBitmapDC::s_phdcDst, (HBRUSH)brush);
1288 ::SetBkColor(*CUIFBitmapDC::s_phdcDst, rgbBack);
1289
1290 ::BitBlt(*CUIFBitmapDC::s_phdcMask, 0, 0, width, height, *CUIFBitmapDC::s_phdcDst, 0, 0, MERGECOPY);
1291 ::SetBkColor(*CUIFBitmapDC::s_phdcDst, RGB(255, 255, 255));
1292 ::SetTextColor(*CUIFBitmapDC::s_phdcDst, RGB(0, 0, 0));
1293 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, 0xE20746u);
1294
1295 CUIFBitmapDC::s_phdcSrc->Uninit();
1296 CUIFBitmapDC::s_phdcMask->Uninit();
1297 CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
1298 return CUIFBitmapDC::s_phdcDst->DetachBitmap();
1299 }
1300
1301 HBITMAP
cicConvertBlackBKGBitmap(LPCRECT prc,HBITMAP hbm1,HBITMAP hbm2,HBRUSH hBrush)1302 cicConvertBlackBKGBitmap(LPCRECT prc, HBITMAP hbm1, HBITMAP hbm2, HBRUSH hBrush)
1303 {
1304 if (!CUIFBitmapDC::s_fInitBitmapDCs)
1305 return NULL;
1306
1307 if (IS_INTRESOURCE(hBrush))
1308 hBrush = ::GetSysColorBrush(HandleToLong(hBrush) - 1);
1309
1310 LOGBRUSH lb;
1311 ::GetObject(hBrush, sizeof(lb), &lb);
1312 if (lb.lbStyle || lb.lbColor)
1313 return NULL;
1314
1315 INT width = prc->right - prc->left;
1316 INT height = prc->bottom - prc->top;
1317
1318 HBITMAP hBitmap = cicChangeBitmapColor(prc, hbm1, 0, RGB(255, 255, 255));
1319 if ( !hBitmap )
1320 return NULL;
1321
1322 CUIFBitmapDC::s_phdcDst->SetDIB(width, height, 1, 32);
1323 CUIFBitmapDC::s_phdcSrc->SetBitmap(hBitmap);
1324 CUIFBitmapDC::s_phdcMask->SetBitmap(hbm2);
1325
1326 RECT rc = { 0, 0, width, height };
1327
1328 HBRUSH hbrWhite = (HBRUSH)GetStockObject(WHITE_BRUSH);
1329 ::FillRect(*CUIFBitmapDC::s_phdcDst, &rc, hbrWhite);
1330
1331 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, 0x660046u);
1332 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcSrc, 0, 0, 0x8800C6u);
1333
1334 CUIFBitmapDC::s_phdcSrc->Uninit();
1335 CUIFBitmapDC::s_phdcMask->Uninit();
1336 CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
1337 ::DeleteObject(hBitmap);
1338 return CUIFBitmapDC::s_phdcDst->DetachBitmap();
1339 }
1340
1341 HBITMAP
cicCreateMaskBmp(LPCRECT prc,HBITMAP hbm1,HBITMAP hbm2,HBRUSH hbr,COLORREF rgbColor,COLORREF rgbBack)1342 cicCreateMaskBmp(LPCRECT prc, HBITMAP hbm1, HBITMAP hbm2,
1343 HBRUSH hbr, COLORREF rgbColor, COLORREF rgbBack)
1344 {
1345 if (!CUIFBitmapDC::s_fInitBitmapDCs)
1346 return NULL;
1347
1348 INT width = prc->right - prc->left;
1349 INT height = prc->bottom - prc->top;
1350 HBITMAP hBitmap = cicConvertBlackBKGBitmap(prc, hbm1, hbm2, hbr);
1351 if (hBitmap)
1352 return hBitmap;
1353
1354 CUIFBitmapDC::s_phdcDst->SetDIB(width, height, 1, 32);
1355 CUIFBitmapDC::s_phdcSrc->SetBitmap(hbm1);
1356 CUIFBitmapDC::s_phdcMask->SetBitmap(hbm2);
1357
1358 RECT rc = { 0, 0, width, height };
1359
1360 COLORREF OldTextColor = ::SetTextColor(*CUIFBitmapDC::s_phdcDst, rgbColor);
1361 COLORREF OldBkColor = ::SetBkColor(*CUIFBitmapDC::s_phdcDst, rgbBack);
1362 ::FillRect(*CUIFBitmapDC::s_phdcDst, &rc, hbr);
1363 ::SetTextColor(*CUIFBitmapDC::s_phdcDst, OldTextColor);
1364 ::SetBkColor(*CUIFBitmapDC::s_phdcDst, OldBkColor);
1365
1366 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCAND);
1367 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, width, height, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCINVERT);
1368 CUIFBitmapDC::s_phdcSrc->Uninit();
1369 CUIFBitmapDC::s_phdcMask->Uninit();
1370 CUIFBitmapDC::s_phdcDst->Uninit(TRUE);
1371
1372 return CUIFBitmapDC::s_phdcDst->DetachBitmap();
1373 }
1374
cicGetIconBitmaps(HICON hIcon,HBITMAP * hbm1,HBITMAP * hbm2,const SIZE * pSize)1375 BOOL cicGetIconBitmaps(HICON hIcon, HBITMAP *hbm1, HBITMAP *hbm2, const SIZE *pSize)
1376 {
1377 if (!CUIFBitmapDC::s_fInitBitmapDCs)
1378 return FALSE;
1379
1380 SIZE size;
1381 if (pSize)
1382 {
1383 size = *pSize;
1384 }
1385 else
1386 {
1387 if (!cicGetIconSize(hIcon, &size))
1388 return FALSE;
1389 }
1390
1391 CUIFBitmapDC::s_phdcSrc->SetDIB(size.cx, size.cy, 1, 32);
1392 CUIFBitmapDC::s_phdcMask->SetBitmap(size.cx, size.cy, 1, 1);
1393
1394 RECT rc = { 0, 0, size.cx, size.cy };
1395 ::FillRect(*CUIFBitmapDC::s_phdcSrc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
1396
1397 ::DrawIconEx(*CUIFBitmapDC::s_phdcSrc, 0, 0, hIcon, size.cx, size.cy, 0, 0, DI_NORMAL);
1398 ::DrawIconEx(*CUIFBitmapDC::s_phdcMask, 0, 0, hIcon, size.cx, size.cy, 0, 0, DI_MASK);
1399
1400 CUIFBitmapDC::s_phdcSrc->Uninit(TRUE);
1401 CUIFBitmapDC::s_phdcMask->Uninit(TRUE);
1402 *hbm1 = CUIFBitmapDC::s_phdcSrc->DetachBitmap();
1403 *hbm2 = CUIFBitmapDC::s_phdcMask->DetachBitmap();
1404 return TRUE;
1405 }
1406
cicDrawMaskBmpOnDC(HDC hDC,LPCRECT prc,HBITMAP hbmp,HBITMAP hbmpMask)1407 void cicDrawMaskBmpOnDC(HDC hDC, LPCRECT prc, HBITMAP hbmp, HBITMAP hbmpMask)
1408 {
1409 if (!CUIFBitmapDC::s_fInitBitmapDCs)
1410 return;
1411
1412 LONG cx = prc->right - prc->left, cy = prc->bottom - prc->top;
1413 CUIFBitmapDC::s_phdcDst->SetDIB(cx, cy, 1, 32);
1414 CUIFBitmapDC::s_phdcSrc->SetBitmap(hbmp);
1415 CUIFBitmapDC::s_phdcMask->SetBitmap(hbmpMask);
1416 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, cx, cy, hDC, prc->left, prc->top, SRCCOPY);
1417 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, cx, cy, *CUIFBitmapDC::s_phdcMask, 0, 0, SRCAND);
1418 ::BitBlt(*CUIFBitmapDC::s_phdcDst, 0, 0, cx, cy, *CUIFBitmapDC::s_phdcSrc, 0, 0, SRCINVERT);
1419 ::BitBlt(hDC, prc->left, prc->top, cx, cy, *CUIFBitmapDC::s_phdcDst, 0, 0, SRCCOPY);
1420 CUIFBitmapDC::s_phdcSrc->Uninit(FALSE);
1421 CUIFBitmapDC::s_phdcMask->Uninit(FALSE);
1422 CUIFBitmapDC::s_phdcDst->Uninit(FALSE);
1423 }
1424
1425 /////////////////////////////////////////////////////////////////////////////
1426 // CUIFWindow
1427
CUIFWindow(HINSTANCE hInst,DWORD style)1428 CUIFWindow::CUIFWindow(HINSTANCE hInst, DWORD style)
1429 : CUIFObject(NULL, 0, NULL, style)
1430 {
1431 m_hInst = hInst;
1432 m_nLeft = 200;
1433 m_nTop = 200;
1434 m_nWidth = 200;
1435 m_nHeight = 200;
1436 m_hWnd = 0;
1437 m_pWindow = this;
1438 m_pCaptured = NULL;
1439 m_pTimerObject = NULL;
1440 m_pPointed = NULL;
1441 m_bPointing = FALSE;
1442 m_pToolTip = NULL;
1443 m_pShadow = NULL;
1444 m_bShowShadow = TRUE;
1445 m_pBehindModal = NULL;
1446 CUIFWindow::CreateScheme();
1447 }
1448
~CUIFWindow()1449 CUIFWindow::~CUIFWindow()
1450 {
1451 if (m_pToolTip)
1452 {
1453 delete m_pToolTip;
1454 m_pToolTip = NULL;
1455 }
1456 if (m_pShadow)
1457 {
1458 delete m_pShadow;
1459 m_pShadow = NULL;
1460 }
1461 for (size_t i = m_ObjectArray.size(); i > 0; )
1462 {
1463 --i;
1464 CUIFObject *pObject = m_ObjectArray[i];
1465 m_ObjectArray[i] = NULL;
1466 m_ObjectArray.Remove(pObject);
1467 delete pObject;
1468 }
1469 if (m_pScheme)
1470 {
1471 delete m_pScheme;
1472 m_pScheme = NULL;
1473 }
1474 }
1475
STDMETHODIMP_(BOOL)1476 STDMETHODIMP_(BOOL)
1477 CUIFWindow::Initialize()
1478 {
1479 LPCTSTR pszClass = GetClassName();
1480
1481 WNDCLASSEX wcx;
1482 ZeroMemory(&wcx, sizeof(wcx));
1483 wcx.cbSize = sizeof(WNDCLASSEXW);
1484 if (!::GetClassInfoEx(m_hInst, pszClass, &wcx))
1485 {
1486 ZeroMemory(&wcx, sizeof(wcx));
1487 wcx.cbSize = sizeof(wcx);
1488 wcx.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
1489 wcx.lpfnWndProc = CUIFWindow::WindowProcedure;
1490 wcx.cbClsExtra = 0;
1491 wcx.cbWndExtra = sizeof(LONG_PTR) * 2;
1492 wcx.hInstance = m_hInst;
1493 wcx.hIcon = NULL;
1494 wcx.hCursor = ::LoadCursor(NULL, IDC_ARROW);
1495 wcx.lpszClassName = pszClass;
1496 wcx.hbrBackground = NULL;
1497 wcx.lpszMenuName = NULL;
1498 wcx.hIconSm = NULL;
1499 ::RegisterClassEx(&wcx);
1500 }
1501
1502 cicUpdateUIFSys();
1503 cicUpdateUIFScheme();
1504
1505 if (m_style & UIF_WINDOW_TOOLTIP)
1506 {
1507 DWORD style = (m_style & UIF_WINDOW_LAYOUTRTL) | UIF_WINDOW_TOPMOST | 0x10;
1508 m_pToolTip = new(cicNoThrow) CUIFToolTip(m_hInst, style, this);
1509 if (m_pToolTip)
1510 m_pToolTip->Initialize();
1511 }
1512
1513 if (m_style & UIF_WINDOW_SHADOW)
1514 {
1515 m_pShadow = new(cicNoThrow) CUIFShadow(m_hInst, UIF_WINDOW_TOPMOST, this);
1516 if (m_pShadow)
1517 m_pShadow->Initialize();
1518 }
1519
1520 return CUIFObject::Initialize();
1521 }
1522
STDMETHODIMP_(LRESULT)1523 STDMETHODIMP_(LRESULT)
1524 CUIFWindow::OnSettingChange(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1525 {
1526 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
1527 }
1528
UpdateUI(LPCRECT prc)1529 void CUIFWindow::UpdateUI(LPCRECT prc)
1530 {
1531 if (::IsWindow(m_hWnd))
1532 ::InvalidateRect(m_hWnd, prc, FALSE);
1533 }
1534
1535 CUIFWindow*
GetThis(HWND hWnd)1536 CUIFWindow::GetThis(HWND hWnd)
1537 {
1538 return (CUIFWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
1539 }
1540
1541 void
SetThis(HWND hWnd,LONG_PTR dwNewLong)1542 CUIFWindow::SetThis(HWND hWnd, LONG_PTR dwNewLong)
1543 {
1544 ::SetWindowLongPtr(hWnd, GWLP_USERDATA, dwNewLong);
1545 }
1546
CreateScheme()1547 void CUIFWindow::CreateScheme()
1548 {
1549 if (m_pScheme)
1550 {
1551 delete m_pScheme;
1552 m_pScheme = NULL;
1553 }
1554
1555 INT iScheme = 0;
1556 if (m_style & UIF_WINDOW_USESCHEME1)
1557 iScheme = 1;
1558 else if (m_style & UIF_WINDOW_USESCHEME2)
1559 iScheme = 2;
1560 else if (m_style & UIF_WINDOW_USESCHEME3)
1561 iScheme = 3;
1562
1563 m_pScheme = cicCreateUIFScheme(iScheme);
1564 SetScheme(m_pScheme);
1565 }
1566
STDMETHODIMP_(DWORD)1567 STDMETHODIMP_(DWORD)
1568 CUIFWindow::GetWndStyle()
1569 {
1570 DWORD ret;
1571
1572 if (m_style & UIF_WINDOW_CHILD)
1573 ret = WS_CHILD | WS_CLIPSIBLINGS;
1574 else
1575 ret = WS_POPUP | WS_DISABLED;
1576
1577 if (m_style & UIF_WINDOW_USESCHEME1)
1578 ret |= WS_BORDER;
1579 else if (m_style & UIF_WINDOW_DLGFRAME)
1580 ret |= WS_DLGFRAME;
1581 else if ((m_style & UIF_WINDOW_USESCHEME2) || (m_style & 0x10))
1582 ret |= WS_BORDER;
1583
1584 return ret;
1585 }
1586
STDMETHODIMP_(DWORD)1587 STDMETHODIMP_(DWORD)
1588 CUIFWindow::GetWndStyleEx()
1589 {
1590 DWORD ret = 0;
1591 if (m_style & UIF_WINDOW_TOPMOST)
1592 ret |= WS_EX_TOPMOST;
1593 if (m_style & UIF_WINDOW_TOOLWINDOW)
1594 ret |= WS_EX_TOOLWINDOW;
1595 if (m_style & UIF_WINDOW_LAYOUTRTL)
1596 ret |= WS_EX_LAYOUTRTL;
1597 return ret;
1598 }
1599
STDMETHODIMP_(HWND)1600 STDMETHODIMP_(HWND)
1601 CUIFWindow::CreateWnd(HWND hwndParent)
1602 {
1603 HWND hWnd = CreateWindowEx(GetWndStyleEx(), GetClassName(), GetWndTitle(), GetWndStyle(),
1604 m_nLeft, m_nTop, m_nWidth, m_nHeight,
1605 hwndParent, NULL, m_hInst, this);
1606 if (m_pToolTip)
1607 m_pToolTip->CreateWnd(hWnd);
1608 if (m_pShadow)
1609 m_pShadow->CreateWnd(hWnd);
1610 return hWnd;
1611 }
1612
Show(BOOL bVisible)1613 void CUIFWindow::Show(BOOL bVisible)
1614 {
1615 if (!IsWindow(m_hWnd))
1616 return;
1617
1618 if (bVisible && (m_style & UIF_WINDOW_TOPMOST))
1619 ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1620
1621 m_bVisible = bVisible;
1622 ::ShowWindow(m_hWnd, (bVisible ? SW_SHOWNOACTIVATE : 0));
1623 }
1624
STDMETHODIMP_(BOOL)1625 STDMETHODIMP_(BOOL)
1626 CUIFWindow::AnimateWnd(DWORD dwTime, DWORD dwFlags)
1627 {
1628 if (!::IsWindow(m_hWnd))
1629 return FALSE;
1630
1631 BOOL bVisible = !(dwFlags & 0x10000);
1632 OnAnimationStart();
1633 BOOL ret = ::AnimateWindow(m_hWnd, dwTime, dwFlags);
1634 if (!ret)
1635 m_bVisible = bVisible;
1636 OnAnimationEnd();
1637 return ret;
1638 }
1639
SetCaptureObject(CUIFObject * pCaptured)1640 void CUIFWindow::SetCaptureObject(CUIFObject *pCaptured)
1641 {
1642 if (pCaptured)
1643 {
1644 m_pCaptured = pCaptured;
1645 SetCapture(TRUE);
1646 }
1647 else
1648 {
1649 m_pCaptured = NULL;
1650 SetCapture(FALSE);
1651 }
1652 }
1653
STDMETHODIMP_(void)1654 STDMETHODIMP_(void)
1655 CUIFWindow::SetCapture(BOOL bSet)
1656 {
1657 if (bSet)
1658 ::SetCapture(m_hWnd);
1659 else
1660 ::ReleaseCapture();
1661 }
1662
SetObjectPointed(CUIFObject * pPointed,POINT pt)1663 void CUIFWindow::SetObjectPointed(CUIFObject *pPointed, POINT pt)
1664 {
1665 if (pPointed == m_pPointed)
1666 return;
1667
1668 if (m_pCaptured)
1669 {
1670 if (m_pCaptured == m_pPointed && m_pPointed->m_bEnable)
1671 m_pPointed->OnMouseOut(pt.x, pt.y);
1672 }
1673 else if (m_pPointed && m_pPointed->m_bEnable)
1674 {
1675 m_pPointed->OnMouseOut(pt.x, pt.y);
1676 }
1677
1678 m_pPointed = pPointed;
1679
1680 if (m_pCaptured)
1681 {
1682 if (m_pCaptured == m_pPointed && m_pPointed->m_bEnable)
1683 m_pPointed->OnMouseIn(pt.x, pt.y);
1684 }
1685 else if (m_pPointed && m_pPointed->m_bEnable)
1686 {
1687 m_pPointed->OnMouseIn(pt.x, pt.y);
1688 }
1689 }
1690
STDMETHODIMP_(void)1691 STDMETHODIMP_(void)
1692 CUIFWindow::OnObjectMoved(CUIFObject *pObject)
1693 {
1694 if (!::IsWindow(m_hWnd))
1695 return;
1696
1697 POINT pt;
1698 ::GetCursorPos(&pt);
1699 ::ScreenToClient(m_hWnd, &pt);
1700 POINT pt2 = pt;
1701 CUIFObject *pFound = ObjectFromPoint(pt);
1702 SetObjectPointed(pFound, pt2);
1703 }
1704
STDMETHODIMP_(void)1705 STDMETHODIMP_(void)
1706 CUIFWindow::SetRect(LPCRECT prc)
1707 {
1708 RECT Rect = { 0, 0, 0, 0 };
1709
1710 if (::IsWindow(m_hWnd))
1711 ::GetClientRect(m_hWnd, &Rect);
1712
1713 CUIFObject::SetRect(&Rect);
1714 }
1715
STDMETHODIMP_(void)1716 STDMETHODIMP_(void)
1717 CUIFWindow::ClientRectToWindowRect(LPRECT lpRect)
1718 {
1719 DWORD style, exstyle;
1720 if (::IsWindow(m_hWnd))
1721 {
1722 style = ::GetWindowLongPtr(m_hWnd, GWL_STYLE);
1723 exstyle = ::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
1724 }
1725 else
1726 {
1727 style = GetWndStyle();
1728 exstyle = GetWndStyleEx();
1729 }
1730 ::AdjustWindowRectEx(lpRect, style, FALSE, exstyle);
1731 }
1732
STDMETHODIMP_(void)1733 STDMETHODIMP_(void)
1734 CUIFWindow::GetWindowFrameSize(LPSIZE pSize)
1735 {
1736 RECT rc = { 0, 0, 0, 0 };
1737
1738 ClientRectToWindowRect(&rc);
1739 pSize->cx = (rc.right - rc.left) / 2;
1740 pSize->cy = (rc.bottom - rc.top) / 2;
1741 }
1742
STDMETHODIMP_(void)1743 STDMETHODIMP_(void)
1744 CUIFWindow::OnAnimationEnd()
1745 {
1746 if (m_pShadow && m_bShowShadow)
1747 m_pShadow->Show(m_bVisible);
1748 }
1749
STDMETHODIMP_(void)1750 STDMETHODIMP_(void)
1751 CUIFWindow::OnThemeChanged(HWND hWnd, WPARAM wParam, LPARAM lParam)
1752 {
1753 ClearTheme();
1754 }
1755
1756 LRESULT
WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)1757 CUIFWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1758 {
1759 switch (uMsg)
1760 {
1761 case WM_GETOBJECT:
1762 return OnGetObject(hWnd, WM_GETOBJECT, wParam, lParam);
1763
1764 case WM_SYSCOLORCHANGE:
1765 cicUpdateUIFScheme();
1766 OnSysColorChange();
1767 return 0;
1768
1769 case WM_ENDSESSION:
1770 OnEndSession(hWnd, wParam, lParam);
1771 return 0;
1772
1773 case WM_SHOWWINDOW:
1774 if (m_pShadow && m_bShowShadow)
1775 m_pShadow->Show(wParam);
1776 return OnShowWindow(hWnd, WM_SHOWWINDOW, wParam, lParam);
1777
1778 case WM_SETTINGCHANGE:
1779 cicUpdateUIFSys();
1780 cicUpdateUIFScheme();
1781 return OnSettingChange(hWnd, WM_SETTINGCHANGE, wParam, lParam);
1782 case WM_SETCURSOR:
1783 {
1784 POINT Point;
1785 ::GetCursorPos(&Point);
1786 ::ScreenToClient(m_hWnd, &Point);
1787
1788 if (m_pBehindModal)
1789 {
1790 m_pBehindModal->ModalMouseNotify(HIWORD(lParam), Point.x, Point.y);
1791 return TRUE;
1792 }
1793
1794 if (!m_bPointing)
1795 {
1796 ::SetTimer(m_hWnd, POINTING_TIMER_ID, 1000, NULL);
1797 m_bPointing = TRUE;
1798 }
1799
1800 if (m_pToolTip)
1801 {
1802 MSG msg = { m_hWnd, HIWORD(lParam), 0, MAKELPARAM(Point.x, Point.y) };
1803 m_pToolTip->RelayEvent(&msg);
1804 }
1805
1806 if (!(m_style & UIF_WINDOW_NOMOUSEMSG))
1807 HandleMouseMsg(HIWORD(lParam), Point.x, Point.y);
1808
1809 return TRUE;
1810 }
1811 case WM_MOUSEACTIVATE:
1812 return MA_NOACTIVATE;
1813 case WM_ERASEBKGND:
1814 return OnEraseBkGnd(hWnd, WM_ERASEBKGND, wParam, lParam);
1815 case WM_CREATE:
1816 SetRect(NULL);
1817 OnCreate(hWnd);
1818 return 0;
1819 case WM_DESTROY:
1820 if (m_pToolTip && ::IsWindow(*m_pToolTip))
1821 ::DestroyWindow(*m_pToolTip);
1822 if (m_pShadow && ::IsWindow(*m_pShadow))
1823 ::DestroyWindow(*m_pShadow);
1824 OnDestroy(hWnd);
1825 return 0;
1826 case WM_SIZE:
1827 SetRect(NULL);
1828 return 0;
1829 case WM_ACTIVATE:
1830 return OnActivate(hWnd, WM_ACTIVATE, wParam, lParam);
1831 case WM_SETFOCUS:
1832 OnSetFocus(hWnd);
1833 return 0;
1834 case WM_KILLFOCUS:
1835 OnKillFocus(hWnd);
1836 return 0;
1837 case WM_PAINT:
1838 {
1839 PAINTSTRUCT Paint;
1840 HDC hDC = ::BeginPaint(hWnd, &Paint);
1841 PaintObject(hDC, &Paint.rcPaint);
1842 ::EndPaint(hWnd, &Paint);
1843 return 0;
1844 }
1845 case WM_PRINTCLIENT:
1846 {
1847 PaintObject((HDC)wParam, NULL);
1848 return 0;
1849 }
1850 case WM_THEMECHANGED:
1851 {
1852 OnThemeChanged(hWnd, wParam, lParam);
1853 return 0;
1854 }
1855 case WM_COMMAND:
1856 {
1857 return 0;
1858 }
1859 case WM_TIMER:
1860 {
1861 switch (wParam)
1862 {
1863 case USER_TIMER_ID:
1864 {
1865 if (m_pTimerObject)
1866 m_pTimerObject->OnTimer();
1867 break;
1868 }
1869 case POINTING_TIMER_ID:
1870 {
1871 POINT pt;
1872 ::GetCursorPos(&pt);
1873
1874 POINT pt2 = pt;
1875 ::ScreenToClient(m_hWnd, &pt2);
1876
1877 RECT rc;
1878 ::GetWindowRect(m_hWnd, &rc);
1879
1880 if (::PtInRect(&rc, pt) && ::WindowFromPoint(pt) == m_hWnd)
1881 {
1882 m_pBehindModal->ModalMouseNotify(WM_MOUSEMOVE, pt2.x, pt2.y);
1883 }
1884 else
1885 {
1886 ::KillTimer(m_hWnd, POINTING_TIMER_ID);
1887 m_bPointing = FALSE;
1888 SetObjectPointed(NULL, pt2);
1889 OnMouseOutFromWindow(pt2.x, pt2.y);
1890 }
1891
1892 if (m_pToolTip)
1893 {
1894 MSG msg = { m_hWnd, WM_MOUSEMOVE, 0, MAKELPARAM(pt2.x, pt2.y) };
1895 m_pToolTip->RelayEvent(&msg);
1896 }
1897 break;
1898 }
1899 default:
1900 {
1901 OnTimer(wParam);
1902 break;
1903 }
1904 }
1905 break;
1906 }
1907 case WM_MOUSEMOVE:
1908 case WM_LBUTTONDOWN:
1909 case WM_LBUTTONDBLCLK:
1910 case WM_LBUTTONUP:
1911 case WM_MBUTTONDOWN:
1912 case WM_MBUTTONDBLCLK:
1913 case WM_MBUTTONUP:
1914 case WM_RBUTTONDOWN:
1915 case WM_RBUTTONDBLCLK:
1916 case WM_RBUTTONUP:
1917 {
1918 if (m_pBehindModal)
1919 m_pBehindModal->ModalMouseNotify(uMsg, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
1920 else
1921 HandleMouseMsg(uMsg, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
1922 break;
1923 }
1924 case WM_KEYUP:
1925 {
1926 OnKeyUp(hWnd, wParam, lParam);
1927 break;
1928 }
1929 case WM_WINDOWPOSCHANGING:
1930 {
1931 WINDOWPOS *pwp = (WINDOWPOS *)lParam;
1932 if (m_pShadow && (pwp->flags & SWP_HIDEWINDOW))
1933 m_pShadow->Show(FALSE);
1934 if (!(pwp->flags & SWP_NOZORDER) && pwp->hwndInsertAfter == m_pShadow->m_hWnd)
1935 pwp->flags |= SWP_NOZORDER;
1936 m_pShadow->OnOwnerWndMoved(!(pwp->flags & SWP_NOSIZE));
1937 return OnWindowPosChanging(hWnd, WM_WINDOWPOSCHANGING, wParam, lParam);
1938 }
1939 case WM_WINDOWPOSCHANGED:
1940 {
1941 WINDOWPOS *pwp = (WINDOWPOS *)lParam;
1942 if (m_pShadow)
1943 m_pShadow->OnOwnerWndMoved(!(pwp->flags & SWP_NOSIZE));
1944 return OnWindowPosChanged(hWnd, WM_WINDOWPOSCHANGED, wParam, lParam);
1945 }
1946 case WM_NOTIFY:
1947 OnNotify(hWnd, wParam, lParam);
1948 return 0;
1949 case WM_NOTIFYFORMAT:
1950 return OnNotifyFormat(hWnd, wParam, lParam);
1951 case WM_DISPLAYCHANGE:
1952 cicUpdateUIFSys();
1953 cicUpdateUIFScheme();
1954 return OnDisplayChange(hWnd, WM_DISPLAYCHANGE, wParam, lParam);
1955 case WM_NCDESTROY:
1956 OnNCDestroy(hWnd);
1957 return 0;
1958 case WM_KEYDOWN:
1959 OnKeyDown(hWnd, wParam, lParam);
1960 return 0;
1961 default:
1962 {
1963 if (uMsg >= WM_USER)
1964 {
1965 CUIFWindow *pThis = CUIFWindow::GetThis(hWnd);
1966 pThis->OnUser(hWnd, uMsg, wParam, lParam);
1967 break;
1968 }
1969 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
1970 }
1971 }
1972
1973 return 0;
1974 }
1975
1976 LRESULT CALLBACK
WindowProcedure(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)1977 CUIFWindow::WindowProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1978 {
1979 CUIFWindow *This;
1980
1981 if (uMsg == WM_NCCREATE)
1982 {
1983 This = (CUIFWindow*)((CREATESTRUCT*)lParam)->lpCreateParams;
1984 CUIFWindow::SetThis(hWnd, (LONG_PTR)This);
1985 This->m_hWnd = hWnd;
1986 }
1987 else
1988 {
1989 This = CUIFWindow::GetThis(hWnd);
1990 }
1991
1992 if (uMsg == WM_GETMINMAXINFO)
1993 {
1994 if (This)
1995 return This->WindowProc(hWnd, uMsg, wParam, lParam);
1996 else
1997 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
1998 }
1999
2000 if (!This)
2001 return 0;
2002
2003 if (uMsg == WM_NCDESTROY)
2004 {
2005 This->m_hWnd = NULL;
2006 ::SetWindowLongPtr(hWnd, GWLP_USERDATA, 0);
2007 }
2008
2009 return This->WindowProc(hWnd, uMsg, wParam, lParam);
2010 }
2011
2012 BOOL
GetWorkArea(LPCRECT prcWnd,LPRECT prcWorkArea)2013 CUIFWindow::GetWorkArea(LPCRECT prcWnd, LPRECT prcWorkArea)
2014 {
2015 if (!(m_style & (UIF_WINDOW_WORKAREA | UIF_WINDOW_MONITOR)))
2016 return FALSE;
2017
2018 HMONITOR hMon = ::MonitorFromRect(prcWnd, MONITOR_DEFAULTTONEAREST);
2019 MONITORINFO mi;
2020 mi.cbSize = sizeof(MONITORINFO);
2021 if (!hMon || !::GetMonitorInfo(hMon, &mi))
2022 {
2023 if (m_style & UIF_WINDOW_WORKAREA)
2024 return ::SystemParametersInfo(SPI_GETWORKAREA, 0, prcWorkArea, 0);
2025
2026 prcWorkArea->left = prcWorkArea->top = 0;
2027 prcWorkArea->right = ::GetSystemMetrics(SM_CXSCREEN);
2028 prcWorkArea->bottom = ::GetSystemMetrics(SM_CYSCREEN);
2029 return TRUE;
2030 }
2031
2032 if (m_style & UIF_WINDOW_WORKAREA)
2033 {
2034 *prcWorkArea = mi.rcWork;
2035 return TRUE;
2036 }
2037
2038 *prcWorkArea = mi.rcMonitor;
2039 return TRUE;
2040 }
2041
2042 void
AdjustWindowPosition()2043 CUIFWindow::AdjustWindowPosition()
2044 {
2045 RECT rc;
2046 rc.left = m_nLeft;
2047 rc.right = m_nLeft + m_nWidth;
2048 rc.top = m_nTop;
2049 rc.bottom = m_nTop + m_nHeight;
2050
2051 RECT rcWorkArea;
2052 if (!GetWorkArea(&rc, &rcWorkArea))
2053 return;
2054
2055 if (m_nLeft < rcWorkArea.left)
2056 m_nLeft = rcWorkArea.left;
2057 if (m_nTop < rcWorkArea.top)
2058 m_nTop = rcWorkArea.top;
2059 if (m_nLeft + m_nWidth >= rcWorkArea.right)
2060 m_nLeft = rcWorkArea.right - m_nWidth;
2061 if (m_nTop + m_nHeight >= rcWorkArea.bottom)
2062 m_nTop = rcWorkArea.bottom - m_nHeight;
2063 }
2064
SetBehindModal(CUIFWindow * pBehindModal)2065 void CUIFWindow::SetBehindModal(CUIFWindow *pBehindModal)
2066 {
2067 m_pBehindModal = pBehindModal;
2068 }
2069
SetTimerObject(CUIFObject * pTimerObject,UINT uElapse)2070 void CUIFWindow::SetTimerObject(CUIFObject *pTimerObject, UINT uElapse)
2071 {
2072 if (pTimerObject)
2073 {
2074 m_pTimerObject = pTimerObject;
2075 ::SetTimer(m_hWnd, USER_TIMER_ID, uElapse, NULL);
2076 }
2077 else
2078 {
2079 m_pTimerObject = NULL;
2080 ::KillTimer(m_hWnd, USER_TIMER_ID);
2081 }
2082 }
2083
STDMETHODIMP_(void)2084 STDMETHODIMP_(void)
2085 CUIFWindow::PaintObject(HDC hDC, LPCRECT prc)
2086 {
2087 BOOL bGotDC = FALSE;
2088 if (!hDC)
2089 {
2090 hDC = ::GetDC(m_hWnd);
2091 bGotDC = TRUE;
2092 }
2093
2094 if (!prc)
2095 prc = &m_rc;
2096
2097 HDC hMemDC = ::CreateCompatibleDC(hDC);
2098 HBITMAP hbmMem = ::CreateCompatibleBitmap(hDC, prc->right - prc->left, prc->bottom - prc->top);
2099
2100 HGDIOBJ hbmOld = ::SelectObject(hMemDC, hbmMem);
2101 ::SetViewportOrgEx(hMemDC, -prc->left, -prc->top, NULL);
2102 if (FAILED(EnsureThemeData(m_hWnd)) ||
2103 ((!(m_style & UIF_WINDOW_CHILD) || FAILED(DrawThemeParentBackground(m_hWnd, hMemDC, &m_rc))) &&
2104 FAILED(DrawThemeBackground(hMemDC, m_iStateId, &m_rc, NULL))))
2105 {
2106 if (m_pScheme)
2107 m_pScheme->FillRect(hMemDC, prc, 22);
2108 }
2109
2110 CUIFObject::PaintObject(hMemDC, prc);
2111 ::BitBlt(hDC, prc->left, prc->top,
2112 prc->right - prc->left, prc->bottom - prc->top,
2113 hMemDC, prc->left, prc->top, SRCCOPY);
2114 ::SelectObject(hMemDC, hbmOld);
2115 ::DeleteObject(hbmMem);
2116 ::DeleteDC(hMemDC);
2117
2118 if (bGotDC)
2119 ::ReleaseDC(m_hWnd, hDC);
2120 }
2121
STDMETHODIMP_(void)2122 STDMETHODIMP_(void)
2123 CUIFWindow::Move(INT x, INT y, INT nWidth, INT nHeight)
2124 {
2125 m_nLeft = x;
2126 m_nTop = y;
2127 if (nWidth >= 0)
2128 m_nWidth = nWidth;
2129 if (nHeight >= 0)
2130 m_nHeight = nHeight;
2131 if (::IsWindow(m_hWnd))
2132 {
2133 AdjustWindowPosition();
2134 ::MoveWindow(m_hWnd, m_nLeft, m_nTop, m_nWidth, m_nHeight, TRUE);
2135 }
2136 }
2137
STDMETHODIMP_(void)2138 STDMETHODIMP_(void)
2139 CUIFWindow::RemoveUIObj(CUIFObject *pRemove)
2140 {
2141 if (pRemove == m_pCaptured)
2142 SetCaptureObject(NULL);
2143
2144 if (pRemove == m_pTimerObject)
2145 {
2146 m_pTimerObject = NULL;
2147 ::KillTimer(m_hWnd, USER_TIMER_ID);
2148 }
2149
2150 if (pRemove == m_pPointed)
2151 m_pPointed = NULL;
2152
2153 CUIFObject::RemoveUIObj(pRemove);
2154 }
2155
STDMETHODIMP_(void)2156 STDMETHODIMP_(void)
2157 CUIFWindow::HandleMouseMsg(UINT uMsg, LONG x, LONG y)
2158 {
2159 POINT pt = { x, y };
2160
2161 CUIFObject *pFound = (CUIFWindow *)ObjectFromPoint(pt);
2162
2163 SetObjectPointed(pFound, pt);
2164
2165 if (m_pCaptured)
2166 pFound = m_pCaptured;
2167
2168 if (!pFound || OnSetCursor(uMsg, pt.x, pt.y))
2169 {
2170 HCURSOR hCursor = ::LoadCursor(NULL, IDC_ARROW);
2171 ::SetCursor(hCursor);
2172 }
2173
2174 if (pFound && pFound->m_bEnable)
2175 {
2176 switch (uMsg)
2177 {
2178 case WM_MOUSEMOVE:
2179 pFound->OnMouseMove(pt.x, pt.y);
2180 break;
2181 case WM_LBUTTONDOWN:
2182 pFound->OnLButtonDown(pt.x, pt.y);
2183 break;
2184 case WM_LBUTTONUP:
2185 pFound->OnLButtonUp(pt.x, pt.y);
2186 break;
2187 case WM_RBUTTONDOWN:
2188 pFound->OnRButtonDown(pt.x, pt.y);
2189 break;
2190 case WM_RBUTTONUP:
2191 pFound->OnRButtonUp(pt.x, pt.y);
2192 break;
2193 case WM_MBUTTONDOWN:
2194 pFound->OnMButtonDown(pt.x, pt.y);
2195 break;
2196 case WM_MBUTTONUP:
2197 pFound->OnMButtonUp(pt.x, pt.y);
2198 break;
2199 }
2200 }
2201 }
2202
2203 /////////////////////////////////////////////////////////////////////////////
2204 // CUIFShadow
2205
2206 /// @unimplemented
CUIFShadow(HINSTANCE hInst,DWORD style,CUIFWindow * pShadowOwner)2207 CUIFShadow::CUIFShadow(HINSTANCE hInst, DWORD style, CUIFWindow *pShadowOwner)
2208 : CUIFWindow(hInst, (style | UIF_WINDOW_TOOLWINDOW))
2209 {
2210 m_pShadowOwner = pShadowOwner;
2211 m_rgbShadowColor = RGB(0, 0, 0);
2212 m_dwUnknown11[0] = 0;
2213 m_dwUnknown11[1] = 0;
2214 m_xShadowDelta = m_yShadowDelta = 0;
2215 m_bLayerAvailable = FALSE;
2216 }
2217
~CUIFShadow()2218 CUIFShadow::~CUIFShadow()
2219 {
2220 if (m_pShadowOwner)
2221 m_pShadowOwner->m_pShadow = NULL;
2222 }
2223
2224 /// @unimplemented
InitSettings()2225 void CUIFShadow::InitSettings()
2226 {
2227 m_bLayerAvailable = FALSE;
2228 m_rgbShadowColor = RGB(128, 128, 128);
2229 m_xShadowDelta = m_yShadowDelta = 2;
2230 }
2231
2232 /// @unimplemented
InitShadow()2233 void CUIFShadow::InitShadow()
2234 {
2235 if (m_bLayerAvailable)
2236 {
2237 //FIXME
2238 }
2239 }
2240
AdjustWindowPos()2241 void CUIFShadow::AdjustWindowPos()
2242 {
2243 HWND hwndOwner = *m_pShadowOwner;
2244 if (!::IsWindow(m_hWnd))
2245 return;
2246
2247 RECT rc;
2248 ::GetWindowRect(hwndOwner, &rc);
2249 ::SetWindowPos(m_hWnd, hwndOwner,
2250 rc.left + m_xShadowDelta,
2251 rc.top + m_yShadowDelta,
2252 rc.right - rc.left,
2253 rc.bottom - rc.top,
2254 SWP_NOOWNERZORDER | SWP_NOACTIVATE);
2255 }
2256
OnOwnerWndMoved(BOOL bDoSize)2257 void CUIFShadow::OnOwnerWndMoved(BOOL bDoSize)
2258 {
2259 if (::IsWindow(m_hWnd) && ::IsWindowVisible(m_hWnd))
2260 {
2261 AdjustWindowPos();
2262 if (bDoSize)
2263 InitShadow();
2264 }
2265 }
2266
STDMETHODIMP_(BOOL)2267 STDMETHODIMP_(BOOL)
2268 CUIFShadow::Initialize()
2269 {
2270 InitSettings();
2271 return CUIFWindow::Initialize();
2272 }
2273
STDMETHODIMP_(DWORD)2274 STDMETHODIMP_(DWORD)
2275 CUIFShadow::GetWndStyleEx()
2276 {
2277 DWORD exstyle = CUIFWindow::GetWndStyleEx();
2278 if (m_bLayerAvailable)
2279 exstyle |= WS_EX_LAYERED;
2280 return exstyle;
2281 }
2282
STDMETHODIMP_(void)2283 STDMETHODIMP_(void)
2284 CUIFShadow::OnPaint(HDC hDC)
2285 {
2286 RECT rc = m_rc;
2287 HBRUSH hBrush = ::CreateSolidBrush(m_rgbShadowColor);
2288 ::FillRect(hDC, &rc, hBrush);
2289 ::DeleteObject(hBrush);
2290 }
2291
STDMETHODIMP_(LRESULT)2292 STDMETHODIMP_(LRESULT)
2293 CUIFShadow::OnWindowPosChanging(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
2294 {
2295 WINDOWPOS *wp = (WINDOWPOS *)lParam;
2296 wp->hwndInsertAfter = *m_pShadowOwner;
2297 return ::DefWindowProc(hWnd, Msg, wParam, lParam);
2298 }
2299
STDMETHODIMP_(LRESULT)2300 STDMETHODIMP_(LRESULT)
2301 CUIFShadow::OnSettingChange(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2302 {
2303 InitSettings();
2304
2305 DWORD exstyle;
2306 if (m_bLayerAvailable)
2307 exstyle = ::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED;
2308 else
2309 exstyle = ::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) & ~WS_EX_LAYERED;
2310
2311 ::SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, exstyle);
2312
2313 AdjustWindowPos();
2314 InitShadow();
2315
2316 return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
2317 }
2318
STDMETHODIMP_(void)2319 STDMETHODIMP_(void)
2320 CUIFShadow::Show(BOOL bVisible)
2321 {
2322 if (bVisible && ::IsWindow(m_hWnd) && !::IsWindowVisible(m_hWnd))
2323 {
2324 AdjustWindowPos();
2325 InitShadow();
2326 }
2327
2328 if (::IsWindow(m_hWnd))
2329 {
2330 m_bVisible = bVisible;
2331 ::ShowWindow(m_hWnd, (bVisible ? SW_SHOWNOACTIVATE : SW_HIDE));
2332 }
2333 }
2334
2335 /////////////////////////////////////////////////////////////////////////////
2336 // CUIFToolTip
2337
CUIFToolTip(HINSTANCE hInst,DWORD style,CUIFWindow * pToolTipOwner)2338 CUIFToolTip::CUIFToolTip(HINSTANCE hInst, DWORD style, CUIFWindow *pToolTipOwner)
2339 : CUIFWindow(hInst, style)
2340 {
2341 m_pToolTipOwner = pToolTipOwner;
2342 m_rcToolTipMargin.left = 2;
2343 m_rcToolTipMargin.top = 2;
2344 m_rcToolTipMargin.right = 2;
2345 m_rcToolTipMargin.bottom = 2;
2346 m_pToolTipTarget = NULL;
2347 m_pszToolTipText = NULL;
2348 m_dwUnknown10 = 0; //FIXME: name and type
2349 m_nDelayTimeType2 = -1;
2350 m_nDelayTimeType3 = -1;
2351 m_nDelayTimeType1 = -1;
2352 m_cxToolTipWidth = -1;
2353 m_bToolTipHasBkColor = 0;
2354 m_bToolTipHasTextColor = 0;
2355 m_rgbToolTipBkColor = 0;
2356 m_rgbToolTipTextColor = 0;
2357 }
2358
~CUIFToolTip()2359 CUIFToolTip::~CUIFToolTip()
2360 {
2361 if (m_pToolTipOwner)
2362 m_pToolTipOwner->m_pToolTip = NULL;
2363 if (m_pszToolTipText)
2364 delete[] m_pszToolTipText;
2365 }
2366
2367 LONG
GetDelayTime(UINT uType)2368 CUIFToolTip::GetDelayTime(UINT uType)
2369 {
2370 LONG nDelayTime;
2371 switch (uType)
2372 {
2373 case 1:
2374 {
2375 nDelayTime = m_nDelayTimeType1;
2376 if (nDelayTime == -1)
2377 return ::GetDoubleClickTime() / 5;
2378 return nDelayTime;
2379 }
2380 case 2:
2381 {
2382 nDelayTime = m_nDelayTimeType2;
2383 if (nDelayTime == -1)
2384 return 10 * ::GetDoubleClickTime();
2385 return nDelayTime;
2386 }
2387 case 3:
2388 {
2389 nDelayTime = m_nDelayTimeType3;
2390 if (nDelayTime == -1)
2391 return ::GetDoubleClickTime();
2392 return nDelayTime;
2393 }
2394 default:
2395 {
2396 return 0;
2397 }
2398 }
2399 }
2400
GetMargin(LPRECT prc)2401 void CUIFToolTip::GetMargin(LPRECT prc)
2402 {
2403 if (prc)
2404 *prc = m_rcToolTipMargin;
2405 }
2406
2407 COLORREF
GetTipBkColor()2408 CUIFToolTip::GetTipBkColor()
2409 {
2410 if (m_bToolTipHasBkColor)
2411 return m_rgbToolTipBkColor;
2412 return ::GetSysColor(COLOR_INFOBK);
2413 }
2414
2415 COLORREF
GetTipTextColor()2416 CUIFToolTip::GetTipTextColor()
2417 {
2418 if (m_bToolTipHasTextColor)
2419 return m_rgbToolTipTextColor;
2420 return ::GetSysColor(COLOR_INFOTEXT);
2421 }
2422
2423 CUIFObject*
FindObject(HWND hWnd,POINT pt)2424 CUIFToolTip::FindObject(HWND hWnd, POINT pt)
2425 {
2426 if (hWnd == *m_pToolTipOwner)
2427 return m_pToolTipOwner->ObjectFromPoint(pt);
2428 return NULL;
2429 }
2430
2431 void
ShowTip()2432 CUIFToolTip::ShowTip()
2433 {
2434 ::KillTimer(m_hWnd, TOOLTIP_TIMER_ID);
2435
2436 if (!m_pToolTipTarget)
2437 return;
2438
2439 LPCWSTR pszText = m_pToolTipTarget->GetToolTip();
2440 if (!pszText)
2441 return;
2442
2443 if (!m_pToolTipTarget || m_pToolTipTarget->OnShowToolTip())
2444 return;
2445
2446 POINT Point;
2447 ::GetCursorPos(&Point);
2448 ::ScreenToClient(*m_pToolTipTarget->m_pWindow, &Point);
2449
2450 RECT rc;
2451 m_pToolTipTarget->GetRect(&rc);
2452 if (!::PtInRect(&rc, Point))
2453 return;
2454
2455 size_t cchText = wcslen(pszText);
2456 m_pszToolTipText = new(cicNoThrow) WCHAR[cchText + 1];
2457 if (!m_pszToolTipText)
2458 return;
2459
2460 lstrcpynW(m_pszToolTipText, pszText, cchText + 1);
2461
2462 SIZE size;
2463 GetTipWindowSize(&size);
2464
2465 RECT rc2 = rc;
2466 ::ClientToScreen(*m_pToolTipTarget->m_pWindow, (LPPOINT)&rc);
2467 ::ClientToScreen(*m_pToolTipTarget->m_pWindow, (LPPOINT)&rc.right);
2468 GetTipWindowRect(&rc2, size, &rc);
2469
2470 m_bShowToolTip = TRUE;
2471 Move(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
2472 Show(TRUE);
2473 }
2474
2475 void
HideTip()2476 CUIFToolTip::HideTip()
2477 {
2478 ::KillTimer(m_hWnd, TOOLTIP_TIMER_ID);
2479 m_bShowToolTip = FALSE;
2480
2481 if (m_pToolTipTarget)
2482 m_pToolTipTarget->OnHideToolTip();
2483
2484 if (m_bVisible)
2485 {
2486 if (m_pszToolTipText)
2487 {
2488 delete[] m_pszToolTipText;
2489 m_pszToolTipText = NULL;
2490 }
2491 Show(FALSE);
2492 }
2493 }
2494
2495 void
GetTipWindowSize(LPSIZE pSize)2496 CUIFToolTip::GetTipWindowSize(LPSIZE pSize)
2497 {
2498 if (!m_pszToolTipText)
2499 return;
2500
2501 HDC hDC = ::GetDC(m_hWnd);
2502 HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
2503
2504 RECT rcText = { 0, 0, 0, 0 };
2505 INT cyText;
2506 if (m_cxToolTipWidth <= 0)
2507 {
2508 cyText = ::DrawTextW(hDC, m_pszToolTipText, -1, &rcText, DT_CALCRECT | DT_SINGLELINE);
2509 }
2510 else
2511 {
2512 rcText.right = m_cxToolTipWidth;
2513 cyText = ::DrawTextW(hDC, m_pszToolTipText, -1, &rcText, DT_CALCRECT | DT_WORDBREAK);
2514 }
2515
2516 RECT rcMargin;
2517 GetMargin(&rcMargin);
2518
2519 RECT rc;
2520 rc.left = rcText.left - rcMargin.left;
2521 rc.top = rcText.top - rcMargin.top;
2522 rc.right = rcText.right + rcMargin.right;
2523 rc.bottom = rcText.top + cyText + rcMargin.bottom;
2524 ClientRectToWindowRect(&rc);
2525
2526 pSize->cx = rc.right - rc.left;
2527 pSize->cy = rc.bottom - rc.top;
2528
2529 ::SelectObject(hDC, hFontOld);
2530 ::ReleaseDC(m_hWnd, hDC);
2531 }
2532
2533 void
GetTipWindowRect(LPRECT pRect,SIZE toolTipSize,LPCRECT prc)2534 CUIFToolTip::GetTipWindowRect(LPRECT pRect, SIZE toolTipSize, LPCRECT prc)
2535 {
2536 POINT Point;
2537 GetCursorPos(&Point);
2538
2539 HCURSOR hCursor = ::GetCursor();
2540 ICONINFO IconInfo;
2541 INT yHotspot = 0;
2542 INT cyCursor = ::GetSystemMetrics(SM_CYCURSOR);
2543 if (hCursor && ::GetIconInfo(hCursor, &IconInfo))
2544 {
2545 BITMAP bm;
2546 ::GetObject(IconInfo.hbmMask, sizeof(bm), &bm);
2547 if (!IconInfo.fIcon)
2548 {
2549 cyCursor = bm.bmHeight;
2550 yHotspot = IconInfo.yHotspot;
2551 if (!IconInfo.hbmColor)
2552 cyCursor = bm.bmHeight / 2;
2553 }
2554 if (IconInfo.hbmColor)
2555 ::DeleteObject(IconInfo.hbmColor);
2556 if (IconInfo.hbmMask)
2557 ::DeleteObject(IconInfo.hbmMask);
2558 }
2559
2560 RECT rcMonitor;
2561 rcMonitor.left = 0;
2562 rcMonitor.top = 0;
2563 rcMonitor.right = GetSystemMetrics(SM_CXSCREEN);
2564 rcMonitor.bottom = GetSystemMetrics(SM_CYSCREEN);
2565
2566 HMONITOR hMon = ::MonitorFromPoint(Point, MONITOR_DEFAULTTONEAREST);
2567 MONITORINFO mi;
2568 if (hMon)
2569 {
2570 mi.cbSize = sizeof(MONITORINFO);
2571 if (::GetMonitorInfo(hMon, &mi))
2572 rcMonitor = mi.rcMonitor;
2573 }
2574
2575 pRect->left = Point.x;
2576 pRect->right = pRect->left + toolTipSize.cx;
2577 pRect->top = Point.y + cyCursor - yHotspot;
2578 pRect->bottom = pRect->top + toolTipSize.cy;
2579
2580 if (rcMonitor.right < pRect->right)
2581 {
2582 pRect->left = rcMonitor.right - toolTipSize.cx;
2583 pRect->right = rcMonitor.right;
2584 }
2585 if (pRect->left < rcMonitor.left)
2586 {
2587 pRect->left = rcMonitor.left;
2588 pRect->right = rcMonitor.left + toolTipSize.cx;
2589 }
2590 if (rcMonitor.bottom < pRect->bottom)
2591 {
2592 pRect->top = rcMonitor.bottom - toolTipSize.cy;
2593 pRect->bottom = rcMonitor.bottom;
2594 }
2595 if (pRect->top < rcMonitor.top)
2596 {
2597 pRect->top = rcMonitor.top;
2598 pRect->bottom = rcMonitor.top + toolTipSize.cy;
2599 }
2600 }
2601
2602 void
RelayEvent(LPMSG pMsg)2603 CUIFToolTip::RelayEvent(LPMSG pMsg)
2604 {
2605 if (!pMsg)
2606 return;
2607
2608 switch (pMsg->message)
2609 {
2610 case WM_MOUSEMOVE:
2611 {
2612 if (m_bEnable &&
2613 ::GetKeyState(VK_LBUTTON) >= 0 &&
2614 ::GetKeyState(VK_MBUTTON) >= 0 &&
2615 ::GetKeyState(VK_RBUTTON) >= 0)
2616 {
2617 POINT pt = { (SHORT)LOWORD(pMsg->lParam), (SHORT)HIWORD(pMsg->lParam) };
2618 CUIFObject *pFound = CUIFToolTip::FindObject(pMsg->hwnd, pt);
2619 if (pFound)
2620 {
2621 if (m_pToolTipTarget != pFound)
2622 {
2623 HideTip();
2624
2625 LONG DelayTime;
2626 if (!m_bVisible)
2627 DelayTime = GetDelayTime(3);
2628 else
2629 DelayTime = GetDelayTime(1);
2630 ::SetTimer(m_hWnd, TOOLTIP_TIMER_ID, DelayTime, NULL);
2631 }
2632 }
2633 else
2634 {
2635 HideTip();
2636 }
2637 m_pToolTipTarget = pFound;
2638 }
2639 break;
2640 }
2641 case WM_LBUTTONDOWN:
2642 case WM_RBUTTONDOWN:
2643 case WM_MBUTTONDOWN:
2644 {
2645 HideTip();
2646 break;
2647 }
2648 }
2649 }
2650
STDMETHODIMP_(void)2651 STDMETHODIMP_(void) CUIFToolTip::OnPaint(HDC hDC)
2652 {
2653 HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
2654 INT iBkModeOld = ::SetBkMode(hDC, TRANSPARENT);
2655
2656 COLORREF rgbTextColor = GetTipTextColor();
2657 COLORREF rgbOldTextColor = ::SetTextColor(hDC, rgbTextColor);
2658
2659 COLORREF rgbBkColor = GetTipBkColor();
2660 HBRUSH hbrBack = ::CreateSolidBrush(rgbBkColor);
2661 RECT rc = m_rc;
2662 if (hbrBack)
2663 {
2664 ::FillRect(hDC, &rc, hbrBack);
2665 ::DeleteObject(hbrBack);
2666 }
2667
2668 RECT rcMargin;
2669 GetMargin(&rcMargin);
2670
2671 rc.left += rcMargin.left;
2672 rc.top += rcMargin.top;
2673 rc.right -= rcMargin.right;
2674 rc.bottom -= rcMargin.bottom;
2675
2676 if (m_cxToolTipWidth <= 0)
2677 ::DrawTextW(hDC, m_pszToolTipText, -1, &rc, DT_SINGLELINE);
2678 else
2679 ::DrawTextW(hDC, m_pszToolTipText, -1, &rc, DT_WORDBREAK);
2680
2681 ::SetTextColor(hDC, rgbOldTextColor);
2682 ::SetBkMode(hDC, iBkModeOld);
2683 ::SelectObject(hDC, hFontOld);
2684 }
2685
STDMETHODIMP_(void)2686 STDMETHODIMP_(void) CUIFToolTip::Enable(BOOL bEnable)
2687 {
2688 if (!bEnable)
2689 HideTip();
2690 CUIFObject::Enable(bEnable);
2691 }
2692
STDMETHODIMP_(void)2693 STDMETHODIMP_(void) CUIFToolTip::OnTimer(WPARAM wParam)
2694 {
2695 if (wParam == TOOLTIP_TIMER_ID)
2696 ShowTip();
2697 }
2698
2699 /////////////////////////////////////////////////////////////////////////////
2700 // CUIFButton
2701
CUIFButton(CUIFObject * pParent,DWORD nObjectID,LPCRECT prc,DWORD style)2702 CUIFButton::CUIFButton(
2703 CUIFObject *pParent,
2704 DWORD nObjectID,
2705 LPCRECT prc,
2706 DWORD style) : CUIFObject(pParent, nObjectID, prc, style)
2707 {
2708 m_ButtonIcon.m_hIcon = NULL;
2709 m_ButtonIcon.m_hImageList = NULL;
2710 m_dwUnknown9 = 0;
2711 m_uButtonStatus = 0;
2712 m_bPressed = FALSE;
2713 m_hbmButton1 = NULL;
2714 m_hbmButton2 = NULL;
2715 m_pszButtonText = NULL;
2716 }
2717
~CUIFButton()2718 CUIFButton::~CUIFButton()
2719 {
2720 if (m_pszButtonText)
2721 {
2722 delete[] m_pszButtonText;
2723 m_pszButtonText = NULL;
2724 }
2725
2726 if (m_ButtonIcon.m_hImageList)
2727 ImageList_Destroy(m_ButtonIcon.m_hImageList);
2728 }
2729
2730 void
DrawBitmapProc(HDC hDC,LPCRECT prc,BOOL bPressed)2731 CUIFButton::DrawBitmapProc(HDC hDC, LPCRECT prc, BOOL bPressed)
2732 {
2733 INT width = m_rc.right - m_rc.left;
2734 INT height = m_rc.bottom - m_rc.top;
2735 if (m_hbmButton2)
2736 {
2737 HBITMAP hbmMask = cicCreateMaskBmp(&m_rc, m_hbmButton1, m_hbmButton2,
2738 (HBRUSH)UlongToHandle(COLOR_BTNFACE + 1), 0, 0);
2739 ::DrawState(hDC, NULL, NULL, (LPARAM)hbmMask, 0,
2740 prc->left + bPressed, prc->top + bPressed,
2741 width - bPressed, height - bPressed,
2742 DST_BITMAP | (m_bEnable ? 0 : (DSS_MONO | DSS_DISABLED)));
2743 ::DeleteObject(hbmMask);
2744 }
2745 else
2746 {
2747 ::DrawState(hDC, NULL, NULL, (LPARAM)m_hbmButton1, 0,
2748 prc->left + bPressed, prc->top + bPressed,
2749 width - bPressed, height - bPressed,
2750 DST_BITMAP | (m_bEnable ? 0 : (DSS_MONO | DSS_DISABLED)));
2751 }
2752 }
2753
2754 void
DrawEdgeProc(HDC hDC,LPCRECT prc,BOOL bPressed)2755 CUIFButton::DrawEdgeProc(HDC hDC, LPCRECT prc, BOOL bPressed)
2756 {
2757 RECT rc = *prc;
2758 if (bPressed)
2759 ::DrawEdge(hDC, &rc, BDR_SUNKENOUTER, BF_RECT);
2760 else
2761 ::DrawEdge(hDC, &rc, BDR_RAISEDINNER, BF_RECT);
2762 }
2763
DrawIconProc(HDC hDC,LPRECT prc,BOOL bPressed)2764 void CUIFButton::DrawIconProc(HDC hDC, LPRECT prc, BOOL bPressed)
2765 {
2766 INT width = prc->right - prc->left;
2767 INT height = prc->bottom - prc->top;
2768 RECT rc = { 0, 0, width, height };
2769
2770 HDC hMemDC = ::CreateCompatibleDC(hDC);
2771 if (!hMemDC)
2772 return;
2773
2774 HBITMAP hbmMem = ::CreateCompatibleBitmap(hDC, width, height);
2775 if (!hbmMem)
2776 {
2777 ::DeleteDC(hMemDC);
2778 return;
2779 }
2780
2781 HGDIOBJ hbmOld = ::SelectObject(hMemDC, hbmMem);
2782 if (m_bEnable)
2783 {
2784 ::BitBlt(hMemDC, rc.left, rc.top, width, height, hDC, prc->left, prc->top, SRCCOPY);
2785 }
2786 else
2787 {
2788 HBRUSH hbrWhite = (HBRUSH)::GetStockObject(WHITE_BRUSH);
2789 ::FillRect(hMemDC, &rc, hbrWhite);
2790 }
2791
2792 if (m_style & UIF_BUTTON_LARGE_ICON)
2793 {
2794 ::DrawIconEx(hMemDC,
2795 2 + bPressed, 2 + bPressed,
2796 m_ButtonIcon.m_hIcon,
2797 width - 4, height - 4,
2798 0, NULL, DI_NORMAL);
2799 }
2800 else
2801 {
2802 ::DrawIconEx(hMemDC,
2803 (width - 16) / 2 + bPressed,
2804 (height - 16) / 2 + bPressed,
2805 m_ButtonIcon.m_hIcon,
2806 16, 16,
2807 0, NULL, DI_NORMAL);
2808 }
2809
2810 ::SelectObject(hMemDC, hbmOld);
2811 ::DrawState(hDC, NULL, NULL, (LPARAM)hbmMem, 0,
2812 prc->left, prc->top, width, height,
2813 DST_BITMAP | (m_bEnable ? 0 : (DSS_MONO | DSS_DISABLED)));
2814 ::DeleteObject(hbmMem);
2815 ::DeleteDC(hMemDC);
2816 }
2817
2818 void
DrawTextProc(HDC hDC,LPCRECT prc,BOOL bPressed)2819 CUIFButton::DrawTextProc(HDC hDC, LPCRECT prc, BOOL bPressed)
2820 {
2821 if (!m_pszButtonText)
2822 return;
2823
2824 HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
2825 INT cchText = lstrlenW(m_pszButtonText);
2826 SIZE textSize;
2827 ::GetTextExtentPoint32W(hDC, m_pszButtonText, cchText, &textSize);
2828
2829 INT xText, yText;
2830 if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_CENTER)
2831 xText = (m_rc.right - m_rc.left - textSize.cx) / 2;
2832 else if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_RIGHT)
2833 xText = m_rc.right - m_rc.left - textSize.cx;
2834 else
2835 xText = 0;
2836
2837 if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_MIDDLE)
2838 yText = (m_rc.bottom - m_rc.top - textSize.cy) / 2;
2839 else if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_BOTTOM)
2840 yText = m_rc.bottom - m_rc.top - textSize.cy;
2841 else
2842 yText = 0;
2843
2844 ::SetBkMode(hDC, TRANSPARENT);
2845
2846 if (m_bEnable)
2847 {
2848 ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNTEXT));
2849 ::ExtTextOutW(hDC,
2850 xText + prc->left + bPressed, yText + prc->top + bPressed,
2851 ETO_CLIPPED, prc,
2852 m_pszButtonText, cchText, NULL);
2853 }
2854 else
2855 {
2856 ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHILIGHT));
2857 ::ExtTextOutW(hDC,
2858 xText + prc->left + bPressed + 1, yText + prc->top + bPressed + 1,
2859 ETO_CLIPPED, prc,
2860 m_pszButtonText, cchText, NULL);
2861
2862 ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNSHADOW));
2863 ::ExtTextOutW(hDC,
2864 xText + prc->left + bPressed, yText + prc->top + bPressed,
2865 ETO_CLIPPED, prc,
2866 m_pszButtonText, cchText, NULL);
2867 }
2868
2869 ::SelectObject(hDC, hFontOld);
2870 }
2871
STDMETHODIMP_(void)2872 STDMETHODIMP_(void)
2873 CUIFButton::Enable(BOOL bEnable)
2874 {
2875 CUIFObject::Enable(bEnable);
2876 if (!m_bEnable)
2877 {
2878 SetStatus(0);
2879 if (IsCapture())
2880 CUIFObject::EndCapture();
2881 }
2882 }
2883
2884 void
GetIconSize(HICON hIcon,LPSIZE pSize)2885 CUIFButton::GetIconSize(HICON hIcon, LPSIZE pSize)
2886 {
2887 ICONINFO IconInfo;
2888 if (::GetIconInfo(hIcon, &IconInfo))
2889 {
2890 BITMAP bm;
2891 ::GetObject(IconInfo.hbmColor, sizeof(bm), &bm);
2892 ::DeleteObject(IconInfo.hbmColor);
2893 ::DeleteObject(IconInfo.hbmMask);
2894 pSize->cx = bm.bmWidth;
2895 pSize->cy = bm.bmHeight;
2896 }
2897 else
2898 {
2899 pSize->cx = ::GetSystemMetrics(SM_CXSMICON);
2900 pSize->cy = ::GetSystemMetrics(SM_CYSMICON);
2901 }
2902 }
2903
2904 void
GetTextSize(LPCWSTR pszText,LPSIZE pSize)2905 CUIFButton::GetTextSize(LPCWSTR pszText, LPSIZE pSize)
2906 {
2907 HDC hDC = ::GetDC(NULL);
2908 INT cchText = lstrlenW(pszText);
2909 HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
2910
2911 if (!m_bHasCustomFont && SUCCEEDED(EnsureThemeData(*m_pWindow)))
2912 {
2913 RECT rc;
2914 GetThemeTextExtent(hDC, 0, pszText, cchText, 0, NULL, &rc);
2915 pSize->cx = rc.right;
2916 pSize->cy = rc.bottom;
2917 }
2918 else
2919 {
2920 ::GetTextExtentPoint32W(hDC, pszText, cchText, pSize);
2921 }
2922
2923 if (m_style & UIF_BUTTON_VERTICAL)
2924 {
2925 INT tmp = pSize->cx;
2926 pSize->cx = pSize->cy;
2927 pSize->cy = tmp;
2928 }
2929
2930 ::SelectObject(hDC, hFontOld);
2931 ::ReleaseDC(NULL, hDC);
2932 }
2933
STDMETHODIMP_(void)2934 STDMETHODIMP_(void)
2935 CUIFButton::OnLButtonDown(LONG x, LONG y)
2936 {
2937 SetStatus(1);
2938 StartCapture();
2939 if ((m_style & 0x30) == 0x20)
2940 NotifyCommand(1, 0);
2941 }
2942
2943 /// @unimplemented
STDMETHODIMP_(void)2944 STDMETHODIMP_(void)
2945 CUIFButton::OnLButtonUp(LONG x, LONG y)
2946 {
2947 POINT pt = { x, y };
2948 BOOL bCapture = IsCapture();
2949 if (bCapture)
2950 EndCapture();
2951
2952 BOOL bNotInObject = (m_style & 0x30) == 0x20;
2953 if ((m_style & 0x30) != 0x10)
2954 {
2955 bNotInObject = !PtInObject(pt);
2956 if (bNotInObject)
2957 {
2958 SetStatus(0);
2959 return;
2960 }
2961 }
2962 else
2963 {
2964 if (!bNotInObject)
2965 {
2966 bNotInObject = !PtInObject(pt);
2967 if (!bNotInObject)
2968 {
2969 SetStatus(2);
2970 NotifyCommand(1, 0);
2971 return;
2972 }
2973 }
2974 SetStatus(0);
2975 return;
2976 }
2977
2978 SetStatus(2);
2979
2980 if (bCapture)
2981 {
2982 m_bPressed = !m_bPressed;
2983 NotifyCommand(1, 0);
2984 }
2985 }
2986
OnMouseIn(LONG x,LONG y)2987 void CUIFButton::OnMouseIn(LONG x, LONG y)
2988 {
2989 if ((m_style & 0x30) == 0x20)
2990 {
2991 if (IsCapture())
2992 SetStatus(0);
2993 else
2994 SetStatus(2);
2995 }
2996 else
2997 {
2998 if (IsCapture())
2999 SetStatus(1);
3000 else
3001 SetStatus(2);
3002 }
3003 }
3004
OnMouseOut(LONG x,LONG y)3005 void CUIFButton::OnMouseOut(LONG x, LONG y)
3006 {
3007 if ((m_style & 0x30) == 0x20)
3008 SetStatus(0);
3009 else if (IsCapture())
3010 SetStatus(3);
3011 else
3012 SetStatus(0);
3013 }
3014
STDMETHODIMP_(void)3015 STDMETHODIMP_(void)
3016 CUIFButton::OnPaintNoTheme(HDC hDC)
3017 {
3018 ::FillRect(hDC, &m_rc, (HBRUSH)UlongToHandle(COLOR_BTNFACE + 1));
3019
3020 if (m_bPressed && ((m_uButtonStatus == 0) || (m_uButtonStatus == 3)))
3021 {
3022 HBRUSH hbr = cicCreateDitherBrush();
3023 if (hbr)
3024 {
3025 COLORREF OldTextColor = ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNFACE));
3026 COLORREF OldBkColor = ::SetBkColor(hDC, ::GetSysColor(COLOR_BTNHIGHLIGHT));
3027 RECT rc = m_rc;
3028 ::InflateRect(&rc, -2, -2);
3029 ::FillRect(hDC, &rc, hbr);
3030 ::SetTextColor(hDC, OldTextColor);
3031 ::SetBkColor(hDC, OldBkColor);
3032 ::DeleteObject(hbr);
3033 }
3034 }
3035
3036 BOOL bPressed = (m_bPressed || (m_uButtonStatus == 1));
3037 if (m_hbmButton1)
3038 DrawBitmapProc(hDC, &m_rc, bPressed);
3039 else if (m_ButtonIcon.m_hIcon)
3040 DrawIconProc(hDC, &m_rc, bPressed);
3041 else
3042 DrawTextProc(hDC, &m_rc, bPressed);
3043
3044 if (m_bPressed || (m_uButtonStatus == 1))
3045 DrawEdgeProc(hDC, &m_rc, TRUE);
3046 else if (2 <= m_uButtonStatus && m_uButtonStatus <= 3)
3047 DrawEdgeProc(hDC, &m_rc, FALSE);
3048 }
3049
SetIcon(HICON hIcon)3050 void CUIFButton::SetIcon(HICON hIcon)
3051 {
3052 m_ButtonIcon = hIcon;
3053
3054 if (m_ButtonIcon.m_hIcon)
3055 GetIconSize(m_ButtonIcon.m_hIcon, &m_IconSize);
3056 else
3057 m_IconSize.cx = m_IconSize.cy = 0;
3058
3059 CallOnPaint();
3060 }
3061
SetStatus(UINT uStatus)3062 void CUIFButton::SetStatus(UINT uStatus)
3063 {
3064 if (uStatus != m_uButtonStatus)
3065 {
3066 m_uButtonStatus = uStatus;
3067 CallOnPaint();
3068 }
3069 }
3070
SetText(LPCWSTR pszText)3071 void CUIFButton::SetText(LPCWSTR pszText)
3072 {
3073 if (m_pszButtonText)
3074 {
3075 delete[] m_pszButtonText;
3076 m_pszButtonText = NULL;
3077 }
3078
3079 m_TextSize.cx = m_TextSize.cy = 0;
3080
3081 if (pszText)
3082 {
3083 INT cch = lstrlenW(pszText);
3084 m_pszButtonText = new(cicNoThrow) WCHAR[cch + 1];
3085 if (!m_pszButtonText)
3086 return;
3087
3088 lstrcpynW(m_pszButtonText, pszText, cch + 1);
3089 GetTextSize(m_pszButtonText, &m_TextSize);
3090 }
3091
3092 CallOnPaint();
3093 }
3094
3095 /////////////////////////////////////////////////////////////////////////////
3096 // CUIFButton2
3097
CUIFButton2(CUIFObject * pParent,DWORD nObjectID,LPCRECT prc,DWORD style)3098 CUIFButton2::CUIFButton2(
3099 CUIFObject *pParent,
3100 DWORD nObjectID,
3101 LPCRECT prc,
3102 DWORD style) : CUIFButton(pParent, nObjectID, prc, style)
3103 {
3104 m_iStateId = 0;
3105 m_iPartId = BP_PUSHBUTTON;
3106 m_pszClassList = L"TOOLBAR";
3107 }
3108
~CUIFButton2()3109 CUIFButton2::~CUIFButton2()
3110 {
3111 CloseThemeData();
3112 }
3113
MakeDrawFlag()3114 DWORD CUIFButton2::MakeDrawFlag()
3115 {
3116 DWORD dwDrawFlags = 0;
3117 if (m_bPressed)
3118 dwDrawFlags |= UIF_DRAW_PRESSED;
3119 if (m_uButtonStatus == 1)
3120 dwDrawFlags |= 0x2;
3121 else if (2 <= m_uButtonStatus && m_uButtonStatus <= 3)
3122 dwDrawFlags |= 0x1;
3123 if (!m_bEnable)
3124 dwDrawFlags |= UIF_DRAW_DISABLED;
3125 return dwDrawFlags;
3126 }
3127
3128 /// @unimplemented
STDMETHODIMP_(BOOL)3129 STDMETHODIMP_(BOOL)
3130 CUIFButton2::OnPaintTheme(HDC hDC)
3131 {
3132 //FIXME
3133 return FALSE;
3134 }
3135
STDMETHODIMP_(void)3136 STDMETHODIMP_(void)
3137 CUIFButton2::OnPaintNoTheme(HDC hDC)
3138 {
3139 if (!m_pScheme)
3140 return;
3141
3142 INT width = m_rc.right - m_rc.left;
3143 INT height = m_rc.bottom - m_rc.top;
3144 HDC hdcMem = ::CreateCompatibleDC(hDC);
3145 if (!hdcMem)
3146 return;
3147
3148 HBITMAP hbmMem = ::CreateCompatibleBitmap(hDC, width, height);
3149 if ( !hbmMem )
3150 {
3151 ::DeleteDC(hdcMem);
3152 return;
3153 }
3154
3155 HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbmMem);
3156 HGDIOBJ hFontOld = ::SelectObject(hdcMem, m_hFont);
3157 RECT rcBack = { 0, 0, width, height };
3158
3159 INT cxText = 0, cyText = 0, cxContent = 0, cyContent = 0;
3160 INT cxyBorders, cxButton, cyButton;
3161 if (m_pszButtonText)
3162 {
3163 cxText = m_TextSize.cx;
3164 cyText = m_TextSize.cy;
3165 }
3166
3167 if (m_ButtonIcon.m_hIcon)
3168 {
3169 cxContent = m_IconSize.cx;
3170 cyContent = m_IconSize.cy;
3171 }
3172 else if (m_hbmButton1)
3173 {
3174 cxContent = m_BitmapSize.cx;
3175 cyContent = m_BitmapSize.cy;
3176 }
3177
3178 if (m_style & UIF_BUTTON_VERTICAL)
3179 {
3180 cxyBorders = ((cyText && cyContent) ? 2 : 0);
3181
3182 cxButton = cxContent;
3183 cyButton = cyText + cyContent + cxyBorders;
3184 if (cxText > cxContent)
3185 cxButton = cxText;
3186 }
3187 else
3188 {
3189 cxyBorders = ((cxText && cxContent) ? 2 : 0);
3190
3191 cxButton = cxText + cxContent + cxyBorders;
3192 cyButton = cyContent;
3193 if (cyText > cyButton)
3194 cyButton = cyText;
3195 }
3196
3197 INT xOffset, yOffset;
3198 if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_CENTER)
3199 xOffset = (rcBack.left + rcBack.right - cxButton) / 2;
3200 else if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_RIGHT)
3201 xOffset = rcBack.right - cxText - 2;
3202 else
3203 xOffset = rcBack.left + 2;
3204
3205
3206 if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_MIDDLE)
3207 yOffset = (rcBack.top + rcBack.bottom - cyButton) / 2;
3208 else if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_BOTTOM)
3209 yOffset = rcBack.bottom - cyButton - 2;
3210 else
3211 yOffset = rcBack.top + 2;
3212
3213 RECT rc = { xOffset, yOffset, xOffset + cxButton, cyButton + yOffset };
3214 SIZE offsetSize = { 0, 0 };
3215 DWORD dwDrawFlags = MakeDrawFlag();
3216 m_pScheme->GetCtrlFaceOffset(((m_style & 0x200) ? 0xA5 : 0x54),
3217 dwDrawFlags,
3218 &offsetSize);
3219 ::OffsetRect(&rc, offsetSize.cx, offsetSize.cy);
3220
3221 RECT rcImage, rcText;
3222 if (m_style & UIF_BUTTON_VERTICAL)
3223 {
3224 rcImage.left = (rc.left + rc.right - cxContent) / 2;
3225 rcImage.top = rc.top;
3226 rcImage.right = rcImage.left + cxContent;
3227 rcImage.bottom = rc.top + cyContent;
3228 rcText.left = (rc.left + rc.right - cxText) / 2;
3229 rcText.top = rc.bottom - cyText;
3230 rcText.right = rcText.left + cxText;
3231 rcText.bottom = rc.bottom;
3232 }
3233 else
3234 {
3235 rcImage.left = rc.left;
3236 rcImage.top = (rc.top + rc.bottom - cyContent) / 2;
3237 rcImage.bottom = rcImage.top + cyContent;
3238 rcImage.right = rc.left + cxContent;
3239 rcText.left = rc.right - cxText;
3240 rcText.top = (rc.top + rc.bottom - cyText) / 2;
3241 rcText.right = rc.right;
3242 rcText.bottom = rcText.top + cyText;
3243 }
3244
3245 if (IsRTL())
3246 m_pScheme->m_bMirroring = TRUE;
3247
3248 m_pScheme->DrawCtrlBkgd(hdcMem,
3249 &rcBack,
3250 ((m_style & 0x200) ? 0xA5 : 0x54),
3251 dwDrawFlags);
3252 if (m_pszButtonText)
3253 {
3254 m_pScheme->DrawCtrlText(hdcMem, &rcText, m_pszButtonText, -1, dwDrawFlags,
3255 !!(m_style & UIF_BUTTON_VERTICAL));
3256 }
3257
3258 if (m_ButtonIcon.m_hIcon)
3259 m_pScheme->DrawCtrlIcon(hdcMem, &rcImage, m_ButtonIcon.m_hIcon, dwDrawFlags, &m_IconSize);
3260 else if (m_hbmButton1)
3261 m_pScheme->DrawCtrlBitmap(hdcMem, &rcImage, m_hbmButton1, m_hbmButton2, dwDrawFlags);
3262
3263 if (IsRTL())
3264 m_pScheme->m_bMirroring = FALSE;
3265
3266 m_pScheme->DrawCtrlEdge(hdcMem,
3267 &rcBack,
3268 ((m_style & 0x200) ? 0xA5 : 0x54),
3269 dwDrawFlags);
3270
3271 ::BitBlt(hDC, m_rc.left, m_rc.top, width, height, hdcMem, 0, 0, SRCCOPY);
3272 ::SelectObject(hdcMem, hFontOld);
3273 ::SelectObject(hdcMem, hbmOld);
3274 ::DeleteObject(hbmMem);
3275 }
3276
3277 /////////////////////////////////////////////////////////////////////////////
3278 // CUIFGripper
3279
CUIFGripper(CUIFObject * pParent,LPCRECT prc,DWORD style)3280 CUIFGripper::CUIFGripper(CUIFObject *pParent, LPCRECT prc, DWORD style)
3281 : CUIFObject(pParent, 0, prc, style)
3282 {
3283 m_iStateId = 0;
3284 m_pszClassList = L"REBAR";
3285 if (m_style & UIF_GRIPPER_VERTICAL)
3286 m_iPartId = RP_GRIPPERVERT;
3287 else
3288 m_iPartId = RP_GRIPPER;
3289 }
3290
~CUIFGripper()3291 CUIFGripper::~CUIFGripper()
3292 {
3293 }
3294
STDMETHODIMP_(void)3295 STDMETHODIMP_(void)
3296 CUIFGripper::OnMouseMove(LONG x, LONG y)
3297 {
3298 if (IsCapture())
3299 {
3300 POINT pt;
3301 ::GetCursorPos(&pt);
3302 m_pWindow->Move(pt.x - m_ptGripper.x, pt.y - m_ptGripper.y, -1, -1);
3303 }
3304 }
3305
STDMETHODIMP_(void)3306 STDMETHODIMP_(void)
3307 CUIFGripper::OnLButtonDown(LONG x, LONG y)
3308 {
3309 StartCapture();
3310 m_ptGripper.x = x;
3311 m_ptGripper.y = y;
3312 ::ScreenToClient(*m_pWindow, &m_ptGripper);
3313 RECT rc;
3314 ::GetWindowRect(*m_pWindow, &rc);
3315 m_ptGripper.x -= rc.left;
3316 m_ptGripper.y -= rc.top;
3317 }
3318
STDMETHODIMP_(void)3319 STDMETHODIMP_(void)
3320 CUIFGripper::OnLButtonUp(LONG x, LONG y)
3321 {
3322 if (IsCapture())
3323 EndCapture();
3324 }
3325
STDMETHODIMP_(BOOL)3326 STDMETHODIMP_(BOOL)
3327 CUIFGripper::OnPaintTheme(HDC hDC)
3328 {
3329 if (FAILED(EnsureThemeData(*m_pWindow)))
3330 return FALSE;
3331
3332 if (m_style & UIF_GRIPPER_VERTICAL)
3333 {
3334 m_rc.top += 2;
3335 m_rc.bottom -= 2;
3336 }
3337 else
3338 {
3339 m_rc.left += 2;
3340 m_rc.right -= 2;
3341 }
3342
3343 if (FAILED(DrawThemeBackground(hDC, 1, &m_rc, 0)))
3344 return FALSE;
3345
3346 return TRUE;
3347 }
3348
STDMETHODIMP_(void)3349 STDMETHODIMP_(void)
3350 CUIFGripper::OnPaintNoTheme(HDC hDC)
3351 {
3352 if (m_pScheme)
3353 {
3354 m_pScheme->DrawDragHandle(hDC, &m_rc, !!(m_style & UIF_GRIPPER_VERTICAL));
3355 return;
3356 }
3357
3358 RECT rc;
3359 if (m_style & UIF_GRIPPER_VERTICAL)
3360 rc = { m_rc.left, m_rc.top + 1, m_rc.right, m_rc.top + 4 };
3361 else
3362 rc = { m_rc.left + 1, m_rc.top, m_rc.left + 4, m_rc.bottom };
3363
3364 ::DrawEdge(hDC, &rc, BDR_RAISEDINNER, BF_RECT);
3365 }
3366
STDMETHODIMP_(BOOL)3367 STDMETHODIMP_(BOOL)
3368 CUIFGripper::OnSetCursor(UINT uMsg, LONG x, LONG y)
3369 {
3370 HCURSOR hCursor = ::LoadCursor(NULL, IDC_SIZEALL);
3371 ::SetCursor(hCursor);
3372 return TRUE;
3373 }
3374
STDMETHODIMP_(void)3375 STDMETHODIMP_(void)
3376 CUIFGripper::SetStyle(DWORD style)
3377 {
3378 m_style = style;
3379 if (m_style & UIF_GRIPPER_VERTICAL)
3380 SetActiveTheme(L"REBAR", RP_GRIPPERVERT, 0);
3381 else
3382 SetActiveTheme(L"REBAR", RP_GRIPPER, 0);
3383 }
3384
3385 /////////////////////////////////////////////////////////////////////////////
3386 // CUIFToolbarMenuButton
3387
CUIFToolbarMenuButton(CUIFToolbarButton * pParent,DWORD nObjectID,LPCRECT prc,DWORD style)3388 CUIFToolbarMenuButton::CUIFToolbarMenuButton(
3389 CUIFToolbarButton *pParent,
3390 DWORD nObjectID,
3391 LPCRECT prc,
3392 DWORD style) : CUIFButton2(pParent, nObjectID, prc, style)
3393 {
3394 m_pToolbarButton = pParent;
3395
3396 HFONT hFont = ::CreateFontW(8, 8, 0, 0, FW_NORMAL, 0, 0, 0, SYMBOL_CHARSET,
3397 0, 0, 0, 0, L"Marlett");
3398 SetFont(hFont);
3399 SetText(L"u"); // downward triangle
3400 }
3401
~CUIFToolbarMenuButton()3402 CUIFToolbarMenuButton::~CUIFToolbarMenuButton()
3403 {
3404 ::DeleteObject(m_hFont);
3405 SetFont(NULL);
3406 }
3407
STDMETHODIMP_(void)3408 STDMETHODIMP_(void)
3409 CUIFToolbarMenuButton::OnLButtonUp(LONG x, LONG y)
3410 {
3411 CUIFButton::OnLButtonUp(x, y);
3412 m_pToolbarButton->OnUnknownMouse0();
3413 }
3414
STDMETHODIMP_(BOOL)3415 STDMETHODIMP_(BOOL)
3416 CUIFToolbarMenuButton::OnSetCursor(UINT uMsg, LONG x, LONG y)
3417 {
3418 m_pToolbarButton->OnSetCursor(uMsg, x, y);
3419 return FALSE;
3420 }
3421
3422 /////////////////////////////////////////////////////////////////////////////
3423 // CUIFToolbarButtonElement
3424
CUIFToolbarButtonElement(CUIFToolbarButton * pParent,DWORD nObjectID,LPCRECT prc,DWORD style)3425 CUIFToolbarButtonElement::CUIFToolbarButtonElement(
3426 CUIFToolbarButton *pParent,
3427 DWORD nObjectID,
3428 LPCRECT prc,
3429 DWORD style) : CUIFButton2(pParent, nObjectID, prc, style)
3430 {
3431 m_pToolbarButton = pParent;
3432 }
3433
STDMETHODIMP_(LPCWSTR)3434 STDMETHODIMP_(LPCWSTR)
3435 CUIFToolbarButtonElement::GetToolTip()
3436 {
3437 if (m_pToolbarButton)
3438 return m_pToolbarButton->GetToolTip();
3439 return NULL;
3440 }
3441
STDMETHODIMP_(void)3442 STDMETHODIMP_(void)
3443 CUIFToolbarButtonElement::OnLButtonUp(LONG x, LONG y)
3444 {
3445 CUIFButton::OnLButtonUp(x, y);
3446 if ((m_pToolbarButton->m_dwToolbarButtonFlags & 0x30000) == 0x20000)
3447 m_pToolbarButton->OnUnknownMouse0();
3448 else
3449 m_pToolbarButton->OnLeftClick();
3450 }
3451
STDMETHODIMP_(void)3452 STDMETHODIMP_(void)
3453 CUIFToolbarButtonElement::OnRButtonUp(LONG x, LONG y)
3454 {
3455 if ((m_pToolbarButton->m_dwToolbarButtonFlags & 0x30000) != 0x20000)
3456 m_pToolbarButton->OnRightClick();
3457 }
3458
3459 /////////////////////////////////////////////////////////////////////////////
3460 // CUIFToolbarButton
3461
CUIFToolbarButton(CUIFObject * pParent,DWORD nObjectID,LPCRECT prc,DWORD style,DWORD dwToolbarButtonFlags,LPCWSTR pszUnknownText)3462 CUIFToolbarButton::CUIFToolbarButton(
3463 CUIFObject *pParent,
3464 DWORD nObjectID,
3465 LPCRECT prc,
3466 DWORD style,
3467 DWORD dwToolbarButtonFlags,
3468 LPCWSTR pszUnknownText) : CUIFObject(pParent, nObjectID, prc, style)
3469 {
3470 m_dwToolbarButtonFlags = dwToolbarButtonFlags;
3471 m_pszUnknownText = pszUnknownText;
3472 }
3473
Init()3474 BOOL CUIFToolbarButton::Init()
3475 {
3476 RECT rc1, rc2;
3477 rc1 = rc2 = m_rc;
3478
3479 if ((m_dwToolbarButtonFlags & 0x30000) == 0x30000)
3480 {
3481 rc1.right -= 12;
3482 rc2.left = rc1.right + 1;
3483 }
3484
3485 DWORD style = UIF_BUTTON_LARGE_ICON | UIF_BUTTON_V_ALIGN_MIDDLE | UIF_BUTTON_H_ALIGN_CENTER;
3486 if (m_dwToolbarButtonFlags & 0x2000)
3487 style |= 0x10;
3488 if (m_dwToolbarButtonFlags & 0x80000)
3489 style |= UIF_BUTTON_VERTICAL;
3490 m_pToolbarButtonElement = new(cicNoThrow) CUIFToolbarButtonElement(this, m_nObjectID, &rc1, style);
3491 if (!m_pToolbarButtonElement)
3492 return FALSE;
3493
3494 m_pToolbarButtonElement->Initialize();
3495 AddUIObj(m_pToolbarButtonElement);
3496
3497 if (!m_bEnable)
3498 m_pToolbarButtonElement->Enable(FALSE);
3499
3500 if ((m_dwToolbarButtonFlags & 0x30000) == 0x30000)
3501 {
3502 style = UIF_BUTTON_LARGE_ICON | UIF_BUTTON_H_ALIGN_CENTER;
3503 if (m_dwToolbarButtonFlags & 0x80000)
3504 style |= UIF_BUTTON_VERTICAL;
3505
3506 m_pToolbarMenuButton = new(cicNoThrow) CUIFToolbarMenuButton(this, 0, &rc2, style);
3507 if (!m_pToolbarMenuButton)
3508 return FALSE;
3509
3510 m_pToolbarMenuButton->Initialize();
3511 AddUIObj(m_pToolbarMenuButton);
3512
3513 if (!m_bEnable)
3514 m_pToolbarMenuButton->Enable(FALSE);
3515 }
3516
3517 return TRUE;
3518 }
3519
GetIcon()3520 HICON CUIFToolbarButton::GetIcon()
3521 {
3522 return m_pToolbarButtonElement->m_ButtonIcon.m_hIcon;
3523 }
3524
SetIcon(HICON hIcon)3525 void CUIFToolbarButton::SetIcon(HICON hIcon)
3526 {
3527 m_pToolbarButtonElement->SetIcon(hIcon);
3528 }
3529
STDMETHODIMP_(void)3530 STDMETHODIMP_(void)
3531 CUIFToolbarButton::ClearWndObj()
3532 {
3533 if (m_pToolbarButtonElement)
3534 m_pToolbarButtonElement->ClearWndObj();
3535 if (m_pToolbarMenuButton)
3536 m_pToolbarMenuButton->ClearWndObj();
3537
3538 CUIFObject::ClearWndObj();
3539 }
3540
STDMETHODIMP_(void)3541 STDMETHODIMP_(void)
3542 CUIFToolbarButton::DetachWndObj()
3543 {
3544 if (m_pToolbarButtonElement)
3545 m_pToolbarButtonElement->DetachWndObj();
3546 if (m_pToolbarMenuButton)
3547 m_pToolbarMenuButton->DetachWndObj();
3548
3549 CUIFObject::DetachWndObj();
3550 }
3551
STDMETHODIMP_(void)3552 STDMETHODIMP_(void)
3553 CUIFToolbarButton::Enable(BOOL bEnable)
3554 {
3555 CUIFObject::Enable(bEnable);
3556 if (m_pToolbarButtonElement)
3557 m_pToolbarButtonElement->Enable(bEnable);
3558 if (m_pToolbarMenuButton)
3559 m_pToolbarMenuButton->Enable(bEnable);
3560 }
3561
STDMETHODIMP_(LPCWSTR)3562 STDMETHODIMP_(LPCWSTR)
3563 CUIFToolbarButton::GetToolTip()
3564 {
3565 return CUIFObject::GetToolTip();
3566 }
3567
STDMETHODIMP_(void)3568 STDMETHODIMP_(void)
3569 CUIFToolbarButton::SetActiveTheme(LPCWSTR pszClassList, INT iPartId, INT iStateId)
3570 {
3571 if (m_pToolbarButtonElement)
3572 m_pToolbarButtonElement->SetActiveTheme(pszClassList, iPartId, iStateId);
3573 if (m_pToolbarMenuButton)
3574 m_pToolbarMenuButton->SetActiveTheme(pszClassList, iPartId, iStateId);
3575
3576 m_pszClassList = pszClassList;
3577 m_iPartId = iPartId;
3578 m_iStateId = iStateId;
3579 }
3580
STDMETHODIMP_(void)3581 STDMETHODIMP_(void)
3582 CUIFToolbarButton::SetFont(HFONT hFont)
3583 {
3584 m_pToolbarButtonElement->SetFont(hFont);
3585 }
3586
STDMETHODIMP_(void)3587 STDMETHODIMP_(void)
3588 CUIFToolbarButton::SetRect(LPCRECT prc)
3589 {
3590 CUIFObject::SetRect(prc);
3591
3592 RECT rc1, rc2;
3593 rc1 = rc2 = m_rc;
3594
3595 if ((m_dwToolbarButtonFlags & 0x30000) == 0x30000)
3596 {
3597 rc1.right -= 12;
3598 rc2.left = rc1.right + 1;
3599 }
3600
3601 if (m_pToolbarButtonElement)
3602 m_pToolbarButtonElement->SetRect(&rc1);
3603 if (m_pToolbarMenuButton)
3604 m_pToolbarMenuButton->SetRect(&rc2);
3605 }
3606
STDMETHODIMP_(void)3607 STDMETHODIMP_(void)
3608 CUIFToolbarButton::SetToolTip(LPCWSTR pszToolTip)
3609 {
3610 CUIFObject::SetToolTip(pszToolTip);
3611 if (m_pToolbarButtonElement)
3612 m_pToolbarButtonElement->SetToolTip(pszToolTip);
3613 if (m_pToolbarMenuButton)
3614 m_pToolbarMenuButton->SetToolTip(pszToolTip);
3615 }
3616
3617 /////////////////////////////////////////////////////////////////////////////
3618 // CUIFWndFrame
3619
CUIFWndFrame(CUIFObject * pParent,LPCRECT prc,DWORD style)3620 CUIFWndFrame::CUIFWndFrame(
3621 CUIFObject *pParent,
3622 LPCRECT prc,
3623 DWORD style) : CUIFObject(pParent, 0, prc, style)
3624 {
3625 m_iPartId = 7;
3626 m_iStateId = 0;
3627 m_pszClassList = L"WINDOW";
3628 m_dwHitTest = 0;
3629 m_cxFrame = m_cyFrame = 0;
3630
3631 if (m_pScheme)
3632 {
3633 if ((m_style & 0xF) && (m_style & 0xF) <= 2)
3634 {
3635 m_cxFrame = m_pScheme->CxSizeFrame();
3636 m_cyFrame = m_pScheme->CySizeFrame();
3637 }
3638 else
3639 {
3640 m_cxFrame = m_pScheme->CxWndBorder();
3641 m_cyFrame = m_pScheme->CyWndBorder();
3642 }
3643 }
3644
3645 m_cxMin = GetSystemMetrics(SM_CXMIN);
3646 m_cyMin = GetSystemMetrics(SM_CYMIN);
3647 }
3648
GetFrameSize(LPSIZE pSize)3649 void CUIFWndFrame::GetFrameSize(LPSIZE pSize)
3650 {
3651 pSize->cx = m_cxFrame;
3652 pSize->cy = m_cyFrame;
3653 }
3654
HitTest(LONG x,LONG y)3655 DWORD CUIFWndFrame::HitTest(LONG x, LONG y)
3656 {
3657 DWORD dwFlags = 0;
3658 if ( m_rc.left <= x && x < m_rc.left + m_cxFrame)
3659 dwFlags |= 0x10;
3660 if (m_rc.top <= y && y < m_rc.top + m_cyFrame )
3661 dwFlags |= 0x20;
3662 if (m_rc.right - m_cxFrame <= x && x < m_rc.right)
3663 dwFlags |= 0x40;
3664 if (m_rc.bottom - m_cyFrame <= y && y < m_rc.bottom)
3665 dwFlags |= 0x80;
3666 return dwFlags;
3667 }
3668
STDMETHODIMP_(void)3669 STDMETHODIMP_(void)
3670 CUIFWndFrame::OnMouseMove(LONG x, LONG y)
3671 {
3672 if (!IsCapture())
3673 return;
3674
3675 POINT Point;
3676 ::ClientToScreen(*m_pWindow, &Point);
3677
3678 RECT rc = m_rcWnd;
3679
3680 if (m_dwHitTest & 0x10)
3681 rc.left = Point.x + m_rcWnd.left - m_ptHit.x;
3682
3683 if (m_dwHitTest & 0x20)
3684 rc.top = Point.y + m_rcWnd.top - m_ptHit.y;
3685
3686 if (m_dwHitTest & 0x40)
3687 {
3688 rc.right = Point.x + m_rcWnd.right - m_ptHit.x;
3689 if (rc.right <= rc.left + m_cxMin)
3690 rc.right = rc.left + m_cxMin;
3691 }
3692
3693 if (m_dwHitTest & 0x80)
3694 {
3695 rc.bottom = Point.y + m_rcWnd.bottom - m_ptHit.y;
3696 if (rc.bottom <= rc.top + m_cyMin)
3697 rc.bottom = rc.top + m_cyMin;
3698 }
3699
3700 m_pWindow->Move(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
3701 }
3702
STDMETHODIMP_(void)3703 STDMETHODIMP_(void)
3704 CUIFWndFrame::OnLButtonDown(LONG x, LONG y)
3705 {
3706 POINT Point = { x, y };
3707 DWORD hitTest = m_style & HitTest(x, y);
3708 if (!hitTest)
3709 return;
3710
3711 ::ClientToScreen(*m_pWindow, &Point);
3712 m_ptHit = Point;
3713 m_pWindow = m_pWindow;
3714 m_dwHitTest = hitTest;
3715 ::GetWindowRect(*m_pWindow, &m_rcWnd);
3716 StartCapture();
3717 }
3718
STDMETHODIMP_(void)3719 STDMETHODIMP_(void)
3720 CUIFWndFrame::OnLButtonUp(LONG x, LONG y)
3721 {
3722 if (IsCapture())
3723 EndCapture();
3724 }
3725
STDMETHODIMP_(BOOL)3726 STDMETHODIMP_(BOOL)
3727 CUIFWndFrame::OnPaintTheme(HDC hDC)
3728 {
3729 if (FAILED(EnsureThemeData(*m_pWindow)))
3730 return FALSE;
3731
3732 RECT rc = m_rc;
3733 rc.right = m_cxFrame;
3734 if (FAILED(DrawThemeEdge(hDC, 0, &rc, 5, 1, NULL)))
3735 return FALSE;
3736
3737 rc = m_rc;
3738 rc.left = rc.right - m_cxFrame;
3739 if (FAILED(DrawThemeEdge(hDC, 0, &rc, 10, 4, NULL)))
3740 return FALSE;
3741
3742 rc = m_rc;
3743 rc.bottom = m_cyFrame;
3744 if (FAILED(DrawThemeEdge(hDC, 0, &rc, 5, 2, NULL)))
3745 return FALSE;
3746
3747 rc = m_rc;
3748 rc.top = rc.bottom - m_cyFrame;
3749 if (FAILED(DrawThemeEdge(hDC, 0, &rc, 10, 8, NULL)))
3750 return FALSE;
3751
3752 return TRUE;
3753 }
3754
STDMETHODIMP_(void)3755 STDMETHODIMP_(void)
3756 CUIFWndFrame::OnPaintNoTheme(HDC hDC)
3757 {
3758 if (!m_pScheme)
3759 return;
3760
3761 DWORD type = 0;
3762 if ((m_style & 0xF) == 1)
3763 type = 1;
3764 else if ( (m_style & 0xF) == 2 )
3765 type = 2;
3766
3767 m_pScheme->DrawWndFrame(hDC, &m_rc, type, m_cxFrame, m_cyFrame);
3768 }
3769
STDMETHODIMP_(BOOL)3770 STDMETHODIMP_(BOOL)
3771 CUIFWndFrame::OnSetCursor(UINT uMsg, LONG x, LONG y)
3772 {
3773 DWORD dwHitTest = m_dwHitTest;
3774 if (!IsCapture())
3775 dwHitTest = m_style & HitTest(x, y);
3776
3777 LPTSTR pszCursor = NULL;
3778 switch (dwHitTest)
3779 {
3780 case 0x30:
3781 case 0xC0:
3782 pszCursor = IDC_SIZENWSE;
3783 break;
3784 case 0x90:
3785 case 0x60:
3786 pszCursor = IDC_SIZENESW;
3787 break;
3788 case 0x10:
3789 case 0x40:
3790 pszCursor = IDC_SIZEWE;
3791 break;
3792 case 0x20:
3793 case 0x80:
3794 pszCursor = IDC_SIZENS;
3795 break;
3796 default:
3797 return FALSE;
3798 }
3799
3800 HCURSOR hCursor = ::LoadCursor(NULL, pszCursor);
3801 ::SetCursor(hCursor);
3802 return TRUE;
3803 }
3804
3805 /////////////////////////////////////////////////////////////////////////////
3806 // CUIFBalloonButton
3807
CUIFBalloonButton(CUIFObject * pParent,DWORD nObjectID,LPCRECT prc,DWORD style)3808 CUIFBalloonButton::CUIFBalloonButton(
3809 CUIFObject *pParent,
3810 DWORD nObjectID,
3811 LPCRECT prc,
3812 DWORD style) : CUIFButton(pParent, nObjectID, prc, style)
3813 {
3814 m_nCommandID = 0;
3815 }
3816
STDMETHODIMP_(void)3817 STDMETHODIMP_(void)
3818 CUIFBalloonButton::OnPaint(HDC hDC)
3819 {
3820 RECT rc = m_rc;
3821 ::OffsetRect(&rc, -rc.left, -rc.top);
3822
3823 HDC hMemDC = ::CreateCompatibleDC(hDC);
3824 HBITMAP hbmMem = ::CreateCompatibleBitmap(hDC, rc.right, rc.bottom);
3825 HGDIOBJ hbmOld = ::SelectObject(hMemDC, hbmMem);
3826
3827 BOOL bPressed;
3828 COLORREF rgbShadow, rgbBorder;
3829 if (m_uButtonStatus == 1)
3830 {
3831 bPressed = TRUE;
3832 rgbShadow = ::GetSysColor(COLOR_BTNSHADOW);
3833 rgbBorder = ::GetSysColor(COLOR_BTNHIGHLIGHT);
3834 }
3835 else
3836 {
3837 bPressed = FALSE;
3838 if (m_uButtonStatus < 4)
3839 {
3840 rgbShadow = ::GetSysColor(COLOR_BTNHIGHLIGHT);
3841 rgbBorder = ::GetSysColor(COLOR_BTNSHADOW);
3842 }
3843 else
3844 {
3845 rgbShadow = ::GetSysColor(COLOR_INFOBK);
3846 rgbBorder = ::GetSysColor(COLOR_INFOBK);
3847 }
3848 }
3849
3850 COLORREF rgbInfoBk = ::GetSysColor(COLOR_INFOBK);
3851 HBRUSH hbrBack = ::CreateSolidBrush(rgbInfoBk);
3852 ::FillRect(hMemDC, &rc, hbrBack);
3853 ::DeleteObject(hbrBack);
3854
3855 DrawTextProc(hMemDC, &rc, bPressed);
3856
3857 HBRUSH hNullBrush = (HBRUSH)::GetStockObject(NULL_BRUSH);
3858 HGDIOBJ hbrOld = ::SelectObject(hMemDC, hNullBrush);
3859
3860 HPEN hPen = ::CreatePen(PS_SOLID, 0, rgbShadow);
3861 HGDIOBJ hPenOld = ::SelectObject(hMemDC, hPen);
3862 ::RoundRect(hMemDC, rc.left, rc.top, rc.right - 1, rc.bottom - 1, 6, 6);
3863 ::SelectObject(hMemDC, hPenOld);
3864 ::DeleteObject(hPen);
3865
3866 hPen = ::CreatePen(PS_SOLID, 0, rgbBorder);
3867 hPenOld = ::SelectObject(hMemDC, hPen);
3868 ::RoundRect(hMemDC, rc.left + 1, rc.top + 1, rc.right, rc.bottom, 6, 6);
3869 ::SelectObject(hMemDC, hPenOld);
3870 ::DeleteObject(hPen);
3871
3872 hPen = ::CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNFACE));
3873 hPenOld = ::SelectObject(hMemDC, hPen);
3874 ::RoundRect(hMemDC, rc.left + 1, rc.top + 1, rc.right - 1, rc.bottom - 1, 6, 6);
3875 ::SelectObject(hMemDC, hPenOld);
3876 ::DeleteObject(hPen);
3877
3878 ::SelectObject(hMemDC, hbrOld);
3879 ::BitBlt(hDC, m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - m_rc.top,
3880 hMemDC, rc.left, rc.top, SRCCOPY);
3881 ::SelectObject(hMemDC, hbmOld);
3882 ::DeleteObject(hbmMem);
3883 ::DeleteDC(hMemDC);
3884 }
3885
3886 void
DrawTextProc(HDC hDC,LPCRECT prc,BOOL bPressed)3887 CUIFBalloonButton::DrawTextProc(HDC hDC, LPCRECT prc, BOOL bPressed)
3888 {
3889 if (!m_pszButtonText)
3890 return;
3891
3892 UINT uFlags = DT_SINGLELINE;
3893
3894 if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_CENTER)
3895 uFlags |= DT_CENTER;
3896 else if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_RIGHT)
3897 uFlags |= DT_RIGHT;
3898
3899 if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_MIDDLE)
3900 uFlags |= DT_VCENTER;
3901 else if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_BOTTOM)
3902 uFlags |= DT_BOTTOM;
3903
3904 COLORREF rgbOldColor = ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNTEXT));
3905 INT nOldBkMode = ::SetBkMode(hDC, TRANSPARENT);
3906
3907 RECT rc = *prc;
3908 if (bPressed)
3909 ::OffsetRect(&rc, 1, 1);
3910
3911 HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
3912 ::DrawTextW(hDC, m_pszButtonText, -1, &rc, uFlags);
3913 ::SelectObject(hDC, hFontOld);
3914
3915 ::SetBkMode(hDC, nOldBkMode);
3916 ::SetTextColor(hDC, rgbOldColor);
3917 }
3918
3919 /////////////////////////////////////////////////////////////////////////////
3920 // CUIFBalloonWindow
3921
CUIFBalloonWindow(HINSTANCE hInst,DWORD style)3922 CUIFBalloonWindow::CUIFBalloonWindow(HINSTANCE hInst, DWORD style) : CUIFWindow(hInst, style)
3923 {
3924 m_dwUnknown6 = -1;
3925 m_nActionID = -1;
3926 m_hRgn = NULL;
3927 m_pszBalloonText = NULL;
3928 m_bHasBkColor = m_bHasTextColor = FALSE;
3929 m_rgbBkColor = 0;
3930 m_rgbTextColor = 0;
3931 m_ptTarget.x = m_ptTarget.y = 0;
3932 ZeroMemory(&m_rcExclude, sizeof(m_rcExclude));
3933 m_dwUnknown7 = 0;
3934 m_nBalloonType = 0;
3935 m_dwUnknown8[0] = 0;
3936 m_dwUnknown8[1] = 0;
3937 m_ptBalloon.x = m_ptBalloon.y = 0;
3938 m_cButtons = 0;
3939 m_hwndNotif = NULL;
3940 m_uNotifMsg = 0;
3941 m_rcMargin.left = 8;
3942 m_rcMargin.top = 8;
3943 m_rcMargin.right = 8;
3944 m_rcMargin.bottom = 8;
3945 }
3946
~CUIFBalloonWindow()3947 CUIFBalloonWindow::~CUIFBalloonWindow()
3948 {
3949 if (m_pszBalloonText)
3950 {
3951 delete[] m_pszBalloonText;
3952 m_pszBalloonText = NULL;
3953 }
3954 }
3955
STDMETHODIMP_(BOOL)3956 STDMETHODIMP_(BOOL)
3957 CUIFBalloonWindow::Initialize()
3958 {
3959 CUIFWindow::Initialize();
3960
3961 if ((m_style & UIF_BALLOON_WINDOW_TYPE_MASK) == UIF_BALLOON_WINDOW_OK)
3962 {
3963 AddButton(IDOK);
3964 }
3965 else if ((m_style & UIF_BALLOON_WINDOW_TYPE_MASK) == UIF_BALLOON_WINDOW_YESNO)
3966 {
3967 AddButton(IDYES);
3968 AddButton(IDNO);
3969 }
3970
3971 return TRUE;
3972 }
3973
STDMETHODIMP_(void)3974 STDMETHODIMP_(void)
3975 CUIFBalloonWindow::OnCreate(HWND hWnd)
3976 {
3977 m_nActionID = -1;
3978 AdjustPos();
3979 }
3980
STDMETHODIMP_(void)3981 STDMETHODIMP_(void)
3982 CUIFBalloonWindow::OnDestroy(HWND hWnd)
3983 {
3984 SendNotification(m_nActionID);
3985 DoneWindowRegion();
3986 }
3987
STDMETHODIMP_(void)3988 STDMETHODIMP_(void)
3989 CUIFBalloonWindow::OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
3990 {
3991 CUIFBalloonButton *pButton = NULL;
3992
3993 switch (wParam)
3994 {
3995 case VK_RETURN:
3996 pButton = (CUIFBalloonButton *)FindUIObject(0);
3997 break;
3998 case VK_ESCAPE:
3999 m_nActionID = -1;
4000 ::DestroyWindow(m_hWnd);
4001 return;
4002 case TEXT('Y'):
4003 pButton = FindButton(IDYES);
4004 break;
4005 case TEXT('N'):
4006 pButton = FindButton(IDNO);
4007 break;
4008 }
4009
4010 if (!pButton)
4011 return;
4012
4013 m_nActionID = pButton->m_nCommandID;
4014 ::DestroyWindow(m_hWnd);
4015 }
4016
STDMETHODIMP_(LRESULT)4017 STDMETHODIMP_(LRESULT)
4018 CUIFBalloonWindow::OnObjectNotify(CUIFObject *pObject, WPARAM wParam, LPARAM lParam)
4019 {
4020 CUIFBalloonButton *pButton = (CUIFBalloonButton *)pObject;
4021 m_nActionID = pButton->m_nCommandID;
4022 ::DestroyWindow(m_hWnd);
4023 return 0;
4024 }
4025
STDMETHODIMP_(void)4026 STDMETHODIMP_(void)
4027 CUIFBalloonWindow::OnPaint(HDC hDC)
4028 {
4029 RECT rc;
4030 GetRect(&rc);
4031 PaintFrameProc(hDC, &rc);
4032
4033 switch (m_nBalloonType)
4034 {
4035 case 1:
4036 rc.top += 16;
4037 break;
4038 case 2:
4039 rc.right -= 16;
4040 break;
4041 case 3:
4042 rc.left += 16;
4043 break;
4044 default:
4045 rc.bottom -= 16;
4046 break;
4047 }
4048
4049 RECT rcMargin;
4050 GetMargin(&rcMargin);
4051
4052 rc.left += rcMargin.left;
4053 rc.top += rcMargin.top;
4054 rc.right -= rcMargin.right;
4055 rc.bottom -= rcMargin.bottom;
4056
4057 PaintMessageProc(hDC, &rc, m_pszBalloonText);
4058 }
4059
4060 void
AddButton(UINT nCommandId)4061 CUIFBalloonWindow::AddButton(UINT nCommandId)
4062 {
4063 RECT rc = { 0, 0, 0, 0 };
4064 if (!((IDOK <= nCommandId) && (nCommandId <= IDNO)))
4065 return;
4066
4067 CUIFBalloonButton *pButton = new(cicNoThrow) CUIFBalloonButton(this, m_cButtons, &rc, 5);
4068 if (!pButton)
4069 return;
4070
4071 pButton->Initialize();
4072 pButton->m_nCommandID = nCommandId;
4073
4074 LPCWSTR pszText;
4075 #ifdef IDS_OK
4076 extern HINSTANCE g_hInst;
4077 WCHAR szText[64];
4078 ::LoadStringW(g_hInst, IDS_OK + (nCommandId - IDOK), szText, _countof(szText));
4079 pszText = szText;
4080 #else
4081 switch (nCommandId)
4082 {
4083 case IDOK: pszText = L"OK"; break;
4084 case IDCANCEL: pszText = L"Cancel"; break;
4085 case IDABORT: pszText = L"&Abort"; break;
4086 case IDRETRY: pszText = L"&Retry"; break;
4087 case IDIGNORE: pszText = L"&Ignore"; break;
4088 case IDYES: pszText = L"&Yes"; break;
4089 default: pszText = L"&No"; break;
4090 }
4091 #endif
4092
4093 pButton->SetText(pszText);
4094
4095 AddUIObj(pButton);
4096 ++m_cButtons;
4097 }
4098
4099 /// @unimplemented
4100 void
AdjustPos()4101 CUIFBalloonWindow::AdjustPos()
4102 {
4103 //FIXME
4104 }
4105
4106 HRGN
CreateRegion(LPCRECT prc)4107 CUIFBalloonWindow::CreateRegion(LPCRECT prc)
4108 {
4109 POINT Points[4];
4110 HRGN hRgn;
4111 BOOL bFlag = FALSE;
4112 LONG x, y;
4113
4114 switch (m_nBalloonType)
4115 {
4116 case 1:
4117 hRgn = ::CreateRoundRectRgn(prc->left, prc->top + 16, prc->right, prc->bottom, 16, 16);
4118 y = prc->top + 16;
4119 bFlag = TRUE;
4120 break;
4121
4122 case 2:
4123 hRgn = ::CreateRoundRectRgn(prc->left, prc->top, prc->right - 16, prc->bottom, 16, 16);
4124 x = prc->right - 17;
4125 break;
4126
4127 case 3:
4128 hRgn = ::CreateRoundRectRgn(prc->left + 16, prc->top, prc->right, prc->bottom, 16, 16);
4129 x = prc->left + 16;
4130 break;
4131
4132 default:
4133 hRgn = ::CreateRoundRectRgn(prc->left, prc->top, prc->right, prc->bottom - 16, 16, 16);
4134 y = prc->bottom - 17;
4135 bFlag = TRUE;
4136 break;
4137 }
4138
4139 if (bFlag)
4140 {
4141 x = Points[1].x = m_ptBalloon.x;
4142 Points[1].y = m_ptBalloon.y;
4143 Points[0].y = Points[2].y = Points[3].y = y;
4144 Points[2].x = x + 10 * (2 * (m_dwUnknown8[0] == 0) - 1);
4145 }
4146 else
4147 {
4148 Points[2].x = x;
4149 y = Points[0].y = Points[1].y = Points[3].y = m_ptBalloon.y;
4150 Points[1].x = m_ptBalloon.x;
4151 Points[2].y = y + 10 * (2 * (m_dwUnknown8[0] == 2) - 1);
4152 }
4153
4154 Points[0].x = Points[3].x = x;
4155
4156 HRGN hPolygonRgn = ::CreatePolygonRgn(Points, _countof(Points), WINDING);
4157 ::CombineRgn(hRgn, hRgn, hPolygonRgn, RGN_OR);
4158 ::DeleteObject(hPolygonRgn);
4159 return hRgn;
4160 }
4161
4162 void
DoneWindowRegion()4163 CUIFBalloonWindow::DoneWindowRegion()
4164 {
4165 if (m_hRgn)
4166 {
4167 ::SetWindowRgn(m_hWnd, NULL, TRUE);
4168 ::DeleteObject(m_hRgn);
4169 m_hRgn = NULL;
4170 }
4171 }
4172
4173 CUIFBalloonButton *
FindButton(UINT nCommandID)4174 CUIFBalloonWindow::FindButton(UINT nCommandID)
4175 {
4176 for (UINT iButton = 0; iButton < m_cButtons; ++iButton)
4177 {
4178 CUIFBalloonButton *pButton = (CUIFBalloonButton *)FindUIObject(iButton);
4179 if (pButton && (pButton->m_nCommandID == nCommandID))
4180 return pButton;
4181 }
4182 return NULL;
4183 }
4184
4185 CUIFObject *
FindUIObject(UINT nObjectID)4186 CUIFBalloonWindow::FindUIObject(UINT nObjectID)
4187 {
4188 for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
4189 {
4190 CUIFObject *pObject = m_ObjectArray[iItem];
4191 if (pObject->m_nObjectID == nObjectID)
4192 return pObject;
4193 }
4194 return NULL;
4195 }
4196
4197 COLORREF
GetBalloonBkColor()4198 CUIFBalloonWindow::GetBalloonBkColor()
4199 {
4200 if (m_bHasBkColor)
4201 return m_rgbBkColor;
4202 else
4203 return ::GetSysColor(COLOR_INFOBK);
4204 }
4205
4206 COLORREF
GetBalloonTextColor()4207 CUIFBalloonWindow::GetBalloonTextColor()
4208 {
4209 if (m_bHasTextColor)
4210 return m_rgbTextColor;
4211 else
4212 return ::GetSysColor(COLOR_INFOTEXT);
4213 }
4214
4215 void
GetButtonSize(LPSIZE pSize)4216 CUIFBalloonWindow::GetButtonSize(LPSIZE pSize)
4217 {
4218 HDC hDisplayDC = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
4219
4220 TEXTMETRIC tm;
4221 HGDIOBJ hFontOld = ::SelectObject(hDisplayDC, m_hFont);
4222 ::GetTextMetrics(hDisplayDC, &tm);
4223 ::SelectObject(hDisplayDC, hFontOld);
4224 ::DeleteDC(hDisplayDC);
4225
4226 pSize->cx = 16 * tm.tmAveCharWidth;
4227 pSize->cy = tm.tmHeight + 10;
4228 }
4229
4230 void
GetMargin(LPRECT prcMargin)4231 CUIFBalloonWindow::GetMargin(LPRECT prcMargin)
4232 {
4233 if (prcMargin)
4234 *prcMargin = m_rcMargin;
4235 }
4236
4237 void
SetExcludeRect(LPCRECT prcExclude)4238 CUIFBalloonWindow::SetExcludeRect(LPCRECT prcExclude)
4239 {
4240 m_rcExclude = *prcExclude;
4241 AdjustPos();
4242 }
4243
4244 void
SetTargetPos(POINT ptTarget)4245 CUIFBalloonWindow::SetTargetPos(POINT ptTarget)
4246 {
4247 m_ptTarget = ptTarget;
4248 AdjustPos();
4249 }
4250
4251 void
SetText(LPCWSTR pszText)4252 CUIFBalloonWindow::SetText(LPCWSTR pszText)
4253 {
4254 if (m_pszBalloonText)
4255 {
4256 delete[] m_pszBalloonText;
4257 m_pszBalloonText = NULL;
4258 }
4259
4260 if (pszText == NULL)
4261 pszText = L"";
4262
4263 size_t cch = wcslen(pszText);
4264 m_pszBalloonText = new(cicNoThrow) WCHAR[cch + 1];
4265 if (m_pszBalloonText)
4266 lstrcpynW(m_pszBalloonText, pszText, cch + 1);
4267
4268 AdjustPos();
4269 }
4270
4271 void
InitWindowRegion()4272 CUIFBalloonWindow::InitWindowRegion()
4273 {
4274 RECT rc;
4275 GetRect(&rc);
4276 m_hRgn = CreateRegion(&rc);
4277 if (m_hRgn)
4278 ::SetWindowRgn(m_hWnd, m_hRgn, TRUE);
4279 }
4280
4281 void
LayoutObject()4282 CUIFBalloonWindow::LayoutObject()
4283 {
4284 SIZE size;
4285 GetButtonSize(&size);
4286
4287 RECT rc;
4288 GetRect(&rc);
4289
4290 switch (m_nBalloonType)
4291 {
4292 case 1:
4293 rc.top += 16;
4294 break;
4295 case 2:
4296 rc.right -= 16;
4297 break;
4298 case 3:
4299 rc.left += 16;
4300 break;
4301 default:
4302 rc.bottom -= 16;
4303 break;
4304 }
4305
4306 RECT rcMargin;
4307 GetMargin(&rcMargin);
4308 rc.left += rcMargin.left;
4309 rc.top += rcMargin.top;
4310 rc.right -= rcMargin.right;
4311 rc.bottom -= rcMargin.bottom;
4312
4313 LONG xLeft = (rc.left + rc.right - size.cx * (((m_cButtons - 1) / 2) - m_cButtons)) / 2;
4314 for (UINT iButton = 0; iButton < m_cButtons; ++iButton)
4315 {
4316 CUIFObject *UIObject = FindUIObject(iButton);
4317 if (!UIObject)
4318 continue;
4319
4320 rcMargin.left = xLeft + iButton * (size.cx * 3 / 2);
4321 rcMargin.top = rc.bottom - size.cy;
4322 rcMargin.right = rcMargin.left + size.cx;
4323 rcMargin.bottom = rc.bottom;
4324
4325 UIObject->SetRect(&rcMargin);
4326 UIObject->Show(TRUE);
4327 }
4328 }
4329
4330 void
PaintFrameProc(HDC hDC,LPCRECT prc)4331 CUIFBalloonWindow::PaintFrameProc(HDC hDC, LPCRECT prc)
4332 {
4333 HRGN hRgn = CreateRegion(prc);
4334 HBRUSH hbrBack = ::CreateSolidBrush(GetBalloonBkColor());
4335 HBRUSH hbrFrame = ::CreateSolidBrush(::GetSysColor(COLOR_WINDOWFRAME));
4336 ::FillRgn(hDC, hRgn, hbrBack);
4337 ::FrameRgn(hDC, hRgn, hbrFrame, 1, 1);
4338 ::DeleteObject(hbrBack);
4339 ::DeleteObject(hbrFrame);
4340 ::DeleteObject(hRgn);
4341 }
4342
4343 void
PaintMessageProc(HDC hDC,LPRECT prc,LPCWSTR pszText)4344 CUIFBalloonWindow::PaintMessageProc(HDC hDC, LPRECT prc, LPCWSTR pszText)
4345 {
4346 HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
4347 COLORREF rgbOldColor = ::SetTextColor(hDC, GetBalloonTextColor());
4348 INT nOldBkMode = ::SetBkMode(hDC, TRANSPARENT);
4349 ::DrawTextW(hDC, pszText, -1, prc, DT_WORDBREAK);
4350 ::SelectObject(hDC, hFontOld);
4351 ::SetTextColor(hDC, rgbOldColor);
4352 ::SetBkMode(hDC, nOldBkMode);
4353 }
4354
4355 void
SendNotification(WPARAM wParam)4356 CUIFBalloonWindow::SendNotification(WPARAM wParam)
4357 {
4358 if (m_hwndNotif)
4359 ::PostMessage(m_hwndNotif, m_uNotifMsg, wParam, 0);
4360 }
4361
4362 /////////////////////////////////////////////////////////////////////////////
4363 // CUIFMenu
4364
CUIFMenu(HINSTANCE hInst,DWORD style,DWORD dwUnknown14)4365 CUIFMenu::CUIFMenu(
4366 HINSTANCE hInst,
4367 DWORD style,
4368 DWORD dwUnknown14) : CUIFWindow(hInst, style)
4369 {
4370 m_nSelectedID = -1;
4371 m_dwUnknown14 = dwUnknown14;
4372 SetMenuFont();
4373 }
4374
~CUIFMenu()4375 CUIFMenu::~CUIFMenu()
4376 {
4377 for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
4378 delete m_MenuItems[iItem];
4379
4380 ::DeleteObject(m_hMenuFont);
4381 ClearMenuFont();
4382 }
4383
CancelMenu()4384 void CUIFMenu::CancelMenu()
4385 {
4386 if (m_pVisibleSubMenu)
4387 {
4388 UninitShow();
4389 }
4390 else if (m_bModal)
4391 {
4392 SetSelectedId(0xFFFFFFFF);
4393 ::PostMessage(m_hWnd, WM_NULL, 0, 0);
4394 }
4395 }
4396
ClearMenuFont()4397 void CUIFMenu::ClearMenuFont()
4398 {
4399 SetFont(NULL);
4400 ::DeleteObject(m_hFont);
4401 }
4402
4403 CUIFMenuItem*
GetNextItem(CUIFMenuItem * pItem)4404 CUIFMenu::GetNextItem(CUIFMenuItem *pItem)
4405 {
4406 size_t iItem, cItems = m_MenuItems.size();
4407
4408 if (cItems == 0)
4409 return NULL;
4410
4411 if (!m_pSelectedItem)
4412 return m_MenuItems[0];
4413
4414 for (iItem = 0; iItem < cItems; )
4415 {
4416 if (m_MenuItems[iItem++] == pItem)
4417 break;
4418 }
4419
4420 for (;;)
4421 {
4422 if (iItem == cItems)
4423 iItem = 0;
4424 if (!m_MenuItems[iItem] || !m_MenuItems[iItem]->m_bMenuItemDisabled)
4425 break;
4426 ++iItem;
4427 }
4428
4429 return m_MenuItems[iItem];
4430 }
4431
4432 CUIFMenuItem*
GetPrevItem(CUIFMenuItem * pItem)4433 CUIFMenu::GetPrevItem(CUIFMenuItem *pItem)
4434 {
4435 ptrdiff_t iItem, cItems = m_MenuItems.size();
4436
4437 if (cItems == 0)
4438 return NULL;
4439
4440 if (!m_pSelectedItem)
4441 return m_MenuItems[cItems - 1];
4442
4443 for (iItem = cItems - 1; iItem >= 0; )
4444 {
4445 if (m_MenuItems[iItem--] == pItem)
4446 break;
4447 }
4448
4449 for (;;)
4450 {
4451 if (iItem < 0)
4452 iItem = cItems - 1;
4453 if (!m_MenuItems[iItem] || !m_MenuItems[iItem]->m_bMenuItemDisabled)
4454 break;
4455 --iItem;
4456 }
4457
4458 return m_MenuItems[iItem];
4459 }
4460
4461 CUIFMenu*
GetTopSubMenu()4462 CUIFMenu::GetTopSubMenu()
4463 {
4464 CUIFMenu *pMenu;
4465 for (pMenu = this; pMenu->m_pParentMenu; pMenu = pMenu->m_pParentMenu)
4466 ;
4467 return pMenu;
4468 }
4469
HandleMouseMsg(UINT uMsg,LONG x,LONG y)4470 void CUIFMenu::HandleMouseMsg(UINT uMsg, LONG x, LONG y)
4471 {
4472 POINT pt = { x, y };
4473 if (!::PtInRect(&m_rc, pt) &&
4474 (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP))
4475 {
4476 SetSelectedId(-1);
4477 PostMessage(m_hWnd, WM_NULL, 0, 0);
4478 }
4479 CUIFWindow::HandleMouseMsg(uMsg, x, y);
4480 }
4481
STDMETHODIMP_(BOOL)4482 STDMETHODIMP_(BOOL)
4483 CUIFMenu::InitShow(CUIFWindow *pWindow, LPCRECT prc, BOOL bFlag, BOOL bDoAnimation)
4484 {
4485 HWND hWnd = NULL;
4486 if (pWindow)
4487 hWnd = *pWindow;
4488
4489 CreateWnd(hWnd);
4490
4491 m_bHasMargin = FALSE;
4492
4493 for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
4494 {
4495 if (m_MenuItems[iItem])
4496 m_MenuItems[iItem]->InitMenuExtent();
4497 }
4498
4499 INT cxMax = 0;
4500
4501 m_cxMenuExtent = 0;
4502 for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
4503 {
4504 CUIFMenuItem *pItem = m_MenuItems[iItem];
4505 if (!pItem)
4506 continue;
4507
4508 INT cxItem = m_cxyMargin + pItem->m_MenuLeftExtent.cx;
4509 if (cxMax < cxItem)
4510 cxMax = cxItem;
4511 m_cxMenuExtent = max(m_cxMenuExtent, pItem->m_MenuRightExtent.cx);
4512 if (!m_bHasMargin && pItem->m_hbmColor && pItem->IsCheck())
4513 m_bHasMargin = TRUE;
4514 }
4515
4516 RECT rcItem = { 0, 0, 0, 0 };
4517 for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
4518 {
4519 CUIFMenuItem *pItem = m_MenuItems[iItem];
4520 if (!pItem)
4521 continue;
4522
4523 INT cyItem = pItem->m_MenuLeftExtent.cy;
4524 rcItem.right = rcItem.left + cxMax + m_cxMenuExtent;
4525 rcItem.bottom = rcItem.top + cyItem;
4526 pItem->SetRect(&rcItem);
4527 rcItem.top += cyItem;
4528 AddUIObj(pItem);
4529 }
4530
4531 rcItem.top = 0;
4532 DWORD style = ::GetWindowLongPtr(hWnd, GWL_STYLE);
4533 cxMax = rcItem.right;
4534 INT cyMax = rcItem.bottom;
4535 if (style & WS_DLGFRAME)
4536 {
4537 cxMax = rcItem.right + 2 * ::GetSystemMetrics(SM_CXDLGFRAME);
4538 cyMax += 2 * ::GetSystemMetrics(SM_CYDLGFRAME);
4539 }
4540 else if (style & WS_BORDER)
4541 {
4542 cxMax = rcItem.right + 2 * ::GetSystemMetrics(SM_CXBORDER);
4543 cyMax += 2 * ::GetSystemMetrics(SM_CYBORDER);
4544 }
4545
4546 RECT rc = { 0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN) };
4547
4548 RECT rc3 = *prc;
4549 HMONITOR hMon = ::MonitorFromRect(&rc3, MONITOR_DEFAULTTONEAREST);
4550 if (hMon)
4551 {
4552 MONITORINFO mi = { sizeof(mi) };
4553 if (::GetMonitorInfo(hMon, &mi))
4554 rc = mi.rcMonitor;
4555 }
4556
4557 if (m_style & 0x200)
4558 rcItem.left -= cxMax;
4559
4560 INT x, y;
4561 DWORD dwFlags2 = 0;
4562
4563 if (bFlag)
4564 {
4565 INT bottom = prc->bottom;
4566 x = rcItem.left + prc->left;
4567 if (rcItem.top + bottom + cyMax > rc.bottom)
4568 {
4569 bottom = prc->top - cyMax;
4570 dwFlags2 = 8;
4571 }
4572 else
4573 {
4574 dwFlags2 = 4;
4575 }
4576
4577 y = rcItem.top + bottom;
4578
4579 if (rcItem.left + cxMax + prc->right > rc.right)
4580 x = rc.right - cxMax;
4581 }
4582 else
4583 {
4584 y = rcItem.top + prc->top;
4585 if (rcItem.left + prc->right + cxMax > rc.right)
4586 {
4587 x = rcItem.left + prc->left - cxMax;
4588 dwFlags2 = 2;
4589 }
4590 else
4591 {
4592 x = rcItem.left + prc->right;
4593 dwFlags2 = 1;
4594 }
4595 if (rcItem.top + cyMax + prc->bottom > rc.bottom)
4596 y = rc.bottom - cyMax;
4597 }
4598
4599 if (x > rc.right - cxMax)
4600 x = rc.right - cxMax;
4601 if (x < rc.left)
4602 x = rc.left;
4603 if (y > rc.bottom - cyMax)
4604 y = rc.bottom - cyMax;
4605 if (y < rc.top)
4606 y = rc.top;
4607
4608 Move(x, y, cxMax, -1);
4609
4610 SetRect(NULL);
4611
4612 BOOL bAnimation = FALSE;
4613 if (bDoAnimation &&
4614 ::SystemParametersInfo(SPI_GETMENUANIMATION, 0, &bAnimation, 0) && bAnimation)
4615 {
4616 BOOL bMenuFade = FALSE;
4617 if (!::SystemParametersInfoA(SPI_GETMENUFADE, 0, &bMenuFade, 0))
4618 bMenuFade = FALSE;
4619
4620 DWORD dwFlags = (bMenuFade ? 0x80000 : dwFlags2) | 0x40000;
4621 if (!AnimateWnd(200, dwFlags))
4622 Show(TRUE);
4623 }
4624 else
4625 {
4626 Show(TRUE);
4627 }
4628
4629 if (m_pVisibleSubMenu)
4630 m_pVisibleSubMenu->m_pParentMenu = this;
4631
4632 return TRUE;
4633 }
4634
InsertItem(CUIFMenuItem * pItem)4635 BOOL CUIFMenu::InsertItem(CUIFMenuItem *pItem)
4636 {
4637 if (!m_MenuItems.Add(pItem))
4638 return FALSE;
4639
4640 pItem->SetFont(m_hFont);
4641 return TRUE;
4642 }
4643
InsertSeparator()4644 BOOL CUIFMenu::InsertSeparator()
4645 {
4646 CUIFMenuItemSeparator *pSep = new(cicNoThrow) CUIFMenuItemSeparator(this);
4647 if (!pSep)
4648 return FALSE;
4649
4650 if (!m_MenuItems.Add(pSep))
4651 {
4652 delete pSep;
4653 return FALSE;
4654 }
4655
4656 pSep->Initialize();
4657 return TRUE;
4658 }
4659
STDMETHODIMP_(void)4660 STDMETHODIMP_(void)
4661 CUIFMenu::ModalMessageLoop()
4662 {
4663 MSG msg;
4664
4665 while (::GetMessage(&msg, 0, 0, 0) && msg.message != WM_NULL &&
4666 (msg.hwnd == m_hWnd || msg.message <= WM_MOUSEFIRST || WM_MOUSELAST <= msg.message))
4667 {
4668 if (!msg.hwnd && WM_KEYFIRST <= msg.message && msg.message <= WM_KEYLAST)
4669 msg.hwnd = GetTopSubMenu()->m_hWnd;
4670 ::TranslateMessage(&msg);
4671 ::DispatchMessage(&msg);
4672 }
4673 }
4674
STDMETHODIMP_(void)4675 STDMETHODIMP_(void)
4676 CUIFMenu::ModalMouseNotify(UINT uMsg, LONG x, LONG y)
4677 {
4678 if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN)
4679 CancelMenu();
4680 }
4681
STDMETHODIMP_(void)4682 STDMETHODIMP_(void)
4683 CUIFMenu::OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
4684 {
4685 CUIFMenuItem *pTargetItem;
4686
4687 BYTE vKey = (BYTE)wParam;
4688
4689 switch (vKey)
4690 {
4691 case VK_ESCAPE:
4692 CancelMenu();
4693 return;
4694
4695 case VK_LEFT:
4696 if (!m_pVisibleSubMenu)
4697 return;
4698
4699 CancelMenu();
4700 return;
4701
4702 case VK_RIGHT:
4703 if (m_pSelectedItem && m_pSelectedItem->m_pSubMenu)
4704 {
4705 m_pSelectedItem->ShowSubPopup();
4706 CUIFMenu *pSubMenu = m_pSelectedItem->m_pSubMenu;
4707 pTargetItem = pSubMenu->GetNextItem(NULL);
4708 pSubMenu->SetSelectedItem(pTargetItem);
4709 }
4710 return;
4711
4712 case VK_UP:
4713 pTargetItem = GetPrevItem(m_pSelectedItem);
4714 SetSelectedItem(pTargetItem);
4715 return;
4716
4717 case VK_DOWN:
4718 pTargetItem = GetNextItem(m_pSelectedItem);
4719 SetSelectedItem(pTargetItem);
4720 return;
4721
4722 case VK_RETURN:
4723 break;
4724
4725 default:
4726 {
4727 if (!(('A' <= vKey && vKey <= 'Z') || ('0' <= vKey && vKey <= '9')))
4728 return;
4729
4730 size_t iItem;
4731 for (iItem = 0; iItem < m_MenuItems.size(); ++iItem)
4732 {
4733 CUIFMenuItem *pItem = m_MenuItems[iItem];
4734 if (pItem->m_nMenuItemVKey == vKey)
4735 {
4736 SetSelectedItem(pItem);
4737 break;
4738 }
4739 }
4740
4741 if (iItem == m_MenuItems.size())
4742 return;
4743 }
4744 }
4745
4746 if (m_pSelectedItem && !m_pSelectedItem->m_bMenuItemGrayed)
4747 {
4748 CUIFMenu *pSubMenu = m_pSelectedItem->m_pSubMenu;
4749 if (pSubMenu)
4750 {
4751 m_pSelectedItem->ShowSubPopup();
4752 pTargetItem = pSubMenu->GetNextItem(NULL);
4753 pSubMenu->SetSelectedItem(pTargetItem);
4754 }
4755 else
4756 {
4757 SetSelectedId(m_pSelectedItem->m_nMenuItemID);
4758 ::PostMessage(m_hWnd, WM_NULL, 0, 0);
4759 }
4760 }
4761 }
4762
PostKey(BOOL bUp,WPARAM wParam,LPARAM lParam)4763 void CUIFMenu::PostKey(BOOL bUp, WPARAM wParam, LPARAM lParam)
4764 {
4765 if (m_bModal)
4766 {
4767 // NOTE: hWnd parameter will be populated in CUIFMenu::ModalMessageLoop.
4768 if (bUp)
4769 ::PostMessage(NULL, WM_KEYUP, wParam, lParam);
4770 else
4771 ::PostMessage(NULL, WM_KEYDOWN, wParam, lParam);
4772 }
4773 }
4774
SetMenuFont()4775 void CUIFMenu::SetMenuFont()
4776 {
4777 LONG height = 14;
4778
4779 NONCLIENTMETRICS ncm = { sizeof(ncm) };
4780 if (::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
4781 {
4782 HFONT hFont = ::CreateFontIndirect(&ncm.lfMenuFont);
4783 SetFont(hFont);
4784
4785 LONG lfHeight = ncm.lfMenuFont.lfHeight;
4786 if (lfHeight < 0)
4787 lfHeight = -lfHeight;
4788 height = (ncm.iMenuHeight + lfHeight) / 2;
4789 }
4790
4791 m_hMenuFont = ::CreateFontW(height, 0, 0, 0, FW_NORMAL, 0, 0, 0, SYMBOL_CHARSET,
4792 0, 0, 0, 0, L"Marlett");
4793 INT cxSmallIcon = ::GetSystemMetrics(SM_CXSMICON);
4794 m_cxyMargin = max(height, cxSmallIcon) + 2;
4795 }
4796
SetSelectedId(UINT nSelectID)4797 void CUIFMenu::SetSelectedId(UINT nSelectID)
4798 {
4799 CUIFMenu *pMenu = this;
4800
4801 while (pMenu->m_pVisibleSubMenu)
4802 pMenu = pMenu->m_pVisibleSubMenu;
4803
4804 pMenu->m_nSelectedID = nSelectID;
4805 }
4806
SetSelectedItem(CUIFMenuItem * pItem)4807 void CUIFMenu::SetSelectedItem(CUIFMenuItem *pItem)
4808 {
4809 CUIFMenuItem *pOldItem = m_pSelectedItem;
4810 if (pOldItem == pItem)
4811 return;
4812
4813 m_pSelectedItem = pItem;
4814 if (pOldItem)
4815 pOldItem->CallOnPaint();
4816 if (m_pSelectedItem)
4817 m_pSelectedItem->CallOnPaint();
4818 }
4819
ShowModalPopup(CUIFWindow * pWindow,LPCRECT prc,BOOL bFlag)4820 UINT CUIFMenu::ShowModalPopup(CUIFWindow *pWindow, LPCRECT prc, BOOL bFlag)
4821 {
4822 CUIFObject *pCaptured = NULL;
4823 if (pWindow)
4824 {
4825 pCaptured = pWindow->m_pCaptured;
4826 CUIFWindow::SetCaptureObject(NULL);
4827 }
4828
4829 UINT nSelectedID = -1;
4830 if (InitShow(pWindow, prc, bFlag, TRUE))
4831 {
4832 m_bModal = TRUE;
4833 pWindow->SetBehindModal(this);
4834 ModalMessageLoop();
4835 nSelectedID = m_nSelectedID;
4836 pWindow->SetBehindModal(NULL);
4837 m_bModal = FALSE;
4838 }
4839
4840 UninitShow();
4841
4842 if (pWindow)
4843 pWindow->SetCaptureObject(pCaptured);
4844
4845 return nSelectedID;
4846 }
4847
ShowSubPopup(CUIFMenu * pSubMenu,LPCRECT prc,BOOL bFlag)4848 void CUIFMenu::ShowSubPopup(CUIFMenu *pSubMenu, LPCRECT prc, BOOL bFlag)
4849 {
4850 m_pVisibleSubMenu = pSubMenu;
4851 InitShow(pSubMenu, prc, bFlag, TRUE);
4852 }
4853
STDMETHODIMP_(BOOL)4854 STDMETHODIMP_(BOOL)
4855 CUIFMenu::UninitShow()
4856 {
4857 if (m_pParentMenu)
4858 m_pParentMenu->UninitShow();
4859
4860 Show(FALSE);
4861
4862 if (m_pVisibleSubMenu)
4863 m_pVisibleSubMenu->m_pParentMenu = NULL;
4864
4865 for (size_t iItem = 0; iItem < m_MenuItems.size(); ++iItem)
4866 RemoveUIObj(m_MenuItems[iItem]);
4867
4868 ::DestroyWindow(m_hWnd);
4869 return TRUE;
4870 }
4871
4872 /////////////////////////////////////////////////////////////////////////////
4873 // CUIFMenuItem
4874
CUIFMenuItem(CUIFMenu * pMenu,BOOL bDisabled)4875 CUIFMenuItem::CUIFMenuItem(
4876 CUIFMenu *pMenu,
4877 BOOL bDisabled) : CUIFObject(pMenu, 0, NULL, 0)
4878 {
4879 m_ichMenuItemPrefix = -1;
4880 m_nMenuItemID = 0;
4881 m_pszMenuItemLeft = m_pszMenuItemRight = NULL;
4882 m_cchMenuItemLeft = m_cchMenuItemRight = 0;
4883 m_nMenuItemVKey = 0;
4884 m_hbmColor = m_hbmMask = NULL;
4885 m_bMenuItemChecked = m_bMenuItemGrayed = FALSE;
4886 m_bMenuItemDisabled = bDisabled;
4887 m_pMenu = pMenu;
4888 }
4889
~CUIFMenuItem()4890 CUIFMenuItem::~CUIFMenuItem()
4891 {
4892 if (m_pszMenuItemLeft)
4893 {
4894 delete[] m_pszMenuItemLeft;
4895 m_pszMenuItemLeft = NULL;
4896 }
4897
4898 if (m_pszMenuItemRight)
4899 {
4900 delete[] m_pszMenuItemRight;
4901 m_pszMenuItemRight = NULL;
4902 }
4903
4904 if (m_pSubMenu)
4905 {
4906 delete m_pSubMenu;
4907 m_pSubMenu = NULL;
4908 }
4909 }
4910
Init(UINT nMenuItemID,LPCWSTR pszText)4911 BOOL CUIFMenuItem::Init(UINT nMenuItemID, LPCWSTR pszText)
4912 {
4913 m_nMenuItemID = nMenuItemID;
4914
4915 if (!pszText)
4916 {
4917 m_pszMenuItemLeft = NULL;
4918 m_cchMenuItemLeft = 0;
4919 return TRUE;
4920 }
4921
4922 INT cch = lstrlenW(pszText);
4923 m_pszMenuItemLeft = new(cicNoThrow) WCHAR[cch + 1];
4924 if (!m_pszMenuItemLeft)
4925 return FALSE;
4926
4927 const WCHAR *pch0 = pszText;
4928 INT ich1, ich2;
4929 for (ich1 = 0; *pch0 && *pch0 != L'\t'; ++ich1, ++pch0)
4930 {
4931 if (*pch0 == L'&' && *++pch0 != L'&')
4932 {
4933 m_nMenuItemVKey = ::VkKeyScanW(*pch0);
4934 if (!m_nMenuItemVKey)
4935 m_nMenuItemVKey = (BYTE)VkKeyScanA(*(BYTE*)pch0);
4936 m_ichMenuItemPrefix = ich1;
4937 }
4938 m_pszMenuItemLeft[ich1] = *pch0;
4939 }
4940 m_pszMenuItemLeft[ich1] = 0;
4941 m_cchMenuItemLeft = lstrlenW(m_pszMenuItemLeft);
4942
4943 if (*pch0 == L'\t')
4944 {
4945 m_cchMenuItemRight = 0;
4946 m_pszMenuItemRight = new(cicNoThrow) WCHAR[cch + 1];
4947 if (m_pszMenuItemRight)
4948 {
4949 ++pch0;
4950 WCHAR wch = *pch0;
4951 for (ich2 = 0; *pch0; ++ich2)
4952 {
4953 m_pszMenuItemRight[ich2] = wch;
4954 wch = *++pch0;
4955 }
4956 m_pszMenuItemRight[ich2] = 0;
4957 m_cchMenuItemRight = lstrlenW(m_pszMenuItemRight);
4958 }
4959 }
4960
4961 return TRUE;
4962 }
4963
STDMETHODIMP_(void)4964 STDMETHODIMP_(void)
4965 CUIFMenuItem::InitMenuExtent()
4966 {
4967 if (!m_pszMenuItemLeft)
4968 {
4969 if (m_hbmColor)
4970 {
4971 BITMAP bm;
4972 ::GetObject(m_hbmColor, sizeof(bm), &bm);
4973 m_MenuLeftExtent.cx = bm.bmWidth + 2;
4974 m_MenuLeftExtent.cy = bm.bmHeight + 4;
4975 }
4976 else
4977 {
4978 m_MenuLeftExtent.cx = m_MenuLeftExtent.cy = 0;
4979 }
4980 return;
4981 }
4982
4983 HDC hDC = ::GetDC(*m_pWindow);
4984
4985 HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
4986 ::GetTextExtentPoint32W(hDC, m_pszMenuItemLeft, m_cchMenuItemLeft, &m_MenuLeftExtent);
4987 m_MenuLeftExtent.cx += 16;
4988 m_MenuLeftExtent.cy += 8;
4989 if (m_pszMenuItemRight)
4990 {
4991 ::GetTextExtentPoint32W(hDC, m_pszMenuItemRight, m_cchMenuItemRight, &m_MenuRightExtent);
4992 m_MenuRightExtent.cy += 8;
4993 }
4994 ::SelectObject(hDC, hFontOld);
4995
4996 if (m_pSubMenu)
4997 m_MenuLeftExtent.cx += m_MenuLeftExtent.cy + 2;
4998 if (m_pMenu->m_style & UIF_MENU_USE_OFF10)
4999 m_MenuLeftExtent.cx += 24;
5000
5001 ::ReleaseDC(*m_pWindow, hDC);
5002 }
5003
IsCheck()5004 BOOL CUIFMenuItem::IsCheck()
5005 {
5006 return m_bMenuItemChecked || m_bMenuItemForceChecked;
5007 }
5008
DrawArrow(HDC hDC,INT xLeft,INT yTop)5009 void CUIFMenuItem::DrawArrow(HDC hDC, INT xLeft, INT yTop)
5010 {
5011 if (!m_pSubMenu)
5012 return;
5013
5014 HGDIOBJ hFontOld = ::SelectObject(hDC, m_pMenu->m_hMenuFont);
5015 ::TextOutW(hDC, xLeft, yTop, L"4", 1); // rightward triangle
5016 ::SelectObject(hDC, hFontOld);
5017 }
5018
DrawBitmapProc(HDC hDC,INT xLeft,INT yTop)5019 void CUIFMenuItem::DrawBitmapProc(HDC hDC, INT xLeft, INT yTop)
5020 {
5021 if (!m_pScheme || !m_hbmColor)
5022 return;
5023
5024 BITMAP bm;
5025 ::GetObject(m_hbmColor, sizeof(bm), &bm);
5026
5027 INT width = m_pMenu->m_cxyMargin, height = m_rc.bottom - m_rc.top;
5028 if (width > bm.bmWidth)
5029 {
5030 width = bm.bmWidth;
5031 xLeft += (width - bm.bmWidth) / 2;
5032 }
5033 if (height > bm.bmHeight)
5034 {
5035 height = bm.bmHeight;
5036 yTop += (height - bm.bmHeight) / 2;
5037 }
5038
5039 RECT rc = { xLeft, yTop, xLeft + width, yTop + height };
5040
5041 if (IsRTL())
5042 m_pScheme->m_bMirroring = TRUE;
5043
5044 if (m_pMenu->m_pSelectedItem != this || m_bMenuItemDisabled)
5045 m_pScheme->DrawFrameCtrlBitmap(hDC, &rc, m_hbmColor, m_hbmMask, 0);
5046 else
5047 m_pScheme->DrawFrameCtrlBitmap(hDC, &rc, m_hbmColor, m_hbmMask, UIF_DRAW_PRESSED);
5048
5049 if (IsRTL())
5050 m_pScheme->m_bMirroring = FALSE;
5051 }
5052
DrawCheck(HDC hDC,INT xLeft,INT yTop)5053 void CUIFMenuItem::DrawCheck(HDC hDC, INT xLeft, INT yTop)
5054 {
5055 if (!IsCheck())
5056 return;
5057
5058 HGDIOBJ hFontOld = ::SelectObject(hDC, m_pMenu->m_hMenuFont);
5059 WCHAR wch = (m_bMenuItemChecked ? L'a' : L'h'); // checkmark or bullet
5060 ::TextOutW(hDC, xLeft, yTop, &wch, 1);
5061 ::SelectObject(hDC, hFontOld);
5062 }
5063
5064 void
DrawUnderline(HDC hDC,INT xText,INT yText,HBRUSH hbr)5065 CUIFMenuItem::DrawUnderline(HDC hDC, INT xText, INT yText, HBRUSH hbr)
5066 {
5067 if (m_ichMenuItemPrefix > m_cchMenuItemLeft)
5068 return;
5069
5070 SIZE PrePrefixSize, PostPrefixSize;
5071 ::GetTextExtentPoint32W(hDC, m_pszMenuItemLeft, m_ichMenuItemPrefix, &PrePrefixSize);
5072 ::GetTextExtentPoint32W(hDC, m_pszMenuItemLeft, m_ichMenuItemPrefix + 1, &PostPrefixSize);
5073
5074 BOOL bHeadPrefix = (m_ichMenuItemPrefix == 0);
5075
5076 RECT rc;
5077 rc.left = xText + PrePrefixSize.cx + !bHeadPrefix;
5078 rc.right = xText + PostPrefixSize.cx;
5079 rc.top = (yText + PostPrefixSize.cy) - 1;
5080 rc.bottom = yText + PostPrefixSize.cy;
5081 ::FillRect(hDC, &rc, hbr);
5082 }
5083
STDMETHODIMP_(void)5084 STDMETHODIMP_(void)
5085 CUIFMenuItem::OnLButtonUp(LONG x, LONG y)
5086 {
5087 if (!m_bMenuItemGrayed && !m_bMenuItemDisabled && !m_pSubMenu)
5088 {
5089 m_pMenu->SetSelectedId(m_nMenuItemID);
5090 ::PostMessage(*m_pWindow, WM_NULL, 0, 0);
5091 }
5092 }
5093
STDMETHODIMP_(void)5094 STDMETHODIMP_(void)
5095 CUIFMenuItem::OnMouseIn(LONG x, LONG y)
5096 {
5097 if (m_pMenu->m_pParentMenu)
5098 m_pMenu->m_pParentMenu->CancelMenu();
5099
5100 if (m_pSubMenu)
5101 {
5102 DWORD Delay;
5103 if (!::SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &Delay, 0))
5104 Delay = 300;
5105
5106 CUIFObject::StartTimer(Delay);
5107 }
5108
5109 m_pMenu->SetSelectedItem(this);
5110 }
5111
STDMETHODIMP_(void)5112 STDMETHODIMP_(void)
5113 CUIFMenuItem::OnPaint(HDC hDC)
5114 {
5115 if (m_pMenu->m_style & UIF_MENU_USE_OFF10)
5116 OnPaintO10(hDC);
5117 else
5118 OnPaintDef(hDC);
5119 }
5120
STDMETHODIMP_(void)5121 STDMETHODIMP_(void)
5122 CUIFMenuItem::OnPaintO10(HDC hDC)
5123 {
5124 if (!m_pScheme)
5125 return;
5126
5127 HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
5128
5129 SIZE textSize;
5130 ::GetTextExtentPoint32W(hDC, m_pszMenuItemLeft, m_cchMenuItemLeft, &textSize);
5131
5132 LONG cySpace = m_rc.bottom - m_rc.top - textSize.cy;
5133 LONG xCheck = m_rc.left, yCheck = m_rc.top + cySpace / 2;
5134 LONG cxyMargin = (m_pMenu->m_bHasMargin ? m_pMenu->m_cxyMargin : 0);
5135
5136 LONG xBitmap = m_rc.left + cxyMargin, yBitmap = m_rc.top;
5137 LONG xText = m_rc.left + m_pMenu->m_cxyMargin + cxyMargin + 8;
5138 LONG yText = m_rc.top + cySpace / 2;
5139 LONG xArrow = m_rc.left - textSize.cy + m_rc.right - 2;
5140 LONG xRightText = m_rc.right - m_pMenu->m_cxMenuExtent - 8;
5141
5142 RECT rc;
5143 GetRect(&rc);
5144
5145 if (m_bMenuItemDisabled || m_pMenu->m_pSelectedItem != this)
5146 {
5147 rc.right = m_pMenu->m_cxyMargin + rc.left + 2;
5148 if (m_pMenu->m_bHasMargin)
5149 rc.right += m_pMenu->m_cxyMargin;
5150
5151 ::FillRect(hDC, &rc, m_pScheme->GetBrush(9));
5152 }
5153 else
5154 {
5155 m_pScheme->DrawCtrlBkgd(hDC, &rc, 0, UIF_DRAW_PRESSED);
5156 m_pScheme->DrawCtrlEdge(hDC, &rc, 0, UIF_DRAW_PRESSED);
5157 }
5158
5159 ::SetBkMode(hDC, TRANSPARENT);
5160
5161 if (m_bMenuItemGrayed)
5162 {
5163 ::SetTextColor(hDC, m_pScheme->GetColor(11));
5164 ::ExtTextOutW(hDC, xText, yText, ETO_CLIPPED, &m_rc, m_pszMenuItemLeft,
5165 m_cchMenuItemLeft, NULL);
5166 }
5167 else if (m_bMenuItemDisabled || m_pMenu->m_pSelectedItem != this)
5168 {
5169 ::SetTextColor(hDC, m_pScheme->GetColor(10));
5170 ::ExtTextOutW(hDC, xText, yText, ETO_CLIPPED, &m_rc, m_pszMenuItemLeft,
5171 m_cchMenuItemLeft, NULL);
5172 }
5173 else
5174 {
5175 ::SetTextColor(hDC, m_pScheme->GetColor(5));
5176 ::ExtTextOutW(hDC, xText, yText, ETO_CLIPPED, &m_rc, m_pszMenuItemLeft,
5177 m_cchMenuItemLeft, NULL);
5178 }
5179
5180 DrawUnderline(hDC, xText, yText, m_pScheme->GetBrush(5));
5181
5182 if (m_pszMenuItemRight)
5183 {
5184 ::ExtTextOutW(hDC, xRightText, yText, ETO_CLIPPED, &m_rc, m_pszMenuItemRight,
5185 m_cchMenuItemRight, NULL);
5186 }
5187
5188 DrawCheck(hDC, xCheck, yCheck);
5189 DrawBitmapProc(hDC, xBitmap, yBitmap);
5190 DrawArrow(hDC, xArrow, yText);
5191
5192 ::SelectObject(hDC, hFontOld);
5193 }
5194
STDMETHODIMP_(void)5195 STDMETHODIMP_(void)
5196 CUIFMenuItem::OnPaintDef(HDC hDC)
5197 {
5198 HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
5199
5200 SIZE textSize;
5201 ::GetTextExtentPoint32W(hDC, m_pszMenuItemLeft, m_cchMenuItemLeft, &textSize);
5202
5203 LONG cxyMargin = (m_pMenu->m_bHasMargin ? m_pMenu->m_cxyMargin : 0);
5204
5205 LONG cySpace = m_rc.bottom - m_rc.top - textSize.cy;
5206 LONG xCheck = m_rc.left, yCheck = m_rc.top + cySpace / 2;
5207 LONG xBitmap = m_rc.left + cxyMargin, yBitmap = m_rc.top;
5208 LONG xText = m_rc.left + cxyMargin + m_pMenu->m_cxyMargin + 2;
5209 LONG yText = m_rc.top + cySpace / 2;
5210
5211 LONG xArrow = m_rc.right + m_rc.left - 10;
5212
5213 ::SetBkMode(hDC, TRANSPARENT);
5214
5215 if (m_bMenuItemGrayed)
5216 {
5217 UINT uOptions = ETO_CLIPPED;
5218 if (m_bMenuItemDisabled || m_pMenu->m_pSelectedItem != this)
5219 {
5220 ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHIGHLIGHT));
5221 ::ExtTextOutW(hDC, xText + 1, yText + 1, ETO_CLIPPED, &m_rc, m_pszMenuItemLeft,
5222 m_cchMenuItemLeft, NULL);
5223 DrawCheck(hDC, xCheck + 1, yCheck + 1);
5224 DrawBitmapProc(hDC, xBitmap + 1, yBitmap + 1);
5225 DrawArrow(hDC, xArrow + 1, yText + 1);
5226 }
5227 else
5228 {
5229 ::SetBkColor(hDC, ::GetSysColor(COLOR_HIGHLIGHT));
5230 uOptions = ETO_CLIPPED | ETO_OPAQUE;
5231 }
5232 ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNSHADOW));
5233 ::ExtTextOutW(hDC, xText, yText, uOptions, &m_rc, m_pszMenuItemLeft,
5234 m_cchMenuItemLeft, NULL);
5235 DrawUnderline(hDC, xText, yText, (HBRUSH)UlongToHandle(COLOR_BTNSHADOW + 1));
5236 }
5237 else if (m_bMenuItemDisabled || m_pMenu->m_pSelectedItem != this)
5238 {
5239 ::SetTextColor(hDC, ::GetSysColor(COLOR_MENUTEXT));
5240 ::ExtTextOutW(hDC, xText, yText, ETO_CLIPPED, &m_rc, m_pszMenuItemLeft,
5241 m_cchMenuItemLeft, NULL);
5242 DrawUnderline(hDC, xText, yText, (HBRUSH)UlongToHandle(COLOR_MENUTEXT + 1));
5243 }
5244 else
5245 {
5246 ::SetTextColor(hDC, ::GetSysColor(COLOR_HIGHLIGHTTEXT));
5247 ::SetBkColor(hDC, ::GetSysColor(COLOR_HIGHLIGHT));
5248 ::ExtTextOutW(hDC, xText, yText, ETO_CLIPPED | ETO_OPAQUE, &m_rc,
5249 m_pszMenuItemLeft, m_cchMenuItemLeft, NULL);
5250 DrawUnderline(hDC, xText, yText, (HBRUSH)UlongToHandle(COLOR_HIGHLIGHTTEXT + 1));
5251 }
5252
5253 DrawCheck(hDC, xCheck, yCheck);
5254 DrawBitmapProc(hDC, xBitmap, yBitmap);
5255 DrawArrow(hDC, xArrow, yText);
5256
5257 ::SelectObject(hDC, hFontOld);
5258 }
5259
STDMETHODIMP_(void)5260 STDMETHODIMP_(void)
5261 CUIFMenuItem::OnTimer()
5262 {
5263 CUIFObject::EndTimer();
5264 if (m_pMenu->m_pPointed == this)
5265 ShowSubPopup();
5266 }
5267
SetBitmapMask(HBITMAP hbmMask)5268 void CUIFMenuItem::SetBitmapMask(HBITMAP hbmMask)
5269 {
5270 m_hbmMask = hbmMask;
5271 CallOnPaint();
5272 }
5273
ShowSubPopup()5274 void CUIFMenuItem::ShowSubPopup()
5275 {
5276 RECT rc = m_rc;
5277 ::ClientToScreen(*m_pWindow, (LPPOINT)&rc);
5278 ::ClientToScreen(*m_pWindow, (LPPOINT)&rc.right);
5279 m_pSubMenu->ShowSubPopup(m_pMenu, &rc, FALSE);
5280 }
5281
5282 /////////////////////////////////////////////////////////////////////////////
5283 // CUIFMenuItemSeparator
5284
CUIFMenuItemSeparator(CUIFMenu * pMenu)5285 CUIFMenuItemSeparator::CUIFMenuItemSeparator(CUIFMenu *pMenu) : CUIFMenuItem(pMenu, TRUE)
5286 {
5287 m_nMenuItemID = -1;
5288 }
5289
STDMETHODIMP_(void)5290 STDMETHODIMP_(void)
5291 CUIFMenuItemSeparator::InitMenuExtent()
5292 {
5293 m_MenuLeftExtent.cx = 0;
5294 m_MenuLeftExtent.cy = 6;
5295 }
5296
STDMETHODIMP_(void)5297 STDMETHODIMP_(void)
5298 CUIFMenuItemSeparator::OnPaintDef(HDC hDC)
5299 {
5300 if (!m_pScheme)
5301 return;
5302
5303 RECT rc;
5304 rc.left = m_rc.left + 2;
5305 rc.top = m_rc.top + (m_rc.bottom - m_rc.top - 2) / 2;
5306 rc.right = m_rc.right - 2;
5307 rc.bottom = rc.top + 2;
5308 m_pScheme->DrawMenuSeparator(hDC, &rc);
5309 }
5310
STDMETHODIMP_(void)5311 STDMETHODIMP_(void)
5312 CUIFMenuItemSeparator::OnPaintO10(HDC hDC)
5313 {
5314 if (!m_pScheme)
5315 return;
5316
5317 LONG cx = m_rc.right - m_rc.left - 4;
5318 LONG cy = (m_rc.bottom - m_rc.top - 2) / 2;
5319
5320 RECT rc;
5321 GetRect(&rc);
5322
5323 rc.right = rc.left + m_pMenu->m_cxyMargin + 2;
5324 if (m_pMenu->m_bHasMargin)
5325 rc.right += m_pMenu->m_cxyMargin;
5326
5327 HBRUSH hBrush = m_pScheme->GetBrush(9);
5328 ::FillRect(hDC, &rc, hBrush);
5329 rc = {
5330 m_rc.left + m_pMenu->m_cxyMargin + 4,
5331 m_rc.top + cy,
5332 m_rc.left + cx + 2,
5333 m_rc.top + cy + 1
5334 };
5335 m_pScheme->DrawMenuSeparator(hDC, &rc);
5336 }
5337
5338 /////////////////////////////////////////////////////////////////////////////
5339
cicGetWorkAreaRect(POINT pt,LPRECT prc)5340 void cicGetWorkAreaRect(POINT pt, LPRECT prc)
5341 {
5342 ::SystemParametersInfo(SPI_GETWORKAREA, 0, prc, 0);
5343
5344 HMONITOR hMon = ::MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
5345 if (hMon)
5346 {
5347 MONITORINFO mi = { sizeof(mi) };
5348 if (::GetMonitorInfo(hMon, &mi))
5349 *prc = mi.rcWork;
5350 }
5351 }
5352
cicGetScreenRect(POINT pt,LPRECT prc)5353 void cicGetScreenRect(POINT pt, LPRECT prc)
5354 {
5355 *prc = { 0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN) };
5356 HMONITOR hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
5357 if (hMon)
5358 {
5359 MONITORINFO mi = { sizeof(mi) };
5360 GetMonitorInfo(hMon, &mi);
5361 *prc = mi.rcMonitor;
5362 }
5363 }
5364
cicIsFullScreenSize(HWND hWnd)5365 BOOL cicIsFullScreenSize(HWND hWnd)
5366 {
5367 RECT rc;
5368
5369 ::GetWindowRect(hWnd, &rc);
5370 return (rc.left <= 0) && (rc.top <= 0) &&
5371 (rc.right >= GetSystemMetrics(SM_CXFULLSCREEN)) &&
5372 (rc.bottom >= GetSystemMetrics(SM_CYFULLSCREEN));
5373 }
5374
cicGetIconSize(HICON hIcon,LPSIZE pSize)5375 BOOL cicGetIconSize(HICON hIcon, LPSIZE pSize)
5376 {
5377 ICONINFO IconInfo;
5378 if (!GetIconInfo(hIcon, &IconInfo))
5379 return FALSE;
5380
5381 BITMAP bm;
5382 ::GetObject(IconInfo.hbmColor, sizeof(bm), &bm);
5383 ::DeleteObject(IconInfo.hbmColor);
5384 ::DeleteObject(IconInfo.hbmMask);
5385 pSize->cx = bm.bmWidth;
5386 pSize->cy = bm.bmHeight;
5387 return TRUE;
5388 }
5389
5390 /////////////////////////////////////////////////////////////////////////////
5391
cicInitUIFSys(void)5392 void cicInitUIFSys(void)
5393 {
5394 CUIFSystemInfo::s_pSystemInfo = new(cicNoThrow) CUIFSystemInfo();
5395 if (CUIFSystemInfo::s_pSystemInfo)
5396 CUIFSystemInfo::s_pSystemInfo->Initialize();
5397 }
5398
cicDoneUIFSys(void)5399 void cicDoneUIFSys(void)
5400 {
5401 if (CUIFSystemInfo::s_pSystemInfo)
5402 {
5403 delete CUIFSystemInfo::s_pSystemInfo;
5404 CUIFSystemInfo::s_pSystemInfo = NULL;
5405 }
5406 }
5407
cicUpdateUIFSys(void)5408 void cicUpdateUIFSys(void)
5409 {
5410 if (CUIFSystemInfo::s_pSystemInfo)
5411 CUIFSystemInfo::s_pSystemInfo->GetSystemMetrics();
5412 }
5413
5414 /////////////////////////////////////////////////////////////////////////////
5415
cicInitUIFScheme(void)5416 void cicInitUIFScheme(void)
5417 {
5418 CUIFColorTable *pColorTable;
5419
5420 pColorTable = CUIFScheme::s_pColorTableSys = new(cicNoThrow) CUIFColorTableSys();
5421 if (pColorTable)
5422 {
5423 pColorTable->InitColor();
5424 pColorTable->InitBrush();
5425 }
5426
5427 pColorTable = CUIFScheme::s_pColorTableOff10 = new(cicNoThrow) CUIFColorTableOff10();
5428 if (pColorTable)
5429 {
5430 pColorTable->InitColor();
5431 pColorTable->InitBrush();
5432 }
5433 }
5434
cicUpdateUIFScheme(void)5435 void cicUpdateUIFScheme(void)
5436 {
5437 if (CUIFScheme::s_pColorTableSys)
5438 CUIFScheme::s_pColorTableSys->Update();
5439 if (CUIFScheme::s_pColorTableOff10)
5440 CUIFScheme::s_pColorTableOff10->Update();
5441 }
5442
cicDoneUIFScheme(void)5443 void cicDoneUIFScheme(void)
5444 {
5445 if (CUIFScheme::s_pColorTableSys)
5446 {
5447 delete CUIFScheme::s_pColorTableSys;
5448 CUIFScheme::s_pColorTableSys = NULL;
5449 }
5450 if (CUIFScheme::s_pColorTableOff10)
5451 {
5452 delete CUIFScheme::s_pColorTableOff10;
5453 CUIFScheme::s_pColorTableOff10 = NULL;
5454 }
5455 }
5456
5457 /////////////////////////////////////////////////////////////////////////////
5458
cicInitUIFLib(void)5459 void cicInitUIFLib(void)
5460 {
5461 cicInitUIFSys();
5462 cicInitUIFScheme();
5463 cicInitUIFUtil();
5464 }
5465
cicDoneUIFLib(void)5466 void cicDoneUIFLib(void)
5467 {
5468 cicDoneUIFScheme();
5469 cicDoneUIFSys();
5470 cicDoneUIFUtil();
5471 }
5472
5473 /////////////////////////////////////////////////////////////////////////////
5474