Reputation: 105
I have to add a list of sub keys recursively to an item in a Tree control. I am using InsertItem as shown below. I am attaching the path of this element so that i can retrieve when clicked on the tree control.I am able to add the value but not able to retrieve it.
void CMyDlg::FillTreeWithRegistryKeysEx(CString sPath, HTREEITEM hItem)
{
CString sRegKey = sPath.Left(sPath.Find(_T("\\")));
sPath = sPath.Mid((sPath.Find(_T("\\")) + 1));
sPath = CleanRegistryKey(sPath);
int nKeyCount;
CString sSubKey = _T("");
HKEY handle = GetHkey(sRegKey);
HTREEITEM hReItem = NULL;
HKEY phkey;
std::vector<CString> sSubFolders;
if (RegOpenKeyEx(handle, sPath, 0, KEY_ALL_ACCESS, &phkey) == ERROR_SUCCESS)
sSubFolders = EnumRegistryKey(phkey);
nKeyCount = sSubFolders.size();
for (int nIndex = 0; nIndex < nKeyCount; nIndex++)
{
sSubKey = sPath + _T("\\") +sSubFolders.at(nIndex);
hReItem = m_cTreeCtrl.InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE, sSubFolders.at(nIndex),
icoClosedFolder, icoOpenFolder, 0, 0, (LPARAM)(LPCTSTR)sSubKey, hItem, TVI_LAST);
FillTreeWithRegistryKeys(handle, sSubKey, hReItem);
}
RegCloseKey(phkey);
}
While retrieving the string is always blank.
void CMyDlg::OnTvnSelchangedTree(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
LPARAM lp = pNMTreeView->itemNew.lParam;
CString sKey = (LPCTSTR)lp;
}
what is going wrong?
Upvotes: 1
Views: 1051
Reputation: 31669
As pointed out in previous answer, you are using LPARAM
to point to a string which is destroyed when the function exits. The solution is store the strings in permanent storage. There are many ways to do this. One option is to use CStringArray
member data:
class CMyDlg : public CDialog
{
CStringArray m_strings;
...
};
m_strings
. InsertItem
, this returns HTREEITEM
. tree.SetItemData
to match the tree item with an index in m_strings
tree.GetItemData
to retrieve that indexExample:
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
...
m_strings.RemoveAll();
addKey(L"SOFTWARE\\Microsoft\\Internet Explorer", tree.GetRootItem());
return TRUE;
}
void CMyDlg::addKey(CString path, HTREEITEM parent)
{
CRegKey rg;
if (ERROR_SUCCESS != rg.Open(HKEY_CURRENT_USER, path))
return;
for (int i = 0;; i++)
{
wchar_t buf[300];
DWORD bufsize = 300;
if (rg.EnumKey(i, buf, &bufsize) != ERROR_SUCCESS) break;
HTREEITEM hitem = tree.InsertItem(buf, parent);
CString subkey = path + L"\\" + buf;
m_strings.Add(subkey);
tree.SetItemData(hitem, m_strings.GetCount() - 1);
addKey(subkey, hitem);
}
}
void CMyDlg::OnTvnSelchangedTree(NMHDR *pNMHDR, LRESULT *pResult)
{
HTREEITEM hitem = tree.GetSelectedItem();
if (!hitem) return;
int i = tree.GetItemData(hitem);
if (i >= 0 && i < m_strings.GetCount())
SetWindowText(m_strings[i]);
}
Upvotes: 1
Reputation: 1385
The application-defined LPARAM passed to InsertItem is a string object that goes out of scope once the function completes not to mention it is replaced with each loop iteration with a new string. I don't think that is going to work.
The TreeView control however allocates its own copy of the text, so you are safe to fill in the pszText member with local buffers as it appears you are doing.
Upvotes: 2