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