// // Folder.C // // Copyright (C) Microsoft, 1994,1995 All Rights Reserved. // // History: // ral 6/23/94 - First pass // 3/20/95 [stevecat] - NT port & real clean up, unicode, etc. // // #include "priv.h" #include "appwiz.h" #include "help.h" // Help context IDs typedef struct _FILEITEMDATA { DWORD dwFlags; TCHAR szPath[1]; } FILEITEMDATA, * LPFILEITEMDATA; #define FIDFLAG_CANADDNEW 0x00000001 #define FIDFLAG_CANDEL 0x00000002 #define FIDFLAG_ISFOLDER 0x00000004 #define FIDFLAG_ISPROGS 0x00000008 // // // int CALLBACK CompareFolderCB(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { #define lpfid1 ((LPFILEITEMDATA)lParam1) #define lpfid2 ((LPFILEITEMDATA)lParam2) #define b1IsDir (lpfid1->dwFlags & FIDFLAG_ISFOLDER) #define b2IsDir (lpfid2->dwFlags & FIDFLAG_ISFOLDER) // // Programs folder always goes to top // if (lpfid1->dwFlags & FIDFLAG_ISPROGS) { return(-1); } if (lpfid2->dwFlags & FIDFLAG_ISPROGS) { return(1); } if (b1IsDir == b2IsDir) { return(lstrcmpi(lpfid1->szPath, lpfid2->szPath)); } else { if (b1IsDir) { return(-1); } else { return(1); } } #undef b1IsDir #undef b2IsDir #undef lpfid1 #undef lpfid2 } // // Sorts the specified folder so that folders appear at the top and all // files appear in alphabetical order below. // void SortFolder(HWND hwndTree, HTREEITEM hParent) { TV_SORTCB sSortCB; sSortCB.hParent = hParent; sSortCB.lpfnCompare = CompareFolderCB; sSortCB.lParam = 0; TreeView_SortChildrenCB(hwndTree, &sSortCB, FALSE); } // // Adds a new folder for the specifed path and returns its HTREEITEM. If // it is unable to add the item then NULL is returned. // NOTE: If dwFileAttributes == AI_NOATTRIB (-1) then no attributes specified. // If pidl is NULL then no pidl specified. // HTREEITEM AddItem(HWND hwndTree, LPCTSTR pszPath, HTREEITEM hParent, LPITEMIDLIST pidl, DWORD dwFlags) { HTREEITEM newhti = NULL; int cchPath = lstrlen(pszPath) + 1; LPFILEITEMDATA lpfid = (LPFILEITEMDATA)LocalAlloc(LMEM_FIXED, sizeof(FILEITEMDATA) + (cchPath*sizeof(TCHAR)) ); if (lpfid) { TV_INSERTSTRUCT tvis; lpfid->dwFlags = dwFlags; StringCchCopy(lpfid->szPath, cchPath, pszPath); tvis.item.pszText = LPSTR_TEXTCALLBACK; tvis.item.iImage = tvis.item.iSelectedImage = I_IMAGECALLBACK; tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvis.item.lParam = (LPARAM)lpfid; tvis.hParent = hParent; tvis.hInsertAfter = TVI_LAST; newhti = TreeView_InsertItem(hwndTree, &tvis); if (!newhti) LocalFree((LPVOID)lpfid); } return newhti; } // // Flags for FillFolder // #define FFF_AddFiles 1 #define FFF_AddDirs 2 // // Recursively add all folders below CurDir to the tree below hParent // BOOL IsFolderShortcut(LPCTSTR pszName) { SHFOLDERCUSTOMSETTINGS fcs = {0}; CLSID clsid = {0}; fcs.dwSize = sizeof(fcs); fcs.dwMask = FCSM_CLSID; fcs.pclsid = &clsid; if (SUCCEEDED(SHGetSetFolderCustomSettings(&fcs, pszName, FCS_READ))) { return IsEqualGUID(&clsid, &CLSID_FolderShortcut); } return FALSE; } void FillFolder(HWND hwndTree, LPTSTR lpszCurDir, UINT cchCurDir, LPTSTR lpszExclude, HTREEITEM hParent, DWORD dwFlags) { int iStrTerm = lstrlen(lpszCurDir); WIN32_FIND_DATA fd; HANDLE hfind; HTREEITEM hNewItem = NULL; #define bAddFiles (dwFlags & FFF_AddFiles) #define bAddDirs (dwFlags & FFF_AddDirs) StringCchCat(lpszCurDir, cchCurDir, TEXT("\\*.*")); hfind = FindFirstFile(lpszCurDir, &fd); if (hfind != INVALID_HANDLE_VALUE) { do { BOOL bIsDir = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); if (((bAddFiles && !bIsDir) || // skip "." and ".." and hidden files (bAddDirs && bIsDir && (fd.cFileName[0] != TEXT('.')))) && !(fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) { lpszCurDir[iStrTerm] = TEXT('\\'); lstrcpy(lpszCurDir + iStrTerm + 1, fd.cFileName); // let's fudge it -- if it's a folder shortcut, don't treat it // like a real folder, since we can't navigate into it anyway // and it's not worth the trouble to try. if (bIsDir && IsFolderShortcut(lpszCurDir)) { bIsDir = FALSE; } // // Don't add this if it's supposed to be excluded // if (!lpszExclude || !bIsDir || lstrcmpi(lpszExclude, lpszCurDir) != 0) { hNewItem = AddItem(hwndTree, lpszCurDir, hParent, NULL, FIDFLAG_CANADDNEW | FIDFLAG_CANDEL | (bIsDir ? FIDFLAG_ISFOLDER : 0)); if (bIsDir) { FillFolder(hwndTree, lpszCurDir, cchCurDir, NULL, hNewItem, dwFlags); } } } } while (FindNextFile(hfind, &fd)); FindClose(hfind); } lpszCurDir[iStrTerm] = 0; // // Non-null if any items added to folder. // if (hNewItem) { SortFolder(hwndTree, hParent); if (!bAddFiles) { TreeView_Expand(hwndTree, hParent, TVE_EXPAND); } } #undef bAddFiles #undef bRecurse } // // Returns a pointer to the directory string for the currently selected // item. // LPFILEITEMDATA GetCurSel(HWND hwndTree, HTREEITEM * lphtiSel) { TV_ITEM tvi; tvi.hItem = TreeView_GetSelection(hwndTree); if (lphtiSel) { *lphtiSel = tvi.hItem; } if (tvi.hItem == NULL) { return(NULL); } tvi.mask = TVIF_PARAM; TreeView_GetItem(hwndTree, &tvi); return((LPFILEITEMDATA)tvi.lParam); } // // Add the specified special folder.. // HTREEITEM AddSpecialFolder(HWND hwndTree, HTREEITEM htiParent, int nFolder, LPTSTR pszPath, DWORD dwFlags) { LPITEMIDLIST pidl = NULL; HTREEITEM hti = NULL; if (SUCCEEDED(SHGetSpecialFolderLocation(hwndTree, nFolder, &pidl))) { if (SHGetPathFromIDList(pidl, pszPath)) { // // For the desktop, we want the desktop directory, but the icon // for the magic desktop PIDL. // if (nFolder == CSIDL_DESKTOPDIRECTORY) { SHFree(pidl); if (FAILED(SHGetSpecialFolderLocation(hwndTree, CSIDL_DESKTOP, &pidl))) { pidl = NULL; } } if (NULL != pidl) { hti = AddItem(hwndTree, pszPath, htiParent, pidl, FIDFLAG_ISFOLDER | dwFlags); } } } if (NULL != pidl) { SHFree(pidl); } return(hti); } BOOL _inline MakePrgIcon0Index(HWND hwndTree, HIMAGELIST himl) { LPITEMIDLIST pidl; if (SUCCEEDED(SHGetSpecialFolderLocation(hwndTree, CSIDL_PROGRAMS, &pidl))) { SHFILEINFO fi; BOOL_PTR fOk = SHGetFileInfo( (LPTSTR) pidl, 0, &fi, sizeof( fi ), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_PIDL ); SHFree( pidl ); if (fOk) { ImageList_AddIcon(himl, fi.hIcon); DestroyIcon(fi.hIcon); return(TRUE); } } return FALSE; } // // Initialize the tree // void InitFolderTree( HWND hwndTree, BOOL bAddFiles, HIMAGELIST *phiml ) { HCURSOR hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT)); HTREEITEM htiStart = NULL; HTREEITEM htiPrgs = NULL; TCHAR szPathStart[MAX_PATH]; TCHAR szPathPrgs[MAX_PATH]; UINT flags = ILC_MASK | ILC_COLOR32; HIMAGELIST himl; if(IS_WINDOW_RTL_MIRRORED(hwndTree)) { flags |= ILC_MIRROR; } himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), flags, 10, 1); if (phiml) *phiml = himl; if (!himl) { return; } TreeView_SetImageList(hwndTree, himl, TVSIL_NORMAL); // // Add the programs folder as index 0. All sub-folders of programs // will also have the same icon. This saves both memory and time. // if (!MakePrgIcon0Index(hwndTree, himl)) { return; } if (!bAddFiles) { AddSpecialFolder(hwndTree, TVI_ROOT, CSIDL_DESKTOPDIRECTORY, szPathStart, 0); } htiStart = AddSpecialFolder(hwndTree, TVI_ROOT, CSIDL_STARTMENU, szPathStart, FIDFLAG_CANADDNEW); if (htiStart) { htiPrgs = AddSpecialFolder(hwndTree, htiStart, CSIDL_PROGRAMS, szPathPrgs, FIDFLAG_CANADDNEW | FIDFLAG_ISPROGS); if (htiPrgs) { FillFolder(hwndTree, szPathPrgs, ARRAYSIZE(szPathPrgs), NULL, htiPrgs, FFF_AddDirs | (bAddFiles ? FFF_AddFiles : 0)); // // Now fill in the rest of the start menu, excluding programs // FillFolder(hwndTree, szPathStart, ARRAYSIZE(szPathStart), szPathPrgs, htiStart, FFF_AddDirs | (bAddFiles ? FFF_AddFiles : 0)); } } // // Now select and expand the programs folder. // if (htiPrgs) { TreeView_SelectItem(hwndTree, htiPrgs); if (bAddFiles) { TreeView_Expand(hwndTree, htiPrgs, TVE_EXPAND); } } SetCursor(hcurOld); } // // Delete Selected Item // VOID RemoveSelItem(HWND hDlg, HWND hwndTree) { HTREEITEM hCur; LPFILEITEMDATA lpfid = GetCurSel(hwndTree, &hCur); if (!lpfid) { ShellMessageBox(g_hinst, hDlg, MAKEINTRESOURCE(IDS_NONESEL), 0, MB_OK | MB_ICONEXCLAMATION); } else { if (lpfid->dwFlags & FIDFLAG_CANDEL) { TCHAR szFileDblNull[MAX_PATH+1]; SHFILEOPSTRUCT sFileOp = { hDlg, FO_DELETE, szFileDblNull, NULL, (lpfid->dwFlags & FIDFLAG_ISFOLDER) ? FOF_ALLOWUNDO : FOF_SILENT | FOF_ALLOWUNDO, }; StringCchCopy(szFileDblNull, ARRAYSIZE(szFileDblNull), lpfid->szPath); szFileDblNull[lstrlen(szFileDblNull)+1] = 0; if (!SHFileOperation(&sFileOp)) { if (!(sFileOp.fAnyOperationsAborted)) { TreeView_DeleteItem(hwndTree, hCur); } } } else { ShellMessageBox(g_hinst, hDlg, MAKEINTRESOURCE(IDS_CANTDELETE), 0, MB_OK | MB_ICONEXCLAMATION, PathFindFileName(lpfid->szPath)); } } } ///////////////////////////////////////////////////////////////////////////// // END SHARED CODE. BEGIN WIZARD SPECIFIC CODE. ///////////////////////////////////////////////////////////////////////////// // // Returns -1 if no item is selected, otherwise, sets lpwd->lpszFolder // to point to the appropriate string, and returns 0. // LPARAM PickFolderNextHit(LPWIZDATA lpwd) { LPFILEITEMDATA lpfid = GetCurSel(GetDlgItem(lpwd->hwnd, IDC_FOLDERTREE), NULL); if (lpfid) { lpwd->lpszFolder = (LPTSTR)&(lpfid->szPath); lpwd->szProgDesc[0] = 0; return(0); } else { return(-1); } } // // Creates a new, empty folder. // VOID CreateNewFolder(LPWIZDATA lpwd) { TCHAR szNewName[MAX_PATH]; HTREEITEM hParent; LPFILEITEMDATA lpfidParent = GetCurSel(GetDlgItem(lpwd->hwnd, IDC_FOLDERTREE), &hParent); if (lpfidParent && (lpfidParent->dwFlags & FIDFLAG_CANADDNEW)) { int iDirLen = lstrlen(lpfidParent->szPath); TCHAR szNewShort[10]; TCHAR szNewLong[80]; LoadString(g_hinst, IDS_NEWFOLDERSHORT, szNewShort, ARRAYSIZE(szNewShort)); LoadString(g_hinst, IDS_NEWFOLDERLONG, szNewLong, ARRAYSIZE(szNewLong)); PathMakeUniqueName(szNewName, ARRAYSIZE(szNewName), szNewShort, szNewLong, lpfidParent->szPath); if (CreateDirectory(szNewName, NULL)) { HWND hwndTree = GetDlgItem(lpwd->hwnd, IDC_FOLDERTREE); HTREEITEM hNewDude = AddItem(hwndTree, szNewName, hParent, NULL, FIDFLAG_ISFOLDER | FIDFLAG_CANADDNEW | FIDFLAG_CANDEL); if (hNewDude == NULL) { TraceMsg(TF_ERROR, "%s", "Unable to add new folder to tree."); } if (hNewDude) { SortFolder(hwndTree, hParent); TreeView_SelectItem(hwndTree, hNewDude); TreeView_EditLabel(hwndTree, hNewDude); } } else { TraceMsg(TF_ERROR, "%s", "Unable to create new directory"); } } else { TraceMsg(TF_ERROR, "%s", "No group selected. Can't create directory."); } } // // Begin editing a tree label. This function returns FALSE for success, and // TRUE for failure. // BOOL BeginEdit(LPWIZDATA lpwd, TV_DISPINFO * lptvdi) { if (TreeView_GetParent(lptvdi->hdr.hwndFrom, lptvdi->item.hItem)) { lpwd->dwFlags |= WDFLAG_INEDITMODE; return FALSE; } else { return TRUE; } } // // Return FALSE if rename can't happen. True if it worked. // BOOL EndEdit(LPWIZDATA lpwd, TV_DISPINFO * lptvdi) { BOOL bWorked = FALSE; #define lpszNewName (LPTSTR)lptvdi->item.pszText #define lpfidOld ((LPFILEITEMDATA)(lptvdi->item.lParam)) #define hCurItem lptvdi->item.hItem; lpwd->dwFlags &= ~WDFLAG_INEDITMODE; if (lpszNewName) { int cchPath = MAX_PATH; LPFILEITEMDATA lpfidNew = (LPFILEITEMDATA)LocalAlloc(LMEM_FIXED, sizeof(LPFILEITEMDATA)+ (cchPath*sizeof(TCHAR)) ); if (lpfidNew) { lpfidNew->dwFlags = lpfidOld->dwFlags; StringCchCopy(lpfidNew->szPath, cchPath, lpfidOld->szPath); PathRemoveFileSpec(lpfidNew->szPath); PathCleanupSpec(lpfidNew->szPath, lpszNewName); if ( PathCombine(lpfidNew->szPath, lpfidNew->szPath, lpszNewName) && MoveFile(lpfidOld->szPath, lpfidNew->szPath) ) { TV_ITEM tvi; tvi.hItem = hCurItem; tvi.mask = TVIF_PARAM; tvi.lParam = (LPARAM)lpfidNew; TreeView_SetItem(lptvdi->hdr.hwndFrom, &tvi); bWorked = TRUE; } else { TraceMsg(TF_ERROR, "%s", "Unable to rename directory"); } LocalFree(bWorked ? lpfidOld : lpfidNew); } } return(bWorked); #undef lpszNewName #undef lpfidOld #undef hCurItem } // // Called when Next or Back is hit to force the end of label editing. // void ForceEndEdit(LPWIZDATA lpwd) { if (lpwd->dwFlags & WDFLAG_INEDITMODE) { TreeView_EndEditLabelNow(GetDlgItem(lpwd->hwnd, IDC_FOLDERTREE), FALSE); } } void FillInItem(TV_DISPINFO * ptvdi) { SHFILEINFO fi; #define lpfid ((LPFILEITEMDATA)(ptvdi->item.lParam)) if (SHGetFileInfo(lpfid->szPath, 0, &fi, sizeof(fi), SHGFI_ICON | SHGFI_DISPLAYNAME | SHGFI_SMALLICON)) { if (ptvdi->item.mask & TVIF_IMAGE) { ptvdi->item.iImage = ptvdi->item.iSelectedImage = ImageList_AddIcon(TreeView_GetImageList(ptvdi->hdr.hwndFrom, TVSIL_NORMAL), fi.hIcon); ptvdi->item.mask |= TVIF_SELECTEDIMAGE; } if (ptvdi->item.mask & TVIF_TEXT) { StringCchCopy(ptvdi->item.pszText, ptvdi->item.cchTextMax, fi.szDisplayName); } DestroyIcon(fi.hIcon); ptvdi->item.mask |= TVIF_DI_SETITEM; } } // // Main dialog procedure for tree of folders // BOOL_PTR CALLBACK PickFolderDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam) { NMHDR *lpnm = NULL; LPPROPSHEETPAGE lpp = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER)); LPWIZDATA lpwd = lpp ? (LPWIZDATA)lpp->lParam : NULL; switch(message) { case WM_NOTIFY: lpnm = (NMHDR *)lParam; if(lpnm) { switch(lpnm->code) { case PSN_SETACTIVE: if(lpwd) { if (lpwd->dwFlags & WDFLAG_LINKHEREWIZ) { SetDlgMsgResult(hDlg, WM_NOTIFY, -1); } else { lpwd->hwnd = hDlg; PropSheet_SetWizButtons(GetParent(hDlg), (lpwd->dwFlags & WDFLAG_NOBROWSEPAGE) ? PSWIZB_NEXT : PSWIZB_BACK | PSWIZB_NEXT); PostMessage(hDlg, WMPRIV_POKEFOCUS, 0, 0); } } break; case PSN_WIZBACK: if(lpwd) { ForceEndEdit(lpwd); SetDlgMsgResult(hDlg, WM_NOTIFY, 0); } break; case PSN_WIZNEXT: if(lpwd) { ForceEndEdit(lpwd); SetDlgMsgResult(hDlg, WM_NOTIFY, PickFolderNextHit(lpwd)); } break; case PSN_RESET: if(lpwd) { CleanUpWizData(lpwd); } break; case NM_DBLCLK: PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT); break; #define lpfidNew ((LPFILEITEMDATA)(((LPNM_TREEVIEW)lParam)->itemNew.lParam)) case TVN_SELCHANGED: Button_Enable(GetDlgItem(hDlg, IDC_NEWFOLDER), (lpfidNew->dwFlags & FIDFLAG_CANADDNEW)); break; #undef lpfidNew #define lptvdi ((TV_DISPINFO *)lParam) case TVN_BEGINLABELEDIT: if(lpwd) { SetDlgMsgResult(hDlg, WM_NOTIFY, BeginEdit(lpwd, lptvdi)); } break; case TVN_ENDLABELEDIT: if(lpwd) { SetDlgMsgResult(hDlg, WM_NOTIFY, EndEdit(lpwd, lptvdi)); } break; #undef lptvdi #define lptvn ((LPNM_TREEVIEW)lParam) case TVN_ITEMEXPANDING: if (lptvn->action != TVE_EXPAND) { SetDlgMsgResult(hDlg, WM_NOTIFY, -1); } break; case TVN_DELETEITEM: if (lptvn->itemOld.lParam) { LocalFree((LPVOID)lptvn->itemOld.lParam); } break; #undef lptvn case TVN_GETDISPINFO: FillInItem(((TV_DISPINFO *)lParam)); break; default: return FALSE; } } break; case WM_INITDIALOG: lpwd = InitWizSheet(hDlg, lParam, 0); if(lpwd) { lpwd->himl = NULL; if( !( lpwd->dwFlags & WDFLAG_LINKHEREWIZ ) ) { InitFolderTree( GetDlgItem( hDlg, IDC_FOLDERTREE ), FALSE, &lpwd->himl ); } } break; case WM_NCDESTROY: // // See if we should destroy the himl... // if(lpwd) { if (lpwd->himl) { ImageList_Destroy(lpwd->himl); lpwd->himl = NULL; // make sure not twice } } return FALSE; case WMPRIV_POKEFOCUS: SetFocus(GetDlgItem(hDlg, IDC_FOLDERTREE)); break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDC_NEWFOLDER: if(lpwd) { CreateNewFolder(lpwd); } break; /// case IDC_DELFOLDER: /// { /// HWND hTree = GetDlgItem(hDlg, IDC_FOLDERTREE); /// RemoveSelItem(hDlg, hTree); /// SetFocus(hTree); /// break; /// } } default: return FALSE; } return TRUE; } ///////////////////////////////////////////////////////////////////////////// // END WIZARD SPECIFIC CODE. BEGIN DELETE ITEM DIALOG CODE. ///////////////////////////////////////////////////////////////////////////// typedef struct _FOLDERTHREADINFO { HANDLE hThread; HWND hwndTree; HIMAGELIST himl; } FOLDERTHREADINFO, * PFOLDERTHREADINFO; void CALLBACK FolderEnumItems(PFOLDERTHREADINFO pfti, HTREEITEM hParent) { HTREEITEM hitem; hitem = hParent; while (hitem && pfti->hThread) { TV_ITEM tvi; tvi.mask = TVIF_IMAGE; tvi.hItem = hitem; TreeView_GetItem(pfti->hwndTree, &tvi); hitem = TreeView_GetNextSibling(pfti->hwndTree, hitem); } hitem = TreeView_GetChild(pfti->hwndTree, hParent); while (hitem && pfti->hThread) { FolderEnumItems(pfti, hitem); hitem = TreeView_GetNextSibling(pfti->hwndTree, hitem); } } DWORD CALLBACK FolderThread(PFOLDERTHREADINFO pfti) { HANDLE hThread = pfti->hThread; FolderEnumItems(pfti, TreeView_GetRoot(pfti->hwndTree)); CloseHandle(hThread); pfti->hThread = 0; return 0; } VOID CreateFolderThread(PFOLDERTHREADINFO pfti) { // // Create background thread to force list view to draw items // DWORD idThread; if (pfti->hThread) { return; } pfti->hThread = CreateThread(NULL, 0, FolderThread, pfti, 0, &idThread); if(pfti->hThread) { SetThreadPriority(pfti->hThread, THREAD_PRIORITY_BELOW_NORMAL); } } // // Main dialog procedure for delete items dialog. // const static DWORD aDelItemHelpIDs[] = { // Context Help IDs IDC_TEXT, NO_HELP, IDC_FOLDERTREE, IDH_TRAY_REMOVEDLG_LIST, IDC_DELETEITEM, IDH_TRAY_REMOVEDLG_DEL, 0, 0 }; void WaitForThreadToFinish(HWND hDlg, FOLDERTHREADINFO *pfti) { if (pfti->hThread) { SHProcessSentMessagesUntilEvent(hDlg, pfti->hThread, 10000); CloseHandle(pfti->hThread); pfti->hThread = NULL; } } BOOL_PTR CALLBACK DelItemDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam) { PFOLDERTHREADINFO pfti = (PFOLDERTHREADINFO)GetWindowLongPtr(hDlg, DWLP_USER); switch(message) { case WM_NOTIFY: #define lpnm ((NMHDR *)lParam) switch(lpnm->code) { #define lpfidNew ((LPFILEITEMDATA)(((LPNM_TREEVIEW)lParam)->itemNew.lParam)) case TVN_SELCHANGED: { BOOL fCanDel = (lpfidNew->dwFlags & FIDFLAG_CANDEL); HWND hwndDelItem = GetDlgItem(hDlg, IDC_DELETEITEM); if ((!fCanDel) && (GetFocus() == hwndDelItem)) { SetFocus(GetDlgItem(hDlg, IDOK)); SendMessage(hDlg, DM_SETDEFID, IDOK, 0); } Button_Enable(hwndDelItem, fCanDel); break; } #undef lpfidNew #define lptvn ((LPNM_TREEVIEW)lParam) case TVN_DELETEITEM: if (lptvn->itemOld.lParam) { LocalFree((LPVOID)lptvn->itemOld.lParam); } break; #undef lptvn #define lptkd ((TV_KEYDOWN *)lParam) case TVN_KEYDOWN: if (lptkd->wVKey == VK_DELETE) { WaitForThreadToFinish(hDlg, pfti); RemoveSelItem(hDlg, GetDlgItem(hDlg, IDC_FOLDERTREE)); CreateFolderThread(pfti); return TRUE; } break; #undef lptkd case TVN_GETDISPINFO: FillInItem(((TV_DISPINFO *)lParam)); break; default: return FALSE; #undef lpnm } break; case WM_INITDIALOG: SetWindowLongPtr(hDlg, DWLP_USER, lParam); pfti = (PFOLDERTHREADINFO)lParam; InitFolderTree(GetDlgItem(hDlg, IDC_FOLDERTREE), TRUE, &pfti->himl); pfti->hwndTree = GetDlgItem(hDlg, IDC_FOLDERTREE); pfti->hThread = 0; CreateFolderThread(pfti); break; case WM_HELP: WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR)(LPTSTR) aDelItemHelpIDs); break; case WM_CONTEXTMENU: WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID) aDelItemHelpIDs); break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: case IDCANCEL: WaitForThreadToFinish(hDlg, pfti); EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam)); break; case IDC_DELETEITEM: WaitForThreadToFinish(hDlg, pfti); RemoveSelItem(hDlg, GetDlgItem(hDlg, IDC_FOLDERTREE)); CreateFolderThread(pfti); break; } default: return FALSE; } return TRUE; } BOOL RemoveItemsDialog( HWND hParent ) { BOOL fReturn; FOLDERTHREADINFO fti; fti.himl = NULL; // incase we can not create the window fReturn = (int)DialogBoxParam( g_hinst, MAKEINTRESOURCE( DLG_DELITEM ), hParent, DelItemDlgProc, (LPARAM) &fti ); if( fti.himl ) ImageList_Destroy( fti.himl ); return fReturn; }