// @pathprefix: 如果该值为NULL/pathprefix[0]=='\0', 在形成的路径前前加这一串 char* TreeView_FormPath(HWND hctl, HTREEITEM htvi, char *pathprefix) { static char path[_MAX_PATH]; char text[_MAX_PATH]; HTREEITEM htvip; TVITEMEX tvi; path[0] = '\0'; TreeView_GetItem1(hctl, htvi, &tvi, TVIF_TEXT, path); while ((htvip = TreeView_GetParent(hctl, htvi)) && (htvip != TVI_ROOT)) { TreeView_GetItem1(hctl, htvip, &tvi, TVIF_TEXT, text); if (path[0]) { strcpy(path, formatstr("%s\\%s", text, path)); } else { strcpy(path, text); } htvi = htvip; } if (!is_empty_str(pathprefix)) { if (path[0]) { strcpy(path, formatstr("%s\\%s", pathprefix, path)); } else { strcpy(path, pathprefix); } } return path; }
int CALLBACK fn_tvi_compare_sort(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { HWND hctl = (HWND)lParamSort; TVITEMEX tvi1, tvi2; int tvi1_type, tvi2_type; char name1[_MAX_PATH], name2[_MAX_PATH]; memset(&tvi1, 0, sizeof(TVITEMEX)); memset(&tvi2, 0, sizeof(TVITEMEX)); TreeView_GetItem1(hctl, (HTREEITEM)lParam1, &tvi1, TVIF_HANDLE | TVIF_TEXT | TVIF_IMAGE, name1); TreeView_GetItem1(hctl, (HTREEITEM)lParam2, &tvi2, TVIF_HANDLE | TVIF_TEXT | TVIF_IMAGE, name2); tvi1_type = tvi1.iImage? 1: 0; tvi2_type = tvi2.iImage? 1: 0; if (tvi1_type < tvi2_type) { // tvi1是目录, tvi2是文件 return -1; } else if (tvi1_type > tvi2_type) { // tvi1是文件, tvi2是目录 return 1; } else { // lvi1和lvi2都是目录或文件,只好用字符串比较 return strcasecmp(name1, name2); } }
void TreeView_FormVector(HWND hctl, HTREEITEM htvi, std::vector<std::pair<LPARAM, std::string> >& vec) { char text[_MAX_PATH]; HTREEITEM htvip; TVITEMEX tvi; TreeView_GetItem1(hctl, htvi, &tvi, TVIF_TEXT | TVIF_PARAM, text); vec.push_back(std::make_pair<LPARAM, std::string>(tvi.lParam, text)); while ((htvip = TreeView_GetParent(hctl, htvi)) && (htvip != TVI_ROOT)) { TreeView_GetItem1(hctl, htvip, &tvi, TVIF_TEXT | TVIF_PARAM, text); vec.push_back(std::make_pair<LPARAM, std::string>(tvi.lParam, text)); htvi = htvip; } }
void tvisual::on_rclick(LPNMHDR lpNMHdr, HTREEITEM htvi) { TVITEMEX tvi; if (type_ == BIN_WML) { TreeView_GetItem1(lpNMHdr->hwndFrom, htvi, &tvi, TVIF_CHILDREN, NULL); if (tvi.cChildren && !TreeView_GetChild(lpNMHdr->hwndFrom, htvi)) { std::vector<std::pair<LPARAM, std::string> > vec; LPARAM cfg_index; const config* cfg = &game_config_; TreeView_FormVector(lpNMHdr->hwndFrom, htvi, vec); for (std::vector<std::pair<LPARAM, std::string> >::reverse_iterator ritor = vec.rbegin(); ritor != vec.rend(); ++ ritor) { if (ritor == vec.rbegin()) { continue; } cfg_index = 0; foreach (const config::any_child& value, cfg->all_children_range()) { if (cfg_index ++ == ritor->first) { cfg = &value.cfg; break; } } } wml_2_tv(lpNMHdr->hwndFrom, htvi, *cfg, 0); }
void cb_treeview_walk_find_lparam(HWND hctl, HTREEITEM htvi, uint32_t* ctx) { TVITEMEX tvi; TreeView_GetItem1(hctl, htvi, &tvi, TVIF_PARAM, NULL); if (tvi.lParam == first_visible_lparam) { first_visible_htvi = htvi; } }
void treeview_update_scroll(HWND htv, fn_treeview_update_scroll fn, void* ctx) { TVITEMEX tvi; HTREEITEM htvi = TreeView_GetFirstVisible(htv); TreeView_GetItem1(htv, htvi, &tvi, TVIF_PARAM | TVIF_CHILDREN, NULL); if (htvi && fn) { scroll::first_visible_lparam = tvi.lParam; fn(htv, htvi, tvi, ctx); } first_visible_lparam = 0; }
// // On_DlgDDescNotify() // BOOL On_DlgDDescNotify(HWND hdlgP, int DlgItem, LPNMHDR lpNMHdr) { LPNMTREEVIEW lpnmitem; HTREEITEM htvi; TVITEMEX tvi; char text[_MAX_PATH]; POINT point; if (gdmgr._syncing || (lpNMHdr->idFrom != IDC_TV_DDESC_EXPLORER)) { return FALSE; } lpnmitem = (LPNMTREEVIEW)lpNMHdr; // NM_RCLICK/NM_CLICK/NM_DBLCLK这些通知被发来后,其附代参数没法指定是哪个叶子句柄, // 需通过判断鼠标坐标来判断是哪个叶子被按下? // 1. GetCursorPos, 得到屏幕坐标系下的鼠标坐标 // 2. TreeView_HitTest1(自写宏),由屏幕坐标系下的鼠标坐标返回指向的叶子句柄 GetCursorPos(&point); // 得到的是屏幕坐标 TreeView_HitTest1(lpNMHdr->hwndFrom, point, htvi); // NM_表示对通用控件都通用,范围丛(0, 99) // TVN_表示只能TreeView通用,范围丛(400, 499) if (lpNMHdr->code == NM_RCLICK) { // // 右键单击: 弹出菜单 // // 准备两个菜单上下文变量 TreeView_GetItem1(lpNMHdr->hwndFrom, htvi, &tvi, TVIF_IMAGE | TVIF_PARAM | TVIF_TEXT, text); strcpy(gdmgr._menu_text, TreeView_FormPath(lpNMHdr->hwndFrom, htvi, dirname(game_config::path.c_str()))); gdmgr._menu_lparam = (uint32_t)tvi.lParam; // new if (!can_execute_tack(TASK_NEW) || strcasecmp(gdmgr._menu_text, game_config::path.c_str())) { EnableMenuItem(gdmgr._hpopup_new, IDM_NEW_EXTRAINSDIST, MF_BYCOMMAND | MF_GRAYED); } if (!can_execute_tack(TASK_NEW)) { EnableMenuItem(gdmgr._hpopup_new, IDM_NEW_CAMPAIGN, MF_BYCOMMAND | MF_GRAYED); } // explorer if (!can_execute_tack(TASK_EXPLORER) || (_stricmp(extname(gdmgr._menu_text), "bin") && _stricmp(extname(gdmgr._menu_text), "dat"))) { EnableMenuItem(gdmgr._hpopup_explorer, IDM_EXPLORER_WML, MF_BYCOMMAND | MF_GRAYED); } // delete if (!can_execute_tack(TASK_DELETE) || _stricmp(extname(gdmgr._menu_text), "bin") || !strstr(gdmgr._menu_text, "\\campaigns\\")) { EnableMenuItem(gdmgr._hpopup_delete, IDM_DELETE_ITEM0, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(gdmgr._hpopup_delete, IDM_DELETE_ITEM1, MF_BYCOMMAND | MF_GRAYED); } TrackPopupMenuEx(gdmgr._hpopup_ddesc, 0, point.x, point.y, hdlgP, NULL); EnableMenuItem(gdmgr._hpopup_new, IDM_NEW_EXTRAINSDIST, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(gdmgr._hpopup_explorer, IDM_EXPLORER_WML, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(gdmgr._hpopup_delete, IDM_DELETE_ITEM0, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(gdmgr._hpopup_delete, IDM_DELETE_ITEM1, MF_BYCOMMAND | MF_ENABLED); } else if (lpNMHdr->code == NM_CLICK) { // // 左键单击: 如果底下被击的是目录,且没有生成过叶子,成生叶子 // strcpy(text, TreeView_FormPath(lpNMHdr->hwndFrom, htvi, dirname(game_config::path.c_str()))); TreeView_GetItem1(lpNMHdr->hwndFrom, htvi, &tvi, TVIF_CHILDREN, NULL); if (tvi.cChildren && !TreeView_GetChild(lpNMHdr->hwndFrom, htvi)) { dir_2_tv(lpNMHdr->hwndFrom, htvi, text, 0); } // 址址栏中显示选中目录 strcpy(text, TreeView_FormPath(lpNMHdr->hwndFrom, htvi, dirname(game_config::path.c_str()))); if (!is_directory(text)) { strcpy(text, dirname(text)); } // Edit_SetText(GetDlgItem(hdlgP, IDC_ET_DDESC_WWWROOT), text + strlen(dirname(game_config::path.c_str())) + 1); } else if (lpNMHdr->code == NM_DBLCLK) { // // 目录: 展开/折叠叶子(系统自动) // 文件: 用特定应程序打开 // // 切换到编辑窗口 TreeView_GetItem1(lpNMHdr->hwndFrom, htvi, &tvi, TVIF_IMAGE | TVIF_PARAM | TVIF_TEXT, text); if (!_stricmp(text, "hero.dat")) { strcpy(gdmgr._menu_text, TreeView_FormPath(lpNMHdr->hwndFrom, htvi, dirname(game_config::path.c_str()))); gdmgr._menu_lparam = (uint32_t)tvi.lParam; if (gdmgr._da != da_wgen) { title_select(da_wgen); } else { wgen_enter_ui(); } } else if (!_stricmp(text, "tb.dat") || !_stricmp(text, "tb-1.dat")) { strcpy(gdmgr._menu_text, TreeView_FormPath(lpNMHdr->hwndFrom, htvi, dirname(game_config::path.c_str()))); gdmgr._menu_lparam = (uint32_t)tvi.lParam; editor_config::type = BIN_BUILDINGRULE; if (gdmgr._da != da_visual) { title_select(da_visual); } else { visual_enter_ui(); } } else if (!_stricmp(extname(text), "bin")) { strcpy(gdmgr._menu_text, TreeView_FormPath(lpNMHdr->hwndFrom, htvi, dirname(game_config::path.c_str()))); if (wml_checksum_from_file(std::string(gdmgr._menu_text))) { gdmgr._menu_lparam = (uint32_t)tvi.lParam; if (strstr(gdmgr._menu_text, "\\campaigns\\") && !strstr(gdmgr._menu_text, "duel") && !strstr(gdmgr._menu_text, "legend_of_bei_liu") && !strstr(gdmgr._menu_text, "tower_defense") && !strstr(gdmgr._menu_text, "tutorial")) { if (gdmgr._da != da_campaign) { title_select(da_campaign); } else { campaign_enter_ui(); } } else if (strstr(gdmgr._menu_text, "data.bin")) { if (gdmgr._da != da_core) { title_select(da_core); } else { // core_enter_ui(); } } else { editor_config::type = BIN_WML; if (gdmgr._da != da_visual) { title_select(da_visual); } else { visual_enter_ui(); } } } } } else if (lpNMHdr->code == TVN_ITEMEXPANDED) { // // 子叶子已被展开或折叠, 是折叠时删除所子有叶子, 以便下次展开时通反映最近文件系统 // if (lpnmitem->action & TVE_COLLAPSE) { TreeView_Walk(lpNMHdr->hwndFrom, lpnmitem->itemNew.hItem, FALSE, NULL, NULL, TRUE); TreeView_SetChilerenByPath(lpNMHdr->hwndFrom, htvi, TreeView_FormPath(lpNMHdr->hwndFrom, htvi, dirname(game_config::path.c_str()))); } } return FALSE; }