1 /* 2 * Regedit child window 3 * 4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #include "regedit.h" 22 23 ChildWnd* g_pChildWnd; 24 static int last_split; 25 HBITMAP SizingPattern = 0; 26 HBRUSH SizingBrush = 0; 27 static WCHAR Suggestions[256]; 28 29 extern LPCWSTR get_root_key_name(HKEY hRootKey) 30 { 31 if (hRootKey == HKEY_CLASSES_ROOT) return L"HKEY_CLASSES_ROOT"; 32 if (hRootKey == HKEY_CURRENT_USER) return L"HKEY_CURRENT_USER"; 33 if (hRootKey == HKEY_LOCAL_MACHINE) return L"HKEY_LOCAL_MACHINE"; 34 if (hRootKey == HKEY_USERS) return L"HKEY_USERS"; 35 if (hRootKey == HKEY_CURRENT_CONFIG) return L"HKEY_CURRENT_CONFIG"; 36 if (hRootKey == HKEY_DYN_DATA) return L"HKEY_DYN_DATA"; 37 38 return L"UNKNOWN HKEY, PLEASE REPORT"; 39 } 40 41 extern void ResizeWnd(int cx, int cy) 42 { 43 HDWP hdwp = BeginDeferWindowPos(4); 44 RECT rt, rs, rb; 45 const int nButtonWidth = 44; 46 const int nButtonHeight = 22; 47 int cyEdge = GetSystemMetrics(SM_CYEDGE); 48 const UINT uFlags = SWP_NOZORDER | SWP_NOACTIVATE; 49 SetRect(&rt, 0, 0, cx, cy); 50 cy = 0; 51 if (hStatusBar != NULL) 52 { 53 GetWindowRect(hStatusBar, &rs); 54 cy = rs.bottom - rs.top; 55 } 56 GetWindowRect(g_pChildWnd->hAddressBtnWnd, &rb); 57 cx = g_pChildWnd->nSplitPos + SPLIT_WIDTH / 2; 58 if (hdwp) 59 hdwp = DeferWindowPos(hdwp, g_pChildWnd->hAddressBarWnd, NULL, 60 rt.left, rt.top, 61 rt.right - rt.left - nButtonWidth, nButtonHeight, 62 uFlags); 63 if (hdwp) 64 hdwp = DeferWindowPos(hdwp, g_pChildWnd->hAddressBtnWnd, NULL, 65 rt.right - nButtonWidth, rt.top, 66 nButtonWidth, nButtonHeight, 67 uFlags); 68 if (hdwp) 69 hdwp = DeferWindowPos(hdwp, g_pChildWnd->hTreeWnd, NULL, 70 rt.left, 71 rt.top + nButtonHeight + cyEdge, 72 g_pChildWnd->nSplitPos - SPLIT_WIDTH/2 - rt.left, 73 rt.bottom - rt.top - cy - 2 * cyEdge, 74 uFlags); 75 if (hdwp) 76 hdwp = DeferWindowPos(hdwp, g_pChildWnd->hListWnd, NULL, 77 rt.left + cx, 78 rt.top + nButtonHeight + cyEdge, 79 rt.right - cx, 80 rt.bottom - rt.top - cy - 2 * cyEdge, 81 uFlags); 82 if (hdwp) 83 EndDeferWindowPos(hdwp); 84 } 85 86 /******************************************************************************* 87 * Local module support methods 88 */ 89 90 static void draw_splitbar(HWND hWnd, int x) 91 { 92 RECT rt; 93 HGDIOBJ OldObj; 94 HDC hdc = GetDC(hWnd); 95 96 if(!SizingPattern) 97 { 98 const DWORD Pattern[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA}; 99 SizingPattern = CreateBitmap(8, 8, 1, 1, Pattern); 100 } 101 if(!SizingBrush) 102 { 103 SizingBrush = CreatePatternBrush(SizingPattern); 104 } 105 GetClientRect(hWnd, &rt); 106 rt.left = x - SPLIT_WIDTH/2; 107 rt.right = x + SPLIT_WIDTH/2+1; 108 OldObj = SelectObject(hdc, SizingBrush); 109 PatBlt(hdc, rt.left, rt.top, rt.right - rt.left, rt.bottom - rt.top, PATINVERT); 110 SelectObject(hdc, OldObj); 111 ReleaseDC(hWnd, hdc); 112 } 113 114 /******************************************************************************* 115 * finish_splitbar [internal] 116 * 117 * make the splitbar invisible and resize the windows 118 * (helper for ChildWndProc) 119 */ 120 static void finish_splitbar(HWND hWnd, int x) 121 { 122 RECT rt; 123 124 draw_splitbar(hWnd, last_split); 125 last_split = -1; 126 GetClientRect(hWnd, &rt); 127 g_pChildWnd->nSplitPos = x; 128 ResizeWnd(rt.right, rt.bottom); 129 ReleaseCapture(); 130 } 131 132 /******************************************************************************* 133 * 134 * FUNCTION: ChildWnd_CmdWndProc(HWND, unsigned, WORD, LONG) 135 * 136 * PURPOSE: Processes WM_COMMAND messages for the main frame window. 137 * 138 */ 139 140 static BOOL ChildWnd_CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 141 { 142 HTREEITEM hSelection; 143 HKEY hRootKey; 144 LPCWSTR keyPath, s; 145 WORD wID = LOWORD(wParam); 146 147 UNREFERENCED_PARAMETER(message); 148 149 switch (wID) 150 { 151 /* Parse the menu selections: */ 152 case ID_REGISTRY_EXIT: 153 DestroyWindow(hWnd); 154 break; 155 case ID_VIEW_REFRESH: 156 /* TODO */ 157 break; 158 case ID_TREE_EXPANDBRANCH: 159 TreeView_Expand(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd), TVE_EXPAND); 160 break; 161 case ID_TREE_COLLAPSEBRANCH: 162 TreeView_Expand(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd), TVE_COLLAPSE); 163 break; 164 case ID_TREE_RENAME: 165 SetFocus(g_pChildWnd->hTreeWnd); 166 TreeView_EditLabel(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd)); 167 break; 168 case ID_TREE_DELETE: 169 hSelection = TreeView_GetSelection(g_pChildWnd->hTreeWnd); 170 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, hSelection, &hRootKey); 171 172 if (keyPath == 0 || *keyPath == 0) 173 { 174 MessageBeep(MB_ICONHAND); 175 } 176 else if (DeleteKey(hWnd, hRootKey, keyPath)) 177 DeleteNode(g_pChildWnd->hTreeWnd, 0); 178 break; 179 case ID_TREE_EXPORT: 180 ExportRegistryFile(g_pChildWnd->hTreeWnd); 181 break; 182 case ID_EDIT_FIND: 183 FindDialog(hWnd); 184 break; 185 case ID_EDIT_COPYKEYNAME: 186 hSelection = TreeView_GetSelection(g_pChildWnd->hTreeWnd); 187 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, hSelection, &hRootKey); 188 CopyKeyName(hWnd, hRootKey, keyPath); 189 break; 190 case ID_EDIT_NEW_KEY: 191 CreateNewKey(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd)); 192 break; 193 case ID_EDIT_NEW_STRINGVALUE: 194 case ID_EDIT_NEW_BINARYVALUE: 195 case ID_EDIT_NEW_DWORDVALUE: 196 SendMessageW(hFrameWnd, WM_COMMAND, wParam, lParam); 197 break; 198 case ID_SWITCH_PANELS: 199 g_pChildWnd->nFocusPanel = !g_pChildWnd->nFocusPanel; 200 SetFocus(g_pChildWnd->nFocusPanel? g_pChildWnd->hListWnd: g_pChildWnd->hTreeWnd); 201 break; 202 default: 203 if ((wID >= ID_TREE_SUGGESTION_MIN) && (wID <= ID_TREE_SUGGESTION_MAX)) 204 { 205 s = Suggestions; 206 while(wID > ID_TREE_SUGGESTION_MIN) 207 { 208 if (*s) 209 s += wcslen(s) + 1; 210 wID--; 211 } 212 SelectNode(g_pChildWnd->hTreeWnd, s); 213 break; 214 } 215 return FALSE; 216 } 217 return TRUE; 218 } 219 220 /******************************************************************************* 221 * 222 * Key suggestion 223 */ 224 225 #define MIN(a,b) ((a < b) ? (a) : (b)) 226 227 static void SuggestKeys(HKEY hRootKey, LPCWSTR pszKeyPath, LPWSTR pszSuggestions, 228 size_t iSuggestionsLength) 229 { 230 WCHAR szBuffer[256]; 231 WCHAR szLastFound[256]; 232 size_t i; 233 HKEY hOtherKey, hSubKey; 234 BOOL bFound; 235 236 memset(pszSuggestions, 0, iSuggestionsLength * sizeof(*pszSuggestions)); 237 iSuggestionsLength--; 238 239 /* Are we a root key in HKEY_CLASSES_ROOT? */ 240 if ((hRootKey == HKEY_CLASSES_ROOT) && pszKeyPath[0] && !wcschr(pszKeyPath, L'\\')) 241 { 242 do 243 { 244 bFound = FALSE; 245 246 /* Check default key */ 247 if (QueryStringValue(hRootKey, pszKeyPath, NULL, 248 szBuffer, COUNT_OF(szBuffer)) == ERROR_SUCCESS) 249 { 250 /* Sanity check this key; it cannot be empty, nor can it be a 251 * loop back */ 252 if ((szBuffer[0] != L'\0') && _wcsicmp(szBuffer, pszKeyPath)) 253 { 254 if (RegOpenKeyW(hRootKey, szBuffer, &hOtherKey) == ERROR_SUCCESS) 255 { 256 lstrcpynW(pszSuggestions, L"HKCR\\", (int) iSuggestionsLength); 257 i = wcslen(pszSuggestions); 258 pszSuggestions += i; 259 iSuggestionsLength -= i; 260 261 lstrcpynW(pszSuggestions, szBuffer, (int) iSuggestionsLength); 262 i = MIN(wcslen(pszSuggestions) + 1, iSuggestionsLength); 263 pszSuggestions += i; 264 iSuggestionsLength -= i; 265 RegCloseKey(hOtherKey); 266 267 bFound = TRUE; 268 wcscpy(szLastFound, szBuffer); 269 pszKeyPath = szLastFound; 270 } 271 } 272 } 273 } 274 while(bFound && (iSuggestionsLength > 0)); 275 276 /* Check CLSID key */ 277 if (RegOpenKeyW(hRootKey, pszKeyPath, &hSubKey) == ERROR_SUCCESS) 278 { 279 if (QueryStringValue(hSubKey, L"CLSID", NULL, szBuffer, 280 COUNT_OF(szBuffer)) == ERROR_SUCCESS) 281 { 282 lstrcpynW(pszSuggestions, L"HKCR\\CLSID\\", (int)iSuggestionsLength); 283 i = wcslen(pszSuggestions); 284 pszSuggestions += i; 285 iSuggestionsLength -= i; 286 287 lstrcpynW(pszSuggestions, szBuffer, (int)iSuggestionsLength); 288 i = MIN(wcslen(pszSuggestions) + 1, iSuggestionsLength); 289 pszSuggestions += i; 290 iSuggestionsLength -= i; 291 } 292 RegCloseKey(hSubKey); 293 } 294 } 295 } 296 297 298 LRESULT CALLBACK AddressBarProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 299 { 300 WNDPROC oldwndproc; 301 static WCHAR s_szNode[256]; 302 oldwndproc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA); 303 304 switch (uMsg) 305 { 306 case WM_KEYUP: 307 if (wParam == VK_RETURN) 308 { 309 GetWindowTextW(hwnd, s_szNode, COUNT_OF(s_szNode)); 310 SelectNode(g_pChildWnd->hTreeWnd, s_szNode); 311 } 312 break; 313 default: 314 break; 315 } 316 return CallWindowProcW(oldwndproc, hwnd, uMsg, wParam, lParam); 317 } 318 319 static VOID 320 UpdateAddress(HTREEITEM hItem, HKEY hRootKey, LPCWSTR pszPath) 321 { 322 LPCWSTR keyPath, rootName; 323 LPWSTR fullPath; 324 325 /* Wipe the listview, the status bar and the address bar if the root key was selected */ 326 if (TreeView_GetParent(g_pChildWnd->hTreeWnd, hItem) == NULL) 327 { 328 ListView_DeleteAllItems(g_pChildWnd->hListWnd); 329 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)NULL); 330 SendMessageW(g_pChildWnd->hAddressBarWnd, WM_SETTEXT, 0, (LPARAM)NULL); 331 return; 332 } 333 334 if (pszPath == NULL) 335 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, hItem, &hRootKey); 336 else 337 keyPath = pszPath; 338 339 if (keyPath) 340 { 341 RefreshListView(g_pChildWnd->hListWnd, hRootKey, keyPath); 342 rootName = get_root_key_name(hRootKey); 343 fullPath = HeapAlloc(GetProcessHeap(), 0, (wcslen(rootName) + 1 + wcslen(keyPath) + 1) * sizeof(WCHAR)); 344 if (fullPath) 345 { 346 /* set (correct) the address bar text */ 347 if (keyPath[0] != L'\0') 348 swprintf(fullPath, L"%s\\%s", rootName, keyPath); 349 else 350 fullPath = wcscpy(fullPath, rootName); 351 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath); 352 SendMessageW(g_pChildWnd->hAddressBarWnd, WM_SETTEXT, 0, (LPARAM)fullPath); 353 HeapFree(GetProcessHeap(), 0, fullPath); 354 /* disable hive manipulation items temporarily (enable only if necessary) */ 355 EnableMenuItem(GetSubMenu(hMenuFrame,0), ID_REGISTRY_LOADHIVE, MF_BYCOMMAND | MF_GRAYED); 356 EnableMenuItem(GetSubMenu(hMenuFrame,0), ID_REGISTRY_UNLOADHIVE, MF_BYCOMMAND | MF_GRAYED); 357 /* compare the strings to see if we should enable/disable the "Load Hive" menus accordingly */ 358 if (!(_wcsicmp(rootName, L"HKEY_LOCAL_MACHINE") && 359 _wcsicmp(rootName, L"HKEY_USERS"))) 360 { 361 /* 362 * enable the unload menu item if at the root, otherwise 363 * enable the load menu item if there is no slash in 364 * keyPath (ie. immediate child selected) 365 */ 366 if(keyPath[0] == L'\0') 367 EnableMenuItem(GetSubMenu(hMenuFrame,0), ID_REGISTRY_LOADHIVE, MF_BYCOMMAND | MF_ENABLED); 368 else if(!wcschr(keyPath, L'\\')) 369 EnableMenuItem(GetSubMenu(hMenuFrame,0), ID_REGISTRY_UNLOADHIVE, MF_BYCOMMAND | MF_ENABLED); 370 } 371 } 372 } 373 } 374 375 /******************************************************************************* 376 * 377 * FUNCTION: ChildWndProc(HWND, unsigned, WORD, LONG) 378 * 379 * PURPOSE: Processes messages for the child windows. 380 * 381 * WM_COMMAND - process the application menu 382 * WM_DESTROY - post a quit message and return 383 * 384 */ 385 LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 386 { 387 BOOL Result; 388 389 switch (message) 390 { 391 case WM_CREATE: 392 { 393 WNDPROC oldproc; 394 HFONT hFont; 395 WCHAR buffer[MAX_PATH]; 396 397 /* Load "My Computer" string */ 398 LoadStringW(hInst, IDS_MY_COMPUTER, buffer, COUNT_OF(buffer)); 399 400 g_pChildWnd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ChildWnd)); 401 if (!g_pChildWnd) return 0; 402 403 wcsncpy(g_pChildWnd->szPath, buffer, MAX_PATH); 404 g_pChildWnd->nSplitPos = 250; 405 g_pChildWnd->hWnd = hWnd; 406 g_pChildWnd->hAddressBarWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", NULL, WS_CHILD | WS_VISIBLE | WS_CHILDWINDOW | WS_TABSTOP, 407 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 408 hWnd, (HMENU)0, hInst, 0); 409 g_pChildWnd->hAddressBtnWnd = CreateWindowExW(0, L"Button", L"\x00BB", WS_CHILD | WS_VISIBLE | WS_CHILDWINDOW | WS_TABSTOP | BS_TEXT | BS_CENTER | BS_VCENTER | BS_FLAT | BS_DEFPUSHBUTTON, 410 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 411 hWnd, (HMENU)0, hInst, 0); 412 g_pChildWnd->hTreeWnd = CreateTreeView(hWnd, g_pChildWnd->szPath, (HMENU) TREE_WINDOW); 413 g_pChildWnd->hListWnd = CreateListView(hWnd, (HMENU) LIST_WINDOW/*, g_pChildWnd->szPath*/); 414 SetFocus(g_pChildWnd->hTreeWnd); 415 416 /* set the address bar and button font */ 417 if ((g_pChildWnd->hAddressBarWnd) && (g_pChildWnd->hAddressBtnWnd)) 418 { 419 hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); 420 SendMessageW(g_pChildWnd->hAddressBarWnd, 421 WM_SETFONT, 422 (WPARAM)hFont, 423 0); 424 SendMessageW(g_pChildWnd->hAddressBtnWnd, 425 WM_SETFONT, 426 (WPARAM)hFont, 427 0); 428 } 429 /* Subclass the AddressBar */ 430 oldproc = (WNDPROC)GetWindowLongPtr(g_pChildWnd->hAddressBarWnd, GWLP_WNDPROC); 431 SetWindowLongPtr(g_pChildWnd->hAddressBarWnd, GWLP_USERDATA, (DWORD_PTR)oldproc); 432 SetWindowLongPtr(g_pChildWnd->hAddressBarWnd, GWLP_WNDPROC, (DWORD_PTR)AddressBarProc); 433 break; 434 } 435 case WM_COMMAND: 436 if(HIWORD(wParam) == BN_CLICKED) 437 { 438 PostMessageW(g_pChildWnd->hAddressBarWnd, WM_KEYUP, VK_RETURN, 0); 439 } 440 441 if (!ChildWnd_CmdWndProc(hWnd, message, wParam, lParam)) 442 { 443 goto def; 444 } 445 break; 446 case WM_SETCURSOR: 447 if (LOWORD(lParam) == HTCLIENT) 448 { 449 POINT pt; 450 GetCursorPos(&pt); 451 ScreenToClient(hWnd, &pt); 452 if (pt.x>=g_pChildWnd->nSplitPos-SPLIT_WIDTH/2 && pt.x<g_pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) 453 { 454 SetCursor(LoadCursorW(0, IDC_SIZEWE)); 455 return TRUE; 456 } 457 } 458 goto def; 459 case WM_DESTROY: 460 DestroyListView(g_pChildWnd->hListWnd); 461 DestroyTreeView(g_pChildWnd->hTreeWnd); 462 DestroyMainMenu(); 463 HeapFree(GetProcessHeap(), 0, g_pChildWnd); 464 g_pChildWnd = NULL; 465 PostQuitMessage(0); 466 break; 467 case WM_LBUTTONDOWN: 468 { 469 RECT rt; 470 int x = (short)LOWORD(lParam); 471 GetClientRect(hWnd, &rt); 472 if (x>=g_pChildWnd->nSplitPos-SPLIT_WIDTH/2 && x<g_pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) 473 { 474 last_split = g_pChildWnd->nSplitPos; 475 draw_splitbar(hWnd, last_split); 476 SetCapture(hWnd); 477 } 478 break; 479 } 480 481 case WM_LBUTTONUP: 482 case WM_RBUTTONDOWN: 483 if (GetCapture() == hWnd) 484 { 485 finish_splitbar(hWnd, LOWORD(lParam)); 486 } 487 break; 488 489 case WM_CAPTURECHANGED: 490 if (GetCapture()==hWnd && last_split>=0) 491 draw_splitbar(hWnd, last_split); 492 break; 493 494 case WM_KEYDOWN: 495 if (wParam == VK_ESCAPE) 496 if (GetCapture() == hWnd) 497 { 498 RECT rt; 499 draw_splitbar(hWnd, last_split); 500 GetClientRect(hWnd, &rt); 501 ResizeWnd(rt.right, rt.bottom); 502 last_split = -1; 503 ReleaseCapture(); 504 SetCursor(LoadCursorW(0, IDC_ARROW)); 505 } 506 break; 507 508 case WM_MOUSEMOVE: 509 if (GetCapture() == hWnd) 510 { 511 HDC hdc; 512 RECT rt; 513 HGDIOBJ OldObj; 514 int x = LOWORD(lParam); 515 if(!SizingPattern) 516 { 517 const DWORD Pattern[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA}; 518 SizingPattern = CreateBitmap(8, 8, 1, 1, Pattern); 519 } 520 if(!SizingBrush) 521 { 522 SizingBrush = CreatePatternBrush(SizingPattern); 523 } 524 525 GetClientRect(hWnd, &rt); 526 x = (SHORT) min(max(x, SPLIT_MIN), rt.right - SPLIT_MIN); 527 if(last_split != x) 528 { 529 rt.left = last_split-SPLIT_WIDTH/2; 530 rt.right = last_split+SPLIT_WIDTH/2+1; 531 hdc = GetDC(hWnd); 532 OldObj = SelectObject(hdc, SizingBrush); 533 PatBlt(hdc, rt.left, rt.top, rt.right - rt.left, rt.bottom - rt.top, PATINVERT); 534 last_split = x; 535 rt.left = x-SPLIT_WIDTH/2; 536 rt.right = x+SPLIT_WIDTH/2+1; 537 PatBlt(hdc, rt.left, rt.top, rt.right - rt.left, rt.bottom - rt.top, PATINVERT); 538 SelectObject(hdc, OldObj); 539 ReleaseDC(hWnd, hdc); 540 } 541 } 542 break; 543 544 case WM_SETFOCUS: 545 if (g_pChildWnd != NULL) 546 { 547 SetFocus(g_pChildWnd->nFocusPanel? g_pChildWnd->hListWnd: g_pChildWnd->hTreeWnd); 548 } 549 break; 550 551 case WM_TIMER: 552 break; 553 554 case WM_NOTIFY: 555 if ((int)wParam == TREE_WINDOW && g_pChildWnd != NULL) 556 { 557 switch (((LPNMHDR)lParam)->code) 558 { 559 case TVN_ITEMEXPANDING: 560 return !OnTreeExpanding(g_pChildWnd->hTreeWnd, (NMTREEVIEW*)lParam); 561 case TVN_SELCHANGED: 562 { 563 NMTREEVIEW* pnmtv = (NMTREEVIEW*)lParam; 564 /* Get the parent of the current item */ 565 HTREEITEM hParentItem = TreeView_GetParent(g_pChildWnd->hTreeWnd, pnmtv->itemNew.hItem); 566 567 UpdateAddress(pnmtv->itemNew.hItem, NULL, NULL); 568 569 /* 570 * Disable Delete/Rename menu options for 'My Computer' (first item so doesn't have any parent) 571 * and HKEY_* keys (their parent is 'My Computer' and the previous remark applies). 572 */ 573 if (!hParentItem || !TreeView_GetParent(g_pChildWnd->hTreeWnd, hParentItem)) 574 { 575 EnableMenuItem(hMenuFrame , ID_EDIT_DELETE, MF_BYCOMMAND | MF_GRAYED); 576 EnableMenuItem(hMenuFrame , ID_EDIT_RENAME, MF_BYCOMMAND | MF_GRAYED); 577 EnableMenuItem(hPopupMenus, ID_TREE_DELETE, MF_BYCOMMAND | MF_GRAYED); 578 EnableMenuItem(hPopupMenus, ID_TREE_RENAME, MF_BYCOMMAND | MF_GRAYED); 579 } 580 else 581 { 582 EnableMenuItem(hMenuFrame , ID_EDIT_DELETE, MF_BYCOMMAND | MF_ENABLED); 583 EnableMenuItem(hMenuFrame , ID_EDIT_RENAME, MF_BYCOMMAND | MF_ENABLED); 584 EnableMenuItem(hPopupMenus, ID_TREE_DELETE, MF_BYCOMMAND | MF_ENABLED); 585 EnableMenuItem(hPopupMenus, ID_TREE_RENAME, MF_BYCOMMAND | MF_ENABLED); 586 } 587 588 break; 589 } 590 case NM_SETFOCUS: 591 g_pChildWnd->nFocusPanel = 0; 592 break; 593 case TVN_BEGINLABELEDIT: 594 { 595 LPNMTVDISPINFO ptvdi; 596 /* cancel label edit for rootkeys */ 597 ptvdi = (LPNMTVDISPINFO) lParam; 598 if (!TreeView_GetParent(g_pChildWnd->hTreeWnd, ptvdi->item.hItem) || 599 !TreeView_GetParent(g_pChildWnd->hTreeWnd, TreeView_GetParent(g_pChildWnd->hTreeWnd, ptvdi->item.hItem))) 600 return TRUE; 601 break; 602 } 603 case TVN_ENDLABELEDIT: 604 { 605 LPCWSTR keyPath; 606 HKEY hRootKey; 607 HKEY hKey = NULL; 608 LPNMTVDISPINFO ptvdi; 609 LONG lResult = TRUE; 610 WCHAR szBuffer[MAX_PATH]; 611 612 ptvdi = (LPNMTVDISPINFO) lParam; 613 if (ptvdi->item.pszText) 614 { 615 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, TreeView_GetParent(g_pChildWnd->hTreeWnd, ptvdi->item.hItem), &hRootKey); 616 _snwprintf(szBuffer, COUNT_OF(szBuffer), L"%s\\%s", keyPath, ptvdi->item.pszText); 617 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, ptvdi->item.hItem, &hRootKey); 618 if (RegOpenKeyExW(hRootKey, szBuffer, 0, KEY_READ, &hKey) == ERROR_SUCCESS) 619 { 620 lResult = FALSE; 621 RegCloseKey(hKey); 622 TreeView_EditLabel(g_pChildWnd->hTreeWnd, ptvdi->item.hItem); 623 } 624 else 625 { 626 if (RenameKey(hRootKey, keyPath, ptvdi->item.pszText) != ERROR_SUCCESS) 627 lResult = FALSE; 628 else 629 UpdateAddress(ptvdi->item.hItem, hRootKey, szBuffer); 630 } 631 return lResult; 632 } 633 } 634 default: 635 return 0; 636 } 637 } 638 else 639 { 640 if ((int)wParam == LIST_WINDOW && g_pChildWnd != NULL) 641 { 642 switch (((LPNMHDR)lParam)->code) 643 { 644 case NM_SETFOCUS: 645 g_pChildWnd->nFocusPanel = 1; 646 break; 647 default: 648 if(!ListWndNotifyProc(g_pChildWnd->hListWnd, wParam, lParam, &Result)) 649 { 650 goto def; 651 } 652 return Result; 653 break; 654 } 655 } 656 } 657 break; 658 659 case WM_CONTEXTMENU: 660 { 661 POINT pt; 662 if((HWND)wParam == g_pChildWnd->hListWnd) 663 { 664 int i, cnt; 665 BOOL IsDefault; 666 pt.x = (short) LOWORD(lParam); 667 pt.y = (short) HIWORD(lParam); 668 cnt = ListView_GetSelectedCount(g_pChildWnd->hListWnd); 669 i = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_FOCUSED | LVNI_SELECTED); 670 if (pt.x == -1 && pt.y == -1) 671 { 672 RECT rc; 673 if (i != -1) 674 { 675 rc.left = LVIR_BOUNDS; 676 SendMessageW(g_pChildWnd->hListWnd, LVM_GETITEMRECT, i, (LPARAM) &rc); 677 pt.x = rc.left + 8; 678 pt.y = rc.top + 8; 679 } 680 else 681 pt.x = pt.y = 0; 682 ClientToScreen(g_pChildWnd->hListWnd, &pt); 683 } 684 if(i == -1) 685 { 686 TrackPopupMenu(GetSubMenu(hPopupMenus, PM_NEW), TPM_RIGHTBUTTON, pt.x, pt.y, 0, hFrameWnd, NULL); 687 } 688 else 689 { 690 HMENU mnu = GetSubMenu(hPopupMenus, PM_MODIFYVALUE); 691 SetMenuDefaultItem(mnu, ID_EDIT_MODIFY, MF_BYCOMMAND); 692 IsDefault = IsDefaultValue(g_pChildWnd->hListWnd, i); 693 if(cnt == 1) 694 EnableMenuItem(mnu, ID_EDIT_RENAME, MF_BYCOMMAND | (IsDefault ? MF_DISABLED | MF_GRAYED : MF_ENABLED)); 695 else 696 EnableMenuItem(mnu, ID_EDIT_RENAME, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); 697 EnableMenuItem(mnu, ID_EDIT_MODIFY, MF_BYCOMMAND | (cnt == 1 ? MF_ENABLED : MF_DISABLED | MF_GRAYED)); 698 EnableMenuItem(mnu, ID_EDIT_MODIFY_BIN, MF_BYCOMMAND | (cnt == 1 ? MF_ENABLED : MF_DISABLED | MF_GRAYED)); 699 700 TrackPopupMenu(mnu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, hFrameWnd, NULL); 701 } 702 } 703 else if ((HWND)wParam == g_pChildWnd->hTreeWnd) 704 { 705 TVHITTESTINFO hti; 706 HMENU hContextMenu; 707 TVITEMW item; 708 MENUITEMINFOW mii; 709 WCHAR resource[256]; 710 WCHAR buffer[256]; 711 LPWSTR s; 712 LPCWSTR keyPath; 713 HKEY hRootKey; 714 int iLastPos; 715 WORD wID; 716 717 pt.x = (short) LOWORD(lParam); 718 pt.y = (short) HIWORD(lParam); 719 720 if (pt.x == -1 && pt.y == -1) 721 { 722 RECT rc; 723 hti.hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd); 724 if (hti.hItem != NULL) 725 { 726 TreeView_GetItemRect(g_pChildWnd->hTreeWnd, hti.hItem, &rc, TRUE); 727 pt.x = rc.left + 8; 728 pt.y = rc.top + 8; 729 ClientToScreen(g_pChildWnd->hTreeWnd, &pt); 730 hti.flags = TVHT_ONITEM; 731 } 732 else 733 hti.flags = 0; 734 } 735 else 736 { 737 hti.pt.x = pt.x; 738 hti.pt.y = pt.y; 739 ScreenToClient(g_pChildWnd->hTreeWnd, &hti.pt); 740 TreeView_HitTest(g_pChildWnd->hTreeWnd, &hti); 741 } 742 743 if (hti.flags & TVHT_ONITEM) 744 { 745 hContextMenu = GetSubMenu(hPopupMenus, PM_TREECONTEXT); 746 TreeView_SelectItem(g_pChildWnd->hTreeWnd, hti.hItem); 747 748 memset(&item, 0, sizeof(item)); 749 item.mask = TVIF_STATE | TVIF_CHILDREN; 750 item.hItem = hti.hItem; 751 TreeView_GetItem(g_pChildWnd->hTreeWnd, &item); 752 753 /* Set the Expand/Collapse menu item appropriately */ 754 LoadStringW(hInst, (item.state & TVIS_EXPANDED) ? IDS_COLLAPSE : IDS_EXPAND, buffer, COUNT_OF(buffer)); 755 memset(&mii, 0, sizeof(mii)); 756 mii.cbSize = sizeof(mii); 757 mii.fMask = MIIM_STRING | MIIM_STATE | MIIM_ID; 758 mii.fState = (item.cChildren > 0) ? MFS_DEFAULT : MFS_GRAYED; 759 mii.wID = (item.state & TVIS_EXPANDED) ? ID_TREE_COLLAPSEBRANCH : ID_TREE_EXPANDBRANCH; 760 mii.dwTypeData = (LPWSTR) buffer; 761 SetMenuItemInfo(hContextMenu, 0, TRUE, &mii); 762 763 /* Remove any existing suggestions */ 764 memset(&mii, 0, sizeof(mii)); 765 mii.cbSize = sizeof(mii); 766 mii.fMask = MIIM_ID; 767 GetMenuItemInfo(hContextMenu, GetMenuItemCount(hContextMenu) - 1, TRUE, &mii); 768 if ((mii.wID >= ID_TREE_SUGGESTION_MIN) && (mii.wID <= ID_TREE_SUGGESTION_MAX)) 769 { 770 do 771 { 772 iLastPos = GetMenuItemCount(hContextMenu) - 1; 773 GetMenuItemInfo(hContextMenu, iLastPos, TRUE, &mii); 774 RemoveMenu(hContextMenu, iLastPos, MF_BYPOSITION); 775 } 776 while((mii.wID >= ID_TREE_SUGGESTION_MIN) && (mii.wID <= ID_TREE_SUGGESTION_MAX)); 777 } 778 779 /* Come up with suggestions */ 780 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, NULL, &hRootKey); 781 SuggestKeys(hRootKey, keyPath, Suggestions, COUNT_OF(Suggestions)); 782 if (Suggestions[0]) 783 { 784 AppendMenu(hContextMenu, MF_SEPARATOR, 0, NULL); 785 786 LoadStringW(hInst, IDS_GOTO_SUGGESTED_KEY, resource, COUNT_OF(resource)); 787 788 s = Suggestions; 789 wID = ID_TREE_SUGGESTION_MIN; 790 while(*s && (wID <= ID_TREE_SUGGESTION_MAX)) 791 { 792 _snwprintf(buffer, COUNT_OF(buffer), resource, s); 793 794 memset(&mii, 0, sizeof(mii)); 795 mii.cbSize = sizeof(mii); 796 mii.fMask = MIIM_STRING | MIIM_ID; 797 mii.wID = wID++; 798 mii.dwTypeData = buffer; 799 InsertMenuItem(hContextMenu, GetMenuItemCount(hContextMenu), TRUE, &mii); 800 801 s += wcslen(s) + 1; 802 } 803 } 804 TrackPopupMenu(hContextMenu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, g_pChildWnd->hWnd, NULL); 805 } 806 } 807 break; 808 } 809 810 case WM_SIZE: 811 if (wParam != SIZE_MINIMIZED && g_pChildWnd != NULL) 812 { 813 ResizeWnd(LOWORD(lParam), HIWORD(lParam)); 814 } 815 /* fall through */ 816 default: 817 def: 818 return DefWindowProcW(hWnd, message, wParam, lParam); 819 } 820 return 0; 821 } 822