/thirdparty/wtl/atlctrlx.h
http://crashrpt.googlecode.com/ · C Header · 4978 lines · 4061 code · 711 blank · 206 comment · 941 complexity · 6edefb128a55dda12e6890062fe322aa MD5 · raw file
Large files are truncated click here to view the full file
- // Windows Template Library - WTL version 8.1
- // Copyright (C) Microsoft Corporation. All rights reserved.
- //
- // This file is a part of the Windows Template Library.
- // The use and distribution terms for this software are covered by the
- // Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
- // which can be found in the file CPL.TXT at the root of this distribution.
- // By using this software in any fashion, you are agreeing to be bound by
- // the terms of this license. You must not remove this notice, or
- // any other, from this software.
-
- #ifndef __ATLCTRLX_H__
- #define __ATLCTRLX_H__
-
- #pragma once
-
- #ifndef __ATLAPP_H__
- #error atlctrlx.h requires atlapp.h to be included first
- #endif
-
- #ifndef __ATLCTRLS_H__
- #error atlctrlx.h requires atlctrls.h to be included first
- #endif
-
- #ifndef WM_UPDATEUISTATE
- #define WM_UPDATEUISTATE 0x0128
- #endif // !WM_UPDATEUISTATE
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // Classes in this file:
- //
- // CBitmapButtonImpl<T, TBase, TWinTraits>
- // CBitmapButton
- // CCheckListViewCtrlImpl<T, TBase, TWinTraits>
- // CCheckListViewCtrl
- // CHyperLinkImpl<T, TBase, TWinTraits>
- // CHyperLink
- // CWaitCursor
- // CCustomWaitCursor
- // CMultiPaneStatusBarCtrlImpl<T, TBase>
- // CMultiPaneStatusBarCtrl
- // CPaneContainerImpl<T, TBase, TWinTraits>
- // CPaneContainer
- // CSortListViewImpl<T>
- // CSortListViewCtrlImpl<T, TBase, TWinTraits>
- // CSortListViewCtrl
- // CTabViewImpl<T, TBase, TWinTraits>
- // CTabView
-
- namespace WTL
- {
-
- ///////////////////////////////////////////////////////////////////////////////
- // CBitmapButton - bitmap button implementation
-
- #ifndef _WIN32_WCE
-
- // bitmap button extended styles
- #define BMPBTN_HOVER 0x00000001
- #define BMPBTN_AUTO3D_SINGLE 0x00000002
- #define BMPBTN_AUTO3D_DOUBLE 0x00000004
- #define BMPBTN_AUTOSIZE 0x00000008
- #define BMPBTN_SHAREIMAGELISTS 0x00000010
- #define BMPBTN_AUTOFIRE 0x00000020
-
- template <class T, class TBase = CButton, class TWinTraits = ATL::CControlWinTraits>
- class ATL_NO_VTABLE CBitmapButtonImpl : public ATL::CWindowImpl< T, TBase, TWinTraits>
- {
- public:
- DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
-
- enum
- {
- _nImageNormal = 0,
- _nImagePushed,
- _nImageFocusOrHover,
- _nImageDisabled,
-
- _nImageCount = 4,
- };
-
- enum
- {
- ID_TIMER_FIRST = 1000,
- ID_TIMER_REPEAT = 1001
- };
-
- // Bitmap button specific extended styles
- DWORD m_dwExtendedStyle;
-
- CImageList m_ImageList;
- int m_nImage[_nImageCount];
-
- CToolTipCtrl m_tip;
- LPTSTR m_lpstrToolTipText;
-
- // Internal states
- unsigned m_fMouseOver:1;
- unsigned m_fFocus:1;
- unsigned m_fPressed:1;
-
-
- // Constructor/Destructor
- CBitmapButtonImpl(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) :
- m_ImageList(hImageList), m_dwExtendedStyle(dwExtendedStyle),
- m_lpstrToolTipText(NULL),
- m_fMouseOver(0), m_fFocus(0), m_fPressed(0)
- {
- m_nImage[_nImageNormal] = -1;
- m_nImage[_nImagePushed] = -1;
- m_nImage[_nImageFocusOrHover] = -1;
- m_nImage[_nImageDisabled] = -1;
- }
-
- ~CBitmapButtonImpl()
- {
- if((m_dwExtendedStyle & BMPBTN_SHAREIMAGELISTS) == 0)
- m_ImageList.Destroy();
- delete [] m_lpstrToolTipText;
- }
-
- // overridden to provide proper initialization
- BOOL SubclassWindow(HWND hWnd)
- {
- #if (_MSC_VER >= 1300)
- BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits>::SubclassWindow(hWnd);
- #else // !(_MSC_VER >= 1300)
- typedef ATL::CWindowImpl< T, TBase, TWinTraits> _baseClass;
- BOOL bRet = _baseClass::SubclassWindow(hWnd);
- #endif // !(_MSC_VER >= 1300)
- if(bRet)
- Init();
- return bRet;
- }
-
- // Attributes
- DWORD GetBitmapButtonExtendedStyle() const
- {
- return m_dwExtendedStyle;
- }
-
- DWORD SetBitmapButtonExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
- {
- DWORD dwPrevStyle = m_dwExtendedStyle;
- if(dwMask == 0)
- m_dwExtendedStyle = dwExtendedStyle;
- else
- m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
- return dwPrevStyle;
- }
-
- HIMAGELIST GetImageList() const
- {
- return m_ImageList;
- }
-
- HIMAGELIST SetImageList(HIMAGELIST hImageList)
- {
- HIMAGELIST hImageListPrev = m_ImageList;
- m_ImageList = hImageList;
- if((m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0 && ::IsWindow(m_hWnd))
- SizeToImage();
- return hImageListPrev;
- }
-
- int GetToolTipTextLength() const
- {
- return (m_lpstrToolTipText == NULL) ? -1 : lstrlen(m_lpstrToolTipText);
- }
-
- bool GetToolTipText(LPTSTR lpstrText, int nLength) const
- {
- ATLASSERT(lpstrText != NULL);
- if(m_lpstrToolTipText == NULL)
- return false;
-
- errno_t nRet = SecureHelper::strncpy_x(lpstrText, nLength, m_lpstrToolTipText, _TRUNCATE);
-
- return (nRet == 0 || nRet == STRUNCATE);
- }
-
- bool SetToolTipText(LPCTSTR lpstrText)
- {
- if(m_lpstrToolTipText != NULL)
- {
- delete [] m_lpstrToolTipText;
- m_lpstrToolTipText = NULL;
- }
-
- if(lpstrText == NULL)
- {
- if(m_tip.IsWindow())
- m_tip.Activate(FALSE);
- return true;
- }
-
- int cchLen = lstrlen(lpstrText) + 1;
- ATLTRY(m_lpstrToolTipText = new TCHAR[cchLen]);
- if(m_lpstrToolTipText == NULL)
- return false;
-
- SecureHelper::strcpy_x(m_lpstrToolTipText, cchLen, lpstrText);
- if(m_tip.IsWindow())
- {
- m_tip.Activate(TRUE);
- m_tip.AddTool(m_hWnd, m_lpstrToolTipText);
- }
-
- return true;
- }
-
- // Operations
- void SetImages(int nNormal, int nPushed = -1, int nFocusOrHover = -1, int nDisabled = -1)
- {
- if(nNormal != -1)
- m_nImage[_nImageNormal] = nNormal;
- if(nPushed != -1)
- m_nImage[_nImagePushed] = nPushed;
- if(nFocusOrHover != -1)
- m_nImage[_nImageFocusOrHover] = nFocusOrHover;
- if(nDisabled != -1)
- m_nImage[_nImageDisabled] = nDisabled;
- }
-
- BOOL SizeToImage()
- {
- ATLASSERT(::IsWindow(m_hWnd) && m_ImageList.m_hImageList != NULL);
- int cx = 0;
- int cy = 0;
- if(!m_ImageList.GetIconSize(cx, cy))
- return FALSE;
- return ResizeClient(cx, cy);
- }
-
- // Overrideables
- void DoPaint(CDCHandle dc)
- {
- ATLASSERT(m_ImageList.m_hImageList != NULL); // image list must be set
- ATLASSERT(m_nImage[0] != -1); // main bitmap must be set
-
- // set bitmap according to the current button state
- int nImage = -1;
- bool bHover = IsHoverMode();
- if(!IsWindowEnabled())
- nImage = m_nImage[_nImageDisabled];
- else if(m_fPressed == 1)
- nImage = m_nImage[_nImagePushed];
- else if((!bHover && m_fFocus == 1) || (bHover && m_fMouseOver == 1))
- nImage = m_nImage[_nImageFocusOrHover];
- if(nImage == -1) // not there, use default one
- nImage = m_nImage[_nImageNormal];
-
- // draw the button image
- int xyPos = 0;
- if((m_fPressed == 1) && ((m_dwExtendedStyle & (BMPBTN_AUTO3D_SINGLE | BMPBTN_AUTO3D_DOUBLE)) != 0) && (m_nImage[_nImagePushed] == -1))
- xyPos = 1;
- m_ImageList.Draw(dc, nImage, xyPos, xyPos, ILD_NORMAL);
-
- // draw 3D border if required
- if((m_dwExtendedStyle & (BMPBTN_AUTO3D_SINGLE | BMPBTN_AUTO3D_DOUBLE)) != 0)
- {
- RECT rect;
- GetClientRect(&rect);
-
- if(m_fPressed == 1)
- dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_SUNKENOUTER : EDGE_SUNKEN, BF_RECT);
- else if(!bHover || m_fMouseOver == 1)
- dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_RAISEDINNER : EDGE_RAISED, BF_RECT);
-
- if(!bHover && m_fFocus == 1)
- {
- ::InflateRect(&rect, -2 * ::GetSystemMetrics(SM_CXEDGE), -2 * ::GetSystemMetrics(SM_CYEDGE));
- dc.DrawFocusRect(&rect);
- }
- }
- }
-
- // Message map and handlers
- BEGIN_MSG_MAP(CBitmapButtonImpl)
- MESSAGE_HANDLER(WM_CREATE, OnCreate)
- MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
- MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
- MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
- MESSAGE_HANDLER(WM_PAINT, OnPaint)
- MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
- MESSAGE_HANDLER(WM_SETFOCUS, OnFocus)
- MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus)
- MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
- MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClk)
- MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
- MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
- MESSAGE_HANDLER(WM_ENABLE, OnEnable)
- MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
- MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
- MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
- MESSAGE_HANDLER(WM_KEYUP, OnKeyUp)
- MESSAGE_HANDLER(WM_TIMER, OnTimer)
- MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState)
- END_MSG_MAP()
-
- LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
- {
- Init();
- bHandled = FALSE;
- return 1;
- }
-
- LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
- {
- if(m_tip.IsWindow())
- {
- m_tip.DestroyWindow();
- m_tip.m_hWnd = NULL;
- }
- bHandled = FALSE;
- return 1;
- }
-
- LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
- {
- MSG msg = { m_hWnd, uMsg, wParam, lParam };
- if(m_tip.IsWindow())
- m_tip.RelayEvent(&msg);
- bHandled = FALSE;
- return 1;
- }
-
- LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- return 1; // no background needed
- }
-
- LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- if(wParam != NULL)
- {
- pT->DoPaint((HDC)wParam);
- }
- else
- {
- CPaintDC dc(m_hWnd);
- pT->DoPaint(dc.m_hDC);
- }
- return 0;
- }
-
- LRESULT OnFocus(UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
- {
- m_fFocus = (uMsg == WM_SETFOCUS) ? 1 : 0;
- Invalidate();
- UpdateWindow();
- bHandled = FALSE;
- return 1;
- }
-
- LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
- {
- LRESULT lRet = 0;
- if(IsHoverMode())
- SetCapture();
- else
- lRet = DefWindowProc(uMsg, wParam, lParam);
- if(::GetCapture() == m_hWnd)
- {
- m_fPressed = 1;
- Invalidate();
- UpdateWindow();
- }
- if((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0)
- {
- int nElapse = 250;
- int nDelay = 0;
- if(::SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &nDelay, 0))
- nElapse += nDelay * 250; // all milli-seconds
- SetTimer(ID_TIMER_FIRST, nElapse);
- }
- return lRet;
- }
-
- LRESULT OnLButtonDblClk(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
- {
- LRESULT lRet = 0;
- if(!IsHoverMode())
- lRet = DefWindowProc(uMsg, wParam, lParam);
- if(::GetCapture() != m_hWnd)
- SetCapture();
- if(m_fPressed == 0)
- {
- m_fPressed = 1;
- Invalidate();
- UpdateWindow();
- }
- return lRet;
- }
-
- LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
- {
- LRESULT lRet = 0;
- bool bHover = IsHoverMode();
- if(!bHover)
- lRet = DefWindowProc(uMsg, wParam, lParam);
- if(::GetCapture() == m_hWnd)
- {
- if(bHover && m_fPressed == 1)
- ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
- ::ReleaseCapture();
- }
- return lRet;
- }
-
- LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
- {
- if(m_fPressed == 1)
- {
- m_fPressed = 0;
- Invalidate();
- UpdateWindow();
- }
- bHandled = FALSE;
- return 1;
- }
-
- LRESULT OnEnable(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
- {
- Invalidate();
- UpdateWindow();
- bHandled = FALSE;
- return 1;
- }
-
- LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
- {
- if(::GetCapture() == m_hWnd)
- {
- POINT ptCursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- ClientToScreen(&ptCursor);
- RECT rect = { 0 };
- GetWindowRect(&rect);
- unsigned int uPressed = ::PtInRect(&rect, ptCursor) ? 1 : 0;
- if(m_fPressed != uPressed)
- {
- m_fPressed = uPressed;
- Invalidate();
- UpdateWindow();
- }
- }
- else if(IsHoverMode() && m_fMouseOver == 0)
- {
- m_fMouseOver = 1;
- Invalidate();
- UpdateWindow();
- StartTrackMouseLeave();
- }
- bHandled = FALSE;
- return 1;
- }
-
- LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- if(m_fMouseOver == 1)
- {
- m_fMouseOver = 0;
- Invalidate();
- UpdateWindow();
- }
- return 0;
- }
-
- LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
- {
- if(wParam == VK_SPACE && IsHoverMode())
- return 0; // ignore if in hover mode
- if(wParam == VK_SPACE && m_fPressed == 0)
- {
- m_fPressed = 1;
- Invalidate();
- UpdateWindow();
- }
- bHandled = FALSE;
- return 1;
- }
-
- LRESULT OnKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
- {
- if(wParam == VK_SPACE && IsHoverMode())
- return 0; // ignore if in hover mode
- if(wParam == VK_SPACE && m_fPressed == 1)
- {
- m_fPressed = 0;
- Invalidate();
- UpdateWindow();
- }
- bHandled = FALSE;
- return 1;
- }
-
- LRESULT OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- ATLASSERT((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0);
- switch(wParam) // timer ID
- {
- case ID_TIMER_FIRST:
- KillTimer(ID_TIMER_FIRST);
- if(m_fPressed == 1)
- {
- ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
- int nElapse = 250;
- int nRepeat = 40;
- if(::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &nRepeat, 0))
- nElapse = 10000 / (10 * nRepeat + 25); // milli-seconds, approximated
- SetTimer(ID_TIMER_REPEAT, nElapse);
- }
- break;
- case ID_TIMER_REPEAT:
- if(m_fPressed == 1)
- ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
- else if(::GetCapture() != m_hWnd)
- KillTimer(ID_TIMER_REPEAT);
- break;
- default: // not our timer
- break;
- }
- return 0;
- }
-
- LRESULT OnUpdateUiState(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- // If the control is subclassed or superclassed, this message can cause
- // repainting without WM_PAINT. We don't use this state, so just do nothing.
- return 0;
- }
-
- // Implementation
- void Init()
- {
- // We need this style to prevent Windows from painting the button
- ModifyStyle(0, BS_OWNERDRAW);
-
- // create a tool tip
- m_tip.Create(m_hWnd);
- ATLASSERT(m_tip.IsWindow());
- if(m_tip.IsWindow() && m_lpstrToolTipText != NULL)
- {
- m_tip.Activate(TRUE);
- m_tip.AddTool(m_hWnd, m_lpstrToolTipText);
- }
-
- if(m_ImageList.m_hImageList != NULL && (m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0)
- SizeToImage();
- }
-
- BOOL StartTrackMouseLeave()
- {
- TRACKMOUSEEVENT tme = { 0 };
- tme.cbSize = sizeof(tme);
- tme.dwFlags = TME_LEAVE;
- tme.hwndTrack = m_hWnd;
- return _TrackMouseEvent(&tme);
- }
-
- bool IsHoverMode() const
- {
- return ((m_dwExtendedStyle & BMPBTN_HOVER) != 0);
- }
- };
-
- class CBitmapButton : public CBitmapButtonImpl<CBitmapButton>
- {
- public:
- DECLARE_WND_SUPERCLASS(_T("WTL_BitmapButton"), GetWndClassName())
-
- CBitmapButton(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) :
- CBitmapButtonImpl<CBitmapButton>(dwExtendedStyle, hImageList)
- { }
- };
-
- #endif // !_WIN32_WCE
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // CCheckListCtrlView - list view control with check boxes
-
- template <DWORD t_dwStyle, DWORD t_dwExStyle, DWORD t_dwExListViewStyle>
- class CCheckListViewCtrlImplTraits
- {
- public:
- static DWORD GetWndStyle(DWORD dwStyle)
- {
- return (dwStyle == 0) ? t_dwStyle : dwStyle;
- }
-
- static DWORD GetWndExStyle(DWORD dwExStyle)
- {
- return (dwExStyle == 0) ? t_dwExStyle : dwExStyle;
- }
-
- static DWORD GetExtendedLVStyle()
- {
- return t_dwExListViewStyle;
- }
- };
-
- typedef CCheckListViewCtrlImplTraits<WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT> CCheckListViewCtrlTraits;
-
- template <class T, class TBase = CListViewCtrl, class TWinTraits = CCheckListViewCtrlTraits>
- class ATL_NO_VTABLE CCheckListViewCtrlImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>
- {
- public:
- DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
-
- // Attributes
- static DWORD GetExtendedLVStyle()
- {
- return TWinTraits::GetExtendedLVStyle();
- }
-
- // Operations
- BOOL SubclassWindow(HWND hWnd)
- {
- #if (_MSC_VER >= 1300)
- BOOL bRet = ATL::CWindowImplBaseT< TBase, TWinTraits>::SubclassWindow(hWnd);
- #else // !(_MSC_VER >= 1300)
- typedef ATL::CWindowImplBaseT< TBase, TWinTraits> _baseClass;
- BOOL bRet = _baseClass::SubclassWindow(hWnd);
- #endif // !(_MSC_VER >= 1300)
- if(bRet)
- {
- T* pT = static_cast<T*>(this);
- pT;
- ATLASSERT((pT->GetExtendedLVStyle() & LVS_EX_CHECKBOXES) != 0);
- SetExtendedListViewStyle(pT->GetExtendedLVStyle());
- }
- return bRet;
- }
-
- void CheckSelectedItems(int nCurrItem)
- {
- // first check if this item is selected
- LVITEM lvi = { 0 };
- lvi.iItem = nCurrItem;
- lvi.iSubItem = 0;
- lvi.mask = LVIF_STATE;
- lvi.stateMask = LVIS_SELECTED;
- GetItem(&lvi);
- // if item is not selected, don't do anything
- if(!(lvi.state & LVIS_SELECTED))
- return;
- // new check state will be reverse of the current state,
- BOOL bCheck = !GetCheckState(nCurrItem);
- int nItem = -1;
- int nOldItem = -1;
- while((nItem = GetNextItem(nOldItem, LVNI_SELECTED)) != -1)
- {
- if(nItem != nCurrItem)
- SetCheckState(nItem, bCheck);
- nOldItem = nItem;
- }
- }
-
- // Implementation
- BEGIN_MSG_MAP(CCheckListViewCtrlImpl)
- MESSAGE_HANDLER(WM_CREATE, OnCreate)
- MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
- MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDown)
- MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
- END_MSG_MAP()
-
- LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
- {
- // first let list view control initialize everything
- LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
- T* pT = static_cast<T*>(this);
- pT;
- ATLASSERT((pT->GetExtendedLVStyle() & LVS_EX_CHECKBOXES) != 0);
- SetExtendedListViewStyle(pT->GetExtendedLVStyle());
- return lRet;
- }
-
- LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
- {
- POINT ptMsg = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- LVHITTESTINFO lvh = { 0 };
- lvh.pt = ptMsg;
- if(HitTest(&lvh) != -1 && lvh.flags == LVHT_ONITEMSTATEICON && ::GetKeyState(VK_CONTROL) >= 0)
- {
- T* pT = static_cast<T*>(this);
- pT->CheckSelectedItems(lvh.iItem);
- }
- bHandled = FALSE;
- return 1;
- }
-
- LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
- {
- if(wParam == VK_SPACE)
- {
- int nCurrItem = GetNextItem(-1, LVNI_FOCUSED);
- if(nCurrItem != -1 && ::GetKeyState(VK_CONTROL) >= 0)
- {
- T* pT = static_cast<T*>(this);
- pT->CheckSelectedItems(nCurrItem);
- }
- }
- bHandled = FALSE;
- return 1;
- }
- };
-
- class CCheckListViewCtrl : public CCheckListViewCtrlImpl<CCheckListViewCtrl>
- {
- public:
- DECLARE_WND_SUPERCLASS(_T("WTL_CheckListView"), GetWndClassName())
- };
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // CHyperLink - hyper link control implementation
-
- #if (WINVER < 0x0500) && !defined(_WIN32_WCE)
- __declspec(selectany) struct
- {
- enum { cxWidth = 32, cyHeight = 32 };
- int xHotSpot;
- int yHotSpot;
- unsigned char arrANDPlane[cxWidth * cyHeight / 8];
- unsigned char arrXORPlane[cxWidth * cyHeight / 8];
- } _AtlHyperLink_CursorData =
- {
- 5, 0,
- {
- 0xF9, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF,
- 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF,
- 0xF0, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF,
- 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x7F, 0xFF,
- 0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF,
- 0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
- },
- {
- 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x06, 0xD8, 0x00, 0x00,
- 0x06, 0xDA, 0x00, 0x00, 0x06, 0xDB, 0x00, 0x00, 0x67, 0xFB, 0x00, 0x00, 0x77, 0xFF, 0x00, 0x00,
- 0x37, 0xFF, 0x00, 0x00, 0x17, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00,
- 0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00,
- 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- }
- };
- #endif // (WINVER < 0x0500) && !defined(_WIN32_WCE)
-
- #define HLINK_UNDERLINED 0x00000000
- #define HLINK_NOTUNDERLINED 0x00000001
- #define HLINK_UNDERLINEHOVER 0x00000002
- #define HLINK_COMMANDBUTTON 0x00000004
- #define HLINK_NOTIFYBUTTON 0x0000000C
- #define HLINK_USETAGS 0x00000010
- #define HLINK_USETAGSBOLD 0x00000030
- #define HLINK_NOTOOLTIP 0x00000040
- #define HLINK_AUTOCREATELINKFONT 0x00000080
- #define HLINK_SINGLELINE 0x00000100
-
- // Notes:
- // - HLINK_USETAGS and HLINK_USETAGSBOLD are always left-aligned
- // - When HLINK_USETAGSBOLD is used, the underlined styles will be ignored
-
- template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
- class ATL_NO_VTABLE CHyperLinkImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >
- {
- public:
- LPTSTR m_lpstrLabel;
- LPTSTR m_lpstrHyperLink;
-
- HCURSOR m_hCursor;
- HFONT m_hFontLink;
- HFONT m_hFontNormal;
-
- RECT m_rcLink;
- #ifndef _WIN32_WCE
- CToolTipCtrl m_tip;
- #endif // !_WIN32_WCE
-
- COLORREF m_clrLink;
- COLORREF m_clrVisited;
-
- DWORD m_dwExtendedStyle; // Hyper Link specific extended styles
-
- bool m_bPaintLabel:1;
- bool m_bVisited:1;
- bool m_bHover:1;
- bool m_bInternalLinkFont:1;
- bool m_bInternalNormalFont:1;
-
-
- // Constructor/Destructor
- CHyperLinkImpl(DWORD dwExtendedStyle = HLINK_UNDERLINED) :
- m_lpstrLabel(NULL), m_lpstrHyperLink(NULL),
- m_hCursor(NULL), m_hFontLink(NULL), m_hFontNormal(NULL),
- m_clrLink(RGB(0, 0, 255)), m_clrVisited(RGB(128, 0, 128)),
- m_dwExtendedStyle(dwExtendedStyle),
- m_bPaintLabel(true), m_bVisited(false),
- m_bHover(false), m_bInternalLinkFont(false), m_bInternalNormalFont(false)
- {
- ::SetRectEmpty(&m_rcLink);
- }
-
- ~CHyperLinkImpl()
- {
- delete [] m_lpstrLabel;
- delete [] m_lpstrHyperLink;
- #if (WINVER < 0x0500) && !defined(_WIN32_WCE)
- // It was created, not loaded, so we have to destroy it
- if(m_hCursor != NULL)
- ::DestroyCursor(m_hCursor);
- #endif // (WINVER < 0x0500) && !defined(_WIN32_WCE)
- }
-
- // Attributes
- DWORD GetHyperLinkExtendedStyle() const
- {
- return m_dwExtendedStyle;
- }
-
- DWORD SetHyperLinkExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
- {
- DWORD dwPrevStyle = m_dwExtendedStyle;
- if(dwMask == 0)
- m_dwExtendedStyle = dwExtendedStyle;
- else
- m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
- return dwPrevStyle;
- }
-
- bool GetLabel(LPTSTR lpstrBuffer, int nLength) const
- {
- if(m_lpstrLabel == NULL)
- return false;
- ATLASSERT(lpstrBuffer != NULL);
- if(nLength <= lstrlen(m_lpstrLabel))
- return false;
-
- SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrLabel);
-
- return true;
- }
-
- bool SetLabel(LPCTSTR lpstrLabel)
- {
- delete [] m_lpstrLabel;
- m_lpstrLabel = NULL;
- int cchLen = lstrlen(lpstrLabel) + 1;
- ATLTRY(m_lpstrLabel = new TCHAR[cchLen]);
- if(m_lpstrLabel == NULL)
- return false;
-
- SecureHelper::strcpy_x(m_lpstrLabel, cchLen, lpstrLabel);
- T* pT = static_cast<T*>(this);
- pT->CalcLabelRect();
-
- if(m_hWnd != NULL)
- SetWindowText(lpstrLabel); // Set this for accessibility
-
- return true;
- }
-
- bool GetHyperLink(LPTSTR lpstrBuffer, int nLength) const
- {
- if(m_lpstrHyperLink == NULL)
- return false;
- ATLASSERT(lpstrBuffer != NULL);
- if(nLength <= lstrlen(m_lpstrHyperLink))
- return false;
-
- SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrHyperLink);
-
- return true;
- }
-
- bool SetHyperLink(LPCTSTR lpstrLink)
- {
- delete [] m_lpstrHyperLink;
- m_lpstrHyperLink = NULL;
- int cchLen = lstrlen(lpstrLink) + 1;
- ATLTRY(m_lpstrHyperLink = new TCHAR[cchLen]);
- if(m_lpstrHyperLink == NULL)
- return false;
-
- SecureHelper::strcpy_x(m_lpstrHyperLink, cchLen, lpstrLink);
- if(m_lpstrLabel == NULL)
- {
- T* pT = static_cast<T*>(this);
- pT->CalcLabelRect();
- }
- #ifndef _WIN32_WCE
- if(m_tip.IsWindow())
- {
- m_tip.Activate(TRUE);
- m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1);
- }
- #endif // !_WIN32_WCE
- return true;
- }
-
- HFONT GetLinkFont() const
- {
- return m_hFontLink;
- }
-
- void SetLinkFont(HFONT hFont)
- {
- if(m_bInternalLinkFont)
- {
- ::DeleteObject(m_hFontLink);
- m_bInternalLinkFont = false;
- }
-
- m_hFontLink = hFont;
-
- T* pT = static_cast<T*>(this);
- pT->CalcLabelRect();
- }
-
- int GetIdealHeight() const
- {
- ATLASSERT(::IsWindow(m_hWnd));
- if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
- return -1;
- if(!m_bPaintLabel)
- return -1;
-
- UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
-
- CClientDC dc(m_hWnd);
- RECT rect = { 0 };
- GetClientRect(&rect);
- HFONT hFontOld = dc.SelectFont(m_hFontNormal);
- RECT rcText = rect;
- dc.DrawText(_T("NS"), -1, &rcText, DT_LEFT | uFormat | DT_CALCRECT);
- dc.SelectFont(m_hFontLink);
- RECT rcLink = rect;
- dc.DrawText(_T("NS"), -1, &rcLink, DT_LEFT | uFormat | DT_CALCRECT);
- dc.SelectFont(hFontOld);
- return max(rcText.bottom - rcText.top, rcLink.bottom - rcLink.top);
- }
-
- bool GetIdealSize(SIZE& size) const
- {
- int cx = 0, cy = 0;
- bool bRet = GetIdealSize(cx, cy);
- if(bRet)
- {
- size.cx = cx;
- size.cy = cy;
- }
- return bRet;
- }
-
- bool GetIdealSize(int& cx, int& cy) const
- {
- ATLASSERT(::IsWindow(m_hWnd));
- if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
- return false;
- if(!m_bPaintLabel)
- return false;
-
- CClientDC dc(m_hWnd);
- RECT rcClient = { 0 };
- GetClientRect(&rcClient);
- RECT rcAll = rcClient;
-
- if(IsUsingTags())
- {
- // find tags and label parts
- LPTSTR lpstrLeft = NULL;
- int cchLeft = 0;
- LPTSTR lpstrLink = NULL;
- int cchLink = 0;
- LPTSTR lpstrRight = NULL;
- int cchRight = 0;
-
- const T* pT = static_cast<const T*>(this);
- pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
-
- // get label part rects
- UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
-
- HFONT hFontOld = dc.SelectFont(m_hFontNormal);
- RECT rcLeft = rcClient;
- dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | uFormat | DT_CALCRECT);
-
- dc.SelectFont(m_hFontLink);
- RECT rcLink = { rcLeft.right, rcLeft.top, rcClient.right, rcClient.bottom };
- dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | uFormat | DT_CALCRECT);
-
- dc.SelectFont(m_hFontNormal);
- RECT rcRight = { rcLink.right, rcLink.top, rcClient.right, rcClient.bottom };
- dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | uFormat | DT_CALCRECT);
-
- dc.SelectFont(hFontOld);
-
- int cyMax = max(rcLeft.bottom, max(rcLink.bottom, rcRight.bottom));
- ::SetRect(&rcAll, rcLeft.left, rcLeft.top, rcRight.right, cyMax);
- }
- else
- {
- HFONT hOldFont = NULL;
- if(m_hFontLink != NULL)
- hOldFont = dc.SelectFont(m_hFontLink);
- LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
- DWORD dwStyle = GetStyle();
- UINT uFormat = DT_LEFT;
- if (dwStyle & SS_CENTER)
- uFormat = DT_CENTER;
- else if (dwStyle & SS_RIGHT)
- uFormat = DT_RIGHT;
- uFormat |= IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
- dc.DrawText(lpstrText, -1, &rcAll, uFormat | DT_CALCRECT);
- if(m_hFontLink != NULL)
- dc.SelectFont(hOldFont);
- if (dwStyle & SS_CENTER)
- {
- int dx = (rcClient.right - rcAll.right) / 2;
- ::OffsetRect(&rcAll, dx, 0);
- }
- else if (dwStyle & SS_RIGHT)
- {
- int dx = rcClient.right - rcAll.right;
- ::OffsetRect(&rcAll, dx, 0);
- }
- }
-
- cx = rcAll.right - rcAll.left;
- cy = rcAll.bottom - rcAll.top;
-
- return true;
- }
-
- // for command buttons only
- bool GetToolTipText(LPTSTR lpstrBuffer, int nLength) const
- {
- ATLASSERT(IsCommandButton());
- return GetHyperLink(lpstrBuffer, nLength);
- }
-
- bool SetToolTipText(LPCTSTR lpstrToolTipText)
- {
- ATLASSERT(IsCommandButton());
- return SetHyperLink(lpstrToolTipText);
- }
-
- // Operations
- BOOL SubclassWindow(HWND hWnd)
- {
- ATLASSERT(m_hWnd == NULL);
- ATLASSERT(::IsWindow(hWnd));
- if(m_hFontNormal == NULL)
- m_hFontNormal = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L);
- #if (_MSC_VER >= 1300)
- BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits>::SubclassWindow(hWnd);
- #else // !(_MSC_VER >= 1300)
- typedef ATL::CWindowImpl< T, TBase, TWinTraits> _baseClass;
- BOOL bRet = _baseClass::SubclassWindow(hWnd);
- #endif // !(_MSC_VER >= 1300)
- if(bRet)
- {
- T* pT = static_cast<T*>(this);
- pT->Init();
- }
- return bRet;
- }
-
- bool Navigate()
- {
- ATLASSERT(::IsWindow(m_hWnd));
- bool bRet = true;
- if(IsNotifyButton())
- {
- NMHDR nmhdr = { m_hWnd, GetDlgCtrlID(), NM_CLICK };
- ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr);
- }
- else if(IsCommandButton())
- {
- ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
- }
- else
- {
- ATLASSERT(m_lpstrHyperLink != NULL);
- #ifndef _WIN32_WCE
- DWORD_PTR dwRet = (DWORD_PTR)::ShellExecute(0, _T("open"), m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL);
- bRet = (dwRet > 32);
- #else // CE specific
- SHELLEXECUTEINFO shExeInfo = { sizeof(SHELLEXECUTEINFO), 0, 0, L"open", m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL, 0, 0, 0, 0, 0, 0, 0 };
- ::ShellExecuteEx(&shExeInfo);
- DWORD_PTR dwRet = (DWORD_PTR)shExeInfo.hInstApp;
- bRet = (dwRet == 0) || (dwRet > 32);
- #endif // _WIN32_WCE
- ATLASSERT(bRet);
- if(bRet)
- {
- m_bVisited = true;
- Invalidate();
- }
- }
- return bRet;
- }
-
- void CreateLinkFontFromNormal()
- {
- if(m_bInternalLinkFont)
- {
- ::DeleteObject(m_hFontLink);
- m_bInternalLinkFont = false;
- }
-
- CFontHandle font = (m_hFontNormal != NULL) ? m_hFontNormal : (HFONT)::GetStockObject(SYSTEM_FONT);
- LOGFONT lf = { 0 };
- font.GetLogFont(&lf);
-
- if(IsUsingTagsBold())
- lf.lfWeight = FW_BOLD;
- else if(!IsNotUnderlined())
- lf.lfUnderline = TRUE;
-
- m_hFontLink = ::CreateFontIndirect(&lf);
- m_bInternalLinkFont = true;
- ATLASSERT(m_hFontLink != NULL);
- }
-
- // Message map and handlers
- BEGIN_MSG_MAP(CHyperLinkImpl)
- MESSAGE_HANDLER(WM_CREATE, OnCreate)
- #ifndef _WIN32_WCE
- MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
- MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
- #endif // !_WIN32_WCE
- MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
- MESSAGE_HANDLER(WM_PAINT, OnPaint)
- #ifndef _WIN32_WCE
- MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
- #endif // !_WIN32_WCE
- MESSAGE_HANDLER(WM_SETFOCUS, OnFocus)
- MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus)
- MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
- #ifndef _WIN32_WCE
- MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
- #endif // !_WIN32_WCE
- MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
- MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
- MESSAGE_HANDLER(WM_CHAR, OnChar)
- MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
- MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
- MESSAGE_HANDLER(WM_ENABLE, OnEnable)
- MESSAGE_HANDLER(WM_GETFONT, OnGetFont)
- MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
- MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState)
- MESSAGE_HANDLER(WM_SIZE, OnSize)
- END_MSG_MAP()
-
- LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- pT->Init();
- return 0;
- }
-
- #ifndef _WIN32_WCE
- LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
- {
- if(m_tip.IsWindow())
- {
- m_tip.DestroyWindow();
- m_tip.m_hWnd = NULL;
- }
-
- if(m_bInternalLinkFont)
- {
- ::DeleteObject(m_hFontLink);
- m_hFontLink = NULL;
- m_bInternalLinkFont = false;
- }
-
- if(m_bInternalNormalFont)
- {
- ::DeleteObject(m_hFontNormal);
- m_hFontNormal = NULL;
- m_bInternalNormalFont = false;
- }
-
- bHandled = FALSE;
- return 1;
- }
-
- LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
- {
- MSG msg = { m_hWnd, uMsg, wParam, lParam };
- if(m_tip.IsWindow() && IsUsingToolTip())
- m_tip.RelayEvent(&msg);
- bHandled = FALSE;
- return 1;
- }
- #endif // !_WIN32_WCE
-
- LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- return 1; // no background painting needed (we do it all during WM_PAINT)
- }
-
- LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
- {
- if(!m_bPaintLabel)
- {
- bHandled = FALSE;
- return 1;
- }
-
- T* pT = static_cast<T*>(this);
- if(wParam != NULL)
- {
- pT->DoEraseBackground((HDC)wParam);
- pT->DoPaint((HDC)wParam);
- }
- else
- {
- CPaintDC dc(m_hWnd);
- pT->DoEraseBackground(dc.m_hDC);
- pT->DoPaint(dc.m_hDC);
- }
-
- return 0;
- }
-
- LRESULT OnFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
- {
- if(m_bPaintLabel)
- Invalidate();
- else
- bHandled = FALSE;
- return 0;
- }
-
- LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
- {
- POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt))
- {
- ::SetCursor(m_hCursor);
- if(IsUnderlineHover())
- {
- if(!m_bHover)
- {
- m_bHover = true;
- InvalidateRect(&m_rcLink);
- UpdateWindow();
- #ifndef _WIN32_WCE
- StartTrackMouseLeave();
- #endif // !_WIN32_WCE
- }
- }
- }
- else
- {
- if(IsUnderlineHover())
- {
- if(m_bHover)
- {
- m_bHover = false;
- InvalidateRect(&m_rcLink);
- UpdateWindow();
- }
- }
- bHandled = FALSE;
- }
- return 0;
- }
-
- #ifndef _WIN32_WCE
- LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- if(IsUnderlineHover() && m_bHover)
- {
- m_bHover = false;
- InvalidateRect(&m_rcLink);
- UpdateWindow();
- }
- return 0;
- }
- #endif // !_WIN32_WCE
-
- LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
- {
- POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- if(::PtInRect(&m_rcLink, pt))
- {
- SetFocus();
- SetCapture();
- }
- return 0;
- }
-
- LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
- {
- if(GetCapture() == m_hWnd)
- {
- ReleaseCapture();
- POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- if(::PtInRect(&m_rcLink, pt))
- {
- T* pT = static_cast<T*>(this);
- pT->Navigate();
- }
- }
- return 0;
- }
-
- LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- if(wParam == VK_RETURN || wParam == VK_SPACE)
- {
- T* pT = static_cast<T*>(this);
- pT->Navigate();
- }
- return 0;
- }
-
- LRESULT OnGetDlgCode(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- return DLGC_WANTCHARS;
- }
-
- LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
- {
- POINT pt = { 0, 0 };
- GetCursorPos(&pt);
- ScreenToClient(&pt);
- if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt))
- {
- return TRUE;
- }
- bHandled = FALSE;
- return FALSE;
- }
-
- LRESULT OnEnable(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- Invalidate();
- UpdateWindow();
- return 0;
- }
-
- LRESULT OnGetFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- return (LRESULT)m_hFontNormal;
- }
-
- LRESULT OnSetFont(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
- {
- if(m_bInternalNormalFont)
- {
- ::DeleteObject(m_hFontNormal);
- m_bInternalNormalFont = false;
- }
-
- bool bCreateLinkFont = m_bInternalLinkFont;
-
- m_hFontNormal = (HFONT)wParam;
-
- if(bCreateLinkFont || IsAutoCreateLinkFont())
- CreateLinkFontFromNormal();
-
- T* pT = static_cast<T*>(this);
- pT->CalcLabelRect();
-
- if((BOOL)lParam)
- {
- Invalidate();
- UpdateWindow();
- }
-
- return 0;
- }
-
- LRESULT OnUpdateUiState(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- // If the control is subclassed or superclassed, this message can cause
- // repainting without WM_PAINT. We don't use this state, so just do nothing.
- return 0;
- }
-
- LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
- {
- T* pT = static_cast<T*>(this);
- pT->CalcLabelRect();
- pT->Invalidate();
- return 0;
- }
-
- // Implementation
- void Init()
- {
- ATLASSERT(::IsWindow(m_hWnd));
-
- // Check if we should paint a label
- const int cchBuff = 8;
- TCHAR szBuffer[cchBuff] = { 0 };
- if(::GetClassName(m_hWnd, szBuffer, cchBuff))
- {
- if(lstrcmpi(szBuffer, _T("static")) == 0)
- {
- ModifyStyle(0, SS_NOTIFY); // we need this
- DWORD dwStyle = GetStyle() & 0x000000FF;
- #ifndef _WIN32_WCE
- if(dwStyle == SS_ICON || dwStyle == SS_BLACKRECT || dwStyle == SS_GRAYRECT ||
- dwStyle == SS_WHITERECT || dwStyle == SS_BLACKFRAME || dwStyle == SS_GRAYFRAME ||
- dwStyle == SS_WHITEFRAME || dwStyle == SS_OWNERDRAW ||
- dwStyle == SS_BITMAP || dwStyle == SS_ENHMETAFILE)
- #else // CE specific
- if(dwStyle == SS_ICON || dwStyle == SS_BITMAP)
- #endif // _WIN32_WCE
- m_bPaintLabel = false;
- }
- }
-
- // create or load a cursor
- #if (WINVER >= 0x0500) || defined(_WIN32_WCE)
- m_hCursor = ::LoadCursor(NULL, IDC_HAND);
- #else
- m_hCursor = ::CreateCursor(ModuleHelper::GetModuleInstance(), _AtlHyperLink_CursorData.xHotSpot, _AtlHyperLink_CursorData.yHotSpot, _AtlHyperLink_CursorData.cxWidth, _AtlHyperLink_CursorData.cyHeight, _AtlHyperLink_CursorData.arrANDPlane, _AtlHyperLink_CursorData.arrXORPlane);
- #endif
- ATLASSERT(m_hCursor != NULL);
-
- // set fonts
- if(m_bPaintLabel)
- {
- if(m_hFontNormal == NULL)
- {
- m_hFontNormal = AtlCreateControlFont();
- m_bInternalNormalFont = true;
- }
-
- if(m_hFontLink == NULL)
- CreateLinkFontFromNormal();
- }
-
- #ifndef _WIN32_WCE
- // create a tool tip
- m_tip.Create(m_hWnd);
- ATLASSERT(m_tip.IsWindow());
- #endif // !_WIN32_WCE
-
- // set label (defaults to window text)
- if(m_lpstrLabel == NULL)
- {
- int nLen = GetWindowTextLength();
- if(nLen > 0)
- {
- ATLTRY(m_lpstrLabel = new TCHAR[nLen + 1]);
- if(m_lpstrLabel != NULL)
- ATLVERIFY(GetWindowText(m_lpstrLabel, nLen + 1) > 0);
- }
- }
-
- T* pT = static_cast<T*>(this);
- pT->CalcLabelRect();
-
- // set hyperlink (defaults to label), or just activate tool tip if already set
- if(m_lpstrHyperLink == NULL && !IsCommandButton())
- {
- if(m_lpstrLabel != NULL)
- SetHyperLink(m_lpstrLabel);
- }
- #ifndef _WIN32_WCE
- else
- {
- m_tip.Activate(TRUE);
- m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1);
- }
- #endif // !_WIN32_WCE
-
- // set link colors
- if(m_bPaintLabel)
- {
- CRegKeyEx rk;
- LONG lRet = rk.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Internet Explorer\\Settings"));
- if(lRet == ERROR_SUCCESS)
- {
- const int cchValue = 12;
- TCHAR szValue[cchValue] = { 0 };
- ULONG ulCount = cchValue;
- lRet = rk.QueryStringValue(_T("Anchor Color"), szValue, &ulCount);
- if(lRet == ERROR_SUCCESS)
- {
- COLORREF clr = pT->_ParseColorString(szValue);
- ATLASSERT(clr != CLR_INVALID);
- if(clr != CLR_INVALID)
- m_clrLink = clr;
- }
-
- ulCount = cchValue;
- lRet = rk.QueryStringValue(_T("Anchor Color Visited"), szValue, &ulCount);
- if(lRet == ERROR_SUCCESS)
- {
- COLORREF clr = pT->_ParseColorString(szValue);
- ATLASSERT(clr != CLR_INVALID);
- if(clr != CLR_INVALID)
- m_clrVisited = clr;
- }
- }
- }
- }
-
- static COLORREF _ParseColorString(LPTSTR lpstr)
- {
- int c[3] = { -1, -1, -1 };
- LPTSTR p = NULL;
- for(int i = 0; i < 2; i++)
- {
- for(p = lpstr; *p != _T('\0'); p = ::CharNext(p))
- {
- if(*p == _T(','))
- {
- *p = _T('\0');
- c[i] = MinCrtHelper::_atoi(lpstr);
- lpstr = &p[1];
- break;
- }
- }
- if(c[i] == -1)
- return CLR_INVALID;
- }
- if(*lpstr == _T('\0'))
- return CLR_INVALID;
- c[2] = MinCrtHelper::_atoi(lpstr);
-
- return RGB(c[0], c[1], c[2]);
- }
-
- bool CalcLabelRect()
- {
- if(!::IsWindow(m_hWnd))
- return false;
- if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
- return false;
-
- CClientDC dc(m_hWnd);
- RECT rcClient = { 0 };
- GetClientRect(&rcClient);
- m_rcLink = rcClient;
- if(!m_bPaintLabel)
- return true;
-
- if(IsUsingTags())
- {
- // find tags and label parts
- LPTSTR lpstrLeft = NULL;
- int cchLeft = 0;
- LPTSTR lpstrLink = NULL;
- int cchLink = 0;
- LPTSTR lpstrRight = NULL;
- int cchRight = 0;
-
- T* pT = static_cast<T*>(this);
- pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
- ATLASSERT(lpstrLink != NULL);
- ATLASSERT(cchLink > 0);
-
- // get label part rects
- HFONT hFontOld = dc.SelectFont(m_hFontNormal);
-
- UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
-
- RECT rcLeft = rcClient;
- if(lpstrLeft != NULL)
- dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | uFormat | DT_CALCRECT);
-
- dc.SelectFont(m_hFontLink);
- RECT rcLink = rcClient;
- if(lpstrLeft != NULL)
- rcLink.left = rcLeft.right;
- dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | uFormat | DT_CALCRECT);
-
- dc.SelectFont(hFontOld);
-
- m_rcLink = rcLink;
- }
- else
- {
- HFONT hOldFont = NULL;
- if(m_hFontLink != NULL)
- hOldFont = dc.SelectFont(m_hFontLink);
- LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
- DWORD dwStyle = GetStyle();
- UINT uFormat = DT_LEFT;
- if (dwStyle & SS_CENTER)
- uFormat = DT_CENTER;
- else if (dwStyle & SS_RIGHT)
- uFormat = DT_RIGHT;
- uFormat |= IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
- dc.DrawText(lpstrText, -1, &m_rcLink, uFormat | DT_CALCRECT);
- if(m_hFontLink != NULL)
- dc.SelectFont(hOldFont);
- if (dwStyle & SS_CENTER)
- {
- int dx = (rcClient.right - m_rcLink.right) / 2;
- ::OffsetRect(&m_rcLink, dx, 0);
- }
- else if (dwStyle & SS_RIGHT)
- {
- int dx = rcClient.right - m_rcLink.right;
- ::OffsetRect(&m_rcLink, dx, 0);
- }
- }
-
- return true;
- }
-
- void CalcLabelParts(LPTSTR& lpstrLeft, int& cchLeft, LPTSTR& lpstrLink, int& cchLink, LPTSTR& lpstrRight, int& cchRight) const
- {
- lpstrLeft = NULL;
- cchLeft = 0;
- lpstrLink = NULL;
- cchLink = 0;
- lpstrRight = NULL;
- cchRight = 0;
-
- LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
- int cchText = lstrlen(lpstrText);
- bool bOutsideLink = true;
- for(int i = 0; i < cchText; i++)
- {
- if(lpstrText[i] != _T('<'))
- continue;
-
- if(bOutsideLink)
- {
- if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 3, _T("<A>"), 3) == CSTR_EQUAL)
- {
- if(i > 0)
- {
- lpstrLeft = lpstrText;
- cchLeft = i;
- }
- lpstrLink = &lpstrText[i + 3];
- bOutsideLink = false;
- }
- }
- else
- {
- if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 4, _T("</A>"), 4) == CSTR_EQUAL)
- {
- cchLink = i - 3 - cchLeft;
- if(lpstrText[i + 4] != 0)
- {
- lpstrRight = &lpstrText[i + 4];
- cchRight = cchText - (i + 4);
- break;
- }
- }
- }
- }
-
- }
-
- void DoEraseBackground(CDCHandle dc)
- {
- HBRUSH hBrush = (HBRUSH)::SendMessage(GetParent(), WM_CTLCOLORSTATIC, (WPARAM)dc.m_hDC, (LPARAM)m_hWnd);
- if(hBrush != NULL)
- {
- RECT rect = { 0 };
- GetClientRect(&rect);
- dc.FillRect(&rect, hBrush);
- }
- }
-
- void DoPaint(CDCHandle dc)
- {
- if(IsUsingTags())
- {
- // find tags and label parts
- LPTSTR lpstrLeft = NULL;
- int cchLeft = 0;
- LPTSTR lpstrLink = NULL;
- int cchLink = 0;
- LPTSTR lpstrRight = NULL;
- int cchRight = 0;
-
- T* pT = static_cast<T*>(this);
- pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
-
- // get label part rects
- RECT rcClient = { 0 };
- GetClientRect(&rcClient);
-
- dc.SetBkMode(TRANSPARENT);
- HFONT hFontOld = dc.SelectFont(m_hFontNormal);
-
- UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
-
- if(lpstrLeft != NULL)
- dc.DrawText(lpstrLeft, cchLeft, &rcClient, DT_LEFT | uFormat);
-
- COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT)));
- if(m_hFontLink != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover)))
- dc.SelectFont(m_hFontLink);
- else
- dc.SelectFont(m_hFontNormal);
-
- dc.DrawText(lpstrLink, cchLink, &m_rcLink, DT_LEFT | uFormat);
-
- dc.SetTextColor(clrOld);
- dc.SelectFont(m_hFontNormal);
- if(lpstrRight != NULL)
- {
- RECT rcRight = { m_rcLink.right, m_rcLink.top, rcClient.right, rcClient.bottom };
- dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | uFormat);
- }
-
- if(GetFocus() == m_hWnd)
- dc.DrawFocusRect(&m_rcLink);
-
- dc.SelectFont(hFontOld);
- }
- else
- {
- dc.SetBkMode(TRANSPARENT);
- COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT)));
-
- HFONT hFontOld = NULL;
- if(m_hFontLink != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover)))
- hFontOld = dc.SelectFont(m_hFontLink);
- else
- hFontOld = dc.SelectFont(m_hFontNormal);
-
- LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
-
- DWORD dwStyle = GetStyle();
- UINT uFormat = DT_LEFT;
- if (dwStyle & SS_CENTER)
- uFormat = DT_CENTER;
- else if (dwStyle & SS_RIGHT)
- uFormat = DT_RIGHT;
- uFormat |= IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
-
- dc.DrawText(lpstrText, -1, &m_rcLink, uFormat);
-
- if(GetFocus() == m_hWnd)
- dc.DrawFocusRect(&m_rcLink);
-
- dc.SetTextColor(clrOld);
- dc.SelectFont(hFontOld);
- }
- }
-
- #ifndef _WIN32_WCE
- BOOL StartTrackMouseLeave()
- {
- TRACKMOUSEEVENT tme = { 0 };
- tme.cbSize = sizeof(tme);
- tme.dwFlags = TME_LEAVE;
- tme.hwndTrack = m_hWnd;
- return _TrackMouseEvent(&tme);
- }
- #endif // !_WIN32_WCE
-
- // Implementation helpers
- bool IsUnderlined() const
- {
- return ((m_dwExtendedStyle & (HLINK_NOTUNDERLINED | HLINK_UNDERLINEHOVER)) == 0);
- }
-
- bool IsNotUnderlined() const
- {
- return ((m_dwExtendedStyle & HLINK_NOTUNDERLINED) != 0);
- }
-
- bool IsUnderlineHover() const
- {
- return ((m_dwExtendedStyle & HLINK_UNDERLINEHOVER) != 0);
- }
-
- bool IsCommandButton() const
- {
- return ((m_dwExtendedStyle & HLINK_COMMANDBUTTON) != 0);
- }
-
- bool IsNotifyButton() const
- {
- return ((m_dwExtendedStyle & HLINK_NOTIFYBUTTON) == HLINK_NOTIFYBUTTON);
- }
-
- bool IsUsingTags() const
- {
- return ((m_dwExtendedStyle & HLINK_USETAGS) != 0);
- }
-
- bool IsUsingTagsBold() const
- {
- return ((m_dwExtendedStyle & HLINK_USETAGSBOLD) == HLINK_USETAGSBOLD);
- }
-
- bool IsUsingToolTip() const
- {
- return ((m_dwExtendedStyle & HLINK_NOTOOLTIP) == 0);
- }
-
- bool IsAutoCreateLinkFont() const
- {
- return ((m_dwExtendedStyle & HLINK_AUTOCREATELINKFONT) == HLINK_AUTOCREATELINKFONT);
- }
-
- bool IsSingleLine() const
- {
- return ((m_dwExtendedStyle & HLINK_SINGLELINE) == HLINK_SINGLELINE);
- }
- };
-
- class CHyperLink : public CHyperLinkImpl<CHyperLink>
- {
- public:
- DECLARE_WND_CLASS(_T("WTL_HyperLink"))
- };
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // CWaitCursor - displays a wait cursor
-
- class CWaitCursor
- {
- public:
- // Data
- HCURSOR m_hWaitCursor;
- HCURSOR m_hOldCursor;
- bool m_bInUse;
-
- // Constructor/destructor
- CWaitCursor(bool bSet = true, LPCTSTR lpstrCursor = IDC_WAIT, bool bSys = true) : m_hOldCursor(NULL), m_bInUse(false)
- {
- HINSTANCE hInstance = bSys ? NULL : ModuleHelper::GetResourceInstance();
- m_hWaitCursor = ::LoadCursor(hInstance, lpstrCursor);
- ATLASSERT(m_hWaitCursor != NULL);
-
- if(bSet)
- Set();
- }
-
- ~CWaitCursor()
- {
- Restore();
- }
-
- // Methods
- bool Set()
- {
- if(m_bInUse)
- return false;
- m_hOldCursor = ::SetCursor(m_hWaitCursor);
- m_bInUse = true;
- return true;
- }
-
- bool Restore()
- {
- if(!m_bInUse)
- return false;
- ::SetCursor(m_hOldCursor);
- m_bInUse = false;
- return true;
- }
- };
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // CCustomWaitCursor - for custom and animated cursors
-
- class CCustomWaitCursor : public CWaitCursor
- {
- public:
- // Constructor/destructor
- CCustomWaitCursor(ATL::_U_STRINGorID cursor, bool bSet = true, HINSTANCE hInstance = NULL)…