10 #define __ATLCTRLX_H__ 15 #error atlctrlx.h requires atlapp.h to be included first 18 #ifndef __ATLCTRLS_H__ 19 #error atlctrlx.h requires atlctrls.h to be included first 22 #ifndef WM_UPDATEUISTATE 23 #define WM_UPDATEUISTATE 0x0128 24 #endif // !WM_UPDATEUISTATE 57 #define BMPBTN_HOVER 0x00000001 58 #define BMPBTN_AUTO3D_SINGLE 0x00000002 59 #define BMPBTN_AUTO3D_DOUBLE 0x00000004 60 #define BMPBTN_AUTOSIZE 0x00000008 61 #define BMPBTN_SHAREIMAGELISTS 0x00000010 62 #define BMPBTN_AUTOFIRE 0x00000020 63 #define BMPBTN_CHECK 0x00000040 64 #define BMPBTN_AUTOCHECK 0x00000080 69 template <
class T,
class TBase = CButton,
class TWinTraits = ATL::CControlWinTraits>
73 DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
87 ID_TIMER_FIRST = 1000,
88 ID_TIMER_REPEAT = 1001
92 DWORD m_dwExtendedStyle;
95 int m_nImage[_nImageCount];
98 LPTSTR m_lpstrToolTipText;
101 unsigned m_fMouseOver:1;
103 unsigned m_fPressed:1;
104 unsigned m_fChecked:1;
108 CBitmapButtonImpl(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) :
109 m_dwExtendedStyle(dwExtendedStyle), m_ImageList(hImageList),
110 m_lpstrToolTipText(NULL),
111 m_fMouseOver(0), m_fFocus(0), m_fPressed(0), m_fChecked(0)
113 m_nImage[_nImageNormal] = -1;
114 m_nImage[_nImagePushed] = -1;
115 m_nImage[_nImageFocusOrHover] = -1;
116 m_nImage[_nImageDisabled] = -1;
119 if(((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0) && IsCheckMode())
120 ATLTRACE2(atlTraceUI, 0, _T(
"CBitmapButtonImpl - Check mode and BMPBTN_AUTOFIRE cannot be used together, BMPBTN_AUTOFIRE will be ignored.\n"));
126 if((m_dwExtendedStyle & BMPBTN_SHAREIMAGELISTS) == 0)
127 m_ImageList.Destroy();
128 delete [] m_lpstrToolTipText;
132 BOOL SubclassWindow(HWND hWnd)
134 #if (_MSC_VER >= 1300) 135 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
136 #else // !(_MSC_VER >= 1300) 137 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
138 BOOL bRet = _baseClass::SubclassWindow(hWnd);
139 #endif // !(_MSC_VER >= 1300) 142 T* pT =
static_cast<T*
>(
this);
150 DWORD GetBitmapButtonExtendedStyle()
const 152 return m_dwExtendedStyle;
155 DWORD SetBitmapButtonExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
157 DWORD dwPrevStyle = m_dwExtendedStyle;
159 m_dwExtendedStyle = dwExtendedStyle;
161 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
164 if(((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0) && IsCheckMode())
165 ATLTRACE2(atlTraceUI, 0, _T(
"CBitmapButtonImpl - Check mode and BMPBTN_AUTOFIRE cannot be used together, BMPBTN_AUTOFIRE will be ignored.\n"));
171 HIMAGELIST GetImageList()
const 176 HIMAGELIST SetImageList(HIMAGELIST hImageList)
178 HIMAGELIST hImageListPrev = m_ImageList;
179 m_ImageList = hImageList;
180 if((m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0 && ::IsWindow(m_hWnd))
183 return hImageListPrev;
186 int GetToolTipTextLength()
const 188 return (m_lpstrToolTipText == NULL) ? -1 : lstrlen(m_lpstrToolTipText);
191 bool GetToolTipText(LPTSTR lpstrText,
int nLength)
const 193 ATLASSERT(lpstrText != NULL);
194 if(m_lpstrToolTipText == NULL)
197 errno_t nRet = SecureHelper::strncpy_x(lpstrText, nLength, m_lpstrToolTipText, _TRUNCATE);
199 return (nRet == 0 || nRet == STRUNCATE);
202 bool SetToolTipText(LPCTSTR lpstrText)
204 if(m_lpstrToolTipText != NULL)
206 delete [] m_lpstrToolTipText;
207 m_lpstrToolTipText = NULL;
210 if(lpstrText == NULL)
213 m_tip.Activate(FALSE);
217 int cchLen = lstrlen(lpstrText) + 1;
218 ATLTRY(m_lpstrToolTipText =
new TCHAR[cchLen]);
219 if(m_lpstrToolTipText == NULL)
222 SecureHelper::strcpy_x(m_lpstrToolTipText, cchLen, lpstrText);
225 m_tip.Activate(TRUE);
226 m_tip.AddTool(m_hWnd, m_lpstrToolTipText);
232 bool GetCheck()
const 234 return (m_fChecked == 1);
237 void SetCheck(
bool bCheck,
bool bUpdate =
true)
239 m_fChecked = bCheck ? 1 : 0;
249 void SetImages(
int nNormal,
int nPushed = -1,
int nFocusOrHover = -1,
int nDisabled = -1)
252 m_nImage[_nImageNormal] = nNormal;
254 m_nImage[_nImagePushed] = nPushed;
255 if(nFocusOrHover != -1)
256 m_nImage[_nImageFocusOrHover] = nFocusOrHover;
258 m_nImage[_nImageDisabled] = nDisabled;
263 ATLASSERT(::IsWindow(m_hWnd) && m_ImageList.m_hImageList != NULL);
266 if(!m_ImageList.GetIconSize(cx, cy))
268 return ResizeClient(cx, cy);
274 ATLASSERT(m_ImageList.m_hImageList != NULL);
275 ATLASSERT(m_nImage[0] != -1);
278 bool bHover = IsHoverMode();
279 bool bPressed = (m_fPressed == 1) || (IsCheckMode() && (m_fChecked == 1));
281 if(!IsWindowEnabled())
282 nImage = m_nImage[_nImageDisabled];
284 nImage = m_nImage[_nImagePushed];
285 else if((!bHover && (m_fFocus == 1)) || (bHover && (m_fMouseOver == 1)))
286 nImage = m_nImage[_nImageFocusOrHover];
290 nImage = m_nImage[_nImageNormal];
293 bool bAuto3D = (m_dwExtendedStyle & (BMPBTN_AUTO3D_SINGLE | BMPBTN_AUTO3D_DOUBLE)) != 0;
294 int xyPos = (bPressed && bAuto3D && (m_nImage[_nImagePushed] == -1)) ? 1 : 0;
295 m_ImageList.Draw(dc, nImage, xyPos, xyPos, ILD_NORMAL);
301 GetClientRect(&rect);
304 dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_SUNKENOUTER : EDGE_SUNKEN, BF_RECT);
305 else if(!bHover || (m_fMouseOver == 1))
306 dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_RAISEDINNER : EDGE_RAISED, BF_RECT);
308 if(!bHover && (m_fFocus == 1))
310 ::InflateRect(&rect, -2 * ::GetSystemMetrics(SM_CXEDGE), -2 * ::GetSystemMetrics(SM_CYEDGE));
311 dc.DrawFocusRect(&rect);
318 MESSAGE_HANDLER(WM_CREATE, OnCreate)
319 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
320 MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
321 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
322 MESSAGE_HANDLER(WM_PAINT, OnPaint)
323 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
324 MESSAGE_HANDLER(WM_SETFOCUS, OnFocus)
325 MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus)
326 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
327 MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClk)
328 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
329 MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
330 MESSAGE_HANDLER(WM_ENABLE, OnEnable)
331 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
332 MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
333 MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
334 MESSAGE_HANDLER(WM_KEYUP, OnKeyUp)
335 MESSAGE_HANDLER(WM_TIMER, OnTimer)
336 MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState)
339 LRESULT OnCreate(UINT , WPARAM , LPARAM , BOOL& bHandled)
341 T* pT =
static_cast<T*
>(
this);
348 LRESULT OnDestroy(UINT , WPARAM , LPARAM , BOOL& bHandled)
352 m_tip.DestroyWindow();
359 LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
361 MSG msg = { m_hWnd, uMsg, wParam, lParam };
363 m_tip.RelayEvent(&msg);
368 LRESULT OnEraseBackground(UINT , WPARAM , LPARAM , BOOL& )
373 LRESULT OnPaint(UINT , WPARAM wParam, LPARAM , BOOL& )
375 T* pT =
static_cast<T*
>(
this);
378 pT->DoPaint((HDC)wParam);
383 pT->DoPaint(dc.m_hDC);
388 LRESULT OnFocus(UINT uMsg, WPARAM , LPARAM , BOOL& bHandled)
390 m_fFocus = (uMsg == WM_SETFOCUS) ? 1 : 0;
397 LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
403 lRet = DefWindowProc(uMsg, wParam, lParam);
404 if(::GetCapture() == m_hWnd)
410 if(((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0) && !IsCheckMode())
414 if(::SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &nDelay, 0))
415 nElapse += nDelay * 250;
416 SetTimer(ID_TIMER_FIRST, nElapse);
421 LRESULT OnLButtonDblClk(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
424 if(!IsHoverMode() && !IsCheckMode())
425 lRet = DefWindowProc(uMsg, wParam, lParam);
426 if(::GetCapture() != m_hWnd)
437 LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
439 if(((m_dwExtendedStyle & BMPBTN_AUTOCHECK) != 0) && (m_fPressed == 1))
440 SetCheck(!GetCheck(),
false);
443 if(!IsHoverMode() && !IsCheckMode())
444 lRet = DefWindowProc(uMsg, wParam, lParam);
445 if(::GetCapture() == m_hWnd)
447 if((IsHoverMode() || IsCheckMode()) && (m_fPressed == 1))
448 ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
454 LRESULT OnCaptureChanged(UINT , WPARAM , LPARAM , BOOL& bHandled)
466 LRESULT OnEnable(UINT , WPARAM , LPARAM , BOOL& bHandled)
474 LRESULT OnMouseMove(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
476 if(::GetCapture() == m_hWnd)
478 POINT ptCursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
479 ClientToScreen(&ptCursor);
481 GetWindowRect(&rect);
482 unsigned int uPressed = ::PtInRect(&rect, ptCursor) ? 1 : 0;
483 if(m_fPressed != uPressed)
485 m_fPressed = uPressed;
490 else if(IsHoverMode() && m_fMouseOver == 0)
495 StartTrackMouseLeave();
501 LRESULT OnMouseLeave(UINT , WPARAM , LPARAM , BOOL& )
503 if(m_fMouseOver == 1)
512 LRESULT OnKeyDown(UINT , WPARAM wParam, LPARAM , BOOL& bHandled)
514 if(wParam == VK_SPACE && IsHoverMode())
516 if(wParam == VK_SPACE && m_fPressed == 0)
526 LRESULT OnKeyUp(UINT , WPARAM wParam, LPARAM , BOOL& bHandled)
528 if(wParam == VK_SPACE && IsHoverMode())
530 if(wParam == VK_SPACE && m_fPressed == 1)
533 if((m_dwExtendedStyle & BMPBTN_AUTOCHECK) != 0)
534 SetCheck(!GetCheck(),
false);
542 LRESULT OnTimer(UINT , WPARAM wParam, LPARAM , BOOL& )
544 ATLASSERT((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0);
548 KillTimer(ID_TIMER_FIRST);
551 ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
554 if(::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &nRepeat, 0))
555 nElapse = 10000 / (10 * nRepeat + 25);
556 SetTimer(ID_TIMER_REPEAT, nElapse);
559 case ID_TIMER_REPEAT:
561 ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
562 else if(::GetCapture() != m_hWnd)
563 KillTimer(ID_TIMER_REPEAT);
571 LRESULT OnUpdateUiState(UINT , WPARAM , LPARAM , BOOL& )
582 ModifyStyle(0, BS_OWNERDRAW);
585 m_tip.Create(m_hWnd);
586 ATLASSERT(m_tip.IsWindow());
587 if(m_tip.IsWindow() && m_lpstrToolTipText != NULL)
589 m_tip.Activate(TRUE);
590 m_tip.AddTool(m_hWnd, m_lpstrToolTipText);
593 if(m_ImageList.m_hImageList != NULL && (m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0)
597 BOOL StartTrackMouseLeave()
599 TRACKMOUSEEVENT tme = { 0 };
600 tme.cbSize =
sizeof(tme);
601 tme.dwFlags = TME_LEAVE;
602 tme.hwndTrack = m_hWnd;
603 return _TrackMouseEvent(&tme);
606 bool IsHoverMode()
const 608 return ((m_dwExtendedStyle & BMPBTN_HOVER) != 0);
611 bool IsCheckMode()
const 613 return ((m_dwExtendedStyle & (BMPBTN_CHECK | BMPBTN_AUTOCHECK)) != 0);
620 DECLARE_WND_SUPERCLASS(_T(
"WTL_BitmapButton"), GetWndClassName())
622 CBitmapButton(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) :
627 #endif // !_WIN32_WCE 633 template <DWORD t_dwStyle, DWORD t_dwExStyle, DWORD t_dwExListViewStyle>
637 static DWORD GetWndStyle(DWORD dwStyle)
639 return (dwStyle == 0) ? t_dwStyle : dwStyle;
642 static DWORD GetWndExStyle(DWORD dwExStyle)
644 return (dwExStyle == 0) ? t_dwExStyle : dwExStyle;
647 static DWORD GetExtendedLVStyle()
649 return t_dwExListViewStyle;
655 template <
class T,
class TBase = CListViewCtrl,
class TWinTraits = CCheckListViewCtrlTraits>
659 DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
662 static DWORD GetExtendedLVStyle()
664 return TWinTraits::GetExtendedLVStyle();
668 BOOL SubclassWindow(HWND hWnd)
670 #if (_MSC_VER >= 1300) 671 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
672 #else // !(_MSC_VER >= 1300) 673 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
674 BOOL bRet = _baseClass::SubclassWindow(hWnd);
675 #endif // !(_MSC_VER >= 1300) 678 T* pT =
static_cast<T*
>(
this);
685 void CheckSelectedItems(
int nCurrItem)
689 lvi.iItem = nCurrItem;
691 lvi.mask = LVIF_STATE;
692 lvi.stateMask = LVIS_SELECTED;
695 if(!(lvi.state & LVIS_SELECTED))
698 BOOL bCheck = !GetCheckState(nCurrItem);
701 while((nItem = GetNextItem(nOldItem, LVNI_SELECTED)) != -1)
703 if(nItem != nCurrItem)
704 SetCheckState(nItem, bCheck);
712 T* pT =
static_cast<T*
>(
this);
714 ATLASSERT((pT->GetExtendedLVStyle() & LVS_EX_CHECKBOXES) != 0);
715 SetExtendedListViewStyle(pT->GetExtendedLVStyle());
720 MESSAGE_HANDLER(WM_CREATE, OnCreate)
721 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
722 MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDown)
723 MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
726 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
729 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
732 T* pT =
static_cast<T*
>(
this);
739 LRESULT OnLButtonDown(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
741 POINT ptMsg = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
742 LVHITTESTINFO lvh = { 0 };
744 if(HitTest(&lvh) != -1 && lvh.flags == LVHT_ONITEMSTATEICON && ::GetKeyState(VK_CONTROL) >= 0)
746 T* pT =
static_cast<T*
>(
this);
747 pT->CheckSelectedItems(lvh.iItem);
753 LRESULT OnKeyDown(UINT , WPARAM wParam, LPARAM , BOOL& bHandled)
755 if(wParam == VK_SPACE)
757 int nCurrItem = GetNextItem(-1, LVNI_FOCUSED);
758 if(nCurrItem != -1 && ::GetKeyState(VK_CONTROL) >= 0)
760 T* pT =
static_cast<T*
>(
this);
761 pT->CheckSelectedItems(nCurrItem);
772 DECLARE_WND_SUPERCLASS(_T(
"WTL_CheckListView"), GetWndClassName())
779 #if (WINVER < 0x0500) && !defined(_WIN32_WCE) 780 __declspec(selectany)
struct 782 enum { cxWidth = 32, cyHeight = 32 };
785 unsigned char arrANDPlane[cxWidth * cyHeight / 8];
786 unsigned char arrXORPlane[cxWidth * cyHeight / 8];
787 } _AtlHyperLink_CursorData =
791 0xF9, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF,
792 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF,
793 0xF0, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF,
794 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x7F, 0xFF,
795 0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF,
796 0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
797 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
798 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
801 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
802 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x06, 0xD8, 0x00, 0x00,
803 0x06, 0xDA, 0x00, 0x00, 0x06, 0xDB, 0x00, 0x00, 0x67, 0xFB, 0x00, 0x00, 0x77, 0xFF, 0x00, 0x00,
804 0x37, 0xFF, 0x00, 0x00, 0x17, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00,
805 0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00,
806 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
811 #endif // (WINVER < 0x0500) && !defined(_WIN32_WCE) 813 #define HLINK_UNDERLINED 0x00000000 814 #define HLINK_NOTUNDERLINED 0x00000001 815 #define HLINK_UNDERLINEHOVER 0x00000002 816 #define HLINK_COMMANDBUTTON 0x00000004 817 #define HLINK_NOTIFYBUTTON 0x0000000C 818 #define HLINK_USETAGS 0x00000010 819 #define HLINK_USETAGSBOLD 0x00000030 820 #define HLINK_NOTOOLTIP 0x00000040 821 #define HLINK_AUTOCREATELINKFONT 0x00000080 822 #define HLINK_SINGLELINE 0x00000100 828 template <
class T,
class TBase = ATL::CWindow,
class TWinTraits = ATL::CControlWinTraits>
829 class ATL_NO_VTABLE
CHyperLinkImpl :
public ATL::CWindowImpl< T, TBase, TWinTraits >
833 LPTSTR m_lpstrHyperLink;
842 #endif // !_WIN32_WCE 845 COLORREF m_clrVisited;
847 DWORD m_dwExtendedStyle;
849 bool m_bPaintLabel:1;
852 bool m_bInternalLinkFont:1;
853 bool m_bInternalNormalFont:1;
858 m_lpstrLabel(NULL), m_lpstrHyperLink(NULL),
859 m_hCursor(NULL), m_hFontLink(NULL), m_hFontNormal(NULL),
860 m_clrLink(RGB(0, 0, 255)), m_clrVisited(RGB(128, 0, 128)),
861 m_dwExtendedStyle(dwExtendedStyle),
862 m_bPaintLabel(
true), m_bVisited(
false),
863 m_bHover(
false), m_bInternalLinkFont(
false), m_bInternalNormalFont(
false)
865 ::SetRectEmpty(&m_rcLink);
870 delete [] m_lpstrLabel;
871 delete [] m_lpstrHyperLink;
872 #if (WINVER < 0x0500) && !defined(_WIN32_WCE) 874 if(m_hCursor != NULL)
875 ::DestroyCursor(m_hCursor);
876 #endif // (WINVER < 0x0500) && !defined(_WIN32_WCE) 880 DWORD GetHyperLinkExtendedStyle()
const 882 return m_dwExtendedStyle;
885 DWORD SetHyperLinkExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
887 DWORD dwPrevStyle = m_dwExtendedStyle;
889 m_dwExtendedStyle = dwExtendedStyle;
891 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
895 bool GetLabel(LPTSTR lpstrBuffer,
int nLength)
const 897 if(m_lpstrLabel == NULL)
899 ATLASSERT(lpstrBuffer != NULL);
900 if(nLength <= lstrlen(m_lpstrLabel))
903 SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrLabel);
908 bool SetLabel(LPCTSTR lpstrLabel)
910 delete [] m_lpstrLabel;
912 int cchLen = lstrlen(lpstrLabel) + 1;
913 ATLTRY(m_lpstrLabel =
new TCHAR[cchLen]);
914 if(m_lpstrLabel == NULL)
917 SecureHelper::strcpy_x(m_lpstrLabel, cchLen, lpstrLabel);
918 T* pT =
static_cast<T*
>(
this);
922 SetWindowText(lpstrLabel);
927 bool GetHyperLink(LPTSTR lpstrBuffer,
int nLength)
const 929 if(m_lpstrHyperLink == NULL)
931 ATLASSERT(lpstrBuffer != NULL);
932 if(nLength <= lstrlen(m_lpstrHyperLink))
935 SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrHyperLink);
940 bool SetHyperLink(LPCTSTR lpstrLink)
942 delete [] m_lpstrHyperLink;
943 m_lpstrHyperLink = NULL;
944 int cchLen = lstrlen(lpstrLink) + 1;
945 ATLTRY(m_lpstrHyperLink =
new TCHAR[cchLen]);
946 if(m_lpstrHyperLink == NULL)
949 SecureHelper::strcpy_x(m_lpstrHyperLink, cchLen, lpstrLink);
950 if(m_lpstrLabel == NULL)
952 T* pT =
static_cast<T*
>(
this);
958 m_tip.Activate(TRUE);
959 m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1);
961 #endif // !_WIN32_WCE 965 HFONT GetLinkFont()
const 970 void SetLinkFont(HFONT hFont)
972 if(m_bInternalLinkFont)
974 ::DeleteObject(m_hFontLink);
975 m_bInternalLinkFont =
false;
980 T* pT =
static_cast<T*
>(
this);
984 int GetIdealHeight()
const 986 ATLASSERT(::IsWindow(m_hWnd));
987 if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
992 UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
996 GetClientRect(&rect);
997 HFONT hFontOld = dc.SelectFont(m_hFontNormal);
999 dc.DrawText(_T(
"NS"), -1, &rcText, DT_LEFT | uFormat | DT_CALCRECT);
1000 dc.SelectFont(m_hFontLink);
1002 dc.DrawText(_T(
"NS"), -1, &rcLink, DT_LEFT | uFormat | DT_CALCRECT);
1003 dc.SelectFont(hFontOld);
1004 return __max(rcText.bottom - rcText.top, rcLink.bottom - rcLink.top);
1007 bool GetIdealSize(SIZE& size)
const 1010 bool bRet = GetIdealSize(cx, cy);
1019 bool GetIdealSize(
int& cx,
int& cy)
const 1021 ATLASSERT(::IsWindow(m_hWnd));
1022 if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
1028 RECT rcClient = { 0 };
1029 GetClientRect(&rcClient);
1030 RECT rcAll = rcClient;
1035 LPTSTR lpstrLeft = NULL;
1037 LPTSTR lpstrLink = NULL;
1039 LPTSTR lpstrRight = NULL;
1042 const T* pT =
static_cast<const T*
>(
this);
1043 pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
1046 UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1048 HFONT hFontOld = dc.SelectFont(m_hFontNormal);
1049 RECT rcLeft = rcClient;
1050 dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | uFormat | DT_CALCRECT);
1052 dc.SelectFont(m_hFontLink);
1053 RECT rcLink = { rcLeft.right, rcLeft.top, rcClient.right, rcClient.bottom };
1054 dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | uFormat | DT_CALCRECT);
1056 dc.SelectFont(m_hFontNormal);
1057 RECT rcRight = { rcLink.right, rcLink.top, rcClient.right, rcClient.bottom };
1058 dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | uFormat | DT_CALCRECT);
1060 dc.SelectFont(hFontOld);
1062 int cyMax = __max(rcLeft.bottom, __max(rcLink.bottom, rcRight.bottom));
1063 ::SetRect(&rcAll, rcLeft.left, rcLeft.top, rcRight.right, cyMax);
1067 HFONT hOldFont = NULL;
1068 if(m_hFontLink != NULL)
1069 hOldFont = dc.SelectFont(m_hFontLink);
1070 LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
1071 DWORD dwStyle = GetStyle();
1072 UINT uFormat = DT_LEFT;
1073 if (dwStyle & SS_CENTER)
1074 uFormat = DT_CENTER;
1075 else if (dwStyle & SS_RIGHT)
1077 uFormat |= IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1078 dc.DrawText(lpstrText, -1, &rcAll, uFormat | DT_CALCRECT);
1079 if(m_hFontLink != NULL)
1080 dc.SelectFont(hOldFont);
1081 if (dwStyle & SS_CENTER)
1083 int dx = (rcClient.right - rcAll.right) / 2;
1084 ::OffsetRect(&rcAll, dx, 0);
1086 else if (dwStyle & SS_RIGHT)
1088 int dx = rcClient.right - rcAll.right;
1089 ::OffsetRect(&rcAll, dx, 0);
1093 cx = rcAll.right - rcAll.left;
1094 cy = rcAll.bottom - rcAll.top;
1100 bool GetToolTipText(LPTSTR lpstrBuffer,
int nLength)
const 1102 ATLASSERT(IsCommandButton());
1103 return GetHyperLink(lpstrBuffer, nLength);
1106 bool SetToolTipText(LPCTSTR lpstrToolTipText)
1108 ATLASSERT(IsCommandButton());
1109 return SetHyperLink(lpstrToolTipText);
1113 BOOL SubclassWindow(HWND hWnd)
1115 ATLASSERT(m_hWnd == NULL);
1116 ATLASSERT(::IsWindow(hWnd));
1117 if(m_hFontNormal == NULL)
1118 m_hFontNormal = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L);
1120 #if (_MSC_VER >= 1300) 1121 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
1122 #else // !(_MSC_VER >= 1300) 1123 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
1124 BOOL bRet = _baseClass::SubclassWindow(hWnd);
1125 #endif // !(_MSC_VER >= 1300) 1128 T* pT =
static_cast<T*
>(
this);
1137 ATLASSERT(::IsWindow(m_hWnd));
1139 if(IsNotifyButton())
1141 NMHDR nmhdr = { m_hWnd, (UINT_PTR)GetDlgCtrlID(), NM_CLICK };
1142 ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr);
1144 else if(IsCommandButton())
1146 ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
1150 ATLASSERT(m_lpstrHyperLink != NULL);
1152 DWORD_PTR dwRet = (DWORD_PTR)::ShellExecute(0, _T(
"open"), m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL);
1153 bRet = (dwRet > 32);
1154 #else // CE specific 1155 SHELLEXECUTEINFO shExeInfo = {
sizeof(SHELLEXECUTEINFO), 0, 0, L
"open", m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL, 0, 0, 0, 0, 0, 0, 0 };
1156 ::ShellExecuteEx(&shExeInfo);
1157 DWORD_PTR dwRet = (DWORD_PTR)shExeInfo.hInstApp;
1158 bRet = (dwRet == 0) || (dwRet > 32);
1159 #endif // _WIN32_WCE 1170 void CreateLinkFontFromNormal()
1172 if(m_bInternalLinkFont)
1174 ::DeleteObject(m_hFontLink);
1175 m_bInternalLinkFont =
false;
1178 CFontHandle font = (m_hFontNormal != NULL) ? m_hFontNormal : (HFONT)::GetStockObject(SYSTEM_FONT);
1180 font.GetLogFont(&lf);
1182 if(IsUsingTagsBold())
1183 lf.lfWeight = FW_BOLD;
1184 else if(!IsNotUnderlined())
1185 lf.lfUnderline = TRUE;
1187 m_hFontLink = ::CreateFontIndirect(&lf);
1188 m_bInternalLinkFont =
true;
1189 ATLASSERT(m_hFontLink != NULL);
1194 MESSAGE_HANDLER(WM_CREATE, OnCreate)
1196 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
1197 MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
1198 #endif // !_WIN32_WCE 1199 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
1200 MESSAGE_HANDLER(WM_PAINT, OnPaint)
1202 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
1203 #endif // !_WIN32_WCE 1204 MESSAGE_HANDLER(WM_SETFOCUS, OnFocus)
1205 MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus)
1206 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
1208 MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
1209 #endif // !_WIN32_WCE 1210 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
1211 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
1212 MESSAGE_HANDLER(WM_CHAR, OnChar)
1213 MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
1214 MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
1215 MESSAGE_HANDLER(WM_ENABLE, OnEnable)
1216 MESSAGE_HANDLER(WM_GETFONT, OnGetFont)
1217 MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
1218 MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState)
1219 MESSAGE_HANDLER(WM_SIZE, OnSize)
1222 LRESULT OnCreate(UINT , WPARAM , LPARAM , BOOL& )
1224 T* pT =
static_cast<T*
>(
this);
1230 LRESULT OnDestroy(UINT , WPARAM , LPARAM , BOOL& bHandled)
1232 if(m_tip.IsWindow())
1234 m_tip.DestroyWindow();
1235 m_tip.m_hWnd = NULL;
1238 if(m_bInternalLinkFont)
1240 ::DeleteObject(m_hFontLink);
1242 m_bInternalLinkFont =
false;
1245 if(m_bInternalNormalFont)
1247 ::DeleteObject(m_hFontNormal);
1248 m_hFontNormal = NULL;
1249 m_bInternalNormalFont =
false;
1256 LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1258 MSG msg = { m_hWnd, uMsg, wParam, lParam };
1259 if(m_tip.IsWindow() && IsUsingToolTip())
1260 m_tip.RelayEvent(&msg);
1264 #endif // !_WIN32_WCE 1266 LRESULT OnEraseBackground(UINT , WPARAM , LPARAM , BOOL& )
1271 LRESULT OnPaint(UINT , WPARAM wParam, LPARAM , BOOL& bHandled)
1279 T* pT =
static_cast<T*
>(
this);
1282 pT->DoEraseBackground((HDC)wParam);
1283 pT->DoPaint((HDC)wParam);
1288 pT->DoEraseBackground(dc.m_hDC);
1289 pT->DoPaint(dc.m_hDC);
1295 LRESULT OnFocus(UINT , WPARAM , LPARAM , BOOL& bHandled)
1304 LRESULT OnMouseMove(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
1306 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1307 if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt))
1309 ::SetCursor(m_hCursor);
1310 if(IsUnderlineHover())
1315 InvalidateRect(&m_rcLink);
1318 StartTrackMouseLeave();
1319 #endif // !_WIN32_WCE 1325 if(IsUnderlineHover())
1330 InvalidateRect(&m_rcLink);
1340 LRESULT OnMouseLeave(UINT , WPARAM , LPARAM , BOOL& )
1342 if(IsUnderlineHover() && m_bHover)
1345 InvalidateRect(&m_rcLink);
1350 #endif // !_WIN32_WCE 1352 LRESULT OnLButtonDown(UINT , WPARAM , LPARAM lParam, BOOL& )
1354 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1355 if(::PtInRect(&m_rcLink, pt))
1363 LRESULT OnLButtonUp(UINT , WPARAM , LPARAM lParam, BOOL& )
1365 if(GetCapture() == m_hWnd)
1368 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1369 if(::PtInRect(&m_rcLink, pt))
1371 T* pT =
static_cast<T*
>(
this);
1378 LRESULT OnChar(UINT , WPARAM wParam, LPARAM , BOOL& )
1380 if(wParam == VK_RETURN || wParam == VK_SPACE)
1382 T* pT =
static_cast<T*
>(
this);
1388 LRESULT OnGetDlgCode(UINT , WPARAM , LPARAM , BOOL& )
1390 return DLGC_WANTCHARS;
1393 LRESULT OnSetCursor(UINT , WPARAM , LPARAM , BOOL& bHandled)
1395 POINT pt = { 0, 0 };
1397 ScreenToClient(&pt);
1398 if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt))
1406 LRESULT OnEnable(UINT , WPARAM , LPARAM , BOOL& )
1413 LRESULT OnGetFont(UINT , WPARAM , LPARAM , BOOL& )
1415 return (LRESULT)m_hFontNormal;
1418 LRESULT OnSetFont(UINT , WPARAM wParam, LPARAM lParam, BOOL& )
1420 if(m_bInternalNormalFont)
1422 ::DeleteObject(m_hFontNormal);
1423 m_bInternalNormalFont =
false;
1426 bool bCreateLinkFont = m_bInternalLinkFont;
1428 m_hFontNormal = (HFONT)wParam;
1430 if(bCreateLinkFont || IsAutoCreateLinkFont())
1431 CreateLinkFontFromNormal();
1433 T* pT =
static_cast<T*
>(
this);
1434 pT->CalcLabelRect();
1445 LRESULT OnUpdateUiState(UINT , WPARAM , LPARAM , BOOL& )
1452 LRESULT OnSize(UINT , WPARAM , LPARAM , BOOL& )
1454 T* pT =
static_cast<T*
>(
this);
1455 pT->CalcLabelRect();
1463 ATLASSERT(::IsWindow(m_hWnd));
1466 const int cchBuff = 8;
1467 TCHAR szBuffer[cchBuff] = { 0 };
1468 if(::GetClassName(m_hWnd, szBuffer, cchBuff))
1470 if(lstrcmpi(szBuffer, _T(
"static")) == 0)
1472 ModifyStyle(0, SS_NOTIFY);
1473 DWORD dwStyle = GetStyle() & 0x000000FF;
1475 if(dwStyle == SS_ICON || dwStyle == SS_BLACKRECT || dwStyle == SS_GRAYRECT ||
1476 dwStyle == SS_WHITERECT || dwStyle == SS_BLACKFRAME || dwStyle == SS_GRAYFRAME ||
1477 dwStyle == SS_WHITEFRAME || dwStyle == SS_OWNERDRAW ||
1478 dwStyle == SS_BITMAP || dwStyle == SS_ENHMETAFILE)
1479 #else // CE specific 1480 if(dwStyle == SS_ICON || dwStyle == SS_BITMAP)
1481 #endif // _WIN32_WCE 1482 m_bPaintLabel =
false;
1487 #if (WINVER >= 0x0500) || defined(_WIN32_WCE) 1488 m_hCursor = ::LoadCursor(NULL, IDC_HAND);
1490 m_hCursor = ::CreateCursor(ModuleHelper::GetModuleInstance(), _AtlHyperLink_CursorData.xHotSpot, _AtlHyperLink_CursorData.yHotSpot, _AtlHyperLink_CursorData.cxWidth, _AtlHyperLink_CursorData.cyHeight, _AtlHyperLink_CursorData.arrANDPlane, _AtlHyperLink_CursorData.arrXORPlane);
1492 ATLASSERT(m_hCursor != NULL);
1497 if(m_hFontNormal == NULL)
1499 m_hFontNormal = AtlCreateControlFont();
1500 m_bInternalNormalFont =
true;
1503 if(m_hFontLink == NULL)
1504 CreateLinkFontFromNormal();
1509 m_tip.Create(m_hWnd);
1510 ATLASSERT(m_tip.IsWindow());
1511 #endif // !_WIN32_WCE 1514 if(m_lpstrLabel == NULL)
1516 int nLen = GetWindowTextLength();
1519 ATLTRY(m_lpstrLabel =
new TCHAR[nLen + 1]);
1520 if(m_lpstrLabel != NULL)
1521 ATLVERIFY(GetWindowText(m_lpstrLabel, nLen + 1) > 0);
1525 T* pT =
static_cast<T*
>(
this);
1526 pT->CalcLabelRect();
1529 if(m_lpstrHyperLink == NULL && !IsCommandButton())
1531 if(m_lpstrLabel != NULL)
1532 SetHyperLink(m_lpstrLabel);
1537 m_tip.Activate(TRUE);
1538 m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1);
1540 #endif // !_WIN32_WCE 1546 LONG lRet = rk.Open(HKEY_CURRENT_USER, _T(
"Software\\Microsoft\\Internet Explorer\\Settings"));
1547 if(lRet == ERROR_SUCCESS)
1549 const int cchValue = 12;
1550 TCHAR szValue[cchValue] = { 0 };
1551 ULONG ulCount = cchValue;
1552 lRet = rk.QueryStringValue(_T(
"Anchor Color"), szValue, &ulCount);
1553 if(lRet == ERROR_SUCCESS)
1555 COLORREF clr = pT->_ParseColorString(szValue);
1556 ATLASSERT(clr != CLR_INVALID);
1557 if(clr != CLR_INVALID)
1562 lRet = rk.QueryStringValue(_T(
"Anchor Color Visited"), szValue, &ulCount);
1563 if(lRet == ERROR_SUCCESS)
1565 COLORREF clr = pT->_ParseColorString(szValue);
1566 ATLASSERT(clr != CLR_INVALID);
1567 if(clr != CLR_INVALID)
1574 static COLORREF _ParseColorString(LPTSTR lpstr)
1576 int c[3] = { -1, -1, -1 };
1578 for(
int i = 0; i < 2; i++)
1580 for(p = lpstr; *p != _T(
'\0'); p = ::CharNext(p))
1585 c[i] = MinCrtHelper::_atoi(lpstr);
1593 if(*lpstr == _T(
'\0'))
1595 c[2] = MinCrtHelper::_atoi(lpstr);
1597 return RGB(c[0], c[1], c[2]);
1600 bool CalcLabelRect()
1602 if(!::IsWindow(m_hWnd))
1604 if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
1608 RECT rcClient = { 0 };
1609 GetClientRect(&rcClient);
1610 m_rcLink = rcClient;
1617 LPTSTR lpstrLeft = NULL;
1619 LPTSTR lpstrLink = NULL;
1621 LPTSTR lpstrRight = NULL;
1624 T* pT =
static_cast<T*
>(
this);
1625 pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
1626 ATLASSERT(lpstrLink != NULL);
1627 ATLASSERT(cchLink > 0);
1630 HFONT hFontOld = dc.SelectFont(m_hFontNormal);
1632 UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1634 RECT rcLeft = rcClient;
1635 if(lpstrLeft != NULL)
1636 dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | uFormat | DT_CALCRECT);
1638 dc.SelectFont(m_hFontLink);
1639 RECT rcLink = rcClient;
1640 if(lpstrLeft != NULL)
1641 rcLink.left = rcLeft.right;
1642 dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | uFormat | DT_CALCRECT);
1644 dc.SelectFont(hFontOld);
1650 HFONT hOldFont = NULL;
1651 if(m_hFontLink != NULL)
1652 hOldFont = dc.SelectFont(m_hFontLink);
1653 LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
1654 DWORD dwStyle = GetStyle();
1655 UINT uFormat = DT_LEFT;
1656 if (dwStyle & SS_CENTER)
1657 uFormat = DT_CENTER;
1658 else if (dwStyle & SS_RIGHT)
1660 uFormat |= IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1661 dc.DrawText(lpstrText, -1, &m_rcLink, uFormat | DT_CALCRECT);
1662 if(m_hFontLink != NULL)
1663 dc.SelectFont(hOldFont);
1664 if (dwStyle & SS_CENTER)
1666 int dx = (rcClient.right - m_rcLink.right) / 2;
1667 ::OffsetRect(&m_rcLink, dx, 0);
1669 else if (dwStyle & SS_RIGHT)
1671 int dx = rcClient.right - m_rcLink.right;
1672 ::OffsetRect(&m_rcLink, dx, 0);
1679 void CalcLabelParts(LPTSTR& lpstrLeft,
int& cchLeft, LPTSTR& lpstrLink,
int& cchLink, LPTSTR& lpstrRight,
int& cchRight)
const 1688 LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
1689 int cchText = lstrlen(lpstrText);
1690 bool bOutsideLink =
true;
1691 for(
int i = 0; i < cchText; i++)
1693 if(lpstrText[i] != _T(
'<'))
1698 if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 3, _T(
"<A>"), 3) == CSTR_EQUAL)
1702 lpstrLeft = lpstrText;
1705 lpstrLink = &lpstrText[i + 3];
1706 bOutsideLink =
false;
1711 if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 4, _T(
"</A>"), 4) == CSTR_EQUAL)
1713 cchLink = i - 3 - cchLeft;
1714 if(lpstrText[i + 4] != 0)
1716 lpstrRight = &lpstrText[i + 4];
1717 cchRight = cchText - (i + 4);
1728 HBRUSH hBrush = (HBRUSH)::SendMessage(GetParent(), WM_CTLCOLORSTATIC, (WPARAM)dc.m_hDC, (LPARAM)m_hWnd);
1732 GetClientRect(&rect);
1733 dc.FillRect(&rect, hBrush);
1742 LPTSTR lpstrLeft = NULL;
1744 LPTSTR lpstrLink = NULL;
1746 LPTSTR lpstrRight = NULL;
1749 T* pT =
static_cast<T*
>(
this);
1750 pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
1753 RECT rcClient = { 0 };
1754 GetClientRect(&rcClient);
1756 dc.SetBkMode(TRANSPARENT);
1757 HFONT hFontOld = dc.SelectFont(m_hFontNormal);
1759 UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1761 if(lpstrLeft != NULL)
1762 dc.DrawText(lpstrLeft, cchLeft, &rcClient, DT_LEFT | uFormat);
1764 COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT)));
1765 if(m_hFontLink != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover)))
1766 dc.SelectFont(m_hFontLink);
1768 dc.SelectFont(m_hFontNormal);
1770 dc.DrawText(lpstrLink, cchLink, &m_rcLink, DT_LEFT | uFormat);
1772 dc.SetTextColor(clrOld);
1773 dc.SelectFont(m_hFontNormal);
1774 if(lpstrRight != NULL)
1776 RECT rcRight = { m_rcLink.right, m_rcLink.top, rcClient.right, rcClient.bottom };
1777 dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | uFormat);
1780 if(GetFocus() == m_hWnd)
1781 dc.DrawFocusRect(&m_rcLink);
1783 dc.SelectFont(hFontOld);
1787 dc.SetBkMode(TRANSPARENT);
1788 COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT)));
1790 HFONT hFontOld = NULL;
1791 if(m_hFontLink != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover)))
1792 hFontOld = dc.SelectFont(m_hFontLink);
1794 hFontOld = dc.SelectFont(m_hFontNormal);
1796 LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
1798 DWORD dwStyle = GetStyle();
1799 UINT uFormat = DT_LEFT;
1800 if (dwStyle & SS_CENTER)
1801 uFormat = DT_CENTER;
1802 else if (dwStyle & SS_RIGHT)
1804 uFormat |= IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1806 dc.DrawText(lpstrText, -1, &m_rcLink, uFormat);
1808 if(GetFocus() == m_hWnd)
1809 dc.DrawFocusRect(&m_rcLink);
1811 dc.SetTextColor(clrOld);
1812 dc.SelectFont(hFontOld);
1817 BOOL StartTrackMouseLeave()
1819 TRACKMOUSEEVENT tme = { 0 };
1820 tme.cbSize =
sizeof(tme);
1821 tme.dwFlags = TME_LEAVE;
1822 tme.hwndTrack = m_hWnd;
1823 return _TrackMouseEvent(&tme);
1825 #endif // !_WIN32_WCE 1828 bool IsUnderlined()
const 1830 return ((m_dwExtendedStyle & (HLINK_NOTUNDERLINED | HLINK_UNDERLINEHOVER)) == 0);
1833 bool IsNotUnderlined()
const 1835 return ((m_dwExtendedStyle & HLINK_NOTUNDERLINED) != 0);
1838 bool IsUnderlineHover()
const 1840 return ((m_dwExtendedStyle & HLINK_UNDERLINEHOVER) != 0);
1843 bool IsCommandButton()
const 1845 return ((m_dwExtendedStyle & HLINK_COMMANDBUTTON) != 0);
1848 bool IsNotifyButton()
const 1850 return ((m_dwExtendedStyle & HLINK_NOTIFYBUTTON) == HLINK_NOTIFYBUTTON);
1853 bool IsUsingTags()
const 1855 return ((m_dwExtendedStyle & HLINK_USETAGS) != 0);
1858 bool IsUsingTagsBold()
const 1860 return ((m_dwExtendedStyle & HLINK_USETAGSBOLD) == HLINK_USETAGSBOLD);
1863 bool IsUsingToolTip()
const 1865 return ((m_dwExtendedStyle & HLINK_NOTOOLTIP) == 0);
1868 bool IsAutoCreateLinkFont()
const 1870 return ((m_dwExtendedStyle & HLINK_AUTOCREATELINKFONT) == HLINK_AUTOCREATELINKFONT);
1873 bool IsSingleLine()
const 1875 return ((m_dwExtendedStyle & HLINK_SINGLELINE) == HLINK_SINGLELINE);
1882 DECLARE_WND_CLASS(_T(
"WTL_HyperLink"))
1893 HCURSOR m_hWaitCursor;
1894 HCURSOR m_hOldCursor;
1898 CWaitCursor(
bool bSet =
true, LPCTSTR lpstrCursor = IDC_WAIT,
bool bSys =
true) : m_hOldCursor(NULL), m_bInUse(
false)
1900 HINSTANCE hInstance = bSys ? NULL : ModuleHelper::GetResourceInstance();
1901 m_hWaitCursor = ::LoadCursor(hInstance, lpstrCursor);
1902 ATLASSERT(m_hWaitCursor != NULL);
1918 m_hOldCursor = ::SetCursor(m_hWaitCursor);
1927 ::SetCursor(m_hOldCursor);
1944 if(hInstance == NULL)
1945 hInstance = ModuleHelper::GetResourceInstance();
1946 m_hWaitCursor = (HCURSOR)::LoadImage(hInstance, cursor.m_lpstr, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE);
1955 #if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) 1956 ::DestroyCursor(m_hWaitCursor);
1957 #endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) 1965 template <
class T,
class TBase = CStatusBarCtrl>
1969 DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
1972 enum { m_cxPaneMargin = 3 };
1987 HWND Create(HWND hWndParent, LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
1989 #if (_MSC_VER >= 1300) 1990 return ATL::CWindowImpl< T, TBase >::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID);
1991 #else // !(_MSC_VER >= 1300) 1992 typedef ATL::CWindowImpl< T, TBase > _baseClass;
1993 return _baseClass::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID);
1994 #endif // !(_MSC_VER >= 1300) 1997 HWND Create(HWND hWndParent, UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
1999 const int cchMax = 128;
2000 TCHAR szText[cchMax] = { 0 };
2001 ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax);
2002 return Create(hWndParent, szText, dwStyle, nID);
2005 BOOL SetPanes(
int* pPanes,
int nPanes,
bool bSetText =
true)
2007 ATLASSERT(::IsWindow(m_hWnd));
2008 ATLASSERT(nPanes > 0);
2014 ATLTRY(m_pPane =
new int[nPanes]);
2015 ATLASSERT(m_pPane != NULL);
2020 int* pPanesPos = buff.Allocate(nPanes);
2021 ATLASSERT(pPanesPos != NULL);
2022 if(pPanesPos == NULL)
2025 SecureHelper::memcpy_x(m_pPane, nPanes *
sizeof(
int), pPanes, nPanes *
sizeof(
int));
2029 HFONT hOldFont = dc.SelectFont(GetFont());
2032 int arrBorders[3] = { 0 };
2033 GetBorders(arrBorders);
2035 const int cchBuff = 128;
2036 TCHAR szBuff[cchBuff] = { 0 };
2037 SIZE size = { 0, 0 };
2038 int cxLeft = arrBorders[0];
2041 for(
int i = 0; i < nPanes; i++)
2043 if(pPanes[i] == ID_DEFAULT_PANE)
2046 pPanesPos[i] = INT_MAX / 2;
2050 ::LoadString(ModuleHelper::GetResourceInstance(), pPanes[i], szBuff, cchBuff);
2051 dc.GetTextExtent(szBuff, lstrlen(szBuff), &size);
2052 T* pT =
static_cast<T*
>(
this);
2054 pPanesPos[i] = cxLeft + size.cx + arrBorders[2] + 2 * pT->m_cxPaneMargin;
2056 cxLeft = pPanesPos[i];
2059 BOOL bRet = SetParts(nPanes, pPanesPos);
2061 if(bRet && bSetText)
2063 for(
int i = 0; i < nPanes; i++)
2065 if(pPanes[i] != ID_DEFAULT_PANE)
2067 ::LoadString(ModuleHelper::GetResourceInstance(), pPanes[i], szBuff, cchBuff);
2068 SetPaneText(m_pPane[i], szBuff);
2073 dc.SelectFont(hOldFont);
2077 bool GetPaneTextLength(
int nPaneID,
int* pcchLength = NULL,
int* pnType = NULL)
const 2079 ATLASSERT(::IsWindow(m_hWnd));
2080 int nIndex = GetPaneIndexFromID(nPaneID);
2084 int nLength = GetTextLength(nIndex, pnType);
2085 if(pcchLength != NULL)
2086 *pcchLength = nLength;
2091 BOOL GetPaneText(
int nPaneID, LPTSTR lpstrText,
int* pcchLength = NULL,
int* pnType = NULL)
const 2093 ATLASSERT(::IsWindow(m_hWnd));
2094 int nIndex = GetPaneIndexFromID(nPaneID);
2098 int nLength = GetText(nIndex, lpstrText, pnType);
2099 if(pcchLength != NULL)
2100 *pcchLength = nLength;
2105 BOOL SetPaneText(
int nPaneID, LPCTSTR lpstrText,
int nType = 0)
2107 ATLASSERT(::IsWindow(m_hWnd));
2108 int nIndex = GetPaneIndexFromID(nPaneID);
2112 return SetText(nIndex, lpstrText, nType);
2115 BOOL GetPaneRect(
int nPaneID, LPRECT lpRect)
const 2117 ATLASSERT(::IsWindow(m_hWnd));
2118 int nIndex = GetPaneIndexFromID(nPaneID);
2122 return GetRect(nIndex, lpRect);
2125 BOOL SetPaneWidth(
int nPaneID,
int cxWidth)
2127 ATLASSERT(::IsWindow(m_hWnd));
2128 ATLASSERT(nPaneID != ID_DEFAULT_PANE);
2129 int nIndex = GetPaneIndexFromID(nPaneID);
2135 int* pPanesPos = buff.Allocate(m_nPanes);
2136 if(pPanesPos == NULL)
2138 GetParts(m_nPanes, pPanesPos);
2140 int cxPaneWidth = pPanesPos[nIndex] - ((nIndex == 0) ? 0 : pPanesPos[nIndex - 1]);
2141 int cxOff = cxWidth - cxPaneWidth;
2143 int nDef = m_nPanes;
2144 for(
int i = 0; i < m_nPanes; i++)
2146 if(m_pPane[i] == ID_DEFAULT_PANE)
2155 for(
int i = nIndex; i < nDef; i++)
2156 pPanesPos[i] += cxOff;
2161 for(
int i = nDef; i < nIndex; i++)
2162 pPanesPos[i] -= cxOff;
2165 return SetParts(m_nPanes, pPanesPos);
2168 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) 2169 BOOL GetPaneTipText(
int nPaneID, LPTSTR lpstrText,
int nSize)
const 2171 ATLASSERT(::IsWindow(m_hWnd));
2172 int nIndex = GetPaneIndexFromID(nPaneID);
2176 GetTipText(nIndex, lpstrText, nSize);
2180 BOOL SetPaneTipText(
int nPaneID, LPCTSTR lpstrText)
2182 ATLASSERT(::IsWindow(m_hWnd));
2183 int nIndex = GetPaneIndexFromID(nPaneID);
2187 SetTipText(nIndex, lpstrText);
2190 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) 2192 #if ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500)) 2193 BOOL GetPaneIcon(
int nPaneID, HICON& hIcon)
const 2195 ATLASSERT(::IsWindow(m_hWnd));
2196 int nIndex = GetPaneIndexFromID(nPaneID);
2200 hIcon = GetIcon(nIndex);
2204 BOOL SetPaneIcon(
int nPaneID, HICON hIcon)
2206 ATLASSERT(::IsWindow(m_hWnd));
2207 int nIndex = GetPaneIndexFromID(nPaneID);
2211 return SetIcon(nIndex, hIcon);
2213 #endif // ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500)) 2217 MESSAGE_HANDLER(WM_SIZE, OnSize)
2220 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
2222 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
2223 if(wParam != SIZE_MINIMIZED && m_nPanes > 0)
2225 T* pT =
static_cast<T*
>(
this);
2226 pT->UpdatePanesLayout();
2232 BOOL UpdatePanesLayout()
2236 int* pPanesPos = buff.Allocate(m_nPanes);
2237 ATLASSERT(pPanesPos != NULL);
2238 if(pPanesPos == NULL)
2240 int nRet = GetParts(m_nPanes, pPanesPos);
2241 ATLASSERT(nRet == m_nPanes);
2242 if(nRet != m_nPanes)
2245 RECT rcClient = { 0 };
2246 GetClientRect(&rcClient);
2247 int cxOff = rcClient.right - pPanesPos[m_nPanes - 1];
2250 if((GetStyle() & SBARS_SIZEGRIP) != 0)
2251 cxOff -= ::GetSystemMetrics(SM_CXVSCROLL) + ::GetSystemMetrics(SM_CXEDGE);
2252 #endif // !_WIN32_WCE 2255 for(i = 0; i < m_nPanes; i++)
2257 if(m_pPane[i] == ID_DEFAULT_PANE)
2261 if((i < m_nPanes) && (pPanesPos[i] + cxOff) > ((i == 0) ? 0 : pPanesPos[i - 1]))
2263 for(; i < m_nPanes; i++)
2264 pPanesPos[i] += cxOff;
2267 return SetParts(m_nPanes, pPanesPos);
2270 int GetPaneIndexFromID(
int nPaneID)
const 2272 for(
int i = 0; i < m_nPanes; i++)
2274 if(m_pPane[i] == nPaneID)
2285 DECLARE_WND_SUPERCLASS(_T(
"WTL_MultiPaneStatusBar"), GetWndClassName())
2293 #define PANECNT_NOCLOSEBUTTON 0x00000001 2294 #define PANECNT_VERTICAL 0x00000002 2295 #define PANECNT_FLATBORDER 0x00000004 2296 #define PANECNT_NOBORDER 0x00000008 2297 #define PANECNT_DIVIDER 0x00000010 2298 #define PANECNT_GRADIENT 0x00000020 2302 template <
class T,
class TBase = ATL::CWindow,
class TWinTraits = ATL::CControlWinTraits>
2306 DECLARE_WND_CLASS_EX(NULL, 0, -1)
2312 m_cxyTextOffset = 4,
2321 m_cxToolBar = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder + m_cxyBtnOffset,
2323 m_xBtnImageLeft = 6,
2325 m_xBtnImageRight = 12,
2326 m_yBtnImageBottom = 11,
2328 m_nCloseBtnID = ID_PANE_CLOSE
2333 ATL::CWindow m_wndClient;
2335 TCHAR m_szTitle[m_cchTitle];
2336 DWORD m_dwExtendedStyle;
2338 bool m_bInternalFont;
2342 CPaneContainerImpl() : m_cxyHeader(0), m_dwExtendedStyle(0), m_hFont(NULL), m_bInternalFont(
false)
2348 DWORD GetPaneContainerExtendedStyle()
const 2350 return m_dwExtendedStyle;
2353 DWORD SetPaneContainerExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
2355 DWORD dwPrevStyle = m_dwExtendedStyle;
2357 m_dwExtendedStyle = dwExtendedStyle;
2359 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
2362 T* pT =
static_cast<T*
>(
this);
2363 bool bUpdate =
false;
2365 if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) != 0) && ((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0))
2367 pT->CreateCloseButton();
2370 else if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) == 0) && ((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) != 0))
2372 pT->DestroyCloseButton();
2376 if((dwPrevStyle & PANECNT_VERTICAL) != (m_dwExtendedStyle & PANECNT_VERTICAL))
2382 if((dwPrevStyle & (PANECNT_FLATBORDER | PANECNT_NOBORDER)) !=
2383 (m_dwExtendedStyle & (PANECNT_FLATBORDER | PANECNT_NOBORDER)))
2388 #if (!defined(_WIN32_WCE) && !defined(_ATL_NO_MSIMG)) || (_WIN32_WCE >= 420) 2389 if((dwPrevStyle & PANECNT_GRADIENT) != (m_dwExtendedStyle & PANECNT_GRADIENT))
2393 #endif // (!defined(_WIN32_WCE) && !defined(_ATL_NO_MSIMG)) || (_WIN32_WCE >= 420) 2401 HWND GetClient()
const 2406 HWND SetClient(HWND hWndClient)
2408 HWND hWndOldClient = m_wndClient;
2409 m_wndClient = hWndClient;
2412 T* pT =
static_cast<T*
>(
this);
2415 return hWndOldClient;
2418 BOOL GetTitle(LPTSTR lpstrTitle,
int cchLength)
const 2420 ATLASSERT(lpstrTitle != NULL);
2422 errno_t nRet = SecureHelper::strncpy_x(lpstrTitle, cchLength, m_szTitle, _TRUNCATE);
2424 return (nRet == 0 || nRet == STRUNCATE);
2427 BOOL SetTitle(LPCTSTR lpstrTitle)
2429 ATLASSERT(lpstrTitle != NULL);
2431 errno_t nRet = SecureHelper::strncpy_x(m_szTitle, m_cchTitle, lpstrTitle, _TRUNCATE);
2432 bool bRet = (nRet == 0 || nRet == STRUNCATE);
2433 if(bRet && m_hWnd != NULL)
2435 T* pT =
static_cast<T*
>(
this);
2442 int GetTitleLength()
const 2444 return lstrlen(m_szTitle);
2448 HWND Create(HWND hWndParent, LPCTSTR lpstrTitle = NULL, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
2449 DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL)
2451 if(lpstrTitle != NULL)
2452 SecureHelper::strncpy_x(m_szTitle, m_cchTitle, lpstrTitle, _TRUNCATE);
2453 #if (_MSC_VER >= 1300) 2454 return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
2455 #else // !(_MSC_VER >= 1300) 2456 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
2457 return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
2458 #endif // !(_MSC_VER >= 1300) 2461 HWND Create(HWND hWndParent, UINT uTitleID, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
2462 DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL)
2465 ::LoadString(ModuleHelper::GetResourceInstance(), uTitleID, m_szTitle, m_cchTitle);
2466 #if (_MSC_VER >= 1300) 2467 return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
2468 #else // !(_MSC_VER >= 1300) 2469 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
2470 return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
2471 #endif // !(_MSC_VER >= 1300) 2474 BOOL SubclassWindow(HWND hWnd)
2476 #if (_MSC_VER >= 1300) 2477 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
2478 #else // !(_MSC_VER >= 1300) 2479 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
2480 BOOL bRet = _baseClass::SubclassWindow(hWnd);
2481 #endif // !(_MSC_VER >= 1300) 2484 T* pT =
static_cast<T*
>(
this);
2488 GetClientRect(&rect);
2489 pT->UpdateLayout(rect.right, rect.bottom);
2495 BOOL EnableCloseButton(BOOL bEnable)
2497 ATLASSERT(::IsWindow(m_hWnd));
2498 T* pT =
static_cast<T*
>(
this);
2500 return (m_tb.m_hWnd != NULL) ? m_tb.EnableButton(pT->m_nCloseBtnID, bEnable) : FALSE;
2505 RECT rcClient = { 0 };
2506 GetClientRect(&rcClient);
2507 T* pT =
static_cast<T*
>(
this);
2508 pT->UpdateLayout(rcClient.right, rcClient.bottom);
2513 MESSAGE_HANDLER(WM_CREATE, OnCreate)
2514 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
2515 MESSAGE_HANDLER(WM_SIZE, OnSize)
2516 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
2517 MESSAGE_HANDLER(WM_GETFONT, OnGetFont)
2518 MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
2519 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
2520 MESSAGE_HANDLER(WM_PAINT, OnPaint)
2522 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
2523 #endif // !_WIN32_WCE 2524 MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
2525 MESSAGE_HANDLER(WM_COMMAND, OnCommand)
2526 FORWARD_NOTIFICATIONS()
2529 LRESULT OnCreate(UINT , WPARAM , LPARAM , BOOL& )
2531 T* pT =
static_cast<T*
>(
this);
2537 LRESULT OnDestroy(UINT , WPARAM , LPARAM , BOOL& )
2541 ::DeleteObject(m_hFont);
2543 m_bInternalFont =
false;
2549 LRESULT OnSize(UINT , WPARAM , LPARAM lParam, BOOL& )
2551 T* pT =
static_cast<T*
>(
this);
2552 pT->UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
2556 LRESULT OnSetFocus(UINT , WPARAM , LPARAM , BOOL& )
2558 if(m_wndClient.m_hWnd != NULL)
2559 m_wndClient.SetFocus();
2563 LRESULT OnGetFont(UINT , WPARAM , LPARAM , BOOL& )
2565 return (LRESULT)m_hFont;
2568 LRESULT OnSetFont(UINT , WPARAM wParam, LPARAM lParam, BOOL& )
2572 ::DeleteObject(m_hFont);
2573 m_bInternalFont =
false;
2576 m_hFont = (HFONT)wParam;
2578 T* pT =
static_cast<T*
>(
this);
2581 if((BOOL)lParam != FALSE)
2587 LRESULT OnEraseBackground(UINT , WPARAM wParam, LPARAM , BOOL& )
2589 T* pT =
static_cast<T*
>(
this);
2590 pT->DrawPaneTitleBackground((HDC)wParam);
2595 LRESULT OnPaint(UINT , WPARAM wParam, LPARAM , BOOL& )
2597 T* pT =
static_cast<T*
>(
this);
2600 pT->DrawPaneTitle((HDC)wParam);
2602 if(m_wndClient.m_hWnd == NULL)
2603 pT->DrawPane((HDC)wParam);
2608 pT->DrawPaneTitle(dc.m_hDC);
2610 if(m_wndClient.m_hWnd == NULL)
2611 pT->DrawPane(dc.m_hDC);
2617 LRESULT OnNotify(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
2619 if(m_tb.m_hWnd == NULL)
2625 T* pT =
static_cast<T*
>(
this);
2627 LPNMHDR lpnmh = (LPNMHDR)lParam;
2631 if(lpnmh->code == NM_CUSTOMDRAW && lpnmh->hwndFrom == m_tb.m_hWnd)
2636 else if(lpnmh->code == TTN_GETDISPINFO && lpnmh->idFrom == pT->m_nCloseBtnID)
2637 bHandled = pT->GetToolTipText(lpnmh);
2638 #endif // !_WIN32_WCE 2640 else if(lpnmh->hwndFrom != m_tb.m_hWnd && lpnmh->idFrom != pT->m_nCloseBtnID)
2646 LRESULT OnCommand(UINT , WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2649 if(m_tb.m_hWnd != NULL && (HWND)lParam == m_tb.m_hWnd)
2650 return ::SendMessage(GetParent(), WM_COMMAND, wParam, (LPARAM)m_hWnd);
2657 DWORD OnPrePaint(
int , LPNMCUSTOMDRAW )
2659 return CDRF_NOTIFYITEMDRAW;
2662 DWORD OnItemPrePaint(
int , LPNMCUSTOMDRAW )
2664 return CDRF_NOTIFYPOSTPAINT;
2667 DWORD OnItemPostPaint(
int , LPNMCUSTOMDRAW lpNMCustomDraw)
2670 #if (_WIN32_IE >= 0x0400) 2671 RECT& rc = lpNMCustomDraw->rc;
2672 #else // !(_WIN32_IE >= 0x0400) 2674 m_tb.GetItemRect(0, &rc);
2675 #endif // !(_WIN32_IE >= 0x0400) 2677 RECT rcImage = { m_xBtnImageLeft, m_yBtnImageTop, m_xBtnImageRight + 1, m_yBtnImageBottom + 1 };
2678 ::OffsetRect(&rcImage, rc.left, rc.top);
2679 T* pT =
static_cast<T*
>(
this);
2681 if((lpNMCustomDraw->uItemState & CDIS_DISABLED) != 0)
2683 RECT rcShadow = rcImage;
2684 ::OffsetRect(&rcShadow, 1, 1);
2686 pen1.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT));
2687 pT->DrawButtonImage(dc, rcShadow, pen1);
2689 pen2.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW));
2690 pT->DrawButtonImage(dc, rcImage, pen2);
2694 if((lpNMCustomDraw->uItemState & CDIS_SELECTED) != 0)
2695 ::OffsetRect(&rcImage, 1, 1);
2697 pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNTEXT));
2698 pT->DrawButtonImage(dc, rcImage, pen);
2701 return CDRF_DODEFAULT;
2712 ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT,
sizeof(LOGFONT), &lf, 0) != FALSE);
2714 lf.lfEscapement = 900;
2715 m_hFont = ::CreateFontIndirect(&lf);
2716 #else // CE specific 2717 m_hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
2721 lf.lfEscapement = 900;
2722 m_hFont = ::CreateFontIndirect(&lf);
2724 #endif // _WIN32_WCE 2725 m_bInternalFont =
true;
2728 T* pT =
static_cast<T*
>(
this);
2731 if((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0)
2732 pT->CreateCloseButton();
2735 void UpdateLayout(
int cxWidth,
int cyHeight)
2737 ATLASSERT(::IsWindow(m_hWnd));
2742 ::SetRect(&rect, 0, 0, m_cxyHeader, cyHeight);
2743 if(m_tb.m_hWnd != NULL)
2744 m_tb.SetWindowPos(NULL, m_cxyBorder, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
2746 if(m_wndClient.m_hWnd != NULL)
2747 m_wndClient.SetWindowPos(NULL, m_cxyHeader, 0, cxWidth - m_cxyHeader, cyHeight, SWP_NOZORDER);
2749 rect.right = cxWidth;
2753 ::SetRect(&rect, 0, 0, cxWidth, m_cxyHeader);
2754 if(m_tb.m_hWnd != NULL)
2755 m_tb.SetWindowPos(NULL, rect.right - m_cxToolBar, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
2757 if(m_wndClient.m_hWnd != NULL)
2758 m_wndClient.SetWindowPos(NULL, 0, m_cxyHeader, cxWidth, cyHeight - m_cxyHeader, SWP_NOZORDER);
2760 rect.bottom = cyHeight;
2763 InvalidateRect(&rect);
2766 void CreateCloseButton()
2768 ATLASSERT(m_tb.m_hWnd == NULL);
2770 m_tb.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NOMOVEY | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT, 0);
2771 ATLASSERT(m_tb.IsWindow());
2773 if(m_tb.m_hWnd != NULL)
2775 T* pT =
static_cast<T*
>(
this);
2778 m_tb.SetButtonStructSize();
2780 TBBUTTON tbbtn = { 0 };
2781 tbbtn.idCommand = pT->m_nCloseBtnID;
2782 tbbtn.fsState = TBSTATE_ENABLED;
2783 tbbtn.fsStyle = BTNS_BUTTON;
2784 m_tb.AddButtons(1, &tbbtn);
2786 m_tb.SetBitmapSize(m_cxImageTB, m_cyImageTB);
2787 m_tb.SetButtonSize(m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB);
2790 m_tb.SetWindowPos(NULL, m_cxyBorder + m_cxyBtnOffset, m_cxyBorder + m_cxyBtnOffset, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB + 1, SWP_NOZORDER | SWP_NOACTIVATE);
2792 m_tb.SetWindowPos(NULL, 0, 0, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB + 1, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
2796 void DestroyCloseButton()
2798 if(m_tb.m_hWnd != NULL)
2799 m_tb.DestroyWindow();
2804 T* pT =
static_cast<T*
>(
this);
2807 font = (HFONT)::GetStockObject(SYSTEM_FONT);
2809 font.GetLogFont(lf);
2812 m_cxyHeader = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder + 1;
2816 int cyFont = abs(lf.lfHeight) + m_cxyBorder + 2 * m_cxyTextOffset;
2817 int cyBtn = m_cyImageTB + m_cxyBtnAddTB + m_cxyBorder + 2 * m_cxyBtnOffset + 1;
2818 m_cxyHeader = __max(cyFont, cyBtn);
2822 HFONT GetTitleFont()
const 2828 BOOL GetToolTipText(LPNMHDR )
2832 #endif // !_WIN32_WCE 2837 GetClientRect(&rect);
2839 UINT uBorder = BF_LEFT | BF_TOP | BF_ADJUST;
2842 rect.right = rect.left + m_cxyHeader;
2843 uBorder |= BF_BOTTOM;
2847 rect.bottom = rect.top + m_cxyHeader;
2848 uBorder |= BF_RIGHT;
2851 if((m_dwExtendedStyle & PANECNT_NOBORDER) == 0)
2853 if((m_dwExtendedStyle & PANECNT_FLATBORDER) != 0)
2855 dc.DrawEdge(&rect, EDGE_ETCHED, uBorder);
2858 if((m_dwExtendedStyle & PANECNT_DIVIDER) != 0)
2860 uBorder = BF_FLAT | BF_ADJUST | (IsVertical() ? BF_RIGHT : BF_BOTTOM);
2861 dc.DrawEdge(&rect, BDR_SUNKENOUTER, uBorder);
2865 dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
2866 dc.SetBkMode(TRANSPARENT);
2867 T* pT =
static_cast<T*
>(
this);
2868 HFONT hFontOld = dc.SelectFont(pT->GetTitleFont());
2869 #if defined(_WIN32_WCE) && !defined(DT_END_ELLIPSIS) 2870 const UINT DT_END_ELLIPSIS = 0;
2871 #endif // defined(_WIN32_WCE) && !defined(DT_END_ELLIPSIS) 2875 rect.top += m_cxyTextOffset;
2876 rect.bottom -= m_cxyTextOffset;
2877 if(m_tb.m_hWnd != NULL)
2878 rect.top += m_cxToolBar;;
2880 RECT rcCalc = { rect.left, rect.bottom, rect.right, rect.top };
2881 int cxFont = dc.DrawText(m_szTitle, -1, &rcCalc, DT_TOP | DT_SINGLELINE | DT_END_ELLIPSIS | DT_CALCRECT);
2882 RECT rcText = { 0 };
2883 rcText.left = (rect.right - rect.left - cxFont) / 2;
2884 rcText.right = rcText.left + (rect.bottom - rect.top);
2885 rcText.top = rect.bottom;
2886 rcText.bottom = rect.top;
2887 dc.DrawText(m_szTitle, -1, &rcText, DT_TOP | DT_SINGLELINE | DT_END_ELLIPSIS);
2891 rect.left += m_cxyTextOffset;
2892 rect.right -= m_cxyTextOffset;
2893 if(m_tb.m_hWnd != NULL)
2894 rect.right -= m_cxToolBar;;
2896 dc.DrawText(m_szTitle, -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS);
2899 dc.SelectFont(hFontOld);
2902 void DrawPaneTitleBackground(
CDCHandle dc)
2905 GetClientRect(&rect);
2907 rect.right = m_cxyHeader;
2909 rect.bottom = m_cxyHeader;
2911 #if (!defined(_WIN32_WCE) && !defined(_ATL_NO_MSIMG)) || (_WIN32_WCE >= 420) 2912 if((m_dwExtendedStyle & PANECNT_GRADIENT) != 0)
2913 dc.GradientFillRect(rect, ::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), IsVertical());
2915 #endif // (!defined(_WIN32_WCE) && !defined(_ATL_NO_MSIMG)) || (_WIN32_WCE >= 420) 2916 dc.FillRect(&rect, COLOR_3DFACE);
2923 GetClientRect(&rect);
2925 rect.left += m_cxyHeader;
2927 rect.top += m_cxyHeader;
2928 if((GetExStyle() & WS_EX_CLIENTEDGE) == 0)
2929 dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
2930 dc.FillRect(&rect, COLOR_APPWORKSPACE);
2934 void DrawButtonImage(
CDCHandle dc, RECT& rcImage, HPEN hPen)
2936 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) 2937 HPEN hPenOld = dc.SelectPen(hPen);
2939 dc.MoveTo(rcImage.left, rcImage.top);
2940 dc.LineTo(rcImage.right, rcImage.bottom);
2941 dc.MoveTo(rcImage.left + 1, rcImage.top);
2942 dc.LineTo(rcImage.right + 1, rcImage.bottom);
2944 dc.MoveTo(rcImage.left, rcImage.bottom - 1);
2945 dc.LineTo(rcImage.right, rcImage.top - 1);
2946 dc.MoveTo(rcImage.left + 1, rcImage.bottom - 1);
2947 dc.LineTo(rcImage.right + 1, rcImage.top - 1);
2949 dc.SelectPen(hPenOld);
2950 #else // (_WIN32_WCE < 400) 2954 #endif // (_WIN32_WCE < 400) 2957 bool IsVertical()
const 2959 return ((m_dwExtendedStyle & PANECNT_VERTICAL) != 0);
2966 DECLARE_WND_CLASS_EX(_T(
"WTL_PaneContainer"), 0, -1)
2974 #define SORTLV_USESHELLBITMAPS 0x00000001 2977 #define SLVN_SORTCHANGED LVN_LAST 2992 LVCOLSORT_TEXTNOCASE,
3000 LVCOLSORT_LAST = LVCOLSORT_CUSTOM
3010 m_cchCmpTextMax = 32,
3017 m_nShellSortUpID = 133
3024 DWORD_PTR dwItemData;
3042 bool m_bSortDescending;
3046 int m_fmtOldSortCol;
3047 HBITMAP m_hbmOldSortCol;
3048 DWORD m_dwSortLVExtendedStyle;
3049 ATL::CSimpleArray<WORD> m_arrColSortType;
3050 bool m_bUseWaitCursor;
3053 m_bSortDescending(
false),
3054 m_bCommCtrl6(
false),
3057 m_hbmOldSortCol(NULL),
3058 m_dwSortLVExtendedStyle(SORTLV_USESHELLBITMAPS),
3059 m_bUseWaitCursor(
true)
3064 HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
3065 m_bCommCtrl6 = SUCCEEDED(hRet) && dwMajor >= 6;
3066 #endif // !_WIN32_WCE 3070 void SetSortColumn(
int iCol)
3072 T* pT =
static_cast<T*
>(
this);
3073 ATLASSERT(::IsWindow(pT->m_hWnd));
3075 ATLASSERT(header.m_hWnd != NULL);
3076 ATLASSERT(iCol >= -1 && iCol < m_arrColSortType.GetSize());
3078 int iOldSortCol = m_iSortColumn;
3079 m_iSortColumn = iCol;
3083 const int HDF_SORTUP = 0x0400;
3084 #endif // HDF_SORTUP 3085 #ifndef HDF_SORTDOWN 3086 const int HDF_SORTDOWN = 0x0200;
3087 #endif // HDF_SORTDOWN 3088 const int nMask = HDF_SORTUP | HDF_SORTDOWN;
3089 HDITEM hditem = { HDI_FORMAT };
3090 if(iOldSortCol != iCol && iOldSortCol >= 0 && header.GetItem(iOldSortCol, &hditem))
3092 hditem.fmt &= ~nMask;
3093 header.SetItem(iOldSortCol, &hditem);
3095 if(iCol >= 0 && header.GetItem(iCol, &hditem))
3097 hditem.fmt &= ~nMask;
3098 hditem.fmt |= m_bSortDescending ? HDF_SORTDOWN : HDF_SORTUP;
3099 header.SetItem(iCol, &hditem);
3104 if(m_bmSort[m_iSortUp].IsNull())
3105 pT->CreateSortBitmaps();
3108 HDITEM hditem = { HDI_BITMAP | HDI_FORMAT };
3109 if(iOldSortCol != iCol && iOldSortCol >= 0)
3111 hditem.hbm = m_hbmOldSortCol;
3112 hditem.fmt = m_fmtOldSortCol;
3113 header.SetItem(iOldSortCol, &hditem);
3117 if(iCol >= 0 && header.GetItem(iCol, &hditem))
3119 if(iOldSortCol != iCol)
3121 m_fmtOldSortCol = hditem.fmt;
3122 m_hbmOldSortCol = hditem.hbm;
3124 hditem.fmt &= ~HDF_IMAGE;
3125 hditem.fmt |= HDF_BITMAP | HDF_BITMAP_ON_RIGHT;
3126 int i = m_bSortDescending ? m_iSortDown : m_iSortUp;
3127 hditem.hbm = m_bmSort[i];
3128 header.SetItem(iCol, &hditem);
3132 int GetSortColumn()
const 3134 return m_iSortColumn;
3137 void SetColumnSortType(
int iCol, WORD wType)
3139 ATLASSERT(iCol >= 0 && iCol < m_arrColSortType.GetSize());
3140 ATLASSERT(wType >= LVCOLSORT_NONE && wType <= LVCOLSORT_LAST);
3141 m_arrColSortType[iCol] = wType;
3144 WORD GetColumnSortType(
int iCol)
const 3146 ATLASSERT((iCol >= 0) && iCol < m_arrColSortType.GetSize());
3147 return m_arrColSortType[iCol];
3150 int GetColumnCount()
const 3152 const T* pT =
static_cast<const T*
>(
this);
3153 ATLASSERT(::IsWindow(pT->m_hWnd));
3155 return header.m_hWnd != NULL ? header.GetItemCount() : 0;
3158 bool IsSortDescending()
const 3160 return m_bSortDescending;
3163 DWORD GetSortListViewExtendedStyle()
const 3165 return m_dwSortLVExtendedStyle;
3168 DWORD SetSortListViewExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
3170 DWORD dwPrevStyle = m_dwSortLVExtendedStyle;
3172 m_dwSortLVExtendedStyle = dwExtendedStyle;
3174 m_dwSortLVExtendedStyle = (m_dwSortLVExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
3179 bool DoSortItems(
int iCol,
bool bDescending =
false)
3181 T* pT =
static_cast<T*
>(
this);
3182 ATLASSERT(::IsWindow(pT->m_hWnd));
3183 ATLASSERT(iCol >= 0 && iCol < m_arrColSortType.GetSize());
3185 WORD wType = m_arrColSortType[iCol];
3186 if(wType == LVCOLSORT_NONE)
3189 int nCount = pT->GetItemCount();
3192 m_bSortDescending = bDescending;
3193 SetSortColumn(iCol);
3198 if(m_bUseWaitCursor)
3203 PFNLVCOMPARE pFunc = NULL;
3204 TCHAR pszTemp[pT->m_cchCmpTextMax] = { 0 };
3205 bool bStrValue =
false;
3209 case LVCOLSORT_TEXT:
3210 pFunc = (PFNLVCOMPARE)pT->LVCompareText;
3211 case LVCOLSORT_TEXTNOCASE:
3213 pFunc = (PFNLVCOMPARE)pT->LVCompareTextNoCase;
3214 case LVCOLSORT_CUSTOM:
3217 pFunc = (PFNLVCOMPARE)pT->LVCompareCustom;
3219 for(
int i = 0; i < nCount; i++)
3221 pParam[i].iItem = i;
3222 pParam[i].dwItemData = pT->GetItemData(i);
3223 pParam[i].pszValue =
new TCHAR[pT->m_cchCmpTextMax];
3224 pT->GetItemText(i, iCol, (LPTSTR)pParam[i].pszValue, pT->m_cchCmpTextMax);
3225 pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
3230 case LVCOLSORT_LONG:
3232 pFunc = (PFNLVCOMPARE)pT->LVCompareLong;
3233 for(
int i = 0; i < nCount; i++)
3235 pParam[i].iItem = i;
3236 pParam[i].dwItemData = pT->GetItemData(i);
3237 pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
3238 pParam[i].lValue = pT->StrToLong(pszTemp);
3239 pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
3243 case LVCOLSORT_DOUBLE:
3245 pFunc = (PFNLVCOMPARE)pT->LVCompareDouble;
3246 for(
int i = 0; i < nCount; i++)
3248 pParam[i].iItem = i;
3249 pParam[i].dwItemData = pT->GetItemData(i);
3250 pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
3251 pParam[i].dblValue = pT->StrToDouble(pszTemp);
3252 pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
3256 case LVCOLSORT_DECIMAL:
3258 pFunc = (PFNLVCOMPARE)pT->LVCompareDecimal;
3259 for(
int i = 0; i < nCount; i++)
3261 pParam[i].iItem = i;
3262 pParam[i].dwItemData = pT->GetItemData(i);
3263 pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
3264 pT->StrToDecimal(pszTemp, &pParam[i].decValue);
3265 pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
3269 case LVCOLSORT_DATETIME:
3270 case LVCOLSORT_DATE:
3271 case LVCOLSORT_TIME:
3273 pFunc = (PFNLVCOMPARE)pT->LVCompareDouble;
3274 DWORD dwFlags = LOCALE_NOUSEROVERRIDE;
3275 if(wType == LVCOLSORT_DATE)
3276 dwFlags |= VAR_DATEVALUEONLY;
3277 else if(wType == LVCOLSORT_TIME)
3278 dwFlags |= VAR_TIMEVALUEONLY;
3279 for(
int i = 0; i < nCount; i++)
3281 pParam[i].iItem = i;
3282 pParam[i].dwItemData = pT->GetItemData(i);
3283 pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
3284 pParam[i].dblValue = pT->DateStrToDouble(pszTemp, dwFlags);
3285 pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
3290 ATLTRACE2(atlTraceUI, 0, _T(
"Unknown value for sort type in CSortListViewImpl::DoSortItems()\n"));
3294 ATLASSERT(pFunc != NULL);
3296 bool bRet = ((BOOL)pT->DefWindowProc(LVM_SORTITEMS, (WPARAM)&lvsi, (LPARAM)pFunc) != FALSE);
3297 for(
int i = 0; i < nCount; i++)
3299 DWORD_PTR dwItemData = pT->GetItemData(i);
3301 ATLASSERT(p != NULL);
3303 delete [] (TCHAR*)p->pszValue;
3304 pT->SetItemData(i, p->dwItemData);
3310 m_bSortDescending = bDescending;
3311 SetSortColumn(iCol);
3314 if(m_bUseWaitCursor)
3315 waitCursor.Restore();
3320 void CreateSortBitmaps()
3322 if((m_dwSortLVExtendedStyle & SORTLV_USESHELLBITMAPS) != 0)
3325 LPCTSTR pszModule = _T(
"shell32.dll");
3326 HINSTANCE hShell = ::GetModuleHandle(pszModule);
3330 hShell = ::LoadLibrary(pszModule);
3336 bool bSuccess =
true;
3337 for(
int i = m_iSortUp; i <= m_iSortDown; i++)
3339 if(!m_bmSort[i].IsNull())
3340 m_bmSort[i].DeleteObject();
3341 m_bmSort[i] = (HBITMAP)::LoadImage(hShell, MAKEINTRESOURCE(m_nShellSortUpID + i),
3343 IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
3344 #else // CE specific 3345 IMAGE_BITMAP, 0, 0, 0);
3346 #endif // _WIN32_WCE 3347 if(m_bmSort[i].IsNull())
3354 ::FreeLibrary(hShell);
3360 T* pT =
static_cast<T*
>(
this);
3361 for(
int i = m_iSortUp; i <= m_iSortDown; i++)
3363 if(!m_bmSort[i].IsNull())
3364 m_bmSort[i].DeleteObject();
3368 dcMem.CreateCompatibleDC(dc.m_hDC);
3369 m_bmSort[i].CreateCompatibleBitmap(dc.m_hDC, m_cxSortImage, m_cySortImage);
3370 HBITMAP hbmOld = dcMem.SelectBitmap(m_bmSort[i]);
3371 RECT rc = { 0, 0, m_cxSortImage, m_cySortImage };
3372 pT->DrawSortBitmap(dcMem.m_hDC, i, &rc);
3373 dcMem.SelectBitmap(hbmOld);
3378 void NotifyParentSortChanged(
int iNewSortCol,
int iOldSortCol)
3380 T* pT =
static_cast<T*
>(
this);
3381 int nID = pT->GetDlgCtrlID();
3382 NMSORTLISTVIEW nm = { { pT->m_hWnd, (UINT_PTR)nID, SLVN_SORTCHANGED }, iNewSortCol, iOldSortCol };
3383 ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nID, (LPARAM)&nm);
3394 void DrawSortBitmap(
CDCHandle dc,
int iBitmap, LPRECT prc)
3396 dc.FillRect(prc, ::GetSysColorBrush(COLOR_BTNFACE));
3397 HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW));
3399 pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNSHADOW));
3400 HPEN hpenOld = dc.SelectPen(pen);
3401 POINT ptOrg = { (m_cxSortImage - m_cxSortArrow) / 2, (m_cySortImage - m_cySortArrow) / 2 };
3402 if(iBitmap == m_iSortUp)
3406 { ptOrg.x + m_cxSortArrow / 2, ptOrg.y },
3407 { ptOrg.x, ptOrg.y + m_cySortArrow - 1 },
3408 { ptOrg.x + m_cxSortArrow - 1, ptOrg.y + m_cySortArrow - 1 }
3416 { ptOrg.x, ptOrg.y },
3417 { ptOrg.x + m_cxSortArrow / 2, ptOrg.y + m_cySortArrow - 1 },
3418 { ptOrg.x + m_cxSortArrow - 1, ptOrg.y }
3422 dc.SelectBrush(hbrOld);
3423 dc.SelectPen(hpenOld);
3426 double DateStrToDouble(LPCTSTR lpstr, DWORD dwFlags)
3428 ATLASSERT(lpstr != NULL);
3429 if(lpstr == NULL || lpstr[0] == _T(
'\0'))
3433 HRESULT hRet = E_FAIL;
3435 if (FAILED(hRet = ::VarDateFromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, dwFlags, &dRet)))
3437 ATLTRACE2(atlTraceUI, 0, _T(
"VarDateFromStr failed with result of 0x%8.8X\n"), hRet);
3443 long StrToLong(LPCTSTR lpstr)
3445 ATLASSERT(lpstr != NULL);
3446 if(lpstr == NULL || lpstr[0] == _T(
'\0'))
3450 HRESULT hRet = E_FAIL;
3452 if (FAILED(hRet = ::VarI4FromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, &lRet)))
3454 ATLTRACE2(atlTraceUI, 0, _T(
"VarI4FromStr failed with result of 0x%8.8X\n"), hRet);
3460 double StrToDouble(LPCTSTR lpstr)
3462 ATLASSERT(lpstr != NULL);
3463 if(lpstr == NULL || lpstr[0] == _T(
'\0'))
3467 HRESULT hRet = E_FAIL;
3469 if (FAILED(hRet = ::VarR8FromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, &dblRet)))
3471 ATLTRACE2(atlTraceUI, 0, _T(
"VarR8FromStr failed with result of 0x%8.8X\n"), hRet);
3477 bool StrToDecimal(LPCTSTR lpstr, DECIMAL* pDecimal)
3479 ATLASSERT(lpstr != NULL);
3480 ATLASSERT(pDecimal != NULL);
3481 if(lpstr == NULL || pDecimal == NULL)
3485 HRESULT hRet = E_FAIL;
3486 if (FAILED(hRet = ::VarDecFromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, pDecimal)))
3488 ATLTRACE2(atlTraceUI, 0, _T(
"VarDecFromStr failed with result of 0x%8.8X\n"), hRet);
3491 pDecimal->signscale = 0;
3498 static int CALLBACK LVCompareText(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3500 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3506 int nRet = lstrcmp(pParam1->pszValue, pParam2->pszValue);
3507 return pInfo->bDescending ? -nRet : nRet;
3510 static int CALLBACK LVCompareTextNoCase(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3512 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3518 int nRet = lstrcmpi(pParam1->pszValue, pParam2->pszValue);
3519 return pInfo->bDescending ? -nRet : nRet;
3522 static int CALLBACK LVCompareLong(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3524 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3531 if(pParam1->lValue > pParam2->lValue)
3533 else if(pParam1->lValue < pParam2->lValue)
3535 return pInfo->bDescending ? -nRet : nRet;
3538 static int CALLBACK LVCompareDouble(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3540 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3547 if(pParam1->dblValue > pParam2->dblValue)
3549 else if(pParam1->dblValue < pParam2->dblValue)
3551 return pInfo->bDescending ? -nRet : nRet;
3554 static int CALLBACK LVCompareCustom(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3556 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3562 int nRet = pInfo->pT->CompareItemsCustom(pParam1, pParam2, pInfo->iSortCol);
3563 return pInfo->bDescending ? -nRet : nRet;
3567 static int CALLBACK LVCompareDecimal(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3569 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3575 int nRet = (int)::VarDecCmp(&pParam1->decValue, &pParam2->decValue);
3577 return pInfo->bDescending ? -nRet : nRet;
3581 static int CompareMantissas(
const DECIMAL& decLeft,
const DECIMAL& decRight)
3583 if (decLeft.Hi32 < decRight.Hi32)
3587 if (decLeft.Hi32 > decRight.Hi32)
3592 if (decLeft.Lo64 < decRight.Lo64)
3596 if (decLeft.Lo64 > decRight.Lo64)
3604 static HRESULT VarDecCmp(
const DECIMAL* pdecLeft,
const DECIMAL* pdecRight)
3606 static const ULONG powersOfTen[] =
3618 static const int largestPower =
sizeof(powersOfTen) /
sizeof(powersOfTen[0]);
3619 if (!pdecLeft || !pdecRight)
3626 bool bLeftZero = (!pdecLeft->Lo64 && !pdecLeft->Hi32);
3627 bool bRightZero = (!pdecRight->Lo64 && !pdecRight->Hi32);
3628 if (bLeftZero && bRightZero)
3632 bool bLeftNeg = ((pdecLeft->sign & DECIMAL_NEG) != 0);
3633 bool bRightNeg = ((pdecRight->sign & DECIMAL_NEG) != 0);
3636 return (bRightNeg ? VARCMP_GT : VARCMP_LT);
3639 if (bRightZero || bLeftNeg != bRightNeg)
3641 return (bLeftNeg ? VARCMP_LT : VARCMP_GT);
3654 bool bInvert = bLeftNeg;
3655 if (pdecLeft->scale < pdecRight->scale)
3662 pdecRight = pdecLeft;
3669 while ((comp = CompareMantissas(temp, *pdecRight)) < 0 &&
3670 temp.scale < pdecRight->scale)
3673 int scaleDiff = pdecRight->scale - temp.scale;
3674 if (scaleDiff > largestPower)
3677 scaleDiff = largestPower;
3679 DWORDLONG power = powersOfTen[scaleDiff - 1];
3681 DWORDLONG product = temp.Lo32 * power;
3682 ULONG carry =
static_cast<ULONG
>(product >> 32);
3683 temp.Lo32 =
static_cast<ULONG
>(product);
3684 product = temp.Mid32 * power + carry;
3685 carry =
static_cast<ULONG
>(product >> 32);
3686 temp.Mid32 =
static_cast<ULONG
>(product);
3687 product = temp.Hi32 * power + carry;
3688 if (static_cast<ULONG>(product >> 32))
3693 temp.Hi32 =
static_cast<ULONG
>(product);
3694 temp.scale = (BYTE)(temp.scale + scaleDiff);
3696 if (temp.scale < pdecRight->scale)
3704 return (comp > 0 ? VARCMP_GT : comp < 0 ? VARCMP_LT : VARCMP_EQ);
3707 static int CALLBACK LVCompareDecimal(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3709 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3715 int nRet = (int)VarDecCmp(&pParam1->decValue, &pParam2->decValue);
3717 return pInfo->bDescending ? -nRet : nRet;
3719 #endif // !_WIN32_WCE 3722 MESSAGE_HANDLER(LVM_INSERTCOLUMN, OnInsertColumn)
3723 MESSAGE_HANDLER(LVM_DELETECOLUMN, OnDeleteColumn)
3724 NOTIFY_CODE_HANDLER(HDN_ITEMCLICKA, OnHeaderItemClick)
3725 NOTIFY_CODE_HANDLER(HDN_ITEMCLICKW, OnHeaderItemClick)
3726 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
3729 LRESULT OnInsertColumn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
3731 T* pT =
static_cast<T*
>(
this);
3732 LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam);
3737 m_arrColSortType.Add(wType);
3738 int nCount = m_arrColSortType.GetSize();
3739 ATLASSERT(nCount == GetColumnCount());
3741 for(
int i = nCount - 1; i > lRet; i--)
3742 m_arrColSortType[i] = m_arrColSortType[i - 1];
3743 m_arrColSortType[(int)lRet] = LVCOLSORT_TEXT;
3745 if(lRet <= m_iSortColumn)
3751 LRESULT OnDeleteColumn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
3753 T* pT =
static_cast<T*
>(
this);
3754 LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam);
3758 int iCol = (int)wParam;
3759 if(m_iSortColumn == iCol)
3761 else if(m_iSortColumn > iCol)
3763 m_arrColSortType.RemoveAt(iCol);
3768 LRESULT OnHeaderItemClick(
int , LPNMHDR pnmh, BOOL& bHandled)
3770 LPNMHEADER p = (LPNMHEADER)pnmh;
3773 int iOld = m_iSortColumn;
3774 bool bDescending = (m_iSortColumn == p->iItem) ? !m_bSortDescending :
false;
3775 if(DoSortItems(p->iItem, bDescending))
3776 NotifyParentSortChanged(p->iItem, iOld);
3782 LRESULT OnSettingChange(UINT , WPARAM wParam, LPARAM , BOOL& bHandled)
3785 if(wParam == SPI_SETNONCLIENTMETRICS)
3786 GetSystemSettings();
3787 #else // CE specific 3789 GetSystemSettings();
3790 #endif // _WIN32_WCE 3795 void GetSystemSettings()
3797 if(!m_bCommCtrl6 && !m_bmSort[m_iSortUp].IsNull())
3799 T* pT =
static_cast<T*
>(
this);
3800 pT->CreateSortBitmaps();
3801 if(m_iSortColumn != -1)
3802 SetSortColumn(m_iSortColumn);
3809 typedef ATL::CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | LVS_REPORT | LVS_SHOWSELALWAYS , WS_EX_CLIENTEDGE> CSortListViewCtrlTraits;
3811 template <
class T,
class TBase = CListViewCtrl,
class TWinTraits = CSortListViewCtrlTraits>
3815 DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
3817 bool SortItems(
int iCol,
bool bDescending =
false)
3819 return DoSortItems(iCol, bDescending);
3834 DECLARE_WND_SUPERCLASS(_T(
"WTL_SortListViewCtrl"), GetWndClassName())
3842 #define TBVN_PAGEACTIVATED (0U-741) 3843 #define TBVN_CONTEXTMENU (0U-742) 3855 template <
class T,
class TBase = ATL::CWindow,
class TWinTraits = ATL::CControlWinTraits>
3856 class ATL_NO_VTABLE
CTabViewImpl :
public ATL::CWindowImpl< T, TBase, TWinTraits >
3859 DECLARE_WND_CLASS_EX(NULL, 0, COLOR_APPWORKSPACE)
3871 TCITEMHEADER tciheader;
3874 operator LPTCITEM() {
return (LPTCITEM)
this; }
3882 m_nMenuItemsMax = (ID_WINDOW_TABLAST - ID_WINDOW_TABFIRST + 1)
3886 ATL::CContainedWindowT<CTabCtrl> m_tab;
3892 POINT m_ptStartDrag;
3896 int m_cchTabTextLength;
3898 int m_nMenuItemsCount;
3900 ATL::CWindow m_wndTitleBar;
3901 LPTSTR m_lpstrTitleBarBase;
3902 int m_cchTitleBarLength;
3906 bool m_bDestroyPageOnRemove:1;
3907 bool m_bDestroyImageList:1;
3908 bool m_bActivePageMenuItem:1;
3909 bool m_bActiveAsDefaultMenuItem:1;
3910 bool m_bEmptyMenuItem:1;
3911 bool m_bWindowsMenuItem:1;
3912 bool m_bNoTabDrag:1;
3914 bool m_bTabCapture:1;
3916 bool m_bInternalFont:1;
3924 m_cchTabTextLength(30),
3925 m_nMenuItemsCount(10),
3926 m_lpstrTitleBarBase(NULL),
3927 m_cchTitleBarLength(100),
3928 m_bDestroyPageOnRemove(
true),
3929 m_bDestroyImageList(
true),
3930 m_bActivePageMenuItem(
true),
3931 m_bActiveAsDefaultMenuItem(
false),
3932 m_bEmptyMenuItem(
false),
3933 m_bWindowsMenuItem(
false),
3934 m_bNoTabDrag(
false),
3935 m_bTabCapture(
false),
3937 m_bInternalFont(
false)
3939 m_ptStartDrag.x = 0;
3940 m_ptStartDrag.y = 0;
3945 delete [] m_lpstrTitleBarBase;
3949 BOOL PreTranslateMessage(MSG* pMsg)
3951 if(IsWindow() == FALSE)
3957 int nCount = GetPageCount();
3960 bool bControl = (::GetKeyState(VK_CONTROL) < 0);
3961 if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB) && bControl)
3965 int nPage = m_nActivePage;
3966 bool bShift = (::GetKeyState(VK_SHIFT) < 0);
3968 nPage = (nPage > 0) ? (nPage - 1) : (nCount - 1);
3970 nPage = ((nPage >= 0) && (nPage < (nCount - 1))) ? (nPage + 1) : 0;
3972 SetActivePage(nPage);
3973 T* pT =
static_cast<T*
>(
this);
3974 pT->OnPageActivated(m_nActivePage);
3984 if(m_bTabCapture && pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE)
3994 if(m_nActivePage != -1)
3995 bRet = (BOOL)::SendMessage(GetPageHWND(m_nActivePage), WM_FORWARDMSG, 0, (LPARAM)pMsg);
4002 int GetPageCount()
const 4004 ATLASSERT(::IsWindow(m_hWnd));
4005 return m_tab.GetItemCount();
4008 int GetActivePage()
const 4010 return m_nActivePage;
4013 void SetActivePage(
int nPage)
4015 ATLASSERT(::IsWindow(m_hWnd));
4016 ATLASSERT(IsValidPageIndex(nPage));
4018 T* pT =
static_cast<T*
>(
this);
4022 if(m_nActivePage != -1)
4023 ::ShowWindow(GetPageHWND(m_nActivePage), FALSE);
4024 m_nActivePage = nPage;
4025 m_tab.SetCurSel(m_nActivePage);
4026 ::ShowWindow(GetPageHWND(m_nActivePage), TRUE);
4031 RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
4033 if(::GetFocus() != m_tab.m_hWnd)
4034 ::SetFocus(GetPageHWND(m_nActivePage));
4036 pT->UpdateTitleBar();
4040 HIMAGELIST GetImageList()
const 4042 ATLASSERT(::IsWindow(m_hWnd));
4043 return m_tab.GetImageList();
4046 HIMAGELIST SetImageList(HIMAGELIST hImageList)
4048 ATLASSERT(::IsWindow(m_hWnd));
4049 return m_tab.SetImageList(hImageList);
4052 void SetWindowMenu(HMENU hMenu)
4054 ATLASSERT(::IsWindow(m_hWnd));
4058 T* pT =
static_cast<T*
>(
this);
4062 void SetTitleBarWindow(HWND hWnd)
4064 ATLASSERT(::IsWindow(m_hWnd));
4066 delete [] m_lpstrTitleBarBase;
4067 m_lpstrTitleBarBase = NULL;
4069 m_wndTitleBar = hWnd;
4073 int cchLen = m_wndTitleBar.GetWindowTextLength() + 1;
4074 ATLTRY(m_lpstrTitleBarBase =
new TCHAR[cchLen]);
4075 if(m_lpstrTitleBarBase != NULL)
4077 m_wndTitleBar.GetWindowText(m_lpstrTitleBarBase, cchLen);
4078 T* pT =
static_cast<T*
>(
this);
4079 pT->UpdateTitleBar();
4084 HWND GetPageHWND(
int nPage)
const 4086 ATLASSERT(::IsWindow(m_hWnd));
4087 ATLASSERT(IsValidPageIndex(nPage));
4090 tcix.tciheader.mask = TCIF_PARAM;
4091 m_tab.GetItem(nPage, tcix);
4093 return tcix.tvpage.hWnd;
4096 LPCTSTR GetPageTitle(
int nPage)
const 4098 ATLASSERT(::IsWindow(m_hWnd));
4099 ATLASSERT(IsValidPageIndex(nPage));
4102 tcix.tciheader.mask = TCIF_PARAM;
4103 if(m_tab.GetItem(nPage, tcix) == FALSE)
4106 return tcix.tvpage.lpstrTitle;
4109 bool SetPageTitle(
int nPage, LPCTSTR lpstrTitle)
4111 ATLASSERT(::IsWindow(m_hWnd));
4112 ATLASSERT(IsValidPageIndex(nPage));
4114 T* pT =
static_cast<T*
>(
this);
4116 int cchBuff = lstrlen(lpstrTitle) + 1;
4117 LPTSTR lpstrBuff = NULL;
4118 ATLTRY(lpstrBuff =
new TCHAR[cchBuff]);
4119 if(lpstrBuff == NULL)
4122 SecureHelper::strcpy_x(lpstrBuff, cchBuff, lpstrTitle);
4124 tcix.tciheader.mask = TCIF_PARAM;
4125 if(m_tab.GetItem(nPage, tcix) == FALSE)
4129 LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1);
4130 if(lpstrTabText == NULL)
4133 delete [] tcix.tvpage.lpstrTitle;
4135 pT->ShortenTitle(lpstrTitle, lpstrTabText, m_cchTabTextLength + 1);
4137 tcix.tciheader.mask = TCIF_TEXT | TCIF_PARAM;
4138 tcix.tciheader.pszText = lpstrTabText;
4139 tcix.tvpage.lpstrTitle = lpstrBuff;
4140 if(m_tab.SetItem(nPage, tcix) == FALSE)
4143 pT->UpdateTitleBar();
4149 LPVOID GetPageData(
int nPage)
const 4151 ATLASSERT(::IsWindow(m_hWnd));
4152 ATLASSERT(IsValidPageIndex(nPage));
4155 tcix.tciheader.mask = TCIF_PARAM;
4156 m_tab.GetItem(nPage, tcix);
4158 return tcix.tvpage.pData;
4161 LPVOID SetPageData(
int nPage, LPVOID pData)
4163 ATLASSERT(::IsWindow(m_hWnd));
4164 ATLASSERT(IsValidPageIndex(nPage));
4167 tcix.tciheader.mask = TCIF_PARAM;
4168 m_tab.GetItem(nPage, tcix);
4169 LPVOID pDataOld = tcix.tvpage.pData;
4171 tcix.tvpage.pData = pData;
4172 m_tab.SetItem(nPage, tcix);
4177 int GetPageImage(
int nPage)
const 4179 ATLASSERT(::IsWindow(m_hWnd));
4180 ATLASSERT(IsValidPageIndex(nPage));
4183 tcix.tciheader.mask = TCIF_IMAGE;
4184 m_tab.GetItem(nPage, tcix);
4186 return tcix.tciheader.iImage;
4189 int SetPageImage(
int nPage,
int nImage)
4191 ATLASSERT(::IsWindow(m_hWnd));
4192 ATLASSERT(IsValidPageIndex(nPage));
4195 tcix.tciheader.mask = TCIF_IMAGE;
4196 m_tab.GetItem(nPage, tcix);
4197 int nImageOld = tcix.tciheader.iImage;
4199 tcix.tciheader.iImage = nImage;
4200 m_tab.SetItem(nPage, tcix);
4206 bool AddPage(HWND hWndView, LPCTSTR lpstrTitle,
int nImage = -1, LPVOID pData = NULL)
4208 return InsertPage(GetPageCount(), hWndView, lpstrTitle, nImage, pData);
4211 bool InsertPage(
int nPage, HWND hWndView, LPCTSTR lpstrTitle,
int nImage = -1, LPVOID pData = NULL)
4213 ATLASSERT(::IsWindow(m_hWnd));
4214 ATLASSERT(nPage == GetPageCount() || IsValidPageIndex(nPage));
4216 T* pT =
static_cast<T*
>(
this);
4218 int cchBuff = lstrlen(lpstrTitle) + 1;
4219 LPTSTR lpstrBuff = NULL;
4220 ATLTRY(lpstrBuff =
new TCHAR[cchBuff]);
4221 if(lpstrBuff == NULL)
4224 SecureHelper::strcpy_x(lpstrBuff, cchBuff, lpstrTitle);
4227 LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1);
4228 if(lpstrTabText == NULL)
4231 pT->ShortenTitle(lpstrTitle, lpstrTabText, m_cchTabTextLength + 1);
4236 tcix.tciheader.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
4237 tcix.tciheader.pszText = lpstrTabText;
4238 tcix.tciheader.iImage = nImage;
4239 tcix.tvpage.hWnd = hWndView;
4240 tcix.tvpage.lpstrTitle = lpstrBuff;
4241 tcix.tvpage.pData = pData;
4242 int nItem = m_tab.InsertItem(nPage, tcix);
4245 delete [] lpstrBuff;
4251 if(nPage <= m_nActivePage)
4254 SetActivePage(nItem);
4255 pT->OnPageActivated(m_nActivePage);
4257 if(GetPageCount() == 1)
4258 pT->ShowTabControl(
true);
4263 RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
4268 void RemovePage(
int nPage)
4270 ATLASSERT(::IsWindow(m_hWnd));
4271 ATLASSERT(IsValidPageIndex(nPage));
4273 T* pT =
static_cast<T*
>(
this);
4277 if(GetPageCount() == 1)
4278 pT->ShowTabControl(
false);
4280 if(m_bDestroyPageOnRemove)
4281 ::DestroyWindow(GetPageHWND(nPage));
4283 ::ShowWindow(GetPageHWND(nPage), FALSE);
4284 LPTSTR lpstrTitle = (LPTSTR)GetPageTitle(nPage);
4285 delete [] lpstrTitle;
4287 ATLVERIFY(m_tab.DeleteItem(nPage) != FALSE);
4289 if(m_nActivePage == nPage)
4295 SetActivePage(nPage - 1);
4297 else if(GetPageCount() > 0)
4299 SetActivePage(nPage);
4306 pT->UpdateTitleBar();
4312 nPage = (nPage < m_nActivePage) ? (m_nActivePage - 1) : m_nActivePage;
4314 SetActivePage(nPage);
4317 pT->OnPageActivated(m_nActivePage);
4320 void RemoveAllPages()
4322 ATLASSERT(::IsWindow(m_hWnd));
4324 if(GetPageCount() == 0)
4327 T* pT =
static_cast<T*
>(
this);
4331 pT->ShowTabControl(
false);
4333 for(
int i = 0; i < GetPageCount(); i++)
4335 if(m_bDestroyPageOnRemove)
4336 ::DestroyWindow(GetPageHWND(i));
4338 ::ShowWindow(GetPageHWND(i), FALSE);
4339 LPTSTR lpstrTitle = (LPTSTR)GetPageTitle(i);
4340 delete [] lpstrTitle;
4342 m_tab.DeleteAllItems();
4345 pT->OnPageActivated(m_nActivePage);
4351 pT->UpdateTitleBar();
4355 int PageIndexFromHwnd(HWND hWnd)
const 4359 for(
int i = 0; i < GetPageCount(); i++)
4361 if(GetPageHWND(i) == hWnd)
4371 void BuildWindowMenu(HMENU hMenu,
int nMenuItemsCount = 10,
bool bEmptyMenuItem =
true,
bool bWindowsMenuItem =
true,
bool bActivePageMenuItem =
true,
bool bActiveAsDefaultMenuItem =
false)
4373 ATLASSERT(::IsWindow(m_hWnd));
4376 T* pT =
static_cast<T*
>(
this);
4382 for(nFirstPos = 0; nFirstPos < menu.GetMenuItemCount(); nFirstPos++)
4384 UINT nID = menu.GetMenuItemID(nFirstPos);
4385 if((nID >= ID_WINDOW_TABFIRST && nID <= ID_WINDOW_TABLAST) || nID == ID_WINDOW_SHOWTABLIST)
4388 #else // CE specific 4389 for(nFirstPos = 0; ; nFirstPos++)
4392 mii.fMask = MIIM_ID;
4393 BOOL bRet = menu.GetMenuItemInfo(nFirstPos, TRUE, &mii);
4396 if((mii.wID >= ID_WINDOW_TABFIRST && mii.wID <= ID_WINDOW_TABLAST) || mii.wID == ID_WINDOW_SHOWTABLIST)
4399 #endif // _WIN32_WCE 4403 while(bRet != FALSE)
4404 bRet = menu.DeleteMenu(nFirstPos, MF_BYPOSITION);
4407 int nPageCount = GetPageCount();
4408 if((bWindowsMenuItem || (nPageCount > 0)) && (nFirstPos > 0))
4411 mii.fMask = MIIM_TYPE;
4412 menu.GetMenuItemInfo(nFirstPos - 1, TRUE, &mii);
4413 if((nFirstPos <= 0) || ((mii.fType & MFT_SEPARATOR) == 0))
4415 menu.AppendMenu(MF_SEPARATOR);
4424 const int cchPrefix = 3;
4425 nMenuItemsCount = __min(__min(nPageCount, nMenuItemsCount), (
int)m_nMenuItemsMax);
4426 ATLASSERT(nMenuItemsCount < 100);
4427 if(nMenuItemsCount >= 100)
4428 nMenuItemsCount = 99;
4430 for(
int i = 0; i < nMenuItemsCount; i++)
4432 LPCTSTR lpstrTitle = GetPageTitle(i);
4433 int nLen = lstrlen(lpstrTitle);
4435 LPTSTR lpstrText = buff.Allocate(cchPrefix + nLen + 1);
4436 ATLASSERT(lpstrText != NULL);
4437 if(lpstrText != NULL)
4439 LPCTSTR lpstrFormat = (i < 9) ? _T(
"&%i %s") : _T(
"%i %s");
4440 SecureHelper::wsprintf_x(lpstrText, cchPrefix + nLen + 1, lpstrFormat, i + 1, lpstrTitle);
4441 menu.AppendMenu(MF_STRING, ID_WINDOW_TABFIRST + i, lpstrText);
4446 if(bActivePageMenuItem && (m_nActivePage != -1))
4449 if(bActiveAsDefaultMenuItem)
4451 menu.SetMenuDefaultItem((UINT)-1, TRUE);
4452 menu.SetMenuDefaultItem(nFirstPos + m_nActivePage, TRUE);
4455 #else // CE specific 4456 bActiveAsDefaultMenuItem;
4457 #endif // _WIN32_WCE 4459 menu.CheckMenuRadioItem(nFirstPos, nFirstPos + nMenuItemsCount, nFirstPos + m_nActivePage, MF_BYPOSITION);
4467 menu.AppendMenu(MF_BYPOSITION | MF_STRING, ID_WINDOW_TABFIRST, pT->GetEmptyListText());
4468 menu.EnableMenuItem(ID_WINDOW_TABFIRST, MF_GRAYED);
4472 if(!bEmptyMenuItem && !bWindowsMenuItem && (nFirstPos > 0))
4475 mii.fMask = MIIM_TYPE;
4476 menu.GetMenuItemInfo(nFirstPos - 1, TRUE, &mii);
4477 if((mii.fType & MFT_SEPARATOR) != 0)
4478 menu.DeleteMenu(nFirstPos - 1, MF_BYPOSITION);
4483 if(bWindowsMenuItem)
4484 menu.AppendMenu(MF_BYPOSITION | MF_STRING, ID_WINDOW_SHOWTABLIST, pT->GetWindowsMenuItemText());
4487 BOOL SubclassWindow(HWND hWnd)
4489 #if (_MSC_VER >= 1300) 4490 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
4491 #else // !(_MSC_VER >= 1300) 4492 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
4493 BOOL bRet = _baseClass::SubclassWindow(hWnd);
4494 #endif // !(_MSC_VER >= 1300) 4497 T* pT =
static_cast<T*
>(
this);
4498 pT->CreateTabControl();
4507 MESSAGE_HANDLER(WM_CREATE, OnCreate)
4508 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
4509 MESSAGE_HANDLER(WM_SIZE, OnSize)
4510 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
4511 MESSAGE_HANDLER(WM_GETFONT, OnGetFont)
4512 MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
4513 NOTIFY_HANDLER(m_nTabID, TCN_SELCHANGE, OnTabChanged)
4514 NOTIFY_ID_HANDLER(m_nTabID, OnTabNotification)
4516 NOTIFY_CODE_HANDLER(TTN_GETDISPINFO, OnTabGetDispInfo)
4517 #endif // !_WIN32_WCE 4518 FORWARD_NOTIFICATIONS()
4520 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnTabLButtonDown)
4521 MESSAGE_HANDLER(WM_LBUTTONUP, OnTabLButtonUp)
4522 MESSAGE_HANDLER(WM_CAPTURECHANGED, OnTabCaptureChanged)
4523 MESSAGE_HANDLER(WM_MOUSEMOVE, OnTabMouseMove)
4524 MESSAGE_HANDLER(WM_RBUTTONUP, OnTabRButtonUp)
4525 MESSAGE_HANDLER(WM_SYSKEYDOWN, OnTabSysKeyDown)
4528 LRESULT OnCreate(UINT , WPARAM , LPARAM , BOOL& )
4530 T* pT =
static_cast<T*
>(
this);
4531 pT->CreateTabControl();
4536 LRESULT OnDestroy(UINT , WPARAM , LPARAM , BOOL& )
4540 if(m_bDestroyImageList)
4543 if(il.m_hImageList != NULL)
4549 HFONT hFont = m_tab.GetFont();
4550 m_tab.SetFont(NULL, FALSE);
4551 ::DeleteObject(hFont);
4552 m_bInternalFont =
false;
4558 LRESULT OnSize(UINT , WPARAM , LPARAM , BOOL& )
4560 T* pT =
static_cast<T*
>(
this);
4565 LRESULT OnSetFocus(UINT , WPARAM , LPARAM , BOOL& )
4567 if(m_nActivePage != -1)
4568 ::SetFocus(GetPageHWND(m_nActivePage));
4572 LRESULT OnGetFont(UINT , WPARAM , LPARAM , BOOL& )
4574 return m_tab.SendMessage(WM_GETFONT);
4577 LRESULT OnSetFont(UINT , WPARAM wParam, LPARAM lParam, BOOL& )
4581 HFONT hFont = m_tab.GetFont();
4582 m_tab.SetFont(NULL, FALSE);
4583 ::DeleteObject(hFont);
4584 m_bInternalFont =
false;
4587 m_tab.SendMessage(WM_SETFONT, wParam, lParam);
4589 T* pT =
static_cast<T*
>(
this);
4590 m_cyTabHeight = pT->CalcTabHeight();
4592 if((BOOL)lParam != FALSE)
4598 LRESULT OnTabChanged(
int , LPNMHDR , BOOL& )
4600 SetActivePage(m_tab.GetCurSel());
4601 T* pT =
static_cast<T*
>(
this);
4602 pT->OnPageActivated(m_nActivePage);
4607 LRESULT OnTabNotification(
int , LPNMHDR , BOOL& )
4615 LRESULT OnTabGetDispInfo(
int , LPNMHDR pnmh, BOOL& bHandled)
4617 LPNMTTDISPINFO pTTDI = (LPNMTTDISPINFO)pnmh;
4618 if(pTTDI->hdr.hwndFrom == m_tab.GetTooltips())
4620 T* pT =
static_cast<T*
>(
this);
4621 pT->UpdateTooltipText(pTTDI);
4630 #endif // !_WIN32_WCE 4633 LRESULT OnTabLButtonDown(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
4635 if(!m_bNoTabDrag && (m_tab.GetItemCount() > 1))
4637 m_bTabCapture =
true;
4640 m_ptStartDrag.x = GET_X_LPARAM(lParam);
4641 m_ptStartDrag.y = GET_Y_LPARAM(lParam);
4648 LRESULT OnTabLButtonUp(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
4654 TCHITTESTINFO hti = { 0 };
4655 hti.pt.x = GET_X_LPARAM(lParam);
4656 hti.pt.y = GET_Y_LPARAM(lParam);
4657 int nItem = m_tab.HitTest(&hti);
4659 MovePage(m_nActivePage, nItem);
4669 LRESULT OnTabCaptureChanged(UINT , WPARAM , LPARAM , BOOL& bHandled)
4673 m_bTabCapture =
false;
4678 T* pT =
static_cast<T*
>(
this);
4679 pT->DrawMoveMark(-1);
4682 m_ilDrag.DragLeave(GetDesktopWindow());
4683 #endif // !_WIN32_WCE 4687 m_ilDrag.m_hImageList = NULL;
4695 LRESULT OnTabMouseMove(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
4701 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
4706 if(abs(m_ptStartDrag.x - GET_X_LPARAM(lParam)) >= ::GetSystemMetrics(SM_CXDRAG) ||
4707 abs(m_ptStartDrag.y - GET_Y_LPARAM(lParam)) >= ::GetSystemMetrics(SM_CYDRAG))
4708 #else // CE specific 4709 if(abs(m_ptStartDrag.x - GET_X_LPARAM(lParam)) >= 4 ||
4710 abs(m_ptStartDrag.y - GET_Y_LPARAM(lParam)) >= 4)
4711 #endif // _WIN32_WCE 4713 T* pT =
static_cast<T*
>(
this);
4714 pT->GenerateDragImage(m_nActivePage);
4716 int cxCursor = ::GetSystemMetrics(SM_CXCURSOR);
4717 int cyCursor = ::GetSystemMetrics(SM_CYCURSOR);
4718 m_ilDrag.BeginDrag(0, -(cxCursor / 2), -(cyCursor / 2));
4720 POINT ptEnter = m_ptStartDrag;
4721 m_tab.ClientToScreen(&ptEnter);
4722 m_ilDrag.DragEnter(GetDesktopWindow(), ptEnter);
4723 #endif // !_WIN32_WCE 4731 TCHITTESTINFO hti = { 0 };
4733 int nItem = m_tab.HitTest(&hti);
4735 T* pT =
static_cast<T*
>(
this);
4736 pT->SetMoveCursor(nItem != -1);
4738 if(m_nInsertItem != nItem)
4739 pT->DrawMoveMark(nItem);
4741 m_ilDrag.DragShowNolock((nItem != -1) ? TRUE : FALSE);
4742 m_tab.ClientToScreen(&pt);
4743 m_ilDrag.DragMove(pt);
4752 LRESULT OnTabRButtonUp(UINT , WPARAM , LPARAM lParam, BOOL& )
4754 TCHITTESTINFO hti = { 0 };
4755 hti.pt.x = GET_X_LPARAM(lParam);
4756 hti.pt.y = GET_Y_LPARAM(lParam);
4757 int nItem = m_tab.HitTest(&hti);
4760 T* pT =
static_cast<T*
>(
this);
4761 pT->OnContextMenu(nItem, hti.pt);
4767 LRESULT OnTabSysKeyDown(UINT , WPARAM wParam, LPARAM , BOOL& bHandled)
4769 bool bShift = (::GetKeyState(VK_SHIFT) < 0);
4770 if(wParam == VK_F10 && bShift)
4772 if(m_nActivePage != -1)
4775 m_tab.GetItemRect(m_nActivePage, &rect);
4776 POINT pt = { rect.left, rect.bottom };
4777 T* pT =
static_cast<T*
>(
this);
4778 pT->OnContextMenu(m_nActivePage, pt);
4790 bool IsValidPageIndex(
int nPage)
const 4792 return (nPage >= 0 && nPage < GetPageCount());
4795 bool MovePage(
int nMovePage,
int nInsertBeforePage)
4797 ATLASSERT(IsValidPageIndex(nMovePage));
4798 ATLASSERT(IsValidPageIndex(nInsertBeforePage));
4800 if(!IsValidPageIndex(nMovePage) || !IsValidPageIndex(nInsertBeforePage))
4803 if(nMovePage == nInsertBeforePage)
4807 LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1);
4808 if(lpstrTabText == NULL)
4811 tcix.tciheader.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
4812 tcix.tciheader.pszText = lpstrTabText;
4813 tcix.tciheader.cchTextMax = m_cchTabTextLength + 1;
4814 BOOL bRet = m_tab.GetItem(nMovePage, tcix);
4815 ATLASSERT(bRet != FALSE);
4819 int nInsertItem = (nInsertBeforePage > nMovePage) ? nInsertBeforePage + 1 : nInsertBeforePage;
4820 int nNewItem = m_tab.InsertItem(nInsertItem, tcix);
4821 ATLASSERT(nNewItem == nInsertItem);
4822 if(nNewItem != nInsertItem)
4824 ATLVERIFY(m_tab.DeleteItem(nNewItem));
4828 if(nMovePage > nInsertBeforePage)
4829 ATLVERIFY(m_tab.DeleteItem(nMovePage + 1) != FALSE);
4830 else if(nMovePage < nInsertBeforePage)
4831 ATLVERIFY(m_tab.DeleteItem(nMovePage) != FALSE);
4833 SetActivePage(nInsertBeforePage);
4834 T* pT =
static_cast<T*
>(
this);
4835 pT->OnPageActivated(m_nActivePage);
4841 bool CreateTabControl()
4844 m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_TOOLTIPS, 0, m_nTabID);
4845 #else // CE specific 4846 m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, m_nTabID);
4847 #endif // _WIN32_WCE 4848 ATLASSERT(m_tab.m_hWnd != NULL);
4849 if(m_tab.m_hWnd == NULL)
4852 m_tab.SetFont(AtlCreateControlFont());
4853 m_bInternalFont =
true;
4857 T* pT =
static_cast<T*
>(
this);
4858 m_cyTabHeight = pT->CalcTabHeight();
4865 int nCount = m_tab.GetItemCount();
4866 TCHAR szText[] = _T(
"NS");
4868 tcix.tciheader.mask = TCIF_TEXT;
4869 tcix.tciheader.pszText = szText;
4870 int nIndex = m_tab.InsertItem(nCount, tcix);
4872 RECT rect = { 0, 0, 1000, 1000 };
4873 m_tab.AdjustRect(FALSE, &rect);
4875 RECT rcWnd = { 0, 0, 1000, rect.top };
4876 ::AdjustWindowRectEx(&rcWnd, m_tab.GetStyle(), FALSE, m_tab.GetExStyle());
4878 int nHeight = rcWnd.bottom - rcWnd.top;
4880 m_tab.DeleteItem(nIndex);
4885 void ShowTabControl(
bool bShow)
4887 m_tab.ShowWindow(bShow ? SW_SHOWNOACTIVATE : SW_HIDE);
4888 T* pT =
static_cast<T*
>(
this);
4895 GetClientRect(&rect);
4898 if(m_tab.IsWindow() && ((m_tab.GetStyle() & WS_VISIBLE) != 0))
4900 m_tab.SetWindowPos(NULL, 0, 0, rect.right - rect.left, m_cyTabHeight, SWP_NOZORDER);
4901 cyOffset = m_cyTabHeight;
4904 if(m_nActivePage != -1)
4905 ::SetWindowPos(GetPageHWND(m_nActivePage), NULL, 0, cyOffset, rect.right - rect.left, rect.bottom - rect.top - cyOffset, SWP_NOZORDER);
4910 if(m_menu.m_hMenu != NULL)
4911 BuildWindowMenu(m_menu, m_nMenuItemsCount, m_bEmptyMenuItem, m_bWindowsMenuItem, m_bActivePageMenuItem, m_bActiveAsDefaultMenuItem);
4914 void UpdateTitleBar()
4916 if(!m_wndTitleBar.IsWindow() || m_lpstrTitleBarBase == NULL)
4919 if(m_nActivePage != -1)
4921 T* pT =
static_cast<T*
>(
this);
4922 LPCTSTR lpstrTitle = pT->GetPageTitle(m_nActivePage);
4923 LPCTSTR lpstrDivider = pT->GetTitleDividerText();
4924 int cchBuffer = m_cchTitleBarLength + lstrlen(lpstrDivider) + lstrlen(m_lpstrTitleBarBase) + 1;
4926 LPTSTR lpstrPageTitle = buff.Allocate(cchBuffer);
4927 ATLASSERT(lpstrPageTitle != NULL);
4928 if(lpstrPageTitle != NULL)
4930 pT->ShortenTitle(lpstrTitle, lpstrPageTitle, m_cchTitleBarLength + 1);
4931 SecureHelper::strcat_x(lpstrPageTitle, cchBuffer, lpstrDivider);
4932 SecureHelper::strcat_x(lpstrPageTitle, cchBuffer, m_lpstrTitleBarBase);
4936 lpstrPageTitle = m_lpstrTitleBarBase;
4939 m_wndTitleBar.SetWindowText(lpstrPageTitle);
4943 m_wndTitleBar.SetWindowText(m_lpstrTitleBarBase);
4947 void DrawMoveMark(
int nItem)
4949 T* pT =
static_cast<T*
>(
this);
4951 if(m_nInsertItem != -1)
4954 pT->GetMoveMarkRect(rect);
4955 m_tab.InvalidateRect(&rect);
4958 m_nInsertItem = nItem;
4960 if(m_nInsertItem != -1)
4965 pT->GetMoveMarkRect(rect);
4968 pen.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOWTEXT));
4970 brush.CreateSolidBrush(::GetSysColor(COLOR_WINDOWTEXT));
4972 HPEN hPenOld = dc.SelectPen(pen);
4973 HBRUSH hBrushOld = dc.SelectBrush(brush);
4977 POINT ptsTop[3] = { { x, y }, { x + m_cxMoveMark, y }, { x + (m_cxMoveMark / 2), y + m_cyMoveMark } };
4978 dc.Polygon(ptsTop, 3);
4980 y = rect.bottom - 1;
4981 POINT ptsBottom[3] = { { x, y }, { x + m_cxMoveMark, y }, { x + (m_cxMoveMark / 2), y - m_cyMoveMark } };
4982 dc.Polygon(ptsBottom, 3);
4984 dc.SelectPen(hPenOld);
4985 dc.SelectBrush(hBrushOld);
4989 void GetMoveMarkRect(RECT& rect)
const 4991 m_tab.GetClientRect(&rect);
4993 RECT rcItem = { 0 };
4994 m_tab.GetItemRect(m_nInsertItem, &rcItem);
4996 if(m_nInsertItem <= m_nActivePage)
4998 rect.left = rcItem.left - m_cxMoveMark / 2 - 1;
4999 rect.right = rcItem.left + m_cxMoveMark / 2;
5003 rect.left = rcItem.right - m_cxMoveMark / 2 - 1;
5004 rect.right = rcItem.right + m_cxMoveMark / 2;
5008 void SetMoveCursor(
bool bCanMove)
5010 ::SetCursor(::LoadCursor(NULL, bCanMove ? IDC_ARROW : IDC_NO));
5013 void GenerateDragImage(
int nItem)
5015 ATLASSERT(IsValidPageIndex(nItem));
5018 RECT rcItem = { 0 };
5019 m_tab.GetItemRect(nItem, &rcItem);
5020 ::InflateRect(&rcItem, 2, 2);
5021 #else // CE specific 5023 RECT rcItem = { 0, 0, 40, 20 };
5024 #endif // _WIN32_WCE 5026 ATLASSERT(m_ilDrag.m_hImageList == NULL);
5027 m_ilDrag.Create(rcItem.right - rcItem.left, rcItem.bottom - rcItem.top, ILC_COLORDDB | ILC_MASK, 1, 1);
5031 dcMem.CreateCompatibleDC(dc);
5032 ATLASSERT(dcMem.m_hDC != NULL);
5033 dcMem.SetViewportOrg(-rcItem.left, -rcItem.top);
5036 bmp.CreateCompatibleBitmap(dc, rcItem.right - rcItem.left, rcItem.bottom - rcItem.top);
5037 ATLASSERT(bmp.m_hBitmap != NULL);
5039 HBITMAP hBmpOld = dcMem.SelectBitmap(bmp);
5041 m_tab.SendMessage(WM_PRINTCLIENT, (WPARAM)dcMem.m_hDC);
5042 #else // CE specific 5043 dcMem.Rectangle(&rcItem);
5044 #endif // _WIN32_WCE 5045 dcMem.SelectBitmap(hBmpOld);
5047 ATLVERIFY(m_ilDrag.Add(bmp.m_hBitmap, RGB(255, 0, 255)) != -1);
5050 void ShortenTitle(LPCTSTR lpstrTitle, LPTSTR lpstrShortTitle,
int cchShortTitle)
5052 if(lstrlen(lpstrTitle) >= cchShortTitle)
5054 LPCTSTR lpstrEllipsis = _T(
"...");
5055 int cchEllipsis = lstrlen(lpstrEllipsis);
5056 SecureHelper::strncpy_x(lpstrShortTitle, cchShortTitle, lpstrTitle, cchShortTitle - cchEllipsis - 1);
5057 SecureHelper::strcat_x(lpstrShortTitle, cchShortTitle, lpstrEllipsis);
5061 SecureHelper::strcpy_x(lpstrShortTitle, cchShortTitle, lpstrTitle);
5066 void UpdateTooltipText(LPNMTTDISPINFO pTTDI)
5068 ATLASSERT(pTTDI != NULL);
5069 pTTDI->lpszText = (LPTSTR)GetPageTitle((
int)pTTDI->hdr.idFrom);
5071 #endif // !_WIN32_WCE 5074 static LPCTSTR GetEmptyListText()
5076 return _T(
"(Empty)");
5079 static LPCTSTR GetWindowsMenuItemText()
5081 return _T(
"&Windows...");
5084 static LPCTSTR GetTitleDividerText()
5090 void OnPageActivated(
int nPage)
5092 NMHDR nmhdr = { 0 };
5093 nmhdr.hwndFrom = m_hWnd;
5094 nmhdr.idFrom = nPage;
5095 nmhdr.code = TBVN_PAGEACTIVATED;
5096 ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr);
5099 void OnContextMenu(
int nPage, POINT pt)
5101 m_tab.ClientToScreen(&pt);
5104 cmi.hdr.hwndFrom = m_hWnd;
5105 cmi.hdr.idFrom = nPage;
5106 cmi.hdr.code = TBVN_CONTEXTMENU;
5108 ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&cmi);
5115 DECLARE_WND_CLASS_EX(_T(
"WTL_TabView"), 0, COLOR_APPWORKSPACE)
5120 #endif // __ATLCTRLX_H__
Definition: atlwinx.h:452
Definition: atlctrlx.h:3812
Definition: atlctrlx.h:2303
Definition: atlapp.h:1872
Definition: atlctrlx.h:3035
Definition: atlctrlx.h:1966
Definition: atlgdi.h:3386
Definition: atlctrlx.h:656
Definition: atlctrlx.h:1889
Definition: atlctrlx.h:3005
Definition: atlctrls.h:9933
Definition: atlctrlx.h:3856
Definition: atlctrlx.h:2963
Definition: atlctrlx.h:634
Definition: atlctrlx.h:1937
Definition: atlapp.h:1455
Definition: atlctrlx.h:3831
Definition: atlgdi.h:1209
Definition: atlctrlx.h:1879
Definition: atlctrlx.h:2980
Definition: atlctrlx.h:769
Definition: atlctrlx.h:3021
Definition: atlgdi.h:3362
Definition: atlctrlx.h:829
Definition: atlctrlx.h:3862
Definition: atlctrlx.h:2282
Definition: atlctrlx.h:5112