mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 05:25:48 +00:00
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
This commit is contained in:
parent
ccfa60dea9
commit
32cf34124f
5 changed files with 247 additions and 5 deletions
|
@ -340,6 +340,7 @@ STRINGTABLE DISCARDABLE
|
|||
BEGIN
|
||||
IDS_EXPAND "&Expand"
|
||||
IDS_COLLAPSE "&Collapse"
|
||||
IDS_GOTO_SUGGESTED_KEY "&Go to '%s'"
|
||||
END
|
||||
|
||||
/*****************************************************************/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <tchar.h>
|
||||
#include <process.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue