mirror of
https://github.com/voiceip/tinyphone
synced 2026-08-07 02:26:03 -04:00
191 lines
5.1 KiB
C++
191 lines
5.1 KiB
C++
#include "stdafx.h"
|
|
|
|
#include "CListCtrl_Sortable.h"
|
|
#include "Resource.h"
|
|
|
|
#include <shlwapi.h>
|
|
|
|
BEGIN_MESSAGE_MAP(CListCtrl_Sortable, CListCtrl)
|
|
ON_NOTIFY_REFLECT_EX(LVN_COLUMNCLICK, OnHeaderClick) // Column Click
|
|
END_MESSAGE_MAP()
|
|
|
|
namespace {
|
|
bool IsThemeEnabled()
|
|
{
|
|
HMODULE hinstDll;
|
|
bool XPStyle = false;
|
|
bool (__stdcall *pIsAppThemed)();
|
|
bool (__stdcall *pIsThemeActive)();
|
|
|
|
// Test if operating system has themes enabled
|
|
hinstDll = ::LoadLibrary(_T("UxTheme.dll"));
|
|
if (hinstDll)
|
|
{
|
|
(FARPROC&)pIsAppThemed = ::GetProcAddress(hinstDll, "IsAppThemed");
|
|
(FARPROC&)pIsThemeActive = ::GetProcAddress(hinstDll,"IsThemeActive");
|
|
::FreeLibrary(hinstDll);
|
|
if (pIsAppThemed != NULL && pIsThemeActive != NULL)
|
|
{
|
|
if (pIsAppThemed() && pIsThemeActive())
|
|
{
|
|
// Test if application has themes enabled by loading the proper DLL
|
|
hinstDll = LoadLibrary(_T("comctl32.dll"));
|
|
if (hinstDll)
|
|
{
|
|
DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hinstDll, "DllGetVersion");
|
|
::FreeLibrary(hinstDll);
|
|
if (pDllGetVersion != NULL)
|
|
{
|
|
DLLVERSIONINFO dvi;
|
|
ZeroMemory(&dvi, sizeof(dvi));
|
|
dvi.cbSize = sizeof(dvi);
|
|
HRESULT hRes = pDllGetVersion ((DLLVERSIONINFO *) &dvi);
|
|
if (SUCCEEDED(hRes))
|
|
XPStyle = dvi.dwMajorVersion >= 6;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return XPStyle;
|
|
}
|
|
|
|
LRESULT EnableWindowTheme(HWND hwnd, LPCWSTR app, 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(_T("UxTheme.dll"));
|
|
if (hinstDll)
|
|
{
|
|
(FARPROC&)pOpenThemeData = ::GetProcAddress(hinstDll, "OpenThemeData");
|
|
(FARPROC&)pCloseThemeData = ::GetProcAddress(hinstDll, "CloseThemeData");
|
|
(FARPROC&)pSetWindowTheme = ::GetProcAddress(hinstDll, "SetWindowTheme");
|
|
::FreeLibrary(hinstDll);
|
|
if (pSetWindowTheme && pOpenThemeData && pCloseThemeData)
|
|
{
|
|
HANDLE theme = pOpenThemeData(hwnd,L"ListView");
|
|
if (theme!=NULL)
|
|
{
|
|
VERIFY(pCloseThemeData(theme)==S_OK);
|
|
return pSetWindowTheme(hwnd, app, idlist);
|
|
}
|
|
}
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL CListCtrl_Sortable::OnHeaderClick(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
NMLISTVIEW* pLV = reinterpret_cast<NMLISTVIEW*>(pNMHDR);
|
|
|
|
SetFocus(); // Ensure other controls gets kill-focus
|
|
|
|
int colIndex = pLV->iSubItem;
|
|
|
|
if (m_SortCol==colIndex)
|
|
{
|
|
m_Ascending = !m_Ascending;
|
|
}
|
|
else
|
|
{
|
|
m_SortCol = colIndex;
|
|
m_Ascending = true;
|
|
}
|
|
|
|
if (SortColumn(m_SortCol, m_Ascending))
|
|
SetSortArrow(m_SortCol, m_Ascending);
|
|
|
|
return FALSE; // Let parent-dialog get chance
|
|
}
|
|
|
|
void CListCtrl_Sortable::SetSortArrow(int colIndex, bool ascending)
|
|
{
|
|
if (IsThemeEnabled())
|
|
{
|
|
#if (_WIN32_WINNT >= 0x501)
|
|
for(int i = 0; i < GetHeaderCtrl()->GetItemCount(); ++i)
|
|
{
|
|
HDITEM hditem = {0};
|
|
hditem.mask = HDI_FORMAT;
|
|
VERIFY( GetHeaderCtrl()->GetItem( i, &hditem ) );
|
|
hditem.fmt &= ~(HDF_SORTDOWN|HDF_SORTUP);
|
|
if (i == colIndex)
|
|
{
|
|
hditem.fmt |= ascending ? HDF_SORTUP : HDF_SORTDOWN;
|
|
}
|
|
VERIFY( CListCtrl::GetHeaderCtrl()->SetItem( i, &hditem ) );
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
UINT bitmapID = m_Ascending ? IDB_UPARROW : IDB_DOWNARROW;
|
|
for(int i = 0; i < GetHeaderCtrl()->GetItemCount(); ++i)
|
|
{
|
|
HDITEM hditem = {0};
|
|
hditem.mask = HDI_BITMAP | HDI_FORMAT;
|
|
VERIFY( GetHeaderCtrl()->GetItem( i, &hditem ) );
|
|
if (hditem.fmt & HDF_BITMAP && hditem.fmt & HDF_BITMAP_ON_RIGHT)
|
|
{
|
|
if (hditem.hbm)
|
|
{
|
|
DeleteObject(hditem.hbm);
|
|
hditem.hbm = NULL;
|
|
}
|
|
hditem.fmt &= ~(HDF_BITMAP|HDF_BITMAP_ON_RIGHT);
|
|
VERIFY( CListCtrl::GetHeaderCtrl()->SetItem( i, &hditem ) );
|
|
}
|
|
if (i == colIndex)
|
|
{
|
|
hditem.fmt |= HDF_BITMAP|HDF_BITMAP_ON_RIGHT;
|
|
hditem.hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(bitmapID), IMAGE_BITMAP, 0,0, LR_LOADMAP3DCOLORS);
|
|
VERIFY( hditem.hbm!=NULL );
|
|
VERIFY( CListCtrl::GetHeaderCtrl()->SetItem( i, &hditem ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CListCtrl_Sortable::PreSubclassWindow()
|
|
{
|
|
CListCtrl::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);
|
|
|
|
EnableWindowTheme(GetSafeHwnd(), L"Explorer", NULL);
|
|
}
|
|
|
|
void CListCtrl_Sortable::ResetSortOrder()
|
|
{
|
|
m_Ascending = true;
|
|
m_SortCol = -1;
|
|
SetSortArrow(m_SortCol, m_Ascending);
|
|
}
|
|
|
|
// The column version of GetItemData(), one can specify an unique
|
|
// identifier when using InsertColumn()
|
|
int CListCtrl_Sortable::GetColumnData(int col) const
|
|
{
|
|
LVCOLUMN lvc = {0};
|
|
lvc.mask = LVCF_SUBITEM;
|
|
VERIFY( GetColumn(col, &lvc) );
|
|
return lvc.iSubItem;
|
|
}
|
|
|
|
void CListCtrl_Sortable::SetSortColumn(int columnIndex, bool ascending)
|
|
{
|
|
m_SortCol = columnIndex;
|
|
m_Ascending = ascending;
|
|
if (SortColumn(m_SortCol, m_Ascending)) {
|
|
SetSortArrow(m_SortCol, m_Ascending);
|
|
}
|
|
}
|