PowerToys/src/modules/powerrename/ui/PowerRenameUI.cpp

931 lines
23 KiB
C++
Raw Normal View History

#include "stdafx.h"
#include "resource.h"
#include "PowerRenameUI.h"
#include <commctrl.h>
#include <Shlobj.h>
#include <helpers.h>
#include <windowsx.h>
extern HINSTANCE g_hInst;
int g_rgnMatchModeResIDs[] =
{
IDS_ENTIREITEMNAME,
IDS_NAMEONLY,
IDS_EXTENSIONONLY
};
enum
{
MATCHMODE_FULLNAME = 0,
MATCHMODE_NAMEONLY,
MATCHMODE_EXTENIONONLY
};
struct FlagCheckboxMap
{
DWORD flag;
DWORD id;
};
FlagCheckboxMap g_flagCheckboxMap[] =
{
{ UseRegularExpressions, IDC_CHECK_USEREGEX },
{ ExcludeSubfolders, IDC_CHECK_EXCLUDESUBFOLDERS },
{ EnumerateItems, IDC_CHECK_ENUMITEMS },
{ ExcludeFiles, IDC_CHECK_EXCLUDEFILES },
{ CaseSensitive, IDC_CHECK_CASESENSITIVE },
{ MatchAllOccurences, IDC_CHECK_MATCHALLOCCRENCES },
{ ExcludeFolders, IDC_CHECK_EXCLUDEFOLDERS },
{ NameOnly, IDC_CHECK_NAMEONLY },
{ ExtensionOnly, IDC_CHECK_EXTENSIONONLY }
};
// IUnknown
IFACEMETHODIMP CPowerRenameUI::QueryInterface(__in REFIID riid, __deref_out void** ppv)
{
static const QITAB qit[] =
{
QITABENT(CPowerRenameUI, IPowerRenameUI),
QITABENT(CPowerRenameUI, IPowerRenameManagerEvents),
QITABENT(CPowerRenameUI, IDropTarget),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
IFACEMETHODIMP_(ULONG) CPowerRenameUI::AddRef()
{
return InterlockedIncrement(&m_refCount);
}
IFACEMETHODIMP_(ULONG) CPowerRenameUI::Release()
{
long refCount = InterlockedDecrement(&m_refCount);
if (refCount == 0)
{
delete this;
}
return refCount;
}
HRESULT CPowerRenameUI::s_CreateInstance(_In_ IPowerRenameManager* psrm, _In_opt_ IDataObject* pdo, _In_ bool enableDragDrop, _Outptr_ IPowerRenameUI** ppsrui)
{
*ppsrui = nullptr;
CPowerRenameUI *prui = new CPowerRenameUI();
HRESULT hr = prui ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
// Pass the IPowerRenameManager to the IPowerRenameUI so it can subscribe to events
hr = prui->_Initialize(psrm, pdo, enableDragDrop);
if (SUCCEEDED(hr))
{
hr = prui->QueryInterface(IID_PPV_ARGS(ppsrui));
}
prui->Release();
}
return hr;
}
// IPowerRenameUI
IFACEMETHODIMP CPowerRenameUI::Show()
{
return _DoModal(NULL);
}
IFACEMETHODIMP CPowerRenameUI::Close()
{
_OnCloseDlg();
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::Update()
{
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::get_hwnd(_Out_ HWND* hwnd)
{
*hwnd = m_hwnd;
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::get_showUI(_Out_ bool* showUI)
{
// Let callers know that it is OK to show UI (ex: progress dialog, error dialog and conflict dialog UI)
*showUI = true;
return S_OK;
}
// IPowerRenameManagerEvents
IFACEMETHODIMP CPowerRenameUI::OnItemAdded(_In_ IPowerRenameItem*)
{
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::OnUpdate(_In_ IPowerRenameItem*)
{
UINT itemCount = 0;
if (m_spsrm)
{
m_spsrm->GetItemCount(&itemCount);
}
m_listview.RedrawItems(0, itemCount);
_UpdateCounts();
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::OnError(_In_ IPowerRenameItem*)
{
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::OnRegExStarted(_In_ DWORD threadId)
{
m_disableCountUpdate = true;
m_currentRegExId = threadId;
_UpdateCounts();
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::OnRegExCanceled(_In_ DWORD threadId)
{
if (m_currentRegExId == threadId)
{
m_disableCountUpdate = false;
_UpdateCounts();
}
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::OnRegExCompleted(_In_ DWORD threadId)
{
// Enable list view
if (m_currentRegExId == threadId)
{
m_disableCountUpdate = false;
_UpdateCounts();
}
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::OnRenameStarted()
{
// Disable controls
EnableWindow(m_hwnd, FALSE);
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::OnRenameCompleted()
{
// Enable controls
EnableWindow(m_hwnd, TRUE);
// Close the window
_OnCloseDlg();
return S_OK;
}
// IDropTarget
IFACEMETHODIMP CPowerRenameUI::DragEnter(_In_ IDataObject* pdtobj, DWORD /* grfKeyState */, POINTL pt, _Inout_ DWORD* pdwEffect)
{
if (m_spdth)
{
POINT ptT = { pt.x, pt.y };
m_spdth->DragEnter(m_hwnd, pdtobj, &ptT, *pdwEffect);
}
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::DragOver(DWORD /* grfKeyState */, POINTL pt, _Inout_ DWORD* pdwEffect)
{
if (m_spdth)
{
POINT ptT = { pt.x, pt.y };
m_spdth->DragOver(&ptT, *pdwEffect);
}
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::DragLeave()
{
if (m_spdth)
{
m_spdth->DragLeave();
}
return S_OK;
}
IFACEMETHODIMP CPowerRenameUI::Drop(_In_ IDataObject* pdtobj, DWORD, POINTL pt, _Inout_ DWORD* pdwEffect)
{
if (m_spdth)
{
POINT ptT = { pt.x, pt.y };
m_spdth->Drop(pdtobj, &ptT, *pdwEffect);
}
_OnClear();
EnableWindow(GetDlgItem(m_hwnd, ID_RENAME), TRUE);
EnableWindow(m_hwndLV, TRUE);
// Populate the manager from the data object
if (m_spsrm)
{
_EnumerateItems(pdtobj);
}
return S_OK;
}
HRESULT CPowerRenameUI::_Initialize(_In_ IPowerRenameManager* psrm, _In_opt_ IDataObject* pdo, _In_ bool enableDragDrop)
{
// Cache the smart rename manager
m_spsrm = psrm;
// Cache the data object for enumeration later
m_spdo = pdo;
m_enableDragDrop = enableDragDrop;
HRESULT hr = CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&m_spdth));
if (SUCCEEDED(hr))
{
// Subscribe to smart rename manager events
hr = m_spsrm->Advise(this, &m_cookie);
}
if (FAILED(hr))
{
_Cleanup();
}
return hr;
}
void CPowerRenameUI::_Cleanup()
{
if (m_spsrm && m_cookie != 0)
{
m_spsrm->UnAdvise(m_cookie);
m_cookie = 0;
m_spsrm = nullptr;
}
m_spdo = nullptr;
m_spdth = nullptr;
if (m_enableDragDrop)
{
RevokeDragDrop(m_hwnd);
}
}
void CPowerRenameUI::_EnumerateItems(_In_ IDataObject* pdtobj)
{
// Enumerate the data object and popuplate the manager
if (m_spsrm)
{
m_disableCountUpdate = true;
EnumerateDataObject(pdtobj, m_spsrm);
m_disableCountUpdate = false;
UINT itemCount = 0;
m_spsrm->GetItemCount(&itemCount);
m_listview.SetItemCount(itemCount);
_UpdateCounts();
}
}
// TODO: persist settings made in the UI
HRESULT CPowerRenameUI::_ReadSettings()
{
return S_OK;
}
HRESULT CPowerRenameUI::_WriteSettings()
{
return S_OK;
}
void CPowerRenameUI::_OnClear()
{
}
void CPowerRenameUI::_OnCloseDlg()
{
// Persist the current settings
_WriteSettings();
EndDialog(m_hwnd, 1);
}
void CPowerRenameUI::_OnDestroyDlg()
{
_Cleanup();
}
void CPowerRenameUI::_OnRename()
{
if (m_spsrm)
{
m_spsrm->Rename(m_hwnd);
}
}
void CPowerRenameUI::_OnAbout()
{
// Launch github page
SHELLEXECUTEINFO info = {0};
info.cbSize = sizeof(SHELLEXECUTEINFO);
info.lpVerb = L"open";
info.lpFile = L"https://github.com/microsoft/PowerToys/tree/master/src/modules/powerrename";
info.nShow = SW_SHOWDEFAULT;
ShellExecuteEx(&info);
}
HRESULT CPowerRenameUI::_DoModal(__in_opt HWND hwnd)
{
HRESULT hr = S_OK;
INT_PTR ret = DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_MAIN), hwnd, s_DlgProc, (LPARAM)this);
if (ret < 0)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
return hr;
}
INT_PTR CPowerRenameUI::_DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
INT_PTR bRet = TRUE; // default for all handled cases in switch below
switch (uMsg)
{
case WM_INITDIALOG:
_OnInitDlg();
break;
case WM_COMMAND:
_OnCommand(wParam, lParam);
break;
case WM_NOTIFY:
bRet = _OnNotify(wParam, lParam);
break;
case WM_CLOSE:
_OnCloseDlg();
break;
case WM_DESTROY:
_OnDestroyDlg();
break;
default:
bRet = FALSE;
}
return bRet;
}
void CPowerRenameUI::_OnInitDlg()
{
// Initialize from stored settings
_ReadSettings();
m_hwndLV = GetDlgItem(m_hwnd, IDC_LIST_PREVIEW);
m_listview.Init(m_hwndLV);
// Initialize checkboxes from flags
if (m_spsrm)
{
DWORD flags = 0;
m_spsrm->get_flags(&flags);
_SetCheckboxesFromFlags(flags);
}
if (m_spdo)
{
// Populate the manager from the data object
_EnumerateItems(m_spdo);
}
// Load the main icon
LoadIconWithScaleDown(g_hInst, MAKEINTRESOURCE(IDI_RENAME), 32, 32, &m_iconMain);
// Update the icon associated with our main app window
SendMessage(m_hwnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)m_iconMain);
SendMessage(m_hwnd, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)m_iconMain);
// TODO: put this behind a setting?
if (m_enableDragDrop)
{
RegisterDragDrop(m_hwnd, this);
}
// Disable rename button by default. It will be enabled in _UpdateCounts if
// there are tiems to be renamed
EnableWindow(GetDlgItem(m_hwnd, ID_RENAME), FALSE);
// Update UI elements that depend on number of items selected or to be renamed
_UpdateCounts();
m_initialized = true;
}
void CPowerRenameUI::_OnCommand(_In_ WPARAM wParam, _In_ LPARAM lParam)
{
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
_OnCloseDlg();
break;
case ID_RENAME:
_OnRename();
break;
case ID_ABOUT:
_OnAbout();
break;
case IDC_EDIT_REPLACEWITH:
case IDC_EDIT_SEARCHFOR:
if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
{
_OnSearchReplaceChanged();
}
break;
case IDC_CHECK_CASESENSITIVE:
case IDC_CHECK_ENUMITEMS:
case IDC_CHECK_EXCLUDEFILES:
case IDC_CHECK_EXCLUDEFOLDERS:
case IDC_CHECK_EXCLUDESUBFOLDERS:
case IDC_CHECK_MATCHALLOCCRENCES:
case IDC_CHECK_USEREGEX:
case IDC_CHECK_EXTENSIONONLY:
case IDC_CHECK_NAMEONLY:
if (BN_CLICKED == HIWORD(wParam))
{
_ValidateFlagCheckbox(LOWORD(wParam));
_GetFlagsFromCheckboxes();
}
break;
}
}
BOOL CPowerRenameUI::_OnNotify(_In_ WPARAM wParam, _In_ LPARAM lParam)
{
bool ret = FALSE;
LPNMHDR pnmdr = (LPNMHDR)lParam;
LPNMLISTVIEW pnmlv = (LPNMLISTVIEW)pnmdr;
NMLVEMPTYMARKUP* pnmMarkup = NULL;
if (pnmdr)
{
BOOL checked = FALSE;
switch (pnmdr->code)
{
case HDN_ITEMSTATEICONCLICK:
if (m_spsrm)
{
m_listview.ToggleAll(m_spsrm, (!(((LPNMHEADER)lParam)->pitem->fmt & HDF_CHECKED)));
_UpdateCounts();
}
break;
case LVN_GETEMPTYMARKUP:
pnmMarkup = (NMLVEMPTYMARKUP*)lParam;
pnmMarkup->dwFlags = EMF_CENTERED;
LoadString(g_hInst, IDS_LISTVIEW_EMPTY, pnmMarkup->szMarkup, ARRAYSIZE(pnmMarkup->szMarkup));
ret = TRUE;
break;
case LVN_BEGINLABELEDIT:
ret = TRUE;
break;
case LVN_KEYDOWN:
if (m_spsrm)
{
m_listview.OnKeyDown(m_spsrm, (LV_KEYDOWN*)pnmdr);
_UpdateCounts();
}
break;
case LVN_GETDISPINFO:
if (m_spsrm)
{
m_listview.GetDisplayInfo(m_spsrm, (LV_DISPINFO*)pnmlv);
}
break;
case NM_CLICK:
{
if (m_spsrm)
{
m_listview.OnClickList(m_spsrm, (NM_LISTVIEW*)pnmdr);
_UpdateCounts();
}
break;
}
}
}
return ret;
}
void CPowerRenameUI::_OnSearchReplaceChanged()
{
// Pass updated search and replace terms to the IPowerRenameRegEx handler
CComPtr<IPowerRenameRegEx> spRegEx;
if (m_spsrm && SUCCEEDED(m_spsrm->get_smartRenameRegEx(&spRegEx)))
{
wchar_t buffer[MAX_PATH] = { 0 };
GetDlgItemText(m_hwnd, IDC_EDIT_SEARCHFOR, buffer, ARRAYSIZE(buffer));
spRegEx->put_searchTerm(buffer);
buffer[0] = L'\0';
GetDlgItemText(m_hwnd, IDC_EDIT_REPLACEWITH, buffer, ARRAYSIZE(buffer));
spRegEx->put_replaceTerm(buffer);
}
}
DWORD CPowerRenameUI::_GetFlagsFromCheckboxes()
{
DWORD flags = 0;
for (int i = 0; i < ARRAYSIZE(g_flagCheckboxMap); i++)
{
if (Button_GetCheck(GetDlgItem(m_hwnd, g_flagCheckboxMap[i].id)) == BST_CHECKED)
{
flags |= g_flagCheckboxMap[i].flag;
}
}
// Ensure we update flags
if (m_spsrm)
{
m_spsrm->put_flags(flags);
}
return flags;
}
void CPowerRenameUI::_SetCheckboxesFromFlags(_In_ DWORD flags)
{
for (int i = 0; i < ARRAYSIZE(g_flagCheckboxMap); i++)
{
Button_SetCheck(GetDlgItem(m_hwnd, g_flagCheckboxMap[i].id), flags & g_flagCheckboxMap[i].flag);
}
}
void CPowerRenameUI::_ValidateFlagCheckbox(_In_ DWORD checkBoxId)
{
if (checkBoxId == IDC_CHECK_NAMEONLY)
{
if (Button_GetCheck(GetDlgItem(m_hwnd, IDC_CHECK_NAMEONLY)) == BST_CHECKED)
{
Button_SetCheck(GetDlgItem(m_hwnd, IDC_CHECK_EXTENSIONONLY), FALSE);
}
}
else if (checkBoxId == IDC_CHECK_EXTENSIONONLY)
{
if (Button_GetCheck(GetDlgItem(m_hwnd, IDC_CHECK_EXTENSIONONLY)) == BST_CHECKED)
{
Button_SetCheck(GetDlgItem(m_hwnd, IDC_CHECK_NAMEONLY), FALSE);
}
}
}
void CPowerRenameUI::_UpdateCounts()
{
// This method is CPU intensive. We disable it during certain operations
// for performance reasons.
if (m_disableCountUpdate)
{
return;
}
UINT selectedCount = 0;
UINT renamingCount = 0;
if (m_spsrm)
{
m_spsrm->GetSelectedItemCount(&selectedCount);
m_spsrm->GetRenameItemCount(&renamingCount);
}
if (m_selectedCount != selectedCount ||
m_renamingCount != renamingCount)
{
m_selectedCount = selectedCount;
m_renamingCount = renamingCount;
// Update selected and rename count label
wchar_t countsLabelFormat[100] = { 0 };
LoadString(g_hInst, IDS_COUNTSLABELFMT, countsLabelFormat, ARRAYSIZE(countsLabelFormat));
wchar_t countsLabel[100] = { 0 };
StringCchPrintf(countsLabel, ARRAYSIZE(countsLabel), countsLabelFormat, selectedCount, renamingCount);
SetDlgItemText(m_hwnd, IDC_STATUS_MESSAGE, countsLabel);
// Update Rename button state
EnableWindow(GetDlgItem(m_hwnd, ID_RENAME), (renamingCount > 0));
}
}
void CPowerRenameListView::Init(_In_ HWND hwndLV)
{
if (hwndLV)
{
m_hwndLV = hwndLV;
EnableWindow(m_hwndLV, TRUE);
// Set the standard styles
DWORD dwLVStyle = (DWORD)GetWindowLongPtr(m_hwndLV, GWL_STYLE);
dwLVStyle |= LVS_ALIGNLEFT | LVS_REPORT | LVS_SHAREIMAGELISTS | LVS_SINGLESEL;
SetWindowLongPtr(m_hwndLV, GWL_STYLE, dwLVStyle);
// Set the extended view styles
ListView_SetExtendedListViewStyle(m_hwndLV, LVS_EX_CHECKBOXES | LVS_EX_DOUBLEBUFFER);
// Get the system image lists. Our list view is setup to not destroy
// these since the image list belongs to the entire explorer process
HIMAGELIST himlLarge;
HIMAGELIST himlSmall;
if (Shell_GetImageLists(&himlLarge, &himlSmall))
{
ListView_SetImageList(m_hwndLV, himlSmall, LVSIL_SMALL);
ListView_SetImageList(m_hwndLV, himlLarge, LVSIL_NORMAL);
}
_UpdateColumns();
}
}
void CPowerRenameListView::ToggleAll(_In_ IPowerRenameManager* psrm, _In_ bool selected)
{
if (m_hwndLV)
{
UINT itemCount = 0;
psrm->GetItemCount(&itemCount);
for (UINT i = 0; i < itemCount; i++)
{
CComPtr<IPowerRenameItem> spItem;
if (SUCCEEDED(psrm->GetItemByIndex(i, &spItem)))
{
spItem->put_selected(selected);
}
}
RedrawItems(0, itemCount);
}
}
void CPowerRenameListView::ToggleItem(_In_ IPowerRenameManager* psrm, _In_ int item)
{
CComPtr<IPowerRenameItem> spItem;
if (SUCCEEDED(psrm->GetItemByIndex(item, &spItem)))
{
bool selected = false;
spItem->get_selected(&selected);
spItem->put_selected(!selected);
RedrawItems(item, item);
}
}
void CPowerRenameListView::OnKeyDown(_In_ IPowerRenameManager* psrm, _In_ LV_KEYDOWN* lvKeyDown)
{
if (lvKeyDown->wVKey == VK_SPACE)
{
int selectionMark = ListView_GetSelectionMark(m_hwndLV);
if (selectionMark != -1)
{
ToggleItem(psrm, selectionMark);
}
}
}
void CPowerRenameListView::OnClickList(_In_ IPowerRenameManager* psrm, NM_LISTVIEW* pnmListView)
{
LVHITTESTINFO hitinfo;
//Copy click point
hitinfo.pt = pnmListView->ptAction;
//Make the hit test...
int item = ListView_HitTest(m_hwndLV, &hitinfo);
if (item != -1)
{
if ((hitinfo.flags & LVHT_ONITEM) != 0)
{
ToggleItem(psrm, item);
}
}
}
void CPowerRenameListView::UpdateItemCheckState(_In_ IPowerRenameManager* psrm, _In_ int iItem)
{
if (psrm && m_hwndLV && (iItem > -1))
{
CComPtr<IPowerRenameItem> spItem;
if (SUCCEEDED(psrm->GetItemByIndex(iItem, &spItem)))
{
bool checked = ListView_GetCheckState(m_hwndLV, iItem);
spItem->put_selected(checked);
UINT uSelected = (checked) ? LVIS_SELECTED : 0;
ListView_SetItemState(m_hwndLV, iItem, uSelected, LVIS_SELECTED);
// Update the rename column if necessary
int id = 0;
spItem->get_id(&id);
RedrawItems(id, id);
}
// Get the total number of list items and compare it to what is selected
// We need to update the column checkbox if all items are selected or if
// not all of the items are selected.
bool checkHeader = (ListView_GetSelectedCount(m_hwndLV) == ListView_GetItemCount(m_hwndLV));
_UpdateHeaderCheckState(checkHeader);
}
}
#define COL_ORIGINAL_NAME 0
#define COL_NEW_NAME 1
void CPowerRenameListView::GetDisplayInfo(_In_ IPowerRenameManager* psrm, _Inout_ LV_DISPINFO* plvdi)
{
UINT count = 0;
psrm->GetItemCount(&count);
if (plvdi->item.iItem < 0 || plvdi->item.iItem > static_cast<int>(count))
{
// Invalid index
return;
}
CComPtr<IPowerRenameItem> renameItem;
if (SUCCEEDED(psrm->GetItemByIndex((int)plvdi->item.iItem, &renameItem)))
{
if (plvdi->item.mask & LVIF_IMAGE)
{
renameItem->get_iconIndex(&plvdi->item.iImage);
}
if (plvdi->item.mask & LVIF_STATE)
{
plvdi->item.stateMask = LVIS_STATEIMAGEMASK;
bool isSelected = false;
renameItem->get_selected(&isSelected);
if (isSelected)
{
// Turn check box on
plvdi->item.state = INDEXTOSTATEIMAGEMASK(2);
}
else
{
// Turn check box off
plvdi->item.state = INDEXTOSTATEIMAGEMASK(1);
}
}
if (plvdi->item.mask & LVIF_PARAM)
{
int id = 0;
renameItem->get_id(&id);
plvdi->item.lParam = static_cast<LPARAM>(id);
}
if (plvdi->item.mask & LVIF_INDENT)
{
UINT depth = 0;
renameItem->get_depth(&depth);
plvdi->item.iIndent = static_cast<int>(depth);
}
if (plvdi->item.mask & LVIF_TEXT)
{
PWSTR subItemText = nullptr;
if (plvdi->item.iSubItem == COL_ORIGINAL_NAME)
{
renameItem->get_originalName(&subItemText);
}
else if (plvdi->item.iSubItem == COL_NEW_NAME)
{
DWORD flags = 0;
psrm->get_flags(&flags);
bool shouldRename = false;
if (SUCCEEDED(renameItem->ShouldRenameItem(flags, &shouldRename)) && shouldRename)
{
renameItem->get_newName(&subItemText);
}
}
StringCchCopy(plvdi->item.pszText, plvdi->item.cchTextMax, subItemText ? subItemText : L"");
CoTaskMemFree(subItemText);
subItemText = nullptr;
}
}
}
void CPowerRenameListView::RedrawItems(_In_ int first, _In_ int last)
{
ListView_RedrawItems(m_hwndLV, first, last);
}
void CPowerRenameListView::SetItemCount(_In_ UINT itemCount)
{
ListView_SetItemCount(m_hwndLV, itemCount);
}
void CPowerRenameListView::_UpdateColumns()
{
if (m_hwndLV)
{
// And the list view columns
int iInsertPoint = 0;
LV_COLUMN lvc = { 0 };
lvc.mask = LVCF_FMT | LVCF_ORDER | LVCF_WIDTH | LVCF_TEXT;
lvc.fmt = LVCFMT_LEFT;
lvc.iOrder = iInsertPoint;
wchar_t buffer[64] = { 0 };
LoadString(g_hInst, IDS_ORIGINAL, buffer, ARRAYSIZE(buffer));
lvc.pszText = buffer;
ListView_InsertColumn(m_hwndLV, iInsertPoint, &lvc);
iInsertPoint++;
lvc.iOrder = iInsertPoint;
LoadString(g_hInst, IDS_RENAMED, buffer, ARRAYSIZE(buffer));
lvc.pszText = buffer;
ListView_InsertColumn(m_hwndLV, iInsertPoint, &lvc);
// Get a handle to the header of the columns
HWND hwndHeader = ListView_GetHeader(m_hwndLV);
if (hwndHeader)
{
// Update the header style to allow checkboxes
DWORD dwHeaderStyle = (DWORD)GetWindowLongPtr(hwndHeader, GWL_STYLE);
dwHeaderStyle |= HDS_CHECKBOXES;
SetWindowLongPtr(hwndHeader, GWL_STYLE, dwHeaderStyle);
_UpdateHeaderCheckState(TRUE);
}
_UpdateColumnSizes();
}
}
void CPowerRenameListView::_UpdateColumnSizes()
{
if (m_hwndLV)
{
RECT rc;
GetClientRect(m_hwndLV, &rc);
ListView_SetColumnWidth(m_hwndLV, 0, (rc.right - rc.left) / 2);
ListView_SetColumnWidth(m_hwndLV, 1, (rc.right - rc.left) / 2);
}
}
void CPowerRenameListView::_UpdateHeaderCheckState(_In_ bool check)
{
// Get a handle to the header of the columns
HWND hwndHeader = ListView_GetHeader(m_hwndLV);
if (hwndHeader)
{
wchar_t szBuff[MAX_PATH] = { 0 };
// Retrieve the existing header first so we
// don't trash the text already there
HDITEM hdi = { 0 };
hdi.mask = HDI_FORMAT | HDI_TEXT;
hdi.pszText = szBuff;
hdi.cchTextMax = ARRAYSIZE(szBuff);
Header_GetItem(hwndHeader, 0, &hdi);
// Set the first column to contain a checkbox
hdi.fmt |= HDF_CHECKBOX;
hdi.fmt |= (check) ? HDF_CHECKED : 0;
Header_SetItem(hwndHeader, 0, &hdi);
}
}