📄 listviewex.cpp
字号:
if( lpszDefault == NULL ) m_strDefault = _T("");
else m_strDefault = lpszDefault;
LoadColumnWidths();
}
void CListViewEx::SaveColumnWidths()
{
// get a pointer to the header control.
CHeaderCtrl* pHeader = DYNAMIC_DOWNCAST(CHeaderCtrl, GetDlgItem(0));
ASSERT_KINDOF( CHeaderCtrl, pHeader );
CString strValue;
for( int i = 0; i < pHeader->GetItemCount(); ++i )
{
CString strTemp;
strTemp.Format(_T("%d,"), m_pListCtrl->GetColumnWidth( i ));
strValue += strTemp;
}
AfxGetApp()->WriteProfileString( m_strSection, m_strEntry, strValue );
}
void CListViewEx::LoadColumnWidths()
{
// get a pointer to the header control.
CHeaderCtrl* pHeader = DYNAMIC_DOWNCAST(CHeaderCtrl, GetDlgItem(0));
ASSERT_KINDOF( CHeaderCtrl, pHeader );
for( int i = 0; i < pHeader->GetItemCount(); ++i )
SetColumnWidth(i);
}
void CListViewEx::SetColumnWidth(int nCol)
{
int nWidth = GetStoredWidth( nCol );
if( nWidth > m_nMinColWidth )
m_pListCtrl->SetColumnWidth( nCol, nWidth );
else
AutoSizeColumn( nCol );
}
int CListViewEx::GetStoredWidth(int nCol)
{
// get the value from the registry.
CString strValue = AfxGetApp()->GetProfileString(
m_strSection, m_strEntry, m_strDefault );
// extract the sub string to get the column width.
CString strSubString;
AfxExtractSubString( strSubString, strValue, nCol, _T(','));
// return the width from the registry.
return _ttoi( strSubString );
}
void CListViewEx::OnDestroy()
{
if( m_bAutoSave ) SaveColumnWidths();
CListView::OnDestroy();
}
// Taken from: Autosize a column to fit its content by Roger Onslow.
// http://www.codeguru.com/listview/autosize_col.shtml
// If you don't supply a column number, it will resize all columns.
void CListViewEx::AutoSizeColumn(int nCol/*=-1*/)
{
// Call this after your list control is filled
SetRedraw( false );
int nMinCol = nCol < 0 ? 0 : nCol;
int nMaxCol = nCol < 0 ? GetColumnCount()-1 : nCol;
for (nCol = nMaxCol; nCol >= nMinCol; nCol--)
{
m_pListCtrl->SetColumnWidth( nCol, LVSCW_AUTOSIZE );
int wc1 = m_pListCtrl->GetColumnWidth( nCol );
m_pListCtrl->SetColumnWidth( nCol, LVSCW_AUTOSIZE_USEHEADER );
int wc2 = m_pListCtrl->GetColumnWidth( nCol );
if ( (NULL != m_pHeaderCtrl) && (m_nSortedCol == nCol) )
{
wc2 += m_pHeaderCtrl->GetSortImageWidth();
}
int wc = max( m_nMinColWidth, max( wc1, wc2 ));
if( wc > m_nMaxColWidth )
wc = m_nMaxColWidth;
// set the column width.
m_pListCtrl->SetColumnWidth( nCol,wc );
}
SetRedraw();
}
BOOL CListViewEx::OnEraseBkgnd(CDC* pDC)
{
CRect rectClient;
GetClientRect( &rectClient );
pDC->ExcludeClipRect( &rectClient );
return CListView::OnEraseBkgnd(pDC);
}
int CListViewEx::GetFirstVisibleColumn()
{
int nColCount = m_pListCtrl->GetHeaderCtrl()->GetItemCount();
for(int i = 0; i < nColCount; ++i)
{
int nCol = m_pListCtrl->GetHeaderCtrl()->OrderToIndex(i);
if (IsColumnVisible(nCol))
{
return nCol;
}
}
return -1;
}
BOOL CListViewEx::ShowColumn(int nCol, bool bShow)
{
SetRedraw(FALSE);
ColumnState& columnState = GetColumnState(nCol);
int nColCount = m_pListCtrl->GetHeaderCtrl()->GetItemCount();
int* pOrderArray = new int[nColCount];
VERIFY( m_pListCtrl->GetColumnOrderArray(pOrderArray, nColCount) );
if (bShow)
{
// Restore the position of the column
int nCurIndex = -1;
for(int i = 0; i < nColCount ; ++i)
{
if (pOrderArray[i]==nCol)
nCurIndex = i;
else
if (nCurIndex!=-1)
{
// We want to move it to the original position,
// and after the last hidden column
if ( (i <= columnState.m_OrgPosition)
|| !IsColumnVisible(pOrderArray[i])
)
{
pOrderArray[nCurIndex] = pOrderArray[i];
pOrderArray[i] = nCol;
nCurIndex = i;
}
}
}
}
else
{
// Move the column to the front of the display order list
int nCurIndex(-1);
for(int i = nColCount-1; i >=0 ; --i)
{
if (pOrderArray[i]==nCol)
{
// Backup the current position of the column
columnState.m_OrgPosition = i;
nCurIndex = i;
}
else
if (nCurIndex!=-1)
{
pOrderArray[nCurIndex] = pOrderArray[i];
pOrderArray[i] = nCol;
nCurIndex = i;
}
}
}
VERIFY( m_pListCtrl->SetColumnOrderArray(nColCount, pOrderArray) );
delete [] pOrderArray;
if (bShow)
{
// Restore the column width
columnState.m_Visible = true;
VERIFY( m_pListCtrl->SetColumnWidth(nCol, columnState.m_OrgWidth) );
}
else
{
// Backup the column width
int orgWidth = m_pListCtrl->GetColumnWidth(nCol);
VERIFY( m_pListCtrl->SetColumnWidth(nCol, 0) );
columnState.m_Visible = false;
columnState.m_OrgWidth = orgWidth;
}
SetRedraw(TRUE);
Invalidate(FALSE);
return TRUE;
}
BOOL CListViewEx::SetColumnWidthAuto(int nCol, bool includeHeader)
{
if (nCol == -1)
{
for(int i = 0; i < m_pListCtrl->GetHeaderCtrl()->GetItemCount() ; ++i)
{
SetColumnWidthAuto(i, includeHeader);
}
return TRUE;
}
else
{
if (includeHeader)
return m_pListCtrl->SetColumnWidth(nCol, LVSCW_AUTOSIZE_USEHEADER);
else
return m_pListCtrl->SetColumnWidth(nCol, LVSCW_AUTOSIZE);
}
}
CListViewEx::ColumnState& CListViewEx::GetColumnState(int nCol)
{
VERIFY( nCol >=0 && nCol < m_ColumnStates.GetSize() );
return m_ColumnStates[nCol];
}
bool CListViewEx::IsColumnVisible(int nCol)
{
return GetColumnState(nCol).m_Visible;
}
int CListViewEx::GetColumnStateCount()
{
return m_ColumnStates.GetSize();
}
void CListViewEx::InsertColumnState(int nCol, bool bVisible, int nOrgWidth)
{
VERIFY( nCol >=0 && nCol <= m_ColumnStates.GetSize() );
ColumnState columnState;
columnState.m_OrgWidth = nOrgWidth;
columnState.m_Visible = bVisible;
if (nCol == m_ColumnStates.GetSize())
{
// Append column picker to the end of the array
m_ColumnStates.Add(columnState);
}
else
{
// Insert column in the middle of the array
CSimpleArray<ColumnState> newArray;
for(int i=0 ; i < m_ColumnStates.GetSize(); ++i)
{
if (i == nCol)
newArray.Add(columnState);
newArray.Add(m_ColumnStates[i]);
}
m_ColumnStates = newArray;
}
}
void CListViewEx::DeleteColumnState(int nCol)
{
VERIFY( nCol >=0 && nCol < m_ColumnStates.GetSize() );
m_ColumnStates.RemoveAt(nCol);
}
void CListViewEx::OnContextMenu(CWnd* pWnd, CPoint point)
{
if (point.x==-1 && point.y==-1)
{
// OBS! point is initialized to (-1,-1) if using SHIFT+F10 or VK_APPS
}
else
{
CPoint pt = point;
ScreenToClient(&pt);
#ifndef _WIN32_WCE
CRect headerRect;
m_pListCtrl->GetHeaderCtrl()->GetClientRect(&headerRect);
if (headerRect.PtInRect(pt))
#endif
{
// Show context-menu with the option to show hide columns
CMenu menu;
if (menu.CreatePopupMenu())
{
for( int i = 0 ; i < GetColumnStateCount(); i++)
{
UINT uFlags = MF_BYPOSITION | MF_STRING;
// Put check-box on context-menu
if (IsColumnVisible(i))
uFlags |= MF_CHECKED;
else
uFlags |= MF_UNCHECKED;
// Retrieve column-title
LVCOLUMN lvc = {0};
lvc.mask = LVCF_TEXT;
TCHAR sColText[256];
lvc.pszText = sColText;
lvc.cchTextMax = sizeof(sColText)-1;
VERIFY( m_pListCtrl->GetColumn(i, &lvc) );
menu.InsertMenu(0, uFlags, i, lvc.pszText);
}
menu.TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this, 0);
}
}
ClientToScreen(&pt);
}
}
// Handle context-menu event for showing / hiding columns
BOOL CListViewEx::OnCommand(WPARAM wParam, LPARAM lParam)
{
if (HIWORD(wParam) == 0)
{
int nCol = LOWORD(wParam);
ShowColumn(nCol, !IsColumnVisible(nCol));
}
return TRUE;
}
void CListViewEx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch(nChar)
{
case VK_ADD: // CTRL + NumPlus (Auto size all columns)
{
if (GetKeyState(VK_CONTROL) < 0)
{
// Special handling to avoid showing "hidden" columns
SetColumnWidthAuto(-1);
return;
}
} break;
}
CListView::OnKeyDown(nChar, nRepCnt, nFlags);
}
BOOL CListViewEx::OnHeaderBeginResize(UINT, NMHDR* pNMHDR, LRESULT* pResult)
{
// Check that column is allowed to be resized
NMHEADER* pNMH = (NMHEADER*)pNMHDR;
int nCol = (int)pNMH->iItem;
if (!IsColumnVisible(nCol))
{
*pResult = TRUE; // Block resize
return TRUE; // Block event
}
return FALSE;
}
LRESULT CListViewEx::OnSetColumnWidth(WPARAM wParam, LPARAM lParam)
{
// Check that column is allowed to be resized
int nCol = (int)wParam;
if (!IsColumnVisible(nCol))
{
return FALSE;
}
// Let the CListCtrl handle the event
return DefWindowProc(LVM_SETCOLUMNWIDTH, wParam, lParam);
}
BOOL CListViewEx::OnHeaderEndDrag(UINT, NMHDR* pNMHDR, LRESULT* pResult)
{
NMHEADER* pNMH = (NMHEADER*)pNMHDR;
if (pNMH->pitem->mask & HDI_ORDER)
{
// Correct iOrder so it is just after the last hidden column
int nColCount = m_pListCtrl->GetHeaderCtrl()->GetItemCount();
int* pOrderArray = new int[nColCount];
VERIFY( m_pListCtrl->GetColumnOrderArray(pOrderArray, nColCount) );
for(int i = 0; i < nColCount ; ++i)
{
if (IsColumnVisible(pOrderArray[i]))
{
pNMH->pitem->iOrder = max(pNMH->pitem->iOrder,i);
break;
}
}
delete [] pOrderArray;
}
return FALSE;
}
BOOL CListViewEx::OnHeaderDividerDblClick(UINT, NMHDR* pNMHDR, LRESULT* pResult)
{
NMHEADER* pNMH = (NMHEADER*)pNMHDR;
SetColumnWidthAuto(pNMH->iItem);
return TRUE; // Don't let parent handle the event
}
LRESULT CListViewEx::OnDeleteColumn(WPARAM wParam, LPARAM lParam)
{
// Let the CListCtrl handle the event
LRESULT lRet = DefWindowProc(LVM_DELETECOLUMN, wParam, lParam);
if (lRet == FALSE)
return FALSE;
// Book keeping of columns
DeleteColumnState((int)wParam);
return lRet;
}
LRESULT CListViewEx::OnInsertColumn(WPARAM wParam, LPARAM lParam)
{
// Let the CListCtrl handle the event
LRESULT lRet = DefWindowProc(LVM_INSERTCOLUMN, wParam, lParam);
if (lRet == -1)
return -1;
int nCol = (int)lRet;
// Book keeping of columns
if (GetColumnStateCount() < m_pListCtrl->GetHeaderCtrl()->GetItemCount())
InsertColumnState((int)nCol, true); // Insert as visible
return lRet;
}
/*
namespace
{
LRESULT EnableWindowTheme(HWND hwnd, LPCWSTR classList, LPCWSTR subApp, LPCWSTR idlist)
{
HMODULE hinstDll;
HRESULT (__stdcall *pSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
HANDLE (__stdcall *pOpenThemeData)(HWND hwnd, LPCWSTR pszClassList);
HRESULT (__stdcall *pCloseThemeData)(HANDLE hTheme);
hinstDll = ::LoadLibrary(TEXT("UxTheme.dll"));
if (hinstDll)
{
(FARPROC&)pOpenThemeData = ::GetProcAddress(hinstDll, TEXT("OpenThemeData"));
(FARPROC&)pCloseThemeData = ::GetProcAddress(hinstDll, TEXT("CloseThemeData"));
(FARPROC&)pSetWindowTheme = ::GetProcAddress(hinstDll, TEXT("SetWindowTheme"));
::FreeLibrary(hinstDll);
if (pSetWindowTheme && pOpenThemeData && pCloseThemeData)
{
HANDLE theme = pOpenThemeData(hwnd,classList);
if (theme!=NULL)
{
VERIFY(pCloseThemeData(theme)==S_OK);
return pSetWindowTheme(hwnd, subApp, idlist);
}
}
}
return S_FALSE;
}
}
void CListViewEx::PreSubclassWindow()
{
CListViewEx::PreSubclassWindow();
// Focus retangle is not painted properly without double-buffering
#if (_WIN32_WINNT >= 0x501)
SetExtendedStyle(LVS_EX_DOUBLEBUFFER | GetExtendedStyle());
#endif
SetExtendedStyle(GetExtendedStyle() | LVS_EX_FULLROWSELECT);
SetExtendedStyle(GetExtendedStyle() | LVS_EX_HEADERDRAGDROP);
SetExtendedStyle(GetExtendedStyle() | LVS_EX_GRIDLINES);
// Enable Vista-look if possible
EnableWindowTheme(GetSafeHwnd(), L"ListView", L"Explorer", NULL);
}
*/
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -