SHBrowseForFolder "Make New Folder" behavior in Windows XP - visual-c++

I am using SHBrowseForFolder with the new dialog style which gives you an 'Make New Folder' button on
I am getting some problems with this in Windows XP.
The behavior is like this:
1) First when I invoke the dialog, the behaviour is usual(i.e, It is selecting the current folder. But
the focus is not on the tree item(dimmed).
If I click Make new folder button with this state a new folder is creating but it is not in selected
state(i.e, When ever we create a new folder it will allow you to rename folder with the selection on
the item and editbox).
If i select the directory(i.e, setting focus to the item) and then clicking on new folder creating folder
in selected state.
(In Windows 8,windows 7 and Windows Vista it is working Fine)
Anyone faced this problem.
Is there any solution for this?
bool GetFolder(std::string& folderpath, const char* szCaption = NULL, HWND hOwner = NULL)
{
bool retVal = false;
// The BROWSEINFO struct tells the shell
// how it should display the dialog.
BROWSEINFO bi;
memset(&bi, 0, sizeof(bi));
bi.ulFlags = BIF_NEWDIALOGSTYLE|BIF_RETURNFSANCESTORS|BIF_RETURNONLYFSDIRS;
bi.hwndOwner = hOwner;
bi.lpszTitle = szCaption;
// must call this if using BIF_USENEWUI
::OleInitialize(NULL);
// Show the dialog and get the itemIDList for the selected folder.
LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);
if(pIDL != NULL)
{
// Create a buffer to store the path, then get the path.
char buffer[_MAX_PATH] = {'\0'};
if(::SHGetPathFromIDList(pIDL, buffer) != 0)
{
// Set the string value.
folderpath = "";
retVal = true;
}
// free the item id list
CoTaskMemFree(pIDL);
}
::OleUninitialize();
return retVal;
}

This seems to be a bug in Windows XP.
Try the code below. This may be not quite what you want, it automatically expands the default folder, but at least it results in a more or less correct behaviour. I tested it on Windows XP and on Windows 7. On later versions of Windows this might not work as expected, so possibily you should check if you are running under XP and do that quirk only if you are running under XP.
int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM pData)
{
if (uMsg == BFFM_INITIALIZED)
{
HWND hchild = GetWindow(hWnd, GW_CHILD) ;
while (hchild != NULL)
{
TCHAR classname[200] ;
GetClassName(hchild, classname, 200) ;
if (lstrcmp(classname, "SHBrowseForFolder ShellNameSpace Control") == 0)
{
// hchild is the handle to the ShellName Space Control
HWND hlistctrl = GetWindow(hchild, GW_CHILD) ;
do
{
// browse through all controls of the ShellnameSpace control
GetClassName(hlistctrl, classname, 200) ;
if (lstrcmp(classname, "SysTreeView32") == 0)
break ; // we've got the list control
hlistctrl = GetWindow(hlistctrl, GW_HWNDNEXT) ;
} while (hlistctrl != NULL) ;
if (hlistctrl != NULL)
{
// get the handle to the selected item
HTREEITEM ht = (HTREEITEM)::SendMessage(hlistctrl, TVM_GETNEXTITEM, TVGN_CARET, 0) ;
if (ht != NULL)
{
// expand the selected item
::SendMessage(hlistctrl, TVM_EXPAND, TVE_EXPAND, (LPARAM)ht) ;
}
}
}
hchild = GetWindow(hchild, GW_HWNDNEXT) ;
}
}
return 0;
}
bool GetFolder(CString& folderpath, const char* szCaption, HWND hOwner)
{
bool retVal = false;
// how it should display the dialog.
BROWSEINFO bi;
memset(&bi, 0, sizeof(bi));
bi.ulFlags = BIF_NEWDIALOGSTYLE|BIF_RETURNFSANCESTORS|BIF_RETURNONLYFSDIRS;
bi.lpfn = BrowseCallbackProc ;
bi.hwndOwner = hOwner;
bi.lpszTitle = szCaption;
// must call this if using BIF_USENEWUI
::OleInitialize(NULL);
// Show the dialog and get the itemIDList for the selected folder.
LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);
if (pIDL != NULL)
{
// Create a buffer to store the path, then get the path.
char buffer[_MAX_PATH] = {'\0'};
if(::SHGetPathFromIDList(pIDL, buffer) != 0)
{
// Set the string value.
folderpath = buffer;
retVal = true;
}
// free the item id list
CoTaskMemFree(pIDL);
}
::OleUninitialize();
return retVal;
}
Another solution would be using the BFFM_SETEXPANDED message as shown below. In this example the "C:" folder is automatically expanded and then the "New Folder" button behaves correctly.
int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM pData)
{
if (uMsg == BFFM_INITIALIZED)
{
::SendMessage(hWnd, BFFM_SETEXPANDED, TRUE, (LPARAM)L"C:\\") ;
}
return 0;
}

Related

Is there another way to get a COleDateTime object from another dialog using SendMessage?

I have a registered user message. This is the handler:
afx_msg LRESULT CChristianLifeMinistryEditorDlg::OnGetDate(WPARAM wParam, LPARAM lParam)
{
const auto eDateType = gsl::narrow<CInsertDateDlg::EnumDateType>(wParam);
if (eDateType == CInsertDateDlg::EnumDateType::Start)
{
return CInPlaceDT::GetLongDate(m_datStartDate);
}
if (eDateType == CInsertDateDlg::EnumDateType::End)
{
return CInPlaceDT::GetLongDate(m_datEndDate);
}
if (eDateType == CInsertDateDlg::EnumDateType::Meeting)
{
return CInPlaceDT::GetLongDate(m_pEntry->GetMeetingDate());
}
return CInPlaceDT::GetLongDate(COleDateTime::GetCurrentTime());
}
The referenced function is:
long CInPlaceDT::GetLongDate(COleDateTime timDate) noexcept
{
const long lDate = (timDate.GetYear() * 10000) +
(timDate.GetMonth() * 100 ) +
timDate.GetDay();
return lDate;
}
I use the code like this (some lines stripped out for simplicity):
// 1. CEditTextDlg
// 2. CSMCustomizeDlg
// 3. CChristianLifeMinistryEditor
const CWnd* pParent = GetParent()->GetParent()->GetParent();
if (pParent != nullptr)
{
COleDateTime datToUse;
long lDate{};
lDate = gsl::narrow<long>(pParent->SendMessage(theApp.UWM_GET_DATE_MSG,
gsl::narrow<WPARAM>(CInsertDateDlg::EnumDateType::Start)));
CInPlaceDT::GetOleDateTime(lDate, datToUse);
lDate = gsl::narrow<long>(pParent->SendMessage(theApp.UWM_GET_DATE_MSG,
gsl::narrow<WPARAM>(CInsertDateDlg::EnumDateType::End)));
CInPlaceDT::GetOleDateTime(lDate, datToUse);
lDate = gsl::narrow<long>(pParent->SendMessage(theApp.UWM_GET_DATE_MSG,
gsl::narrow<WPARAM>(CInsertDateDlg::EnumDateType::Meeting)));
CInPlaceDT::GetOleDateTime(lDate, datToUse);
}
The second referenced function is:
void CInPlaceDT::GetOleDateTime(long lDate, COleDateTime &timDate) noexcept
{
const auto nYear = lDate / 10000;
const auto nMonth = (lDate / 100) % 100;
const auto nDay = lDate % 100;
timDate.SetDateTime(nYear, nMonth, nDay, 0, 0, 0);
}
This concept works. It converts the date to a long, returns it via the message and is converted back to a date object.
I just wondered if I could pass the object as a date variable? This is all within the same process. A grandchild dialog is getting a date from the grandparent dialog.
Update
I tried to follow the suggestion in the comments:
afx_msg LRESULT CChristianLifeMinistryEditorDlg::OnGetDate(WPARAM wParam, LPARAM lParam)
{
const auto eDateType = gsl::narrow<CInsertDateDlg::EnumDateType>(wParam);
if (eDateType == CInsertDateDlg::EnumDateType::Start)
{
return gsl::narrow<LRESULT>(&m_datStartDate); // CInPlaceDT::GetLongDate(m_datStartDate);
}
if (eDateType == CInsertDateDlg::EnumDateType::End)
{
return gsl::narrow<LRESULT>(&m_datEndDate); // CInPlaceDT::GetLongDate(m_datEndDate);
}
if (eDateType == CInsertDateDlg::EnumDateType::Meeting)
{
return gsl::narrow<LRESULT>(&(m_pEntry->GetMeetingDate())); // CInPlaceDT::GetLongDate(m_pEntry->GetMeetingDate());
}
return 0;
// return CInPlaceDT::GetLongDate(COleDateTime::GetCurrentTime());
}
But it does not like:
return gsl::narrow<LRESULT>(&(m_pEntry->GetMeetingDate()));
It says:
error C2102: '&' requires l-value
As other window function do it too. Pass a pointer in LPARAM. Save the value in that pointer
afx_msg LRESULT CChristianLifeMinistryEditorDlg::OnGetDate(WPARAM , LPARAM lParam)
{
*reinterpret_cast<COleDateTime*>(lParam) = myValue;
Remember that a COleDateTime is just a DATE (is a double).
You may use a VARIANT* to that may handle all types of data (even an empty/null COleDateTime)
In detail: Use VT_NULL or VT_EMPTY for COleDateTime::null. For COleDateTime::error/invalid you can use VT_ERROR with the value E_INVALIDARG or any suitable.
For a COleDateTime::valid just store the m_dt member in the VARIANT with VT_DATE.

How to change icon for a some files of file type?

I have IconHandler to change icon for some files. But other files icons becomes blank. How to leave default icon for other files?
HRESULT CSimpleShlExt::GetIconLocation(UINT uFlags,
PTSTR pszIconFile,
UINT cchMax,
int *piIndex,
UINT *pwFlags)
{
if (condition)){
// works well
lstrcpyn(pszIconFile, L"C:\\Windows\\System32\\shell32.dll", cchMax);
*piIndex = 5;
*pwFlags = 0;
} else {
// blank icon :(
*pwFlags = GIL_PERINSTANCE | GIL_NOTFILENAME;// | GIL_DONTCACHE ;
}
return S_OK;
}
Here is my .rgs file:
HKCR
{
NoRemove CLSID
{
ForceRemove {B70B7A24-5180-4092-B3BA-6266F914C053} = s 'My Shell Extension'
{
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
TypeLib = s '{62C6D1EB-C172-4E05-BFD2-5F9313832CC3}'
Version = s '1.0'
}
}
NoRemove txtfile
{
NoRemove ShellEx
{
ForceRemove IconHandler = s '{B70B7A24-5180-4092-B3BA-6266F914C053}'
}
}
}
This code works:
HRESULT CSimpleShlExt::GetIconLocation(UINT uFlags,
PTSTR pszIconFile,
UINT cchMax,
int *piIndex,
UINT *pwFlags)
{
if (condition))
{
lstrcpyn(pszIconFile, L"C:\\Windows\\System32\\Test.dll", cchMax);
*piIndex = 0;
}
else
{
*piIndex = 1;
}
*pwFlags = 0;
return S_OK;
}
HRESULT CSimpleShlExt::Extract(
LPCTSTR pszFile,
UINT nIconIndex,
HICON *phiconLarge,
HICON *phiconSmall,
UINT nIconSize)
{
return S_FALSE;
}
Changed .rgs file:
HKCR
{
NoRemove CLSID
{
ForceRemove {B70B7A24-5180-4092-B3BA-6266F914C053} = s 'My Shell Extension'
{
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
TypeLib = s '{62C6D1EB-C172-4E05-BFD2-5F9313832CC3}'
Version = s '1.0'
}
}
NoRemove txtfile
{
NoRemove DefaultIcon = s '%%1'
NoRemove ShellEx
{
ForceRemove IconHandler = s '{B70B7A24-5180-4092-B3BA-6266F914C053}'
}
}
}
From 'MSDN' - How to Create Icon Handlers:
Registering Icon Handlers
When you statically register an icon for a file type, you create a
DefaultIcon subkey under the ProgID for the file type. Its default
value is set to the file that contains the icon. To register an icon
handler, you must still have the DefaultIcon subkey, but its default
value must be set to "%1".
You could do this by passing through a dummy name to SHGetFileInfo. For example,
HRESULT CSimpleShlExt::GetIconLocation(UINT uFlags,
PTSTR pszIconFile,
UINT cchMax,
int *piIndex,
UINT *pwFlags)
{
if (condition){
// works well
lstrcpyn(pszIconFile, L"C:\\Windows\\System32\\shell32.dll", cchMax);
*piIndex = 5;
*pwFlags = 0;
} else {
SHFILEINFO sfi;
SHGetFileInfo(L"dummy", FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi),
SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES);
StringCchCopy(pszIconFile, cchMax, sfi.szDisplayName);
*piIndex = sfi.iIcon;
*pwFlags = 0;
}
return S_OK;
}
The key is to pass the SHGFI_USEFILEATTRIBUTES flag, which means the filename you provide does not need to refer to a real file.
Providing a filename without a file extension (as in the above example) will mean you get back the system's default file icon.
And finally the SHGFI_ICONLOCATION flag returns the icon path and index in the fields of the SHFILEINFO structure.

How to Print the particular contents in the entire document using DHTML

In these example, I want to print the contents in the ID tab_form_1.While trying these
sample to print the tab_form_1 contents,lpOleCommandTarget become NULL while query interface using CComptr .
How to solve this issue?
SAMMPLE
IHTMLDocument2 *pDoc;
GetDHtmlDocument(&pDoc);
CComPtr<IHTMLElement2> spControl;
if(GetElementInterface(_T("tab_form_1") ,&spControl) != S_OK)
return;
//ole command target
LPOLECOMMANDTARGET lpOleCommandTarget = NULL;
spControl->QueryInterface(IID_IOleCommandTarget,(void**)&lpOleCommandTarget);ASSERT(lpOleCommandTarget);
//lpDispatch->Release();
if(lpOleCommandTarget == NULL) return;
//prepare header
CString header = _T("Project Path: &w");
VARIANT header_variant;
VariantInit(&header_variant);
V_VT(&header_variant) = VT_BSTR;
V_BSTR(&header_variant) = CString(header).AllocSysString();
//prepare footer
CString footer = _T("&d &t&b Page&p of &P");
VARIANT footer_variant;
VariantInit(&footer_variant);
V_VT(&footer_variant) = VT_BSTR;
V_BSTR(&footer_variant) = CString(footer).AllocSysString();
//prepare header footer safe arrray
SAFEARRAYBOUND parameter_array_bound[1];
SAFEARRAY *parameter_array = NULL;
parameter_array_bound[0].cElements = 2;
parameter_array_bound[0].lLbound = 0;
parameter_array = SafeArrayCreate(VT_VARIANT,1,parameter_array_bound);
//HRESULT hr;
long index;
index = 0;
HRESULT hr = SafeArrayPutElement(parameter_array,&index,&header_variant);
index = 1;
hr = SafeArrayPutElement(parameter_array,&index,&footer_variant);
VARIANT parameter;
VariantInit(&parameter);
V_VT(&parameter) = VT_ARRAY | VT_BYREF;
V_ARRAY(&parameter) = parameter_array;
// print contents of web browser control
lpOleCommandTarget->Exec(NULL, OLECMDID_PRINT, OLECMDEXECOPT_DODEFAULT, &parameter,NULL);
//clear all variants
VariantClear(&header_variant);
VariantClear(&footer_variant);
if (parameter_array != NULL) {
SafeArrayDestroy(parameter_array);
}
lpOleCommandTarget->Release();
Try this sample.This will eradicate your problem.This code will print the particular contents into the newly created document.
// create DHtmlDocument for Newly Created Dialog
HRESULT hDispatch = printdlg->m_pBrowserApp->get_Document((IDispatch**)&pDisp);
if(hDispatch != S_OK) return;
HRESULT hResult = pDisp->QueryInterface(IID_IHTMLDocument2, (void**)&pNewDoc);
if(hResult != S_OK) return;
//GetDHtmlDocument for new document
GetDHtmlDocument(&pDoc);
BSTR strSummaryText = GetElementHtml(L"tab_form_1");
// Creates a new one-dimensional array
SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1);
if (psaStrings == NULL) {
return;
}
VARIANT *param;
HRESULT hresult = SafeArrayAccessData(psaStrings, (LPVOID*)&param);
param->vt = VT_BSTR;
param->bstrVal = strSummaryText;
hresult = SafeArrayUnaccessData(psaStrings);
//it will write the div part of tab_form_1 into new document to pass the summary contents alone to the printer
hresult = pNewDoc->write(psaStrings);
// SafeArrayDestroy calls SysFreeString for each strtemp
if (psaStrings != NULL) {
SafeArrayDestroy(psaStrings);
}

Is there a way to use normal ASCII characters (like a comma) as wxWidgets menu accelerators?

I want a few menu entries that show accelerators that are normal keys, like the space-bar or comma key, but I don't want wxWidgets to make those accelerators itself (because then they can't be used anywhere in the program, including in things like edit boxes).
Unfortunately, wxWidgets insists on always making anything it recognizes in that column into an accelerator under its control, and simply erases anything it doesn't recognize.
I'm looking for some way to either put arbitrary text into the accelerator column (which I don't think exists, I've looked at the source code), or get 'hold of the accelerator table used for the menus so I can modify it myself (haven't found it yet). Can anyone point me in the right direction?
You can try wxKeyBinder. It allows you to bind hotkeys to commands (usually menu entries), save/load/add/remove/modify ... them easily
I couldn't find a way to access the menu's accelerator keys directly, but modifying the accelerator menu text works just as well. Here's the code I came up with:
In a header file:
class accel_t {
public:
// If idcount == -1, idlist must be null or terminated with a -1 entry.
accel_t(): mMenu(0) { }
accel_t(wxMenuBar *m, int *idlist = 0, int idcount = -1);
void reset(wxMenuBar *m, int *idlist = 0, int idcount = -1);
void restore() const;
void remove() const;
private: //
struct accelitem_t {
accelitem_t(int _id, wxAcceleratorEntry _key): id(_id), hotkey(_key) { }
int id;
wxAcceleratorEntry hotkey;
};
typedef std::vector<accelitem_t> data_t;
void noteProblemMenuItems(wxMenu *m);
static bool isProblemAccelerator(wxAcceleratorEntry *a);
wxMenuBar *mMenu;
data_t mData;
};
In a cpp file:
accel_t::accel_t(wxMenuBar *m, int *idlist, int idcount) {
reset(m, idlist, idcount);
}
void accel_t::reset(wxMenuBar *m, int *idlist, int idcount) {
mMenu = m;
mData.clear();
if (idlist == 0) {
for (int i = 0, ie = m->GetMenuCount(); i != ie; ++i)
noteProblemMenuItems(m->GetMenu(i));
} else {
if (idcount < 0) {
int *i = idlist;
while (*i != -1) ++i;
idcount = (i - idlist);
}
for (int *i = idlist, *ie = i + idcount; i != ie; ++i) {
wxMenuItem *item = mMenu->FindItem(*i);
if (item) {
wxAcceleratorEntry *a = item->GetAccel();
if (a != 0) mData.push_back(accelitem_t(*i, *a));
}
}
}
}
bool accel_t::isProblemAccelerator(wxAcceleratorEntry *a) {
if (a == 0) return false;
int flags = a->GetFlags(), keycode = a->GetKeyCode();
// Normal ASCII characters, when used with no modifier or Shift-only, would
// interfere with editing.
if ((flags == wxACCEL_NORMAL || flags == wxACCEL_SHIFT) &&
(keycode >= 32 && keycode < 127)) return true;
// Certain other values, when used as normal accelerators, could cause
// problems too.
if (flags == wxACCEL_NORMAL) {
if (keycode == WXK_RETURN ||
keycode == WXK_DELETE ||
keycode == WXK_BACK) return true;
}
return false;
}
void accel_t::noteProblemMenuItems(wxMenu *m) {
// Problem menu items have hotkeys that are ASCII characters with normal or
// shift-only modifiers.
for (size_t i = 0, ie = m->GetMenuItemCount(); i != ie; ++i) {
wxMenuItem *item = m->FindItemByPosition(i);
if (item->IsSubMenu())
noteProblemMenuItems(item->GetSubMenu());
else {
wxAcceleratorEntry *a = item->GetAccel();
if (isProblemAccelerator(a))
mData.push_back(accelitem_t(item->GetId(), *a));
}
}
}
void accel_t::restore() const {
if (mMenu == 0) return;
for (data_t::const_iterator i = mData.begin(), ie = mData.end(); i != ie;
++i)
{
wxMenuItem *item = mMenu->FindItem(i->id);
if (item) {
wxString text = item->GetItemLabel().BeforeFirst(wxT('\t'));
wxString hotkey = i->hotkey.ToString();
if (hotkey.empty()) {
// The wxWidgets authors apparently don't expect ASCII
// characters to be used for accelerators, because
// wxAcceleratorEntry::ToString just returns an empty string for
// them. This code deals with that.
int flags = i->hotkey.GetFlags(), key = i->hotkey.GetKeyCode();
if (flags == wxACCEL_SHIFT) hotkey = wx("Shift-") + wxChar(key);
else hotkey = wxChar(key);
}
item->SetItemLabel(text + '\t' + hotkey);
}
}
}
void accel_t::remove() const {
if (mMenu == 0) return;
for (data_t::const_iterator i = mData.begin(), ie = mData.end(); i != ie;
++i)
{
wxMenuItem *item = mMenu->FindItem(i->id);
if (item) {
wxString text = item->GetItemLabel().BeforeFirst(wxT('\t'));
item->SetItemLabel(text);
}
}
}
The easiest way to use it is to create your menu-bar as normal, with all accelerator keys (including the problematic ones) in place, then create an accel_t item from it something like this:
// mProblemAccelerators is an accel_t item in the private part of my frame class.
// This code is in the frame class's constructor.
wxMenuBar *menubar = _createMenuBar();
SetMenuBar(menubar);
mProblemAccelerators.reset(menubar);
It will identify and record the accelerator keys that pose problems. Finally, call the remove and restore functions as needed, to remove or restore the problematic accelerator keys. I'm calling them via messages passed to the frame whenever I open a window that needs to do standard editing.

how to differentiate a Folder Type(Windows/FTP) in MFC(VC++)?

how to differentiate a Folder Type(Windows/FTP) in MFC(VC++)?
In my case I have a MFC Treeview in which i am adding list of folders coming from server , that folders are Windows and CIFS .Now i want to differentiate internally what type of folder are they because i select some folder and say connect then it brings up login page where i need to login credentials details , but before that i need to differentiate what type of folder is that ?
Any treeview property like setting and geeting key or any other approach.
Thanks in Advance.
I get folder list from server in this format volume1/Folder1,volume2/Folder2||Folder3,Folder4 in this below method i am removing "||" and maintaining them in two differnt variables: strDataFolder contains - FTP Folders and
strNASfolders conatins CIFS folder , then one more method i am using UpdateFolder. If it is FTP then directly Add but if it CIFS check for duplication if that folder is already there dont add it again to treeview.
Now iam not able to get it how to differentiate what type of folder are they ?
void CNDSClientDlg::UpdateSharedFolder(CString strNASfolders,HTREEITEM hChildItem)
{
CString strDataFolder = "";
CString strData = "";
int iPos = 0;
int fPosition = 0;
fPosition = strNASfolders.Find("||");
if(fPosition != -1)
{
strDataFolder = strNASfolders.Mid(0,fPosition);
strNASfolders = strNASfolders.Right(strNASfolders.GetLength()-(fPosition+2));
}
else
{
strDataFolder = strNASfolders;
}
if (strDataFolder != "" )
{
UpdateFolders(strDataFolder,hChildItem,false);
}
if (strNASfolders != "" ) //don't add if already exist
{
UpdateFolders(strNASfolders,hChildItem,true);
}
}
void CNDSClientDlg::UpdateFolders(CString strFolderType,HTREEITEM hChildItem,bool bCheck)
{
int iPos = 0 ;
CString strData = "";
CString strCurrFolder ="";
HTREEITEM HShareFolder = NULL;
bool bFound = false ;
while (iPos != -1)
{
iPos = strFolderType.Find(",");
if (iPos != -1)
{
strData = strFolderType.Mid(0,iPos);//get the folder details
}
else
{
strData = strFolderType;//get the last folder details
}
strFolderType = strFolderType.Right(strFolderType.GetLength()-(iPos+1)); //get remaining data
int fPos = strData.ReverseFind('/');
if (fPos != -1)
{
strCurrFolder = strData.Mid(fPos+1,strData.GetLength()); // get required data
}
else
{
strCurrFolder = strData; //else assign all the data
}
if(bCheck == true)
{
bFound = false ;
HTREEITEM hTempItem = NULL;
CString strItemText = "" ;
hTempItem = m_pTreeview->GetChildItem(hChildItem);
strItemText = m_pTreeview->GetItemText(hTempItem);
while(hTempItem != NULL)
{
if(strItemText != strCurrFolder)
{
strItemText = m_pTreeview->GetItemText(hTempItem);
hTempItem = m_pTreeview->GetNextSiblingItem(hTempItem);
}
else
{
bFound = true;
break;
}
}
}
if(bCheck == false || bFound == false)
{
HShareFolder = m_pTreeview->InsertItem(strCurrFolder,hChildItem);
m_pTreeview->SetItemImage(HShareFolder,2,2);
TTipItemData* pToolTipData ;
pToolTipData = new TTipItemData;
pToolTipData->strTool = strData ;
m_pTreeview->SetItemData(HShareFolder,DWORD(pToolTipData));
}
m_pTreeview->Expand(hParentItem,TVE_EXPAND);
m_pTreeview->EnsureVisible(hParentItem);
}
}
Items in treeviews can have arbitrary data associated with them. Check out:
http://msdn.microsoft.com/en-us/library/ettyybhw(VS.80).aspx
The InsertItem method shown here has an LPARAM parameter. This is for your use, and you can set this to some value that is meaningful to your application.
(EDIT: Alternatively, use one of the least convoluted overloads to insert your item and use CTreeCtrl::SetItemData on the handle that is returned afterwards).
To find out what value is associated with your item, use CTreeCtrl::GetItemData.
Minor Example:
HTREEITEM hItem = m_ctrlTree.InsertItem("My Item", TVI_ROOT);
HTREEITEM hOther = m_ctrlTree.InsertItem("Child Item", hItem);
m_ctrlTree.SetItemData(hItem, static_cast<DWORD_PTR>(10)); // set LPARAM to 10
// note, you can also store pointers! This assumes pObj is some kind of instance
// of a class.
m_ctrlTree.SetItemData(hOther, static_cast<DWORD_PTR>(pObj));
// at a later point:
int myVal = static_cast<int>(m_ctrlTree.GetItemData(hItem));
MyObject* pObj = static_cast<MyObject*>(m_ctrlTree.GetItemData(hOther));

Resources