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 RECT rc; 389 390 switch (message) 391 { 392 case WM_CREATE: 393 { 394 WNDPROC oldproc; 395 HFONT hFont; 396 WCHAR buffer[MAX_PATH]; 397 DWORD style; 398 399 /* Load "My Computer" string */ 400 LoadStringW(hInst, IDS_MY_COMPUTER, buffer, COUNT_OF(buffer)); 401 402 g_pChildWnd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ChildWnd)); 403 if (!g_pChildWnd) return 0; 404 405 wcsncpy(g_pChildWnd->szPath, buffer, MAX_PATH); 406 g_pChildWnd->nSplitPos = 190; 407 g_pChildWnd->hWnd = hWnd; 408 409 style = WS_CHILD | WS_VISIBLE | WS_TABSTOP; 410 g_pChildWnd->hAddressBarWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", NULL, style, 411 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 412 hWnd, (HMENU)0, hInst, 0); 413 414 style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_ICON | BS_CENTER | 415 BS_VCENTER | BS_FLAT | BS_DEFPUSHBUTTON; 416 g_pChildWnd->hAddressBtnWnd = CreateWindowExW(0, L"Button", L"\x00BB", style, 417 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 418 hWnd, (HMENU)0, hInst, 0); 419 g_pChildWnd->hArrowIcon = (HICON)LoadImageW(hInst, MAKEINTRESOURCEW(IDI_ARROW), 420 IMAGE_ICON, 12, 12, 0); 421 SendMessageW(g_pChildWnd->hAddressBtnWnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)g_pChildWnd->hArrowIcon); 422 423 GetClientRect(hWnd, &rc); 424 g_pChildWnd->hTreeWnd = CreateTreeView(hWnd, g_pChildWnd->szPath, (HMENU) TREE_WINDOW); 425 g_pChildWnd->hListWnd = CreateListView(hWnd, (HMENU) LIST_WINDOW, rc.right - g_pChildWnd->nSplitPos); 426 SetFocus(g_pChildWnd->hTreeWnd); 427 428 /* set the address bar and button font */ 429 if ((g_pChildWnd->hAddressBarWnd) && (g_pChildWnd->hAddressBtnWnd)) 430 { 431 hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); 432 SendMessageW(g_pChildWnd->hAddressBarWnd, 433 WM_SETFONT, 434 (WPARAM)hFont, 435 0); 436 SendMessageW(g_pChildWnd->hAddressBtnWnd, 437 WM_SETFONT, 438 (WPARAM)hFont, 439 0); 440 } 441 /* Subclass the AddressBar */ 442 oldproc = (WNDPROC)GetWindowLongPtr(g_pChildWnd->hAddressBarWnd, GWLP_WNDPROC); 443 SetWindowLongPtr(g_pChildWnd->hAddressBarWnd, GWLP_USERDATA, (DWORD_PTR)oldproc); 444 SetWindowLongPtr(g_pChildWnd->hAddressBarWnd, GWLP_WNDPROC, (DWORD_PTR)AddressBarProc); 445 break; 446 } 447 case WM_COMMAND: 448 if(HIWORD(wParam) == BN_CLICKED) 449 { 450 PostMessageW(g_pChildWnd->hAddressBarWnd, WM_KEYUP, VK_RETURN, 0); 451 } 452 453 if (!ChildWnd_CmdWndProc(hWnd, message, wParam, lParam)) 454 { 455 goto def; 456 } 457 break; 458 case WM_SETCURSOR: 459 if (LOWORD(lParam) == HTCLIENT) 460 { 461 POINT pt; 462 GetCursorPos(&pt); 463 ScreenToClient(hWnd, &pt); 464 if (pt.x>=g_pChildWnd->nSplitPos-SPLIT_WIDTH/2 && pt.x<g_pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) 465 { 466 SetCursor(LoadCursorW(0, IDC_SIZEWE)); 467 return TRUE; 468 } 469 } 470 goto def; 471 case WM_DESTROY: 472 DestroyListView(g_pChildWnd->hListWnd); 473 DestroyTreeView(g_pChildWnd->hTreeWnd); 474 DestroyMainMenu(); 475 DestroyIcon(g_pChildWnd->hArrowIcon); 476 HeapFree(GetProcessHeap(), 0, g_pChildWnd); 477 g_pChildWnd = NULL; 478 PostQuitMessage(0); 479 break; 480 case WM_LBUTTONDOWN: 481 { 482 RECT rt; 483 int x = (short)LOWORD(lParam); 484 GetClientRect(hWnd, &rt); 485 if (x>=g_pChildWnd->nSplitPos-SPLIT_WIDTH/2 && x<g_pChildWnd->nSplitPos+SPLIT_WIDTH/2+1) 486 { 487 last_split = g_pChildWnd->nSplitPos; 488 draw_splitbar(hWnd, last_split); 489 SetCapture(hWnd); 490 } 491 break; 492 } 493 494 case WM_LBUTTONUP: 495 case WM_RBUTTONDOWN: 496 if (GetCapture() == hWnd) 497 { 498 finish_splitbar(hWnd, LOWORD(lParam)); 499 } 500 break; 501 502 case WM_CAPTURECHANGED: 503 if (GetCapture()==hWnd && last_split>=0) 504 draw_splitbar(hWnd, last_split); 505 break; 506 507 case WM_KEYDOWN: 508 if (wParam == VK_ESCAPE) 509 if (GetCapture() == hWnd) 510 { 511 RECT rt; 512 draw_splitbar(hWnd, last_split); 513 GetClientRect(hWnd, &rt); 514 ResizeWnd(rt.right, rt.bottom); 515 last_split = -1; 516 ReleaseCapture(); 517 SetCursor(LoadCursorW(0, IDC_ARROW)); 518 } 519 break; 520 521 case WM_MOUSEMOVE: 522 if (GetCapture() == hWnd) 523 { 524 HDC hdc; 525 RECT rt; 526 HGDIOBJ OldObj; 527 int x = LOWORD(lParam); 528 if(!SizingPattern) 529 { 530 const DWORD Pattern[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA}; 531 SizingPattern = CreateBitmap(8, 8, 1, 1, Pattern); 532 } 533 if(!SizingBrush) 534 { 535 SizingBrush = CreatePatternBrush(SizingPattern); 536 } 537 538 GetClientRect(hWnd, &rt); 539 x = (SHORT) min(max(x, SPLIT_MIN), rt.right - SPLIT_MIN); 540 if(last_split != x) 541 { 542 rt.left = last_split-SPLIT_WIDTH/2; 543 rt.right = last_split+SPLIT_WIDTH/2+1; 544 hdc = GetDC(hWnd); 545 OldObj = SelectObject(hdc, SizingBrush); 546 PatBlt(hdc, rt.left, rt.top, rt.right - rt.left, rt.bottom - rt.top, PATINVERT); 547 last_split = x; 548 rt.left = x-SPLIT_WIDTH/2; 549 rt.right = x+SPLIT_WIDTH/2+1; 550 PatBlt(hdc, rt.left, rt.top, rt.right - rt.left, rt.bottom - rt.top, PATINVERT); 551 SelectObject(hdc, OldObj); 552 ReleaseDC(hWnd, hdc); 553 } 554 } 555 break; 556 557 case WM_SETFOCUS: 558 if (g_pChildWnd != NULL) 559 { 560 SetFocus(g_pChildWnd->nFocusPanel? g_pChildWnd->hListWnd: g_pChildWnd->hTreeWnd); 561 } 562 break; 563 564 case WM_TIMER: 565 break; 566 567 case WM_NOTIFY: 568 if ((int)wParam == TREE_WINDOW && g_pChildWnd != NULL) 569 { 570 switch (((LPNMHDR)lParam)->code) 571 { 572 case TVN_ITEMEXPANDING: 573 return !OnTreeExpanding(g_pChildWnd->hTreeWnd, (NMTREEVIEW*)lParam); 574 case TVN_SELCHANGED: 575 { 576 NMTREEVIEW* pnmtv = (NMTREEVIEW*)lParam; 577 /* Get the parent of the current item */ 578 HTREEITEM hParentItem = TreeView_GetParent(g_pChildWnd->hTreeWnd, pnmtv->itemNew.hItem); 579 580 UpdateAddress(pnmtv->itemNew.hItem, NULL, NULL); 581 582 /* 583 * Disable Delete/Rename menu options for 'My Computer' (first item so doesn't have any parent) 584 * and HKEY_* keys (their parent is 'My Computer' and the previous remark applies). 585 */ 586 if (!hParentItem || !TreeView_GetParent(g_pChildWnd->hTreeWnd, hParentItem)) 587 { 588 EnableMenuItem(hMenuFrame , ID_EDIT_DELETE, MF_BYCOMMAND | MF_GRAYED); 589 EnableMenuItem(hMenuFrame , ID_EDIT_RENAME, MF_BYCOMMAND | MF_GRAYED); 590 EnableMenuItem(hPopupMenus, ID_TREE_DELETE, MF_BYCOMMAND | MF_GRAYED); 591 EnableMenuItem(hPopupMenus, ID_TREE_RENAME, MF_BYCOMMAND | MF_GRAYED); 592 } 593 else 594 { 595 EnableMenuItem(hMenuFrame , ID_EDIT_DELETE, MF_BYCOMMAND | MF_ENABLED); 596 EnableMenuItem(hMenuFrame , ID_EDIT_RENAME, MF_BYCOMMAND | MF_ENABLED); 597 EnableMenuItem(hPopupMenus, ID_TREE_DELETE, MF_BYCOMMAND | MF_ENABLED); 598 EnableMenuItem(hPopupMenus, ID_TREE_RENAME, MF_BYCOMMAND | MF_ENABLED); 599 } 600 601 break; 602 } 603 case NM_SETFOCUS: 604 g_pChildWnd->nFocusPanel = 0; 605 break; 606 case TVN_BEGINLABELEDIT: 607 { 608 LPNMTVDISPINFO ptvdi; 609 /* cancel label edit for rootkeys */ 610 ptvdi = (LPNMTVDISPINFO) lParam; 611 if (!TreeView_GetParent(g_pChildWnd->hTreeWnd, ptvdi->item.hItem) || 612 !TreeView_GetParent(g_pChildWnd->hTreeWnd, TreeView_GetParent(g_pChildWnd->hTreeWnd, ptvdi->item.hItem))) 613 return TRUE; 614 break; 615 } 616 case TVN_ENDLABELEDIT: 617 { 618 LPCWSTR keyPath; 619 HKEY hRootKey; 620 HKEY hKey = NULL; 621 LPNMTVDISPINFO ptvdi; 622 LONG lResult = TRUE; 623 WCHAR szBuffer[MAX_PATH]; 624 625 ptvdi = (LPNMTVDISPINFO) lParam; 626 if (ptvdi->item.pszText) 627 { 628 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, TreeView_GetParent(g_pChildWnd->hTreeWnd, ptvdi->item.hItem), &hRootKey); 629 _snwprintf(szBuffer, COUNT_OF(szBuffer), L"%s\\%s", keyPath, ptvdi->item.pszText); 630 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, ptvdi->item.hItem, &hRootKey); 631 if (RegOpenKeyExW(hRootKey, szBuffer, 0, KEY_READ, &hKey) == ERROR_SUCCESS) 632 { 633 lResult = FALSE; 634 RegCloseKey(hKey); 635 TreeView_EditLabel(g_pChildWnd->hTreeWnd, ptvdi->item.hItem); 636 } 637 else 638 { 639 if (RenameKey(hRootKey, keyPath, ptvdi->item.pszText) != ERROR_SUCCESS) 640 lResult = FALSE; 641 else 642 UpdateAddress(ptvdi->item.hItem, hRootKey, szBuffer); 643 } 644 return lResult; 645 } 646 } 647 default: 648 return 0; 649 } 650 } 651 else 652 { 653 if ((int)wParam == LIST_WINDOW && g_pChildWnd != NULL) 654 { 655 switch (((LPNMHDR)lParam)->code) 656 { 657 case NM_SETFOCUS: 658 g_pChildWnd->nFocusPanel = 1; 659 break; 660 default: 661 if(!ListWndNotifyProc(g_pChildWnd->hListWnd, wParam, lParam, &Result)) 662 { 663 goto def; 664 } 665 return Result; 666 break; 667 } 668 } 669 } 670 break; 671 672 case WM_CONTEXTMENU: 673 { 674 POINT pt; 675 if((HWND)wParam == g_pChildWnd->hListWnd) 676 { 677 int i, cnt; 678 BOOL IsDefault; 679 pt.x = (short) LOWORD(lParam); 680 pt.y = (short) HIWORD(lParam); 681 cnt = ListView_GetSelectedCount(g_pChildWnd->hListWnd); 682 i = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_FOCUSED | LVNI_SELECTED); 683 if (pt.x == -1 && pt.y == -1) 684 { 685 RECT rc; 686 if (i != -1) 687 { 688 rc.left = LVIR_BOUNDS; 689 SendMessageW(g_pChildWnd->hListWnd, LVM_GETITEMRECT, i, (LPARAM) &rc); 690 pt.x = rc.left + 8; 691 pt.y = rc.top + 8; 692 } 693 else 694 pt.x = pt.y = 0; 695 ClientToScreen(g_pChildWnd->hListWnd, &pt); 696 } 697 if(i == -1) 698 { 699 TrackPopupMenu(GetSubMenu(hPopupMenus, PM_NEW), TPM_RIGHTBUTTON, pt.x, pt.y, 0, hFrameWnd, NULL); 700 } 701 else 702 { 703 HMENU mnu = GetSubMenu(hPopupMenus, PM_MODIFYVALUE); 704 SetMenuDefaultItem(mnu, ID_EDIT_MODIFY, MF_BYCOMMAND); 705 IsDefault = IsDefaultValue(g_pChildWnd->hListWnd, i); 706 if(cnt == 1) 707 EnableMenuItem(mnu, ID_EDIT_RENAME, MF_BYCOMMAND | (IsDefault ? MF_DISABLED | MF_GRAYED : MF_ENABLED)); 708 else 709 EnableMenuItem(mnu, ID_EDIT_RENAME, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); 710 EnableMenuItem(mnu, ID_EDIT_MODIFY, MF_BYCOMMAND | (cnt == 1 ? MF_ENABLED : MF_DISABLED | MF_GRAYED)); 711 EnableMenuItem(mnu, ID_EDIT_MODIFY_BIN, MF_BYCOMMAND | (cnt == 1 ? MF_ENABLED : MF_DISABLED | MF_GRAYED)); 712 713 TrackPopupMenu(mnu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, hFrameWnd, NULL); 714 } 715 } 716 else if ((HWND)wParam == g_pChildWnd->hTreeWnd) 717 { 718 TVHITTESTINFO hti; 719 HMENU hContextMenu; 720 TVITEMW item; 721 MENUITEMINFOW mii; 722 WCHAR resource[256]; 723 WCHAR buffer[256]; 724 LPWSTR s; 725 LPCWSTR keyPath; 726 HKEY hRootKey; 727 int iLastPos; 728 WORD wID; 729 730 pt.x = (short) LOWORD(lParam); 731 pt.y = (short) HIWORD(lParam); 732 733 if (pt.x == -1 && pt.y == -1) 734 { 735 RECT rc; 736 hti.hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd); 737 if (hti.hItem != NULL) 738 { 739 TreeView_GetItemRect(g_pChildWnd->hTreeWnd, hti.hItem, &rc, TRUE); 740 pt.x = rc.left + 8; 741 pt.y = rc.top + 8; 742 ClientToScreen(g_pChildWnd->hTreeWnd, &pt); 743 hti.flags = TVHT_ONITEM; 744 } 745 else 746 hti.flags = 0; 747 } 748 else 749 { 750 hti.pt.x = pt.x; 751 hti.pt.y = pt.y; 752 ScreenToClient(g_pChildWnd->hTreeWnd, &hti.pt); 753 TreeView_HitTest(g_pChildWnd->hTreeWnd, &hti); 754 } 755 756 if (hti.flags & TVHT_ONITEM) 757 { 758 hContextMenu = GetSubMenu(hPopupMenus, PM_TREECONTEXT); 759 TreeView_SelectItem(g_pChildWnd->hTreeWnd, hti.hItem); 760 761 memset(&item, 0, sizeof(item)); 762 item.mask = TVIF_STATE | TVIF_CHILDREN; 763 item.hItem = hti.hItem; 764 TreeView_GetItem(g_pChildWnd->hTreeWnd, &item); 765 766 /* Set the Expand/Collapse menu item appropriately */ 767 LoadStringW(hInst, (item.state & TVIS_EXPANDED) ? IDS_COLLAPSE : IDS_EXPAND, buffer, COUNT_OF(buffer)); 768 memset(&mii, 0, sizeof(mii)); 769 mii.cbSize = sizeof(mii); 770 mii.fMask = MIIM_STRING | MIIM_STATE | MIIM_ID; 771 mii.fState = (item.cChildren > 0) ? MFS_DEFAULT : MFS_GRAYED; 772 mii.wID = (item.state & TVIS_EXPANDED) ? ID_TREE_COLLAPSEBRANCH : ID_TREE_EXPANDBRANCH; 773 mii.dwTypeData = (LPWSTR) buffer; 774 SetMenuItemInfo(hContextMenu, 0, TRUE, &mii); 775 776 /* Remove any existing suggestions */ 777 memset(&mii, 0, sizeof(mii)); 778 mii.cbSize = sizeof(mii); 779 mii.fMask = MIIM_ID; 780 GetMenuItemInfo(hContextMenu, GetMenuItemCount(hContextMenu) - 1, TRUE, &mii); 781 if ((mii.wID >= ID_TREE_SUGGESTION_MIN) && (mii.wID <= ID_TREE_SUGGESTION_MAX)) 782 { 783 do 784 { 785 iLastPos = GetMenuItemCount(hContextMenu) - 1; 786 GetMenuItemInfo(hContextMenu, iLastPos, TRUE, &mii); 787 RemoveMenu(hContextMenu, iLastPos, MF_BYPOSITION); 788 } 789 while((mii.wID >= ID_TREE_SUGGESTION_MIN) && (mii.wID <= ID_TREE_SUGGESTION_MAX)); 790 } 791 792 /* Come up with suggestions */ 793 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, NULL, &hRootKey); 794 SuggestKeys(hRootKey, keyPath, Suggestions, COUNT_OF(Suggestions)); 795 if (Suggestions[0]) 796 { 797 AppendMenu(hContextMenu, MF_SEPARATOR, 0, NULL); 798 799 LoadStringW(hInst, IDS_GOTO_SUGGESTED_KEY, resource, COUNT_OF(resource)); 800 801 s = Suggestions; 802 wID = ID_TREE_SUGGESTION_MIN; 803 while(*s && (wID <= ID_TREE_SUGGESTION_MAX)) 804 { 805 _snwprintf(buffer, COUNT_OF(buffer), resource, s); 806 807 memset(&mii, 0, sizeof(mii)); 808 mii.cbSize = sizeof(mii); 809 mii.fMask = MIIM_STRING | MIIM_ID; 810 mii.wID = wID++; 811 mii.dwTypeData = buffer; 812 InsertMenuItem(hContextMenu, GetMenuItemCount(hContextMenu), TRUE, &mii); 813 814 s += wcslen(s) + 1; 815 } 816 } 817 TrackPopupMenu(hContextMenu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, g_pChildWnd->hWnd, NULL); 818 } 819 } 820 break; 821 } 822 823 case WM_SIZE: 824 if (wParam != SIZE_MINIMIZED && g_pChildWnd != NULL) 825 { 826 ResizeWnd(LOWORD(lParam), HIWORD(lParam)); 827 } 828 /* fall through */ 829 default: 830 def: 831 return DefWindowProcW(hWnd, message, wParam, lParam); 832 } 833 return 0; 834 } 835