From 32cf34124f5277185970b7aaf20055f03f1f1fa8 Mon Sep 17 00:00:00 2001 From: Nathan Woods Date: Mon, 3 Oct 2005 12:39:50 +0000 Subject: [PATCH] Regedit: Added a "Goto key" right-click option. This feature allows the user to right click on certain keys that "link" to other keys, Regedit can provide additional "Go to ...." menu items. For example, if you click on a ProgID under HKCR, a "Go to 'HKCR\CLSID\{....}' menu item will appear. svn path=/trunk/; revision=18243 --- reactos/subsys/system/regedit/En.rc | 1 + reactos/subsys/system/regedit/childwnd.c | 179 ++++++++++++++++++++++- reactos/subsys/system/regedit/main.h | 1 + reactos/subsys/system/regedit/resource.h | 3 + reactos/subsys/system/regedit/treeview.c | 68 +++++++++ 5 files changed, 247 insertions(+), 5 deletions(-) diff --git a/reactos/subsys/system/regedit/En.rc b/reactos/subsys/system/regedit/En.rc index 4733c748e1b..e4cc18fd898 100644 --- a/reactos/subsys/system/regedit/En.rc +++ b/reactos/subsys/system/regedit/En.rc @@ -340,6 +340,7 @@ STRINGTABLE DISCARDABLE BEGIN IDS_EXPAND "&Expand" IDS_COLLAPSE "&Collapse" + IDS_GOTO_SUGGESTED_KEY "&Go to '%s'" END /*****************************************************************/ diff --git a/reactos/subsys/system/regedit/childwnd.c b/reactos/subsys/system/regedit/childwnd.c index e7e75805c6c..a2edea554b2 100644 --- a/reactos/subsys/system/regedit/childwnd.c +++ b/reactos/subsys/system/regedit/childwnd.c @@ -30,6 +30,7 @@ ChildWnd* g_pChildWnd; HBITMAP SizingPattern = 0; HBRUSH SizingBrush = 0; +static TCHAR Suggestions[256]; /******************************************************************************* * Local module support methods @@ -106,11 +107,12 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) ChildWnd* pChildWnd = g_pChildWnd; HTREEITEM hSelection; HKEY hRootKey; - LPCTSTR keyPath; + LPCTSTR keyPath, s; TCHAR szConfirmTitle[256]; TCHAR szConfirmText[256]; + WORD wID = LOWORD(wParam); - switch (LOWORD(wParam)) { + switch (wID) { /* Parse the menu selections: */ case ID_REGISTRY_EXIT: DestroyWindow(hWnd); @@ -154,11 +156,132 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) SetFocus(pChildWnd->nFocusPanel? pChildWnd->hListWnd: pChildWnd->hTreeWnd); break; default: + if ((wID >= ID_TREE_SUGGESTION_MIN) && (wID <= ID_TREE_SUGGESTION_MAX)) + { + s = Suggestions; + while(wID > ID_TREE_SUGGESTION_MIN) + { + if (*s) + s += _tcslen(s) + 1; + wID--; + } + SelectNode(pChildWnd->hTreeWnd, s); + break; + } return FALSE; } return TRUE; } +/******************************************************************************* + * + * Key suggestion + */ + +static LONG RegQueryStringValue(HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, + LPTSTR lpDest, DWORD dwDestLength) +{ + LONG lResult; + HKEY hSubKey = NULL; + DWORD cbData, dwType; + + if (lpSubKey) + { + lResult = RegOpenKey(hKey, lpSubKey, &hSubKey); + if (lResult != ERROR_SUCCESS) + goto done; + hKey = hSubKey; + } + + cbData = (dwDestLength - 1) * sizeof(*lpDest); + lResult = RegQueryValueEx(hKey, lpValueName, NULL, &dwType, + (LPBYTE) lpDest, &cbData); + if (lResult != ERROR_SUCCESS) + goto done; + if (dwType != REG_SZ) + { + lResult = -1; + goto done; + } + + lpDest[cbData / sizeof(*lpDest)] = '\0'; + +done: + if (lResult != ERROR_SUCCESS) + lpDest[0] = '\0'; + if (hSubKey) + RegCloseKey(hSubKey); + return lResult; +} + +static void SuggestKeys(HKEY hRootKey, LPCTSTR pszKeyPath, LPTSTR pszSuggestions, + size_t iSuggestionsLength) +{ + TCHAR szBuffer[256]; + TCHAR szLastFound[256]; + size_t i; + HKEY hOtherKey, hSubKey; + BOOL bFound; + + memset(pszSuggestions, 0, iSuggestionsLength * sizeof(*pszSuggestions)); + iSuggestionsLength--; + + /* Are we a root key in HKEY_CLASSES_ROOT? */ + if ((hRootKey == HKEY_CLASSES_ROOT) && pszKeyPath[0] && !_tcschr(pszKeyPath, '\\')) + { + do + { + bFound = FALSE; + + /* Check default key */ + if (RegQueryStringValue(hRootKey, pszKeyPath, NULL, + szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0])) == ERROR_SUCCESS) + { + if (szBuffer[0] != '\0') + { + if (RegOpenKey(hRootKey, szBuffer, &hOtherKey) == ERROR_SUCCESS) + { + lstrcpyn(pszSuggestions, TEXT("HKCR\\"), iSuggestionsLength); + i = _tcslen(pszSuggestions); + pszSuggestions += i; + iSuggestionsLength -= i; + + lstrcpyn(pszSuggestions, szBuffer, iSuggestionsLength); + i = _tcslen(pszSuggestions) + 1; + pszSuggestions += i; + iSuggestionsLength -= i; + RegCloseKey(hOtherKey); + + bFound = TRUE; + _tcscpy(szLastFound, szBuffer); + pszKeyPath = szLastFound; + } + } + } + } + while(bFound); + + /* Check CLSID key */ + if (RegOpenKey(hRootKey, pszKeyPath, &hSubKey) == ERROR_SUCCESS) + { + if (RegQueryStringValue(hSubKey, TEXT("CLSID"), NULL, + szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0])) == ERROR_SUCCESS) + { + lstrcpyn(pszSuggestions, TEXT("HKCR\\CLSID\\"), iSuggestionsLength); + i = _tcslen(pszSuggestions); + pszSuggestions += i; + iSuggestionsLength -= i; + + lstrcpyn(pszSuggestions, szBuffer, iSuggestionsLength); + i = _tcslen(pszSuggestions) + 1; + pszSuggestions += i; + iSuggestionsLength -= i; + } + RegCloseKey(hSubKey); + } + } +} + /******************************************************************************* * * FUNCTION: ChildWndProc(HWND, unsigned, WORD, LONG) @@ -407,8 +530,13 @@ LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPa HMENU hContextMenu; TVITEM item; MENUITEMINFO mii; + TCHAR resource[256]; TCHAR buffer[256]; LPTSTR s; + LPCTSTR keyPath; + HKEY hRootKey; + int iLastPos; + WORD wID; pt = MAKEPOINTS(lParam); hti.pt.x = pt.x; @@ -426,17 +554,58 @@ LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPa item.hItem = hti.hItem; TreeView_GetItem(pChildWnd->hTreeWnd, &item); + /* Set the Expand/Collapse menu item appropriately */ LoadString(hInst, (item.state & TVIS_EXPANDED) ? IDS_COLLAPSE : IDS_EXPAND, buffer, sizeof(buffer) / sizeof(buffer[0])); - memset(&mii, 0, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_STRING | MIIM_STATE | MIIM_ID; mii.fState = (item.cChildren > 0) ? MFS_DEFAULT : MFS_GRAYED; mii.wID = (item.state & TVIS_EXPANDED) ? ID_TREE_COLLAPSEBRANCH : ID_TREE_EXPANDBRANCH; - s = buffer; - memcpy(&mii.dwTypeData, &s, sizeof(mii.dwTypeData)); /* arg MinGW */ + mii.dwTypeData = (LPTSTR) buffer; SetMenuItemInfo(hContextMenu, 0, TRUE, &mii); + /* Remove any existing suggestions */ + memset(&mii, 0, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID; + GetMenuItemInfo(hContextMenu, GetMenuItemCount(hContextMenu) - 1, TRUE, &mii); + if ((mii.wID >= ID_TREE_SUGGESTION_MIN) && (mii.wID <= ID_TREE_SUGGESTION_MAX)) + { + do + { + iLastPos = GetMenuItemCount(hContextMenu) - 1; + GetMenuItemInfo(hContextMenu, iLastPos, TRUE, &mii); + RemoveMenu(hContextMenu, iLastPos, MF_BYPOSITION); + } + while((mii.wID >= ID_TREE_SUGGESTION_MIN) && (mii.wID <= ID_TREE_SUGGESTION_MAX)); + } + + /* Come up with suggestions */ + keyPath = GetItemPath(pChildWnd->hTreeWnd, NULL, &hRootKey); + SuggestKeys(hRootKey, keyPath, Suggestions, sizeof(Suggestions) / sizeof(Suggestions[0])); + if (Suggestions[0]) + { + AppendMenu(hContextMenu, MF_SEPARATOR, 0, NULL); + + LoadString(hInst, IDS_GOTO_SUGGESTED_KEY, resource, sizeof(resource) / sizeof(resource[0])); + + s = Suggestions; + wID = ID_TREE_SUGGESTION_MIN; + while(*s && (wID <= ID_TREE_SUGGESTION_MAX)) + { + _sntprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), resource, s); + + memset(&mii, 0, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING | MIIM_ID; + mii.wID = wID++; + mii.dwTypeData = buffer; + InsertMenuItem(hContextMenu, GetMenuItemCount(hContextMenu), TRUE, &mii); + + s += _tcslen(s) + 1; + } + } + TrackPopupMenu(hContextMenu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, pChildWnd->hWnd, NULL); } } diff --git a/reactos/subsys/system/regedit/main.h b/reactos/subsys/system/regedit/main.h index f9ca5702194..c693b6212ae 100644 --- a/reactos/subsys/system/regedit/main.h +++ b/reactos/subsys/system/regedit/main.h @@ -105,6 +105,7 @@ extern LPCTSTR GetItemPath(HWND hwndTV, HTREEITEM hItem, HKEY* phRootKey); extern HTREEITEM InsertNode(HWND hwndTV, HTREEITEM hItem, LPTSTR name); extern HWND StartKeyRename(HWND hwndTV); extern BOOL CreateNewKey(HWND hwndTV, HTREEITEM hItem); +extern BOOL SelectNode(HWND hwndTV, LPCTSTR keyPath); /* edit.c */ extern BOOL ModifyValue(HWND hwnd, HKEY hKey, LPCTSTR valueName, BOOL EditBin); diff --git a/reactos/subsys/system/regedit/resource.h b/reactos/subsys/system/regedit/resource.h index 28df746d2e1..cd44a30c4c3 100644 --- a/reactos/subsys/system/regedit/resource.h +++ b/reactos/subsys/system/regedit/resource.h @@ -133,6 +133,8 @@ #define IDS_QUERY_DELETE_KEY_ONE 32875 #define IDS_QUERY_DELETE_KEY_MORE 32876 #define IDS_QUERY_DELETE_KEY_CONFIRM 32877 +#define ID_TREE_SUGGESTION_MIN 32878 +#define ID_TREE_SUGGESTION_MAX 32887 #define IDS_FLT_REGFILES 31001 #define IDS_FLT_REGFILES_FLT 31002 @@ -161,6 +163,7 @@ #define IDS_COLLAPSE 31125 #define IDS_NEW_KEY 31126 #define IDS_NEW_VALUE 31127 +#define IDS_GOTO_SUGGESTED_KEY 31128 #define IDD_EDIT_STRING 2000 diff --git a/reactos/subsys/system/regedit/treeview.c b/reactos/subsys/system/regedit/treeview.c index 6b40f18b79e..55942915e37 100644 --- a/reactos/subsys/system/regedit/treeview.c +++ b/reactos/subsys/system/regedit/treeview.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include "main.h" @@ -558,3 +560,69 @@ HWND CreateTreeView(HWND hwndParent, LPTSTR pHostName, int id) } return hwndTV; } + +BOOL SelectNode(HWND hwndTV, LPCTSTR keyPath) +{ + HTREEITEM hRoot, hItem; + HTREEITEM hChildItem; + TCHAR szPathPart[128]; + TCHAR szBuffer[128]; + LPCTSTR s; + TVITEM tvi; + + hRoot = TreeView_GetRoot(hwndTV); + hItem = hRoot; + + while(keyPath[0]) + { + s = _tcschr(keyPath, '\\'); + lstrcpyn(szPathPart, keyPath, s ? s - keyPath + 1 : _tcslen(keyPath) + 1); + + /* Special case for root to expand root key abbreviations */ + if (hItem == hRoot) + { + if (!_tcscmp(szPathPart, TEXT("HKCR"))) + _tcscpy(szPathPart, TEXT("HKEY_CLASSES_ROOT")); + else if (!_tcscmp(szPathPart, TEXT("HKCU"))) + _tcscpy(szPathPart, TEXT("HKEY_CURRENT_USER")); + else if (!_tcscmp(szPathPart, TEXT("HKLM"))) + _tcscpy(szPathPart, TEXT("HKEY_LOCAL_MACHINE")); + else if (!_tcscmp(szPathPart, TEXT("HKU"))) + _tcscpy(szPathPart, TEXT("HKEY_USERS")); + else if (!_tcscmp(szPathPart, TEXT("HKCC"))) + _tcscpy(szPathPart, TEXT("HKEY_CURRENT_CONFIG")); + else if (!_tcscmp(szPathPart, TEXT("HKDD"))) + _tcscpy(szPathPart, TEXT("HKEY_DYN_DATA")); + } + + for (hChildItem = TreeView_GetChild(hwndTV, hItem); hChildItem; + hChildItem = TreeView_GetNextSibling(hwndTV, hChildItem)) + { + memset(&tvi, 0, sizeof(tvi)); + tvi.hItem = hChildItem; + tvi.mask = TVIF_TEXT; + tvi.pszText = szBuffer; + tvi.cchTextMax = sizeof(szBuffer) / sizeof(szBuffer[0]); + + TreeView_GetItem(hwndTV, &tvi); + + if (!_tcscmp(szBuffer, szPathPart)) + break; + } + + if (!hChildItem) + return FALSE; + + if (!TreeView_Expand(hwndTV, hChildItem, TVE_EXPAND)) + return FALSE; + + keyPath = s ? s + 1 : ""; + hItem = hChildItem; + } + + TreeView_SelectItem(hwndTV, hItem); + TreeView_EnsureVisible(hwndTV, hItem); + + return TRUE; +} +