windows-nt/Source/XPSP1/NT/shell/shell32/ctllogic.h
2020-09-26 16:20:57 +08:00

561 lines
12 KiB
C++

#ifndef CTLLOGIC_H
#define CTLLOGIC_H
#include "dlglogic.h"
#define MAX_ITEMTEXTLEN 50
#define MAX_TILETEXT 50
HRESULT _GetListViewSelectedLPARAM(HWND hwndList, LPARAM* plparam);
HRESULT _GetComboBoxSelectedLRESULT(HWND hwndComboBox, LRESULT* plr);
// ListView
template<typename TData>
class CDLUIDataLVItem : public CDLUIData<TData>
{
public:
virtual ~CDLUIDataLVItem() {}
virtual HRESULT GetText(LPWSTR pszText, DWORD cchText) PURE;
virtual HRESULT GetIconLocation(LPWSTR pszIconLocation,
DWORD cchIconLocation) PURE;
virtual HRESULT GetTileText(int i, LPWSTR pszTileText,
DWORD cchTileText)
{
return E_NOTIMPL;
}
};
template<typename TData>
class CUILListView
{
public:
~CUILListView();
CUILListView();
HRESULT Init(HWND hwndListView);
HRESULT InitTileInfo(const UINT auTileSubItems[], DWORD cTileSubItems);
HRESULT AddItem(CDLUIDataLVItem<TData>* plvitem);
// Note: Caller needs to Release *ppdata at some point
HRESULT GetSelectedItemData(TData** ppdata);
// Assume Single select listview. Also assume that no other item is selected
HRESULT SelectFirstItem();
HRESULT ResetContent();
protected:
HWND _hwndList;
private:
const UINT* _auTileSubItems;
int _cTileSubItems;
};
template<typename TData, typename TCompareData>
class CUILListViewSelect : public CUILListView<TData>
{
public:
HRESULT SelectItem(TCompareData comparedata)
{
HRESULT hr = E_FAIL;
LVITEM lvitem = {0};
int iCount = 0;
lvitem.mask = LVIF_PARAM;
iCount = ListView_GetItemCount(_hwndList);
for (lvitem.iItem = 0; lvitem.iItem < iCount; ++lvitem.iItem)
{
if (ListView_GetItem(_hwndList, &lvitem))
{
CDLUIDataLVItem<TData>* plvitem = (CDLUIDataLVItem<TData>*)lvitem.lParam;
TData* pdata = plvitem->GetData();
if (pdata)
{
int iResult;
hr = pdata->Compare(comparedata, &iResult);
pdata->Release();
if (SUCCEEDED(hr) && !iResult)
{
break;
}
}
}
}
if (lvitem.iItem == iCount)
{
//No Match found, Select first item anyway
lvitem.iItem = 0;
hr = S_FALSE;
}
lvitem.mask = LVIF_STATE;
lvitem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
lvitem.state = LVIS_SELECTED | LVIS_FOCUSED;
ListView_SetItem(_hwndList, &lvitem);
ListView_EnsureVisible(_hwndList, lvitem.iItem, FALSE);
return hr;
}
};
// ComboBox
template<typename TData>
class CDLUIDataCBItem : public CDLUIData<TData>
{
public:
virtual ~CDLUIDataCBItem() {}
virtual HRESULT GetText(LPWSTR pszText, DWORD cchText) PURE;
virtual HRESULT GetIconLocation(LPWSTR pszIconLocation,
DWORD cchIconLocation) PURE;
};
template<typename TData>
class CUILComboBox
{
public:
~CUILComboBox();
HRESULT Init(HWND hwndComboBox);
HRESULT AddItem(CDLUIDataCBItem<TData>* pcbitem);
// Note: Caller needs to Release *ppdata at some point
HRESULT GetSelectedItemData(TData** ppdata);
HRESULT SelectFirstItem();
HRESULT ResetContent();
private:
HWND _hwndCombo;
};
template<typename TData>
class CUILComboBoxEx
{
public:
~CUILComboBoxEx();
HRESULT Init(HWND hwndComboBox);
HRESULT AddItem(CDLUIDataCBItem<TData>* pcbitem);
// Note: Caller needs to Release *ppdata at some point
HRESULT GetSelectedItemData(TData** ppdata);
HRESULT SelectFirstItem();
HRESULT ResetContent();
private:
HWND _hwndCombo;
};
// Implementations
template<typename TData>
CUILListView<TData>::CUILListView() : _cTileSubItems(0)
{}
template<typename TData>
CUILListView<TData>::~CUILListView()
{
ResetContent();
}
template<typename TData>
inline HRESULT CUILListView<TData>::Init(HWND hwndListView)
{
_hwndList = hwndListView;
return S_OK;
}
template<typename TData>
inline HRESULT CUILListView<TData>::InitTileInfo(const UINT auTileSubItems[],
DWORD cTileSubItems)
{
_auTileSubItems = auTileSubItems;
_cTileSubItems = cTileSubItems;
return S_OK;
}
template<typename TData>
inline HRESULT CUILListView<TData>::AddItem(CDLUIDataLVItem<TData>* plvitem)
{
WCHAR szText[MAX_ITEMTEXTLEN];
int iImage;
LVITEM lvitem = {0};
HRESULT hr = plvitem->GetText(szText, ARRAYSIZE(szText));
if (SUCCEEDED(hr))
{
WCHAR szIconLocation[MAX_PATH + 12];
hr = plvitem->GetIconLocation(szIconLocation,
ARRAYSIZE(szIconLocation));
if (SUCCEEDED(hr))
{
int iIcon = PathParseIconLocation(szIconLocation);
iImage = Shell_GetCachedImageIndex(szIconLocation, iIcon, 0);
}
}
if (SUCCEEDED(hr))
{
int iItem;
lvitem.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
lvitem.pszText = szText;
lvitem.iItem = ListView_GetItemCount(_hwndList);
lvitem.iImage = iImage;
lvitem.lParam = (LPARAM)plvitem;
iItem = ListView_InsertItem(_hwndList, &lvitem);
if (-1 != iItem)
{
if (_cTileSubItems)
{
LVTILEINFO lvti = {0};
lvti.cbSize = sizeof(LVTILEINFO);
lvti.iItem = iItem;
lvti.cColumns = ARRAYSIZE(_auTileSubItems);
lvti.puColumns = (UINT*)_auTileSubItems;
ListView_SetTileInfo(_hwndList, &lvti);
for (int i = 0; i < _cTileSubItems; ++i)
{
WCHAR szTileText[MAX_TILETEXT];
hr = plvitem->GetTileText(i, szTileText,
ARRAYSIZE(szTileText));
// 1 based
ListView_SetItemText(_hwndList, iItem, i + 1, szTileText);
}
}
}
else
{
hr = E_FAIL;
}
}
return hr;
}
template<typename TData>
inline HRESULT CUILListView<TData>::GetSelectedItemData(TData** ppdata)
{
HRESULT hr;
BOOL fFound = FALSE;
int iCount = ListView_GetItemCount(_hwndList);
LVITEM lvitem = {0};
lvitem.mask = LVIF_PARAM | LVIF_STATE;
lvitem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
for (int j = 0; !fFound && (j < iCount); ++j)
{
lvitem.iItem = j;
ListView_GetItem(_hwndList, &lvitem);
if (lvitem.state & (LVIS_SELECTED | LVIS_FOCUSED))
{
fFound = TRUE;
}
}
if (fFound)
{
CDLUIDataLVItem<TData>* plvitem = (CDLUIDataLVItem<TData>*)lvitem.lParam;
*ppdata = plvitem->GetData();
hr = ((*ppdata) ? S_OK : S_FALSE);
}
else
{
*ppdata = NULL;
hr = E_FAIL;
}
return hr;
}
template<typename TData>
inline HRESULT CUILListView<TData>::SelectFirstItem()
{
LVITEM lvitem = {0};
lvitem.iItem = 0;
lvitem.mask = LVIF_STATE;
lvitem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
lvitem.state = LVIS_SELECTED | LVIS_FOCUSED;
ListView_SetItem(_hwndList, &lvitem);
ListView_EnsureVisible(_hwndList, lvitem.iItem, FALSE);
return S_OK;
}
template<typename TData>
HRESULT CUILListView<TData>::ResetContent()
{
int iCount = 0;
LVITEM lvitem = {0};
// go through all the items in the listview and delete the strings
// dynamically allocated
lvitem.mask = LVIF_PARAM;
lvitem.iSubItem = 0;
iCount = ListView_GetItemCount(_hwndList);
for (lvitem.iItem = 0; lvitem.iItem < iCount; ++lvitem.iItem)
{
ListView_GetItem(_hwndList, &lvitem);
CDLUIDataLVItem<TData>* plvitem = (CDLUIDataLVItem<TData>*)
lvitem.lParam;
if (plvitem)
{
delete plvitem;
}
}
ListView_DeleteAllItems(_hwndList);
return S_OK;
}
// CUILComboBox
template<typename TData>
CUILComboBox<TData>::~CUILComboBox()
{
ResetContent();
}
template<typename TData>
HRESULT CUILComboBox<TData>::Init(HWND hwndComboBox)
{
_hwndCombo = hwndComboBox;
return S_OK;
}
template<typename TData>
HRESULT CUILComboBox<TData>::AddItem(CDLUIDataCBItem<TData>* pcbitem)
{
WCHAR szText[MAX_ITEMTEXTLEN];
HRESULT hr = pcbitem->GetText(szText, ARRAYSIZE(szText));
if (SUCCEEDED(hr))
{
int i = ComboBox_AddString(_hwndCombo, szText);
if (CB_ERR != i)
{
ComboBox_SetItemData(_hwndCombo, i, pcbitem);
}
}
return hr;
}
template<typename TData>
HRESULT CUILComboBox<TData>::GetSelectedItemData(TData** ppdata)
{
HRESULT hr;
int iCurSel = ComboBox_GetCurSel(_hwndCombo);
LRESULT lr = ComboBox_GetItemData(_hwndCombo, iCurSel);
if (CB_ERR != lr)
{
CDLUIDataCBItem<TData>* pcbitem = (CDLUIDataCBItem<TData>*)lr;
*ppdata = pcbitem->GetData();
hr = ((*ppdata) ? S_OK : S_FALSE);
}
else
{
*ppdata = NULL;
hr = E_FAIL;
}
return hr;
}
template<typename TData>
HRESULT CUILComboBox<TData>::ResetContent()
{
int c = ComboBox_GetCount(_hwndCombo);
for (int i = 0; i < c; ++i)
{
CDLUIDataCBItem<TData>* pcbitem = (CDLUIDataCBItem<TData>*)
ComboBox_GetItemData(_hwndCombo, i);
if (pcbitem)
{
delete pcbitem;
}
}
ComboBox_ResetContent(_hwndCombo);
return S_OK;
}
template<typename TData>
HRESULT CUILComboBox<TData>::SelectFirstItem()
{
ComboBox_SetCurSel(_hwndCombo, 0);
return S_OK;
}
// CUILComboBoxEx
template<typename TData>
CUILComboBoxEx<TData>::~CUILComboBoxEx()
{
ResetContent();
}
template<typename TData>
HRESULT CUILComboBoxEx<TData>::Init(HWND hwndComboBox)
{
_hwndCombo = hwndComboBox;
return S_OK;
}
template<typename TData>
HRESULT CUILComboBoxEx<TData>::AddItem(CDLUIDataCBItem<TData>* pcbitem)
{
WCHAR szText[MAX_ITEMTEXTLEN];
int iImage;
HRESULT hr = pcbitem->GetText(szText, ARRAYSIZE(szText));
if (SUCCEEDED(hr))
{
WCHAR szIconLocation[MAX_PATH + 12];
hr = pcbitem->GetIconLocation(szIconLocation,
ARRAYSIZE(szIconLocation));
if (SUCCEEDED(hr))
{
int iIcon = PathParseIconLocation(szIconLocation);
iImage = Shell_GetCachedImageIndex(szIconLocation, iIcon, 0);
}
}
if (SUCCEEDED(hr))
{
int iItem;
COMBOBOXEXITEM cbitem = {0};
cbitem.mask = CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_TEXT | CBEIF_LPARAM;
cbitem.pszText = szText;
cbitem.iItem = ComboBox_GetCount(_hwndCombo);
cbitem.iImage = iImage;
cbitem.iSelectedImage = iImage;
cbitem.lParam = (LPARAM)pcbitem;
iItem = SendMessage(_hwndCombo, CBEM_INSERTITEM, 0, (LPARAM)&cbitem);
if (-1 != iItem)
{
hr = S_OK;
}
else
{
hr = E_FAIL;
}
}
return hr;
}
template<typename TData>
HRESULT CUILComboBoxEx<TData>::GetSelectedItemData(TData** ppdata)
{
HRESULT hr;
COMBOBOXEXITEM cbitem = {0};
cbitem.mask = CBEIF_LPARAM;
cbitem.iItem = ComboBox_GetCurSel(_hwndCombo);
if (SendMessage(_hwndCombo, CBEM_GETITEM, 0, (LPARAM)&cbitem))
{
CDLUIDataCBItem<TData>* pcbitem = (CDLUIDataCBItem<TData>*)cbitem.lParam;
*ppdata = pcbitem->GetData();
hr = ((*ppdata) ? S_OK : S_FALSE);
}
else
{
*ppdata = NULL;
hr = E_FAIL;
}
return hr;
}
template<typename TData>
HRESULT CUILComboBoxEx<TData>::ResetContent()
{
int c = ComboBox_GetCount(_hwndCombo);
for (int i = 0; i < c; ++i)
{
CDLUIDataCBItem<TData>* pcbitem = (CDLUIDataCBItem<TData>*)
ComboBox_GetItemData(_hwndCombo, i);
if (pcbitem)
{
delete pcbitem;
}
}
ComboBox_ResetContent(_hwndCombo);
return S_OK;
}
template<typename TData>
HRESULT CUILComboBoxEx<TData>::SelectFirstItem()
{
ComboBox_SetCurSel(_hwndCombo, 0);
return S_OK;
}
#endif // CTLLOGIC_H