// winbookmarks.cpp // // Copyright (C) 2002, Chris Laurel // // Miscellaneous utilities for Locations UI implementation. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. #include "winbookmarks.h" #include "res/resource.h" #include #include #include using namespace std; using celestia::util::GetLogger; bool dragging; HTREEITEM hDragItem; HTREEITEM hDropTargetItem; POINT dragPos; static const unsigned int StdItemMask = (TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE); static bool isTopLevel(const FavoritesEntry* fav) { return fav->parentFolder == ""; } HTREEITEM PopulateBookmarksTree(HWND hTree, CelestiaCore* appCore, HINSTANCE appInstance) { //First create an image list for the icons in the control HIMAGELIST himlIcons; HICON hIcon; HTREEITEM hParent=NULL, hParentItem; //Create a masked image list large enough to hold the icons. himlIcons = ImageList_Create(16, 16, ILC_COLOR32, 3, 0); // Load the icon resources, and add the icons to the image list. hIcon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_CLOSEDFOLDER)); ImageList_AddIcon(himlIcons, hIcon); hIcon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_OPENFOLDER)); ImageList_AddIcon(himlIcons, hIcon); hIcon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_ROOTFOLDER)); ImageList_AddIcon(himlIcons, hIcon); hIcon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_BOOKMARK)); ImageList_AddIcon(himlIcons, hIcon); // Associate the image list with the tree-view control. TreeView_SetImageList(hTree, himlIcons, TVSIL_NORMAL); FavoritesList* favorites = appCore->getFavorites(); if (favorites != NULL) { // Create a subtree item called "Bookmarks" TVINSERTSTRUCT tvis; tvis.hParent = TVI_ROOT; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = StdItemMask; tvis.item.pszText = const_cast("Bookmarks"); tvis.item.lParam = 0; tvis.item.iImage = 2; tvis.item.iSelectedImage = 2; if (hParent = TreeView_InsertItem(hTree, &tvis)) { FavoritesList::iterator iter = favorites->begin(); while (iter != favorites->end()) { TVINSERTSTRUCT tvis; FavoritesEntry* fav = *iter; // Is this a folder? if (fav->isFolder) { // Create a subtree item tvis.hParent = hParent; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = StdItemMask; tvis.item.pszText = const_cast(fav->name.c_str()); tvis.item.lParam = reinterpret_cast(fav); tvis.item.iImage = 0; tvis.item.iSelectedImage = 1; if (hParentItem = TreeView_InsertItem(hTree, &tvis)) { FavoritesList::iterator subIter = favorites->begin(); while (subIter != favorites->end()) { FavoritesEntry* child = *subIter; // See if this entry is a child if (!child->isFolder && child->parentFolder == fav->name) { // Add items to sub tree tvis.hParent = hParentItem; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = StdItemMask; tvis.item.pszText = const_cast(child->name.c_str()); tvis.item.lParam = reinterpret_cast(child); tvis.item.iImage = 3; tvis.item.iSelectedImage = 3; TreeView_InsertItem(hTree, &tvis); } subIter++; } // Expand each folder to display bookmark items TreeView_Expand(hTree, hParentItem, TVE_EXPAND); } } else if (isTopLevel(fav)) { // Add item to root "Bookmarks" tvis.hParent = hParent; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = StdItemMask; tvis.item.pszText = const_cast((*iter)->name.c_str()); tvis.item.lParam = reinterpret_cast(fav); tvis.item.iImage = 3; tvis.item.iSelectedImage = 3; TreeView_InsertItem(hTree, &tvis); } iter++; } } } dragging = false; return hParent; } HTREEITEM PopulateBookmarkFolders(HWND hTree, CelestiaCore* appCore, HINSTANCE appInstance) { // First create an image list for the icons in the control HTREEITEM hParent=NULL; HIMAGELIST himlIcons; HICON hIcon; //Create a masked image list large enough to hold the icons. himlIcons = ImageList_Create(16, 16, ILC_COLOR32, 3, 0); // Load the icon resources, and add the icons to the image list. hIcon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_CLOSEDFOLDER)); ImageList_AddIcon(himlIcons, hIcon); hIcon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_OPENFOLDER)); ImageList_AddIcon(himlIcons, hIcon); hIcon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_ROOTFOLDER)); ImageList_AddIcon(himlIcons, hIcon); // Associate the image list with the tree-view control. TreeView_SetImageList(hTree, himlIcons, TVSIL_NORMAL); FavoritesList* favorites = appCore->getFavorites(); if (favorites != NULL) { // Create a subtree item called "Bookmarks" TVINSERTSTRUCT tvis; tvis.hParent = TVI_ROOT; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvis.item.pszText = const_cast("Bookmarks"); tvis.item.lParam = 0; tvis.item.iImage = 2; tvis.item.iSelectedImage = 2; if (hParent = TreeView_InsertItem(hTree, &tvis)) { FavoritesList::iterator iter = favorites->begin(); while (iter != favorites->end()) { FavoritesEntry* fav = *iter; if (fav->isFolder) { // Create a subtree item for the folder TVINSERTSTRUCT tvis; tvis.hParent = hParent; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = StdItemMask; tvis.item.pszText = const_cast(fav->name.c_str()); tvis.item.lParam = reinterpret_cast(fav); tvis.item.iImage = 0; tvis.item.iSelectedImage = 1; TreeView_InsertItem(hTree, &tvis); } iter++; } // Select "Bookmarks" folder TreeView_SelectItem(hTree, hParent); } } return hParent; } void BuildFavoritesMenu(HMENU menuBar, CelestiaCore* appCore, HINSTANCE appInstance, ODMenu* odMenu) { // Add item to bookmarks menu int numStaticItems = 2; // The number of items defined in the .rc file. // Ugly dependence on menu defined in celestia.rc; this needs to change // if the bookmarks menu is moved, or if another item is added to the // menu bar. // TODO: Fix this dependency UINT bookmarksMenuPosition = 5; FavoritesList* favorites = appCore->getFavorites(); if (favorites == NULL) return; MENUITEMINFO menuInfo; menuInfo.cbSize = sizeof(MENUITEMINFO); menuInfo.fMask = MIIM_SUBMENU; if (GetMenuItemInfo(menuBar, bookmarksMenuPosition, TRUE, &menuInfo)) { HMENU bookmarksMenu = menuInfo.hSubMenu; // First, tear down existing menu beyond separator. while (DeleteMenu(bookmarksMenu, numStaticItems, MF_BYPOSITION)) odMenu->DeleteItem(bookmarksMenu, numStaticItems); // Don't continue if there are no items in favorites if (favorites->size() == 0) return; // Insert separator menuInfo.cbSize = sizeof(MENUITEMINFO); menuInfo.fMask = MIIM_TYPE | MIIM_STATE; menuInfo.fType = MFT_SEPARATOR; menuInfo.fState = MFS_UNHILITE; if (InsertMenuItem(bookmarksMenu, numStaticItems, TRUE, &menuInfo)) { odMenu->AddItem(bookmarksMenu, numStaticItems); numStaticItems++; } // Add folders and their sub items int rootMenuIndex = numStaticItems; int rootResIndex = 0; FavoritesList::iterator iter = favorites->begin(); while (iter != favorites->end()) { FavoritesEntry* fav = *iter; // Is this a folder? if (fav->isFolder) { // Create a submenu HMENU subMenu; if (subMenu = CreatePopupMenu()) { // Create a menu item that displays a popup sub menu menuInfo.cbSize = sizeof(MENUITEMINFO); menuInfo.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; menuInfo.fType = MFT_STRING; menuInfo.wID = ID_BOOKMARKS_FIRSTBOOKMARK + rootResIndex; menuInfo.hSubMenu = subMenu; menuInfo.dwTypeData = const_cast(fav->name.c_str()); if (InsertMenuItem(bookmarksMenu, rootMenuIndex, TRUE, &menuInfo)) { odMenu->AddItem(bookmarksMenu, rootMenuIndex); odMenu->SetItemImage(appInstance, menuInfo.wID, IDB_FOLDERCLOSED); rootMenuIndex++; // Now iterate through all Favorites and add items // to this folder where parentFolder == folderName int subMenuIndex = 0; int childResIndex = 0; string folderName = fav->name; for (FavoritesList::iterator childIter = favorites->begin(); childIter != favorites->end(); childIter++, childResIndex++) { FavoritesEntry* child = *childIter; if (!child->isFolder && child->parentFolder == folderName) { GetLogger()->debug(" {}\n", child->name); // Add item to sub menu menuInfo.cbSize = sizeof(MENUITEMINFO); menuInfo.fMask = MIIM_TYPE | MIIM_ID; menuInfo.fType = MFT_STRING; menuInfo.wID = ID_BOOKMARKS_FIRSTBOOKMARK + childResIndex; menuInfo.dwTypeData = const_cast(child->name.c_str()); if (InsertMenuItem(subMenu, subMenuIndex, TRUE, &menuInfo)) { odMenu->AddItem(subMenu, subMenuIndex); odMenu->SetItemImage(appInstance, menuInfo.wID, IDB_BOOKMARK); subMenuIndex++; } } } // Add a disabled "(empty)" item if no items // were added to sub menu if (subMenuIndex == 0) { menuInfo.cbSize = sizeof(MENUITEMINFO); menuInfo.fMask = MIIM_TYPE | MIIM_STATE; menuInfo.fType = MFT_STRING; menuInfo.fState = MFS_DISABLED; menuInfo.dwTypeData = const_cast("(empty)"); if (InsertMenuItem(subMenu, subMenuIndex, TRUE, &menuInfo)) { odMenu->AddItem(subMenu, subMenuIndex); } } } } } rootResIndex++; iter++; } // Add root bookmark items iter = favorites->begin(); rootResIndex = 0; while (iter != favorites->end()) { FavoritesEntry* fav = *iter; // Is this a non folder item? if (!fav->isFolder && isTopLevel(fav)) { // Append to bookmarksMenu AppendMenu(bookmarksMenu, MF_STRING, ID_BOOKMARKS_FIRSTBOOKMARK + rootResIndex, const_cast(fav->name.c_str())); odMenu->AddItem(bookmarksMenu, rootMenuIndex); odMenu->SetItemImage(appInstance, ID_BOOKMARKS_FIRSTBOOKMARK + rootResIndex, IDB_BOOKMARK); rootMenuIndex++; } iter++; rootResIndex++; } } } void AddNewBookmarkFolderInTree(HWND hTree, CelestiaCore* appCore, char* folderName) { // Add new item to bookmark item after other folders but before root items HTREEITEM hParent, hItem, hInsertAfter = nullptr; TVINSERTSTRUCT tvis; TVITEM tvItem; hParent = TreeView_GetChild(hTree, TVI_ROOT); if (hParent) { // Find last "folder" in children of hParent hItem = TreeView_GetChild(hTree, hParent); while (hItem) { // Is this a "folder" tvItem.hItem = hItem; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; if (TreeView_GetItem(hTree, &tvItem)) { FavoritesEntry* fav = reinterpret_cast(tvItem.lParam); if (fav == NULL || fav->isFolder) hInsertAfter = hItem; } hItem = TreeView_GetNextSibling(hTree, hItem); } FavoritesEntry* folderFav = new FavoritesEntry(); folderFav->isFolder = true; folderFav->name = folderName; FavoritesList* favorites = appCore->getFavorites(); favorites->insert(favorites->end(), folderFav); tvis.hParent = hParent; tvis.hInsertAfter = hInsertAfter; tvis.item.mask = StdItemMask; tvis.item.pszText = folderName; tvis.item.lParam = reinterpret_cast(folderFav); tvis.item.iImage = 2; tvis.item.iSelectedImage = 1; if (hItem = TreeView_InsertItem(hTree, &tvis)) { // Make sure root tree item is open and newly // added item is visible. TreeView_Expand(hTree, hParent, TVE_EXPAND); // Select the item TreeView_SelectItem(hTree, hItem); } } } void SyncTreeFoldersWithFavoriteFolders(HWND hTree, CelestiaCore* appCore) { FavoritesList* favorites = appCore->getFavorites(); FavoritesList::iterator iter; TVITEM tvItem; HTREEITEM hItem, hParent; char itemName[33]; bool found; if (favorites != NULL) { // Scan through tree control folders and add any folder that does // not exist in Favorites. if (hParent = TreeView_GetChild(hTree, TVI_ROOT)) { hItem = TreeView_GetChild(hTree, hParent); do { // Get information on item tvItem.hItem = hItem; tvItem.mask = TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE; tvItem.pszText = itemName; tvItem.cchTextMax = sizeof(itemName); if (TreeView_GetItem(hTree, &tvItem)) { // Skip non-folders. if(tvItem.lParam == 0) continue; string name(itemName); if (favorites->size() == 0) { // Just append the folder appCore->addFavoriteFolder(name); continue; } // Loop through favorites to find item = itemName found = false; iter = favorites->begin(); while (iter != favorites->end()) { if ((*iter)->isFolder && (*iter)->name == itemName) { found = true; break; } iter++; } if (!found) { // If not found in favorites, add it. // We want all folders to appear before root items so this // new folder must be inserted after the last item of the // last folder. // Locate position of last folder. FavoritesList::iterator folderIter = favorites->begin(); iter = favorites->begin(); while (iter != favorites->end()) { if ((*iter)->isFolder) folderIter = iter; iter++; } //Now iterate through items until end of folder found folderIter++; while (folderIter != favorites->end() && (*folderIter)->parentFolder != "") folderIter++; //Insert item appCore->addFavoriteFolder(name, &folderIter); } } } while (hItem = TreeView_GetNextSibling(hTree, hItem)); } } } void InsertBookmarkInFavorites(HWND hTree, char* name, CelestiaCore* appCore) { FavoritesList* favorites = appCore->getFavorites(); TVITEM tvItem; HTREEITEM hItem; char itemName[33]; string newBookmark(name); // SyncTreeFoldersWithFavoriteFolders(hTree, appCore); // Determine which tree item (folder) is selected (if any) hItem = TreeView_GetSelection(hTree); if (!TreeView_GetParent(hTree, hItem)) hItem = NULL; if (hItem) { tvItem.hItem = hItem; tvItem.mask = TVIF_TEXT | TVIF_HANDLE; tvItem.pszText = itemName; tvItem.cchTextMax = sizeof(itemName); if (TreeView_GetItem(hTree, &tvItem)) { FavoritesEntry* fav = reinterpret_cast(tvItem.lParam); if (fav != NULL && fav->isFolder) { appCore->addFavorite(newBookmark, string(itemName)); } } } else { // Folder not specified, add to end of favorites appCore->addFavorite(newBookmark, ""); } } void DeleteBookmarkFromFavorites(HWND hTree, CelestiaCore* appCore) { FavoritesList* favorites = appCore->getFavorites(); TVITEM tvItem; HTREEITEM hItem; char itemName[33]; hItem = TreeView_GetSelection(hTree); if (!hItem) return; // Get the selected item text (which is the bookmark name) tvItem.hItem = hItem; tvItem.mask = TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE; tvItem.pszText = itemName; tvItem.cchTextMax = sizeof(itemName); if (!TreeView_GetItem(hTree, &tvItem)) return; FavoritesEntry* fav = reinterpret_cast(tvItem.lParam); if (!fav) return; // Delete the item from the tree view; give up if this fails for some // reason (it shouldn't . . .) if (!TreeView_DeleteItem(hTree, hItem)) return; // Delete item in favorites, as well as all of it's children FavoritesList::iterator iter = favorites->begin(); while (iter != favorites->end()) { if (*iter == fav) { favorites->erase(iter); } else if (fav->isFolder && (*iter)->parentFolder == itemName) { favorites->erase(iter); // delete *iter; } else { iter++; } } } void RenameBookmarkInFavorites(HWND hTree, char* newName, CelestiaCore* appCore) { FavoritesList* favorites = appCore->getFavorites(); TVITEM tvItem; HTREEITEM hItem; char itemName[33]; // First get the selected item hItem = TreeView_GetSelection(hTree); if (!hItem) return; // Get the item text tvItem.hItem = hItem; tvItem.mask = TVIF_TEXT | TVIF_HANDLE; tvItem.pszText = itemName; tvItem.cchTextMax = sizeof(itemName); if (!TreeView_GetItem(hTree, &tvItem)) return; FavoritesEntry* fav = reinterpret_cast(tvItem.lParam); if (fav == NULL) return; tvItem.hItem = hItem; tvItem.mask = TVIF_TEXT | TVIF_HANDLE; tvItem.pszText = newName; if (!TreeView_SetItem(hTree, &tvItem)) return; string oldName = fav->name; fav->name = newName; if (fav->isFolder) { FavoritesList::iterator iter = favorites->begin(); while (iter != favorites->end()) { if ((*iter)->parentFolder == oldName) (*iter)->parentFolder = newName; iter++; } } } void MoveBookmarkInFavorites(HWND hTree, CelestiaCore* appCore) { FavoritesList* favorites = appCore->getFavorites(); TVITEM tvItem; TVINSERTSTRUCT tvis; HTREEITEM hDragItemFolder, hDropItem; char dragItemName[33]; char dragItemFolderName[33]; char dropFolderName[33]; bool bMovedInTree = false; FavoritesEntry* draggedFav = NULL; FavoritesEntry* dropFolderFav = NULL; // First get the target folder name tvItem.hItem = hDropTargetItem; tvItem.mask = TVIF_TEXT | TVIF_HANDLE; tvItem.pszText = dropFolderName; tvItem.cchTextMax = sizeof(dropFolderName); if (!TreeView_GetItem(hTree, &tvItem)) return; if (!TreeView_GetParent(hTree, hDropTargetItem)) dropFolderName[0] = '\0'; // Get the dragged item text tvItem.lParam = 0; tvItem.hItem = hDragItem; tvItem.mask = TVIF_TEXT | TVIF_HANDLE; tvItem.pszText = dragItemName; tvItem.cchTextMax = sizeof(dragItemName); if (TreeView_GetItem(hTree, &tvItem)) { draggedFav = reinterpret_cast(tvItem.lParam); // Get the dragged item folder if (hDragItemFolder = TreeView_GetParent(hTree, hDragItem)) { tvItem.hItem = hDragItemFolder; tvItem.mask = TVIF_TEXT | TVIF_HANDLE; tvItem.pszText = dragItemFolderName; tvItem.cchTextMax = sizeof(dragItemFolderName); if (TreeView_GetItem(hTree, &tvItem)) { if (!TreeView_GetParent(hTree, hDragItemFolder)) dragItemFolderName[0] = '\0'; // Make sure drag and target folders are different if (strcmp(dragItemFolderName, dropFolderName)) { // Delete tree item from source bookmark if (TreeView_DeleteItem(hTree, hDragItem)) { // Add item to dest bookmark tvis.hParent = hDropTargetItem; tvis.hInsertAfter = TVI_LAST; tvis.item.mask = StdItemMask; tvis.item.pszText = dragItemName; tvis.item.lParam = reinterpret_cast(draggedFav); tvis.item.iImage = 3; tvis.item.iSelectedImage = 3; if (hDropItem = TreeView_InsertItem(hTree, &tvis)) { TreeView_Expand(hTree, hDropTargetItem, TVE_EXPAND); // Make the dropped item selected TreeView_SelectItem(hTree, hDropItem); bMovedInTree = true; } } } } } } // Now perform the move in favorites if (bMovedInTree && draggedFav != NULL) { draggedFav->parentFolder = dropFolderName; } } bool isOrganizeBookmarksDragDropActive() { return dragging; } void OrganizeBookmarksOnBeginDrag(HWND hTree, LPNMTREEVIEW lpnmtv) { HIMAGELIST himl; // handle to image list RECT rcItem; // bounding rectangle of item DWORD dwLevel; // heading level of item DWORD dwIndent; // amount that child items are indented //Clear any selected item TreeView_SelectItem(hTree, NULL); // Tell the tree-view control to create an image to use // for dragging. hDragItem = lpnmtv->itemNew.hItem; himl = TreeView_CreateDragImage(hTree, hDragItem); // Get the bounding rectangle of the item being dragged. TreeView_GetItemRect(hTree, hDragItem, &rcItem, TRUE); // Get the heading level and the amount that the child items are // indented. dwLevel = lpnmtv->itemNew.lParam; dwIndent = (DWORD) SendMessage(hTree, TVM_GETINDENT, 0, 0); ImageList_DragShowNolock(TRUE); // Start the drag operation. ImageList_BeginDrag(himl, 0, 7, 7); // Hide the mouse pointer, and direct mouse input to the // parent window. ShowCursor(FALSE); SetCapture(GetParent(hTree)); dragging = true; } void OrganizeBookmarksOnMouseMove(HWND hTree, LONG xCur, LONG yCur) { TVHITTESTINFO tvht; // hit test information TVITEM tvItem; HTREEITEM hItem; //Store away last drag position so timer can perform auto-scrolling. dragPos.x = xCur; dragPos.y = yCur; if (dragging) { // Drag the item to the current position of the mouse pointer. ImageList_DragMove(xCur, yCur); ImageList_DragLeave(hTree); // Find out if the pointer is on the item. If it is, // highlight the item as a drop target. tvht.pt.x = dragPos.x; tvht.pt.y = dragPos.y; if(hItem = TreeView_HitTest(hTree, &tvht)) { // Only select folder items for drop targets tvItem.hItem = hItem; tvItem.mask = TVIF_PARAM | TVIF_HANDLE; if (TreeView_GetItem(hTree, &tvItem)) { FavoritesEntry* fav = reinterpret_cast(tvItem.lParam); if (fav != NULL && fav->isFolder) { hDropTargetItem = hItem; TreeView_SelectDropTarget(hTree, hDropTargetItem); } } } ImageList_DragEnter(hTree, xCur, yCur); } } void OrganizeBookmarksOnLButtonUp(HWND hTree) { if (dragging) { ImageList_EndDrag(); ImageList_DragLeave(hTree); ReleaseCapture(); ShowCursor(TRUE); dragging = false; // Remove TVIS_DROPHILITED state from drop target item TreeView_SelectDropTarget(hTree, NULL); } } void DragDropAutoScroll(HWND hTree) { RECT rect; int i, count; HTREEITEM hItem; GetClientRect(hTree, &rect); ImageList_DragLeave(hTree); // See if we need to scroll. if (dragPos.y > rect.bottom - 10) { // If we are down towards the bottom but have not scrolled to the last // item, we need to scroll down. if (dragPos.x > rect.left && dragPos.x < rect.right) { SendMessage(hTree, WM_VSCROLL, SB_LINEDOWN, 0); count = TreeView_GetVisibleCount(hTree); hItem = TreeView_GetFirstVisible(hTree); for (i = 0; i < count - 1; i++) hItem = TreeView_GetNextVisible(hTree, hItem); if (hItem) { hDropTargetItem = hItem; TreeView_SelectDropTarget(hTree, hDropTargetItem); } } } else if (dragPos.y < rect.top + 10) { // If we are up towards the top but have not scrolled to the first // item, we need to scroll up. if (dragPos.x > rect.left && dragPos.x < rect.right) { SendMessage(hTree, WM_VSCROLL, SB_LINEUP, 0); hItem = TreeView_GetFirstVisible(hTree); if(hItem) { hDropTargetItem = hItem; TreeView_SelectDropTarget(hTree, hDropTargetItem); } } } ImageList_DragEnter(hTree, dragPos.x, dragPos.y); } /* ///////////////////////////////////////////////////////////////////////////// // This function returns the handle of the tree item specified using standard // path notation. ///////////////////////////////////////////////////////////////////////////// HTREEITEM GetTreeViewItemHandle(HWND hTree, char* path, HTREEITEM hParent) { if (!hTree || !hParent) return NULL; char* cP; char itemName[33]; char pathBuf[66]; TVITEM Item; HTREEITEM hItem; strcpy(pathBuf, path); if (cP = strchr(pathBuf, '/')) *cP = '\0'; hItem = NULL; itemName[0] = '\0'; Item.mask = TVIF_TEXT | TVIF_HANDLE; Item.pszText = itemName; Item.cchTextMax = sizeof(itemName); Item.hItem = hParent; if (TreeView_GetItem(hTree, &Item)) { while (strcmp(pathBuf, itemName)) { Item.hItem = TreeView_GetNextSibling(hTree, Item.hItem); if (!Item.hItem) break; TreeView_GetItem(hTree, &Item); } hItem = Item.hItem; } if (!hItem) return NULL; //Prepare to call recursively if (cP) { strcpy(pathBuf, cP + 1); hItem = TreeView_GetChild(hTree, hItem); hItem = GetTreeViewItemHandle(hTree, pathBuf, hItem); } return hItem; } */