You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
872 lines
18 KiB
C++
872 lines
18 KiB
C++
// XTPHeaderCtrl.cpp : implementation of the CXTPHeaderCtrl class.
|
|
//
|
|
// This file is a part of the XTREME CONTROLS MFC class library.
|
|
// (c)1998-2012 Codejock Software, All Rights Reserved.
|
|
//
|
|
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
|
|
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
|
|
// CONSENT OF CODEJOCK SOFTWARE.
|
|
//
|
|
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
|
|
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
|
|
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
|
|
// SINGLE COMPUTER.
|
|
//
|
|
// CONTACT INFORMATION:
|
|
// support@codejock.com
|
|
// http://www.codejock.com
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "Common/XTPResourceManager.h"
|
|
#include "Common/XTPColorManager.h"
|
|
#include "Common/XTPImageManager.h"
|
|
#include "../Util/XTPControlTheme.h"
|
|
#include "Common/XTPDrawHelpers.h"
|
|
|
|
#include "../Defines.h"
|
|
#include "../Resource.h"
|
|
#include "../Util/XTPGlobal.h"
|
|
#include "XTPHeaderCtrlTheme.h"
|
|
#include "XTPHeaderCtrl.h"
|
|
#include "../Util/XTPFunctions.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPHeaderCtrl
|
|
|
|
CXTPHeaderCtrl::CXTPHeaderCtrl()
|
|
: m_iMinSize(0)
|
|
, m_nPos(0)
|
|
, m_iOverIndex(-1)
|
|
, m_nSortedCol(-1)
|
|
, m_bRTL(DetermineRTL())
|
|
, m_bAutoSize(false)
|
|
, m_bEnableMenus(TRUE)
|
|
, m_bAscending(TRUE)
|
|
, m_bLBtnDown(FALSE)
|
|
, m_bPainted(FALSE)
|
|
, m_popupMenuID(0)
|
|
, m_pt(CPoint(0, 0))
|
|
, m_pTheme(NULL)
|
|
{
|
|
m_pImageManager = NULL;
|
|
VERIFY(SetTheme(xtpControlThemeDefault));
|
|
}
|
|
|
|
CXTPHeaderCtrl::~CXTPHeaderCtrl()
|
|
{
|
|
CMDTARGET_RELEASE(m_pTheme);
|
|
CMDTARGET_RELEASE(m_pImageManager);
|
|
}
|
|
|
|
void CXTPHeaderCtrl::SetImageManager(CXTPImageManager* pImageManager)
|
|
{
|
|
CMDTARGET_RELEASE(m_pImageManager);
|
|
m_pImageManager = pImageManager;
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CXTPHeaderCtrl, CHeaderCtrl)
|
|
//{{AFX_MSG_MAP(CXTPHeaderCtrl)
|
|
ON_WM_WINDOWPOSCHANGING()
|
|
ON_WM_SETCURSOR()
|
|
ON_WM_PAINT()
|
|
ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
|
|
ON_WM_ERASEBKGND()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_TIMER()
|
|
ON_WM_DESTROY()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_NOTIFY_REFLECT_EX(HDN_ITEMCHANGING, OnItemchanging)
|
|
ON_COMMAND(XTP_IDC_SORTASC, OnSortAsc)
|
|
ON_COMMAND(XTP_IDC_SORTDSC, OnSortDsc)
|
|
ON_COMMAND(XTP_IDC_ALIGNLEFT, OnAlignLeft)
|
|
ON_COMMAND(XTP_IDC_ALIGNCENTER, OnAlignCenter)
|
|
ON_COMMAND(XTP_IDC_ALIGNRIGHT, OnAlignRight)
|
|
ON_MESSAGE(HDM_LAYOUT, OnLayout)
|
|
//}}AFX_MSG_MAP
|
|
ON_MESSAGE(WM_XTP_SETCONTROLTHEME, OnSetTheme)
|
|
END_MESSAGE_MAP()
|
|
|
|
IMPLEMENT_DYNAMIC(CXTPHeaderCtrl, CHeaderCtrl)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPHeaderCtrl message handlers
|
|
|
|
void CXTPHeaderCtrl::OnThemeChanged()
|
|
{
|
|
RecalcLayout();
|
|
}
|
|
|
|
BOOL CXTPHeaderCtrl::IsThemeValid() const
|
|
{
|
|
return (m_pTheme != NULL);
|
|
}
|
|
|
|
void CXTPHeaderCtrl::ApplyFieldWidths(int iNewWidth)
|
|
{
|
|
CListCtrl* pListCtrl = (CListCtrl*)GetParent();
|
|
ASSERT_VALID(pListCtrl);
|
|
|
|
int iItemCount = GetItemCount();
|
|
int iFrozenCount = (int)m_arFrozenCols.GetCount();
|
|
int iThawedCount = iItemCount - iFrozenCount;
|
|
|
|
if (iThawedCount <= 0)
|
|
return;
|
|
|
|
int iWidth = iNewWidth/iThawedCount;
|
|
|
|
int iItem;
|
|
for (iItem = 0; iItem < iItemCount; iItem++)
|
|
{
|
|
if (IsColFrozen(iItem))
|
|
continue;
|
|
|
|
if (iWidth > m_iMinSize)
|
|
pListCtrl->SetColumnWidth(iItem, iWidth);
|
|
|
|
iNewWidth -= iWidth;
|
|
}
|
|
}
|
|
|
|
void CXTPHeaderCtrl::ResizeColumnsToFit()
|
|
{
|
|
FitFieldWidths(0);
|
|
}
|
|
|
|
void CXTPHeaderCtrl::FitFieldWidths(int iNewWidth)
|
|
{
|
|
if (iNewWidth <= 0)
|
|
{
|
|
CXTPWindowRect rc(this);
|
|
iNewWidth = rc.Width();
|
|
}
|
|
|
|
// adjust for vertical scroll bar.
|
|
DWORD dwStyle = ::GetWindowLong(::GetParent(m_hWnd), GWL_STYLE);
|
|
if ((dwStyle & WS_VSCROLL) == WS_VSCROLL)
|
|
iNewWidth -= ::GetSystemMetrics(SM_CXVSCROLL);
|
|
|
|
// adjust for frozen columns.
|
|
iNewWidth -= GetFrozenColWidth();
|
|
|
|
ApplyFieldWidths(iNewWidth);
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
|
|
{
|
|
if (m_bAutoSize)
|
|
{
|
|
int iCount = GetItemCount();
|
|
if (iCount > 0)
|
|
{
|
|
if (GetCapture() != GetParent()) // indicates scrolling
|
|
{
|
|
// is the window size changing?
|
|
CXTPWindowRect rc(this);
|
|
if (rc.Width() != lpwndpos->cx)
|
|
{
|
|
FitFieldWidths(lpwndpos->cx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CHeaderCtrl::OnWindowPosChanging(lpwndpos);
|
|
}
|
|
}
|
|
|
|
void CXTPHeaderCtrl::EnableAutoSize(bool bEnable/*=true*/)
|
|
{
|
|
m_bAutoSize = bEnable;
|
|
}
|
|
|
|
void CXTPHeaderCtrl::FreezeColumn(int iCol)
|
|
{
|
|
m_arFrozenCols.AddTail(iCol);
|
|
}
|
|
|
|
void CXTPHeaderCtrl::ThawColumn(int iCol)
|
|
{
|
|
for (POSITION pos = m_arFrozenCols.GetHeadPosition(); pos; m_arFrozenCols.GetNext(pos))
|
|
{
|
|
int iNext = m_arFrozenCols.GetAt(pos);
|
|
if (iNext == iCol)
|
|
{
|
|
m_arFrozenCols.RemoveAt(pos);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXTPHeaderCtrl::ThawAllColumns()
|
|
{
|
|
m_arFrozenCols.RemoveAll();
|
|
}
|
|
|
|
BOOL CXTPHeaderCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
{
|
|
if (m_arFrozenCols.GetCount())
|
|
{
|
|
CPoint pt;
|
|
::GetCursorPos(&pt);
|
|
|
|
CPoint ptClient = pt;
|
|
ScreenToClient(&ptClient);
|
|
|
|
HDHITTESTINFO hti;
|
|
::ZeroMemory(&hti, sizeof(hti));
|
|
hti.pt.x = ptClient.x;
|
|
hti.pt.y = ptClient.y;
|
|
|
|
int nIndex = (int)::SendMessage(GetSafeHwnd(),
|
|
HDM_HITTEST, 0L, (LPARAM)&hti);
|
|
|
|
if (nIndex > -1)
|
|
{
|
|
// if we are over one of the frozen columns, we can stop
|
|
if (IsColFrozen(nIndex))
|
|
{
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
|
|
return TRUE;
|
|
}
|
|
|
|
else
|
|
{
|
|
// determine if the current index is adjacent to a frozen column index.
|
|
// if columns are resized by dragging to the right, test for the frozen column on the left.
|
|
// if columns are resized by dragging to the left, test for the frozen column on the right.
|
|
|
|
int iAdjIndex = nIndex + (m_bRTL ? 1 : -1);
|
|
if ((iAdjIndex > -1) && IsColFrozen(iAdjIndex))
|
|
{
|
|
CRect r;
|
|
Header_GetItemRect(m_hWnd, nIndex, &r);
|
|
int nMidPoint = (r.left + (r.Width()/2));
|
|
|
|
// if columns resize to the right and the point is the right half of the header item...
|
|
if (!m_bRTL && (ptClient.x <= nMidPoint))
|
|
{
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
|
|
return TRUE;
|
|
}
|
|
|
|
// if columns resize to the left and the point is the left half of the header item...
|
|
else if (m_bRTL && (ptClient.x >= nMidPoint))
|
|
{
|
|
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return CHeaderCtrl::OnSetCursor(pWnd, nHitTest, message);
|
|
}
|
|
|
|
BOOL CXTPHeaderCtrl::OnItemchanging(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
HD_NOTIFY* pHDN = (HD_NOTIFY*)pNMHDR;
|
|
*pResult = FALSE;
|
|
|
|
if (pHDN && (pHDN->pitem->mask & HDI_WIDTH) != 0)
|
|
{
|
|
// if sizing is disabled for this column, keep the user from resizing
|
|
if (m_arFrozenCols.GetCount() && IsColFrozen(pHDN->iItem))
|
|
*pResult = TRUE;
|
|
|
|
// if the column is smaller than the minimum size, keep the user from resizing
|
|
if (pHDN->pitem->mask & HDI_WIDTH && pHDN->pitem->cxy < m_iMinSize)
|
|
*pResult = TRUE;
|
|
}
|
|
|
|
return BOOL(*pResult);
|
|
}
|
|
|
|
bool CXTPHeaderCtrl::IsColFrozen(int iCol)
|
|
{
|
|
for (POSITION pos = m_arFrozenCols.GetHeadPosition(); pos; m_arFrozenCols.GetNext(pos))
|
|
{
|
|
int iNext = m_arFrozenCols.GetAt(pos);
|
|
if (iNext == iCol)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CXTPHeaderCtrl::DetermineRTL()
|
|
{
|
|
CWindowDC dc(NULL);
|
|
|
|
// determine if columns are resized by dragging them right (most languages) or
|
|
// left (RTL languages like Arabic & Hebrew).
|
|
|
|
UINT nAlign = dc.GetTextAlign();
|
|
ASSERT(nAlign != GDI_ERROR);
|
|
|
|
// will only be true for RTL languages, text is laid out right to left and
|
|
// columns resize to the left
|
|
if ((nAlign != GDI_ERROR) && (nAlign & TA_RTLREADING))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int CXTPHeaderCtrl::GetFrozenColWidth()
|
|
{
|
|
int iFrozenWidth = 0;
|
|
|
|
for (POSITION pos = m_arFrozenCols.GetHeadPosition(); pos; m_arFrozenCols.GetNext(pos))
|
|
{
|
|
int iCol = m_arFrozenCols.GetAt(pos);
|
|
|
|
CRect r;
|
|
Header_GetItemRect(m_hWnd, iCol, &r);
|
|
iFrozenWidth += r.Width();
|
|
}
|
|
|
|
return iFrozenWidth;
|
|
}
|
|
|
|
void CXTPHeaderCtrl::SetMinSize(int iMinSize)
|
|
{
|
|
m_iMinSize = iMinSize;
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnPaint()
|
|
{
|
|
CPaintDC dc(this);
|
|
|
|
if (IsThemeValid())
|
|
{
|
|
CXTPBufferDC memDC(dc);
|
|
m_pTheme->DrawHeader(&memDC, this);
|
|
}
|
|
else
|
|
{
|
|
CHeaderCtrl::DefWindowProc(WM_PAINT, (WPARAM)dc.m_hDC, 0);
|
|
}
|
|
}
|
|
|
|
LRESULT CXTPHeaderCtrl::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
|
|
{
|
|
CDC* pDC = CDC::FromHandle((HDC)wParam);
|
|
if (pDC && IsThemeValid())
|
|
{
|
|
m_pTheme->DrawHeader(pDC, this);
|
|
return TRUE;
|
|
}
|
|
|
|
return Default();
|
|
}
|
|
|
|
BOOL CXTPHeaderCtrl::OnEraseBkgnd(CDC* /*pDC*/)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
m_bLBtnDown = TRUE;
|
|
CHeaderCtrl::OnLButtonDown(nFlags, point);
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
m_bLBtnDown = FALSE;
|
|
CHeaderCtrl::OnLButtonUp(nFlags, point);
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if (IsThemeValid() && m_pTheme->UseWinXPThemes(this))
|
|
{
|
|
SetTimer(1, 10, NULL);
|
|
}
|
|
|
|
CHeaderCtrl::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
int CXTPHeaderCtrl::HitTest(CPoint pt, UINT* pFlags/*=NULL*/) const
|
|
{
|
|
HDHITTESTINFO hti;
|
|
hti.pt.x = pt.x;
|
|
hti.pt.y = pt.y;
|
|
|
|
int iItem = (int)::SendMessage(m_hWnd, HDM_HITTEST, 0, (LPARAM)(&hti));
|
|
|
|
if (pFlags != NULL)
|
|
*pFlags = hti.flags;
|
|
|
|
return iItem;
|
|
}
|
|
|
|
BOOL CXTPHeaderCtrl::ItemPressed(int iItem)
|
|
{
|
|
if (m_bLBtnDown)
|
|
{
|
|
CPoint point;
|
|
::GetCursorPos(&point);
|
|
ScreenToClient(&point);
|
|
|
|
UINT uFlags;
|
|
if (HitTest(point, &uFlags) == iItem)
|
|
return ((uFlags & HHT_ONHEADER) == HHT_ONHEADER);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnTimer(UINT_PTR nIDEvent)
|
|
{
|
|
if (nIDEvent == 1)
|
|
{
|
|
CPoint pt;
|
|
::GetCursorPos(&pt);
|
|
ScreenToClient(&pt);
|
|
|
|
int iOverIndex = HitTest(pt);
|
|
if (iOverIndex == -1)
|
|
{
|
|
KillTimer(1);
|
|
|
|
if (m_bPainted == TRUE)
|
|
{
|
|
RedrawWindow();
|
|
}
|
|
|
|
m_bPainted = false;
|
|
return;
|
|
}
|
|
|
|
if (iOverIndex != m_iOverIndex)
|
|
{
|
|
m_iOverIndex = iOverIndex;
|
|
m_bPainted = false;
|
|
}
|
|
|
|
if (!m_bPainted)
|
|
{
|
|
RedrawWindow();
|
|
m_bPainted = true;
|
|
}
|
|
}
|
|
|
|
CHeaderCtrl::OnTimer(nIDEvent);
|
|
}
|
|
|
|
LRESULT CXTPHeaderCtrl::OnLayout(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (IsThemeValid())
|
|
{
|
|
return (LRESULT)m_pTheme->Layout(
|
|
(LPHDLAYOUT)lParam, this);
|
|
}
|
|
|
|
return CHeaderCtrl::DefWindowProc(HDM_LAYOUT, wParam, lParam);
|
|
}
|
|
|
|
int CXTPHeaderCtrl::SetSortImage(int iSortCol, BOOL bSortAsc)
|
|
{
|
|
ASSERT(iSortCol < GetItemCount());
|
|
|
|
int nPrevCol = m_nSortedCol;
|
|
m_nSortedCol = iSortCol;
|
|
m_bAscending = bSortAsc;
|
|
|
|
RedrawWindow();
|
|
return nPrevCol;
|
|
}
|
|
|
|
int CXTPHeaderCtrl::GetSortedCol(BOOL* pbSortAsc/*=NULL*/)
|
|
{
|
|
if (pbSortAsc)
|
|
*pbSortAsc = m_bAscending;
|
|
|
|
return m_nSortedCol;
|
|
}
|
|
|
|
BOOL CXTPHeaderCtrl::RecalcLayout()
|
|
{
|
|
if (!::IsWindow(m_hWnd))
|
|
return FALSE;
|
|
|
|
HD_LAYOUT hdl;
|
|
|
|
CXTPClientRect rcClient(this);
|
|
hdl.prc = &rcClient;
|
|
|
|
WINDOWPOS wp;
|
|
ZeroMemory(&wp, sizeof(WINDOWPOS));
|
|
hdl.pwpos = ℘
|
|
|
|
if (!Header_Layout(m_hWnd, &hdl))
|
|
return FALSE;
|
|
|
|
// Set the size, position, and visibility of the header window.
|
|
::SetWindowPos(m_hWnd, wp.hwndInsertAfter, wp.x, wp.y,
|
|
wp.cx, wp.cy, wp.flags | SWP_FRAMECHANGED);
|
|
|
|
CWnd* pWndParent = GetParent();
|
|
if (!::IsWindow(pWndParent->GetSafeHwnd()))
|
|
return FALSE;
|
|
|
|
// Force list control to recalculate it's layout.
|
|
CXTPWindowRect rcWindow(pWndParent);
|
|
|
|
const int cx = rcWindow.Width();
|
|
const int cy = rcWindow.Height();
|
|
|
|
pWndParent->SetWindowPos(NULL, 0, 0, cx, cy+1,
|
|
SWP_NOMOVE | SWP_FRAMECHANGED);
|
|
|
|
pWndParent->SetWindowPos(NULL, 0, 0, cx, cy,
|
|
SWP_NOMOVE | SWP_FRAMECHANGED);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnDestroy()
|
|
{
|
|
if (IsThemeValid())
|
|
m_pTheme->CleanUp(this);
|
|
|
|
CHeaderCtrl::OnDestroy();
|
|
}
|
|
|
|
void CXTPHeaderCtrl::SetBitmap(int iCol, UINT uBitmapID, DWORD dwRemove/*=NULL*/)
|
|
{
|
|
if (dwRemove)
|
|
{
|
|
HD_ITEM hdi;
|
|
hdi.mask = HDI_FORMAT;
|
|
GetItem(iCol, &hdi);
|
|
hdi.fmt &= ~dwRemove;
|
|
SetItem(iCol, &hdi);
|
|
}
|
|
|
|
SetBitmap(iCol, uBitmapID, FALSE, RGB(192, 192, 192));
|
|
}
|
|
|
|
void CXTPHeaderCtrl::SetBitmap(int iCol, UINT uBitmapID, BOOL bRemove, COLORREF crMask)
|
|
{
|
|
if (IsThemeValid())
|
|
{
|
|
m_pTheme->SetBitmap(iCol, uBitmapID, bRemove, crMask, this);
|
|
}
|
|
}
|
|
|
|
void CXTPHeaderCtrl::InitializeHeader(BOOL bBoldFont)
|
|
{
|
|
SetFont(bBoldFont ? &XTPAuxData().fontBold : &XTPAuxData().font);
|
|
RedrawWindow();
|
|
}
|
|
|
|
BOOL CXTPHeaderCtrl::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
|
|
{
|
|
if (message == WM_SETTINGCHANGE || message == WM_SYSCOLORCHANGE)
|
|
{
|
|
RefreshMetrics();
|
|
}
|
|
|
|
return CHeaderCtrl::OnWndMsg(message, wParam, lParam, pResult);
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnRButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
CPoint pt = m_pt = point;
|
|
ClientToScreen(&pt);
|
|
|
|
// If no sort headers are defined for the parent control or popup menus
|
|
// has been disabled, call the base class and return.
|
|
CWnd* pParentWnd = GetParent();
|
|
if (pParentWnd->GetStyle() & LVS_NOSORTHEADER || m_bEnableMenus == FALSE)
|
|
{
|
|
CHeaderCtrl::OnRButtonDown(nFlags, point);
|
|
return;
|
|
}
|
|
|
|
// No menu was defined use default
|
|
if (!m_popupMenuID)
|
|
{
|
|
// Get the index to the header item under the cursor.
|
|
int iIndex = HitTest(m_pt);
|
|
|
|
if (iIndex != -1)
|
|
{
|
|
CMenu menu;
|
|
CXTPResourceManager::AssertValid(XTPResourceManager()->LoadMenu(&menu, XTP_IDM_POPUP));
|
|
|
|
CMenu* pPopup = menu.GetSubMenu(2);
|
|
ASSERT(pPopup != NULL);
|
|
if (!pPopup)
|
|
return;
|
|
|
|
if (m_nSortedCol == iIndex && m_bAscending == TRUE)
|
|
pPopup->CheckMenuItem(XTP_IDC_SORTASC, MF_CHECKED | MF_BYCOMMAND);
|
|
|
|
else if (m_nSortedCol == iIndex && m_bAscending == FALSE)
|
|
pPopup->CheckMenuItem(XTP_IDC_SORTDSC, MF_CHECKED | MF_BYCOMMAND);
|
|
|
|
if (pParentWnd && (
|
|
pParentWnd->IsKindOf(RUNTIME_CLASS(CListCtrl)) ||
|
|
pParentWnd->IsKindOf(RUNTIME_CLASS(CListView))))
|
|
{
|
|
LVCOLUMN lvc;
|
|
lvc.mask = LVCF_FMT;
|
|
|
|
ListView_GetColumn(pParentWnd->m_hWnd, iIndex, &lvc);
|
|
|
|
switch (lvc.fmt & LVCFMT_JUSTIFYMASK)
|
|
{
|
|
case LVCFMT_LEFT:
|
|
pPopup->CheckMenuItem(XTP_IDC_ALIGNLEFT, MF_CHECKED | MF_BYCOMMAND);
|
|
break;
|
|
case LVCFMT_CENTER:
|
|
pPopup->CheckMenuItem(XTP_IDC_ALIGNCENTER, MF_CHECKED | MF_BYCOMMAND);
|
|
break;
|
|
case LVCFMT_RIGHT:
|
|
pPopup->CheckMenuItem(XTP_IDC_ALIGNRIGHT, MF_CHECKED | MF_BYCOMMAND);
|
|
break;
|
|
}
|
|
}
|
|
|
|
XTPContextMenu(pPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this, XTP_IDR_TBAR_HDR);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CMenu menu;
|
|
VERIFY(menu.LoadMenu(m_popupMenuID));
|
|
|
|
CMenu* pPopup = menu.GetSubMenu(m_nPos);
|
|
ASSERT(pPopup != NULL);
|
|
if (!pPopup)
|
|
return;
|
|
|
|
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
|
|
pt.x, pt.y, GetOwner());
|
|
}
|
|
}
|
|
|
|
void CXTPHeaderCtrl::SetMenuID(UINT popupMenuID, int nPos)
|
|
{
|
|
m_popupMenuID = popupMenuID;
|
|
m_nPos = nPos;
|
|
}
|
|
|
|
void CXTPHeaderCtrl::SendNotify(int iIndex)
|
|
{
|
|
CWnd* pParentWnd = GetParent();
|
|
if (!pParentWnd || !::IsWindow(pParentWnd->m_hWnd))
|
|
return;
|
|
|
|
if (pParentWnd->IsKindOf(RUNTIME_CLASS(CListCtrl)) ||
|
|
pParentWnd->IsKindOf(RUNTIME_CLASS(CListView)))
|
|
{
|
|
TCHAR lpBuffer[256];
|
|
|
|
HDITEM hdi;
|
|
hdi.mask = HDI_TEXT | HDI_BITMAP | HDI_FORMAT | HDI_IMAGE | HDI_LPARAM | HDI_ORDER | HDI_WIDTH;
|
|
hdi.pszText = lpBuffer;
|
|
hdi.cchTextMax = 256;
|
|
|
|
GetItem(iIndex, &hdi);
|
|
|
|
NMHEADER nmh;
|
|
nmh.hdr.hwndFrom = m_hWnd;
|
|
nmh.hdr.idFrom = GetDlgCtrlID();
|
|
nmh.hdr.code = HDN_ITEMCLICK;
|
|
nmh.iItem = iIndex;
|
|
nmh.iButton = 1;
|
|
nmh.pitem = &hdi;
|
|
|
|
// send message to the parent's owner window.
|
|
pParentWnd->SendMessage(WM_NOTIFY,
|
|
(WPARAM)(int)nmh.hdr.idFrom, (LPARAM)(NMHEADER*)&nmh);
|
|
|
|
// then forward to the descendants.
|
|
pParentWnd->SendMessageToDescendants(WM_NOTIFY,
|
|
(WPARAM)(int)nmh.hdr.idFrom, (LPARAM)(NMHEADER*)&nmh);
|
|
}
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnSortAsc()
|
|
{
|
|
int iIndex = HitTest(m_pt);
|
|
if (iIndex != -1)
|
|
{
|
|
if (m_nSortedCol != iIndex || m_bAscending == FALSE)
|
|
{
|
|
m_bAscending = TRUE;
|
|
m_nSortedCol = iIndex;
|
|
SendNotify(iIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnSortDsc()
|
|
{
|
|
int iIndex = HitTest(m_pt);
|
|
if (iIndex != -1)
|
|
{
|
|
if (m_nSortedCol != iIndex || m_bAscending == TRUE)
|
|
{
|
|
m_bAscending = FALSE;
|
|
m_nSortedCol = iIndex;
|
|
SendNotify(iIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL CXTPHeaderCtrl::SetAlingment(int nFlag)
|
|
{
|
|
int iIndex = HitTest(m_pt);
|
|
|
|
if (iIndex != -1)
|
|
{
|
|
CWnd* pParentWnd = GetParent();
|
|
if (pParentWnd && (
|
|
pParentWnd->IsKindOf(RUNTIME_CLASS(CListCtrl)) ||
|
|
pParentWnd->IsKindOf(RUNTIME_CLASS(CListView))))
|
|
{
|
|
LVCOLUMN lvc;
|
|
lvc.mask = LVCF_FMT;
|
|
|
|
ListView_GetColumn(pParentWnd->m_hWnd, iIndex, &lvc);
|
|
lvc.fmt &= ~LVCFMT_JUSTIFYMASK;
|
|
lvc.fmt |= nFlag;
|
|
ListView_SetColumn(pParentWnd->m_hWnd, iIndex, &lvc);
|
|
ListView_SetWorkAreas(pParentWnd->m_hWnd, 0, NULL);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnAlignLeft()
|
|
{
|
|
SetAlingment(LVCFMT_LEFT);
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnAlignCenter()
|
|
{
|
|
SetAlingment(LVCFMT_CENTER);
|
|
}
|
|
|
|
void CXTPHeaderCtrl::OnAlignRight()
|
|
{
|
|
SetAlingment(LVCFMT_RIGHT);
|
|
}
|
|
|
|
BOOL CXTPHeaderCtrl::HasSortArrow()
|
|
{
|
|
if (IsThemeValid())
|
|
return m_pTheme->HasSortArrow();
|
|
return FALSE;
|
|
}
|
|
|
|
void CXTPHeaderCtrl::ShowSortArrow(BOOL bSortArrow)
|
|
{
|
|
if (IsThemeValid())
|
|
{
|
|
DWORD dwStyle = m_pTheme->GetDrawStyle() & ~HDR_XTP_SORTARROW;
|
|
|
|
if (bSortArrow)
|
|
dwStyle |= HDR_XTP_SORTARROW;
|
|
|
|
m_pTheme->SetDrawStyle(dwStyle, this);
|
|
}
|
|
}
|
|
|
|
void CXTPHeaderCtrl::SetFontBold(BOOL bBoldFont)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
SetFont(bBoldFont ? &XTPAuxData().fontBold : &XTPAuxData().font);
|
|
}
|
|
|
|
void CXTPHeaderCtrl::RefreshMetrics()
|
|
{
|
|
if (m_pTheme)
|
|
m_pTheme->RefreshMetrics(this);
|
|
|
|
if (::IsWindow(m_hWnd))
|
|
RedrawWindow();
|
|
}
|
|
|
|
BOOL CXTPHeaderCtrl::SetTheme(CXTPHeaderCtrlTheme* pTheme)
|
|
{
|
|
CMDTARGET_RELEASE(m_pTheme);
|
|
|
|
m_pTheme = pTheme;
|
|
|
|
RefreshMetrics();
|
|
|
|
return (m_pTheme != NULL);
|
|
}
|
|
|
|
BOOL CXTPHeaderCtrl::SetTheme(XTPControlTheme eTheme)
|
|
{
|
|
CMDTARGET_RELEASE(m_pTheme);
|
|
|
|
switch (eTheme)
|
|
{
|
|
case xtpControlThemeFlat:
|
|
case xtpControlThemeUltraFlat:
|
|
case xtpControlThemeOffice2000:
|
|
case xtpControlThemeOfficeXP:
|
|
m_pTheme = new CXTPHeaderCtrlThemeOfficeXP;
|
|
break;
|
|
|
|
case xtpControlThemeOffice2003:
|
|
m_pTheme = new CXTPHeaderCtrlThemeOffice2003;
|
|
break;
|
|
|
|
case xtpControlThemeVisualStudio2005:
|
|
case xtpControlThemeVisualStudio2008:
|
|
case xtpControlThemeVisualStudio2010:
|
|
case xtpControlThemeNativeWinXP:
|
|
m_pTheme = new CXTPHeaderCtrlThemeExplorer;
|
|
m_pTheme->SetDrawStyle(HDR_XTP_WINDEF|HDR_XTP_HOTTRACKING|HDR_XTP_SORTARROW, this);
|
|
break;
|
|
|
|
case xtpControlThemeResource:
|
|
m_pTheme = new CXTPHeaderCtrlThemeResource;
|
|
break;
|
|
|
|
case xtpControlThemeDefault:
|
|
default:
|
|
m_pTheme = new CXTPHeaderCtrlTheme;
|
|
break;
|
|
}
|
|
|
|
RefreshMetrics();
|
|
|
|
return (m_pTheme != NULL);
|
|
}
|
|
|
|
LRESULT CXTPHeaderCtrl::OnSetTheme(WPARAM wParam, LPARAM /*lParam*/)
|
|
{
|
|
XTPControlTheme eTheme = (XTPControlTheme)wParam;
|
|
|
|
SetTheme(eTheme);
|
|
|
|
return 0;
|
|
}
|