user32: Update the window DPI awareness in SetParent().
[wine.git] / programs / regedit / framewnd.c
blob94da217045a1010e1be7e179763fcfb7b47ac24d
1 /*
2 * Regedit frame window
4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
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.
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.
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 St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
23 #include <windows.h>
24 #include <commctrl.h>
25 #include <commdlg.h>
26 #include <cderr.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <shellapi.h>
31 #include "main.h"
32 #include "regproc.h"
33 #include "wine/debug.h"
34 #include "wine/heap.h"
35 #include "wine/unicode.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(regedit);
39 /********************************************************************************
40 * Global and Local Variables:
43 static const WCHAR favoritesKey[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','A','p','p','l','e','t','s','\\','R','e','g','E','d','i','t','\\','F','a','v','o','r','i','t','e','s',0};
44 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
45 static WCHAR favoriteName[128];
46 static WCHAR searchString[128];
47 static int searchMask = SEARCH_KEYS | SEARCH_VALUES | SEARCH_CONTENT;
49 static WCHAR FileNameBuffer[_MAX_PATH];
50 static WCHAR FileTitleBuffer[_MAX_PATH];
51 static WCHAR FilterBuffer[_MAX_PATH];
52 static WCHAR expandW[32], collapseW[32];
53 static WCHAR modifyW[32], modify_binaryW[64];
55 /*******************************************************************************
56 * Local module support methods
59 static void resize_frame_rect(HWND hWnd, PRECT prect)
61 if (IsWindowVisible(hStatusBar)) {
62 RECT rt;
64 SetupStatusBar(hWnd, TRUE);
65 GetClientRect(hStatusBar, &rt);
66 prect->bottom -= rt.bottom;
68 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
71 static void resize_frame_client(HWND hWnd)
73 RECT rect;
75 GetClientRect(hWnd, &rect);
76 resize_frame_rect(hWnd, &rect);
79 /********************************************************************************/
81 static void OnEnterMenuLoop(HWND hWnd)
83 int nParts;
84 WCHAR empty = 0;
86 /* Update the status bar pane sizes */
87 nParts = -1;
88 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
89 bInMenuLoop = TRUE;
90 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)&empty);
93 static void OnExitMenuLoop(HWND hWnd)
95 bInMenuLoop = FALSE;
96 /* Update the status bar pane sizes*/
97 SetupStatusBar(hWnd, TRUE);
98 UpdateStatusBar();
101 static void update_expand_or_collapse_item(HWND hwndTV, HTREEITEM selection, HMENU hMenu)
103 TVITEMW item;
104 MENUITEMINFOW info;
106 item.hItem = selection;
107 item.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_STATE;
108 item.stateMask = TVIS_EXPANDED;
109 SendMessageW(hwndTV, TVM_GETITEMW, 0, (LPARAM)&item);
111 info.cbSize = sizeof(MENUITEMINFOW);
112 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
113 info.fType = MFT_STRING;
114 info.fState = MFS_ENABLED;
115 info.dwTypeData = expandW;
117 if (!item.cChildren)
119 info.fState = MFS_GRAYED;
120 goto update;
123 if (item.state & TVIS_EXPANDED)
124 info.dwTypeData = collapseW;
126 update:
127 SetMenuItemInfoW(hMenu, ID_TREE_EXPAND_COLLAPSE, FALSE, &info);
130 static void update_modify_items(HMENU hMenu, int index)
132 unsigned int state = MF_ENABLED;
134 if (index == -1)
135 state = MF_GRAYED;
137 EnableMenuItem(hMenu, ID_EDIT_MODIFY, state | MF_BYCOMMAND);
138 EnableMenuItem(hMenu, ID_EDIT_MODIFY_BIN, state | MF_BYCOMMAND);
141 static void update_delete_and_rename_items(HMENU hMenu, WCHAR *keyName, int index)
143 unsigned int state_d = MF_ENABLED, state_r = MF_ENABLED;
145 if (!g_pChildWnd->nFocusPanel)
147 if (!keyName || !*keyName)
148 state_d = state_r = MF_GRAYED;
150 else if (index < 1)
152 state_r = MF_GRAYED;
153 if (index == -1) state_d = MF_GRAYED;
156 EnableMenuItem(hMenu, ID_EDIT_DELETE, state_d | MF_BYCOMMAND);
157 EnableMenuItem(hMenu, ID_EDIT_RENAME, state_r | MF_BYCOMMAND);
160 static void update_new_items_and_copy_keyname(HMENU hMenu, WCHAR *keyName)
162 unsigned int state = MF_ENABLED, i;
163 unsigned int items[] = {ID_EDIT_NEW_KEY, ID_EDIT_NEW_STRINGVALUE, ID_EDIT_NEW_BINARYVALUE,
164 ID_EDIT_NEW_DWORDVALUE, ID_EDIT_NEW_MULTI_STRINGVALUE,
165 ID_EDIT_NEW_EXPANDVALUE, ID_EDIT_COPYKEYNAME};
167 if (!keyName)
168 state = MF_GRAYED;
170 for (i = 0; i < COUNT_OF(items); i++)
171 EnableMenuItem(hMenu, items[i], state | MF_BYCOMMAND);
174 static void UpdateMenuItems(HMENU hMenu) {
175 HWND hwndTV = g_pChildWnd->hTreeWnd;
176 HKEY hRootKey = NULL;
177 LPWSTR keyName;
178 HTREEITEM selection;
179 int index;
181 selection = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
182 keyName = GetItemPath(hwndTV, selection, &hRootKey);
183 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1,
184 MAKELPARAM(LVNI_FOCUSED | LVNI_SELECTED, 0));
186 update_expand_or_collapse_item(hwndTV, selection, hMenu);
187 update_modify_items(hMenu, index);
188 update_delete_and_rename_items(hMenu, keyName, index);
189 update_new_items_and_copy_keyname(hMenu, keyName);
190 EnableMenuItem(hMenu, ID_FAVORITES_ADDTOFAVORITES, (hRootKey ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
191 EnableMenuItem(hMenu, ID_FAVORITES_REMOVEFAVORITE,
192 (GetMenuItemCount(hMenu)>2 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
194 heap_free(keyName);
197 static void add_remove_modify_menu_items(HMENU hMenu)
199 if (!g_pChildWnd->nFocusPanel)
201 while (GetMenuItemCount(hMenu) > 9)
202 DeleteMenu(hMenu, 0, MF_BYPOSITION);
204 else if (GetMenuItemCount(hMenu) < 10)
206 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, 0);
207 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY_BIN, modify_binaryW);
208 InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY, modifyW);
212 static int add_favourite_key_items(HMENU hMenu, HWND hList)
214 HKEY hkey;
215 LONG rc;
216 DWORD num_values, max_value_len, value_len, type, i = 0;
217 WCHAR *value_name;
219 rc = RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey, 0, KEY_READ, &hkey);
220 if (rc != ERROR_SUCCESS) return 0;
222 rc = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &num_values,
223 &max_value_len, NULL, NULL, NULL);
224 if (rc != ERROR_SUCCESS)
226 ERR("RegQueryInfoKey failed: %d\n", rc);
227 goto exit;
230 if (!num_values) goto exit;
232 max_value_len++;
233 value_name = heap_xalloc(max_value_len * sizeof(WCHAR));
235 if (hMenu) AppendMenuW(hMenu, MF_SEPARATOR, 0, 0);
237 for (i = 0; i < num_values; i++)
239 value_len = max_value_len;
240 rc = RegEnumValueW(hkey, i, value_name, &value_len, NULL, &type, NULL, NULL);
241 if (rc == ERROR_SUCCESS && type == REG_SZ)
243 if (hMenu)
244 AppendMenuW(hMenu, MF_ENABLED | MF_STRING, ID_FAVORITE_FIRST + i, value_name);
245 else if (hList)
246 SendMessageW(hList, LB_ADDSTRING, 0, (LPARAM)value_name);
250 heap_free(value_name);
251 exit:
252 RegCloseKey(hkey);
253 return i;
256 static void OnInitMenuPopup(HWND hWnd, HMENU hMenu)
258 if (hMenu == GetSubMenu(hMenuFrame, ID_EDIT_MENU))
259 add_remove_modify_menu_items(hMenu);
260 else if (hMenu == GetSubMenu(hMenuFrame, ID_FAVORITES_MENU))
262 while (GetMenuItemCount(hMenu) > 2)
263 DeleteMenu(hMenu, 2, MF_BYPOSITION);
265 add_favourite_key_items(hMenu, NULL);
268 UpdateMenuItems(hMenu);
271 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
273 WCHAR str[100];
275 str[0] = 0;
276 if (nFlags & MF_POPUP) {
277 if (hSysMenu != GetMenu(hWnd)) {
278 if (nItemID == 2) nItemID = 5;
281 if (LoadStringW(hInst, nItemID, str, 100)) {
282 /* load appropriate string*/
283 LPWSTR lpsz = str;
284 /* first newline terminates actual string*/
285 lpsz = strchrW(lpsz, '\n');
286 if (lpsz != NULL)
287 *lpsz = '\0';
289 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
292 void SetupStatusBar(HWND hWnd, BOOL bResize)
294 RECT rc;
295 int nParts;
296 GetClientRect(hWnd, &rc);
297 nParts = rc.right;
298 /* nParts = -1;*/
299 if (bResize)
300 SendMessageW(hStatusBar, WM_SIZE, 0, 0);
301 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
302 UpdateStatusBar();
305 void UpdateStatusBar(void)
307 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
308 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath);
309 heap_free(fullPath);
312 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
314 BOOL vis = IsWindowVisible(hchild);
315 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
317 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
318 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
319 resize_frame_client(hWnd);
322 static BOOL CheckCommDlgError(HWND hWnd)
324 DWORD dwErrorCode = CommDlgExtendedError();
325 switch (dwErrorCode) {
326 case CDERR_DIALOGFAILURE:
327 break;
328 case CDERR_FINDRESFAILURE:
329 break;
330 case CDERR_NOHINSTANCE:
331 break;
332 case CDERR_INITIALIZATION:
333 break;
334 case CDERR_NOHOOK:
335 break;
336 case CDERR_LOCKRESFAILURE:
337 break;
338 case CDERR_NOTEMPLATE:
339 break;
340 case CDERR_LOADRESFAILURE:
341 break;
342 case CDERR_STRUCTSIZE:
343 break;
344 case CDERR_LOADSTRFAILURE:
345 break;
346 case FNERR_BUFFERTOOSMALL:
347 break;
348 case CDERR_MEMALLOCFAILURE:
349 break;
350 case FNERR_INVALIDFILENAME:
351 break;
352 case CDERR_MEMLOCKFAILURE:
353 break;
354 case FNERR_SUBCLASSFAILURE:
355 break;
356 default:
357 break;
359 return TRUE;
362 static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAMEW *pOpenFileName)
364 if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
366 INT len = SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
367 pOpenFileName->lCustData = (LPARAM)heap_xalloc((len + 1) * sizeof(WCHAR));
368 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
370 else
372 pOpenFileName->lCustData = (LPARAM)heap_xalloc(sizeof(WCHAR));
373 *(WCHAR *)pOpenFileName->lCustData = 0;
377 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
379 static OPENFILENAMEW* pOpenFileName;
380 OFNOTIFYW *pOfNotify;
382 switch (uiMsg) {
383 case WM_INITDIALOG:
384 pOpenFileName = (OPENFILENAMEW*)lParam;
385 break;
386 case WM_COMMAND:
387 if (LOWORD(wParam) == IDC_EXPORT_PATH && HIWORD(wParam) == EN_UPDATE)
388 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_SELECTED);
389 break;
390 case WM_NOTIFY:
391 pOfNotify = (OFNOTIFYW*)lParam;
392 switch (pOfNotify->hdr.code)
394 case CDN_INITDONE:
396 BOOL export_branch = FALSE;
397 WCHAR* path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
398 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
399 if (path && path[0])
400 export_branch = TRUE;
401 heap_free(path);
402 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, export_branch ? IDC_EXPORT_SELECTED : IDC_EXPORT_ALL);
403 break;
405 case CDN_FILEOK:
406 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
407 break;
409 break;
410 default:
411 break;
413 return 0L;
417 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
419 memset(pofn, 0, sizeof(OPENFILENAMEW));
420 pofn->lStructSize = sizeof(OPENFILENAMEW);
421 pofn->hwndOwner = hWnd;
422 pofn->hInstance = hInst;
424 if (FilterBuffer[0] == 0)
426 static const WCHAR filterW[] = {'%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','*','%','c',0};
427 WCHAR filter_reg[MAX_PATH], filter_reg4[MAX_PATH], filter_all[MAX_PATH];
429 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG, filter_reg, MAX_PATH);
430 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG4, filter_reg4, MAX_PATH);
431 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_ALL, filter_all, MAX_PATH);
432 snprintfW( FilterBuffer, MAX_PATH, filterW, filter_reg, 0, 0, filter_reg4, 0, 0, filter_all, 0, 0 );
434 pofn->lpstrFilter = FilterBuffer;
435 pofn->nFilterIndex = 1;
436 pofn->lpstrFile = FileNameBuffer;
437 pofn->nMaxFile = _MAX_PATH;
438 pofn->lpstrFileTitle = FileTitleBuffer;
439 pofn->nMaxFileTitle = _MAX_PATH;
440 pofn->Flags = OFN_HIDEREADONLY;
441 /* some other fields may be set by the caller */
442 return TRUE;
445 static BOOL import_registry_filename(LPWSTR filename)
447 static const WCHAR rb_mode[] = {'r','b',0};
449 BOOL Success;
450 FILE* reg_file = _wfopen(filename, rb_mode);
452 if(!reg_file)
453 return FALSE;
455 Success = import_registry_file(reg_file);
457 if(fclose(reg_file) != 0)
458 Success = FALSE;
460 return Success;
463 static BOOL ImportRegistryFile(HWND hWnd)
465 OPENFILENAMEW ofn;
466 WCHAR title[128];
467 HKEY root_key = NULL;
468 WCHAR *key_path;
470 InitOpenFileName(hWnd, &ofn);
471 ofn.Flags |= OFN_ENABLESIZING;
472 LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
473 ofn.lpstrTitle = title;
474 if (GetOpenFileNameW(&ofn)) {
475 if (!import_registry_filename(ofn.lpstrFile)) {
476 messagebox(hWnd, MB_OK|MB_ICONERROR, IDS_APP_TITLE, IDS_IMPORT_FAILED, ofn.lpstrFile);
477 return FALSE;
478 } else {
479 messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE,
480 IDS_IMPORT_SUCCESSFUL, ofn.lpstrFile);
482 } else {
483 CheckCommDlgError(hWnd);
485 RefreshTreeView(g_pChildWnd->hTreeWnd);
487 key_path = GetItemPath(g_pChildWnd->hTreeWnd, 0, &root_key);
488 RefreshListView(g_pChildWnd->hListWnd, root_key, key_path, NULL);
489 heap_free(key_path);
491 return TRUE;
495 static BOOL ExportRegistryFile(HWND hWnd)
497 OPENFILENAMEW ofn;
498 WCHAR title[128];
500 InitOpenFileName(hWnd, &ofn);
501 LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, COUNT_OF(title));
502 ofn.lpstrTitle = title;
503 ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
504 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
505 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
506 if (GetSaveFileNameW(&ofn)) {
507 BOOL result;
508 result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
509 if (!result) {
510 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
511 return FALSE;
513 } else {
514 CheckCommDlgError(hWnd);
516 return TRUE;
519 static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
521 #if 1
522 PRINTDLGW pd;
524 ZeroMemory(&pd, sizeof(PRINTDLGW));
525 pd.lStructSize = sizeof(PRINTDLGW);
526 pd.hwndOwner = hWnd;
527 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
528 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
529 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
530 pd.nCopies = 1;
531 pd.nFromPage = 0xFFFF;
532 pd.nToPage = 0xFFFF;
533 pd.nMinPage = 1;
534 pd.nMaxPage = 0xFFFF;
535 if (PrintDlgW(&pd)) {
536 FIXME("printing is not yet implemented.\n");
537 /* GDI calls to render output. */
538 DeleteDC(pd.hDC); /* Delete DC when done.*/
540 #else
541 HRESULT hResult;
542 PRINTDLGEXW pd;
544 hResult = PrintDlgExW(&pd);
545 if (hResult == S_OK) {
546 switch (pd.dwResultAction) {
547 case PD_RESULT_APPLY:
548 /*The user clicked the Apply button and later clicked the Cancel button. This indicates that the user wants to apply the changes made in the property sheet, but does not yet want to print. The PRINTDLGEX structure contains the information specified by the user at the time the Apply button was clicked. */
549 FIXME("printing is not yet implemented.\n");
550 break;
551 case PD_RESULT_CANCEL:
552 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
553 break;
554 case PD_RESULT_PRINT:
555 FIXME("printing is not yet implemented.\n");
556 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
557 break;
558 default:
559 break;
561 } else {
562 switch (hResult) {
563 case E_OUTOFMEMORY:
564 /*Insufficient memory. */
565 break;
566 case E_INVALIDARG:
567 /* One or more arguments are invalid. */
568 break;
569 case E_POINTER:
570 /*Invalid pointer. */
571 break;
572 case E_HANDLE:
573 /*Invalid handle. */
574 break;
575 case E_FAIL:
576 /*Unspecified error. */
577 break;
578 default:
579 break;
581 return FALSE;
583 #endif
584 return TRUE;
587 static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
589 BOOL result;
591 result = OpenClipboard(hWnd);
592 if (result) {
593 result = EmptyClipboard();
594 if (result) {
595 int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
596 HANDLE hClipData = GlobalAlloc(GHND, len);
597 LPVOID pLoc = GlobalLock(hClipData);
598 lstrcpyW(pLoc, keyName);
599 GlobalUnlock(hClipData);
600 SetClipboardData(CF_UNICODETEXT, hClipData);
602 } else {
603 /* error emptying clipboard*/
604 /* DWORD dwError = GetLastError(); */
607 if (!CloseClipboard()) {
608 /* error closing clipboard*/
609 /* DWORD dwError = GetLastError(); */
612 } else {
613 /* error opening clipboard*/
614 /* DWORD dwError = GetLastError(); */
617 return result;
620 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
622 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
624 switch(uMsg) {
625 case WM_INITDIALOG:
626 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
627 CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
628 CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
629 CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
630 CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
631 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
632 SetWindowTextW(hwndValue, searchString);
633 return TRUE;
634 case WM_COMMAND:
635 switch(LOWORD(wParam)) {
636 case IDC_VALUE_NAME:
637 if (HIWORD(wParam) == EN_UPDATE) {
638 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue)>0);
639 return TRUE;
641 break;
642 case IDOK:
643 if (GetWindowTextLengthW(hwndValue)>0) {
644 int mask = 0;
645 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
646 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
647 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
648 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
649 searchMask = mask;
650 GetWindowTextW(hwndValue, searchString, 128);
651 EndDialog(hwndDlg, IDOK);
653 return TRUE;
654 case IDCANCEL:
655 EndDialog(hwndDlg, IDCANCEL);
656 return TRUE;
658 break;
660 return FALSE;
663 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
665 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
667 switch(uMsg) {
668 case WM_INITDIALOG:
670 HTREEITEM selected;
671 TVITEMW item;
672 WCHAR buf[128];
674 selected = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
676 item.mask = TVIF_HANDLE | TVIF_TEXT;
677 item.hItem = selected;
678 item.pszText = buf;
679 item.cchTextMax = COUNT_OF(buf);
680 SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETITEMW, 0, (LPARAM)&item);
682 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
683 SetWindowTextW(hwndValue, buf);
684 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
685 return TRUE;
687 case WM_COMMAND:
688 switch(LOWORD(wParam)) {
689 case IDC_VALUE_NAME:
690 if (HIWORD(wParam) == EN_UPDATE) {
691 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue) > 0);
692 return TRUE;
694 break;
695 case IDOK:
696 if (GetWindowTextLengthW(hwndValue)>0) {
697 GetWindowTextW(hwndValue, favoriteName, 128);
698 EndDialog(hwndDlg, IDOK);
700 return TRUE;
701 case IDCANCEL:
702 EndDialog(hwndDlg, IDCANCEL);
703 return TRUE;
705 break;
707 return FALSE;
710 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
712 HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
714 switch(uMsg) {
715 case WM_INITDIALOG:
716 if (!add_favourite_key_items(NULL, hwndList))
717 return FALSE;
718 SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
719 return TRUE;
720 case WM_COMMAND:
721 switch(LOWORD(wParam)) {
722 case IDC_NAME_LIST:
723 if (HIWORD(wParam) == LBN_SELCHANGE) {
724 EnableWindow(GetDlgItem(hwndDlg, IDOK), lParam != -1);
725 return TRUE;
727 break;
728 case IDOK: {
729 int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
730 int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
731 if (len>0) {
732 WCHAR *lpName = heap_xalloc((len + 1) * sizeof(WCHAR));
733 SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
734 if (len>127)
735 lpName[127] = '\0';
736 lstrcpyW(favoriteName, lpName);
737 EndDialog(hwndDlg, IDOK);
738 heap_free(lpName);
740 return TRUE;
742 case IDCANCEL:
743 EndDialog(hwndDlg, IDCANCEL);
744 return TRUE;
746 break;
748 return FALSE;
751 /*******************************************************************************
753 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
755 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
758 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
760 HKEY hKeyRoot = 0;
761 DWORD valueType;
763 if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
764 HKEY hKey;
765 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
766 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
767 WCHAR namebuf[KEY_MAX_LEN];
768 BYTE valuebuf[4096];
769 DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
770 if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
771 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
772 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
773 (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
775 RegCloseKey(hKey);
777 return TRUE;
779 switch (LOWORD(wParam)) {
780 case ID_REGISTRY_IMPORTREGISTRYFILE:
781 ImportRegistryFile(hWnd);
782 break;
783 case ID_EDIT_EXPORT:
784 case ID_REGISTRY_EXPORTREGISTRYFILE:
785 ExportRegistryFile(hWnd);
786 break;
787 case ID_REGISTRY_PRINT:
789 const WCHAR empty = 0;
790 PrintRegistryHive(hWnd, &empty);
791 break;
793 case ID_EDIT_DELETE:
795 HWND hWndDelete = GetFocus();
796 if (hWndDelete == g_pChildWnd->hTreeWnd) {
797 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
798 if (keyPath == 0 || *keyPath == 0) {
799 MessageBeep(MB_ICONHAND);
800 } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
801 DeleteNode(g_pChildWnd->hTreeWnd, 0);
803 heap_free(keyPath);
804 } else if (hWndDelete == g_pChildWnd->hListWnd) {
805 unsigned int num_selected, index, focus_idx;
806 WCHAR *keyPath;
808 if (!(num_selected = SendMessageW(g_pChildWnd->hListWnd, LVM_GETSELECTEDCOUNT, 0, 0L)))
809 break;
811 if (num_selected > 1)
813 if (messagebox(hWnd, MB_YESNO | MB_ICONEXCLAMATION, IDS_DELETE_VALUE_TITLE,
814 IDS_DELETE_VALUE_TEXT_MULTIPLE) != IDYES)
815 break;
818 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
820 focus_idx = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
821 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
823 while (index != -1)
825 WCHAR *valueName = GetItemText(g_pChildWnd->hListWnd, index);
826 if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName, num_selected == 1))
828 heap_free(valueName);
829 break;
831 heap_free(valueName);
832 SendMessageW(g_pChildWnd->hListWnd, LVM_DELETEITEM, index, 0L);
833 /* the default value item is always visible, so add it back in */
834 if (!index)
836 AddEntryToList(g_pChildWnd->hListWnd, NULL, REG_SZ, NULL, 0, 0);
837 if (!focus_idx)
839 LVITEMW item;
840 item.state = item.stateMask = LVIS_FOCUSED;
841 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
844 index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
846 heap_free(keyPath);
847 } else if (IsChild(g_pChildWnd->hTreeWnd, hWndDelete) ||
848 IsChild(g_pChildWnd->hListWnd, hWndDelete)) {
849 SendMessageW(hWndDelete, WM_KEYDOWN, VK_DELETE, 0);
851 break;
853 case ID_EDIT_MODIFY:
854 case ID_EDIT_MODIFY_BIN:
856 LPCWSTR valueName = GetValueName(g_pChildWnd->hListWnd);
857 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
858 ModifyValue(hWnd, hKeyRoot, keyPath, valueName);
859 heap_free(keyPath);
860 break;
862 case ID_EDIT_FIND:
863 case ID_EDIT_FINDNEXT:
865 HTREEITEM hItem;
866 if (LOWORD(wParam) == ID_EDIT_FIND &&
867 DialogBoxW(0, MAKEINTRESOURCEW(IDD_FIND), hWnd, find_dlgproc) != IDOK)
868 break;
869 if (!*searchString)
870 break;
871 hItem = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
872 if (hItem) {
873 int row = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
874 HCURSOR hcursorOld = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
875 hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
876 SetCursor(hcursorOld);
877 if (hItem) {
878 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
879 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
880 UpdateWindow(g_pChildWnd->hTreeWnd);
881 if (row != -1) {
882 LVITEMW item;
884 item.state = 0;
885 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
886 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, (UINT)-1, (LPARAM)&item);
888 item.state = LVIS_FOCUSED | LVIS_SELECTED;
889 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
890 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, row, (LPARAM)&item);
891 SetFocus(g_pChildWnd->hListWnd);
892 } else {
893 SetFocus(g_pChildWnd->hTreeWnd);
895 } else {
896 messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE, IDS_NOTFOUND, searchString);
899 break;
901 case ID_EDIT_COPYKEYNAME:
903 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
904 if (fullPath) {
905 CopyKeyName(hWnd, fullPath);
906 heap_free(fullPath);
908 break;
910 case ID_EDIT_NEW_KEY:
912 WCHAR newKeyW[MAX_NEW_KEY_LEN];
913 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
914 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
915 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
916 StartKeyRename(g_pChildWnd->hTreeWnd);
918 heap_free(keyPath);
920 break;
921 case ID_EDIT_NEW_STRINGVALUE:
922 valueType = REG_SZ;
923 goto create_value;
924 case ID_EDIT_NEW_EXPANDVALUE:
925 valueType = REG_EXPAND_SZ;
926 goto create_value;
927 case ID_EDIT_NEW_MULTI_STRINGVALUE:
928 valueType = REG_MULTI_SZ;
929 goto create_value;
930 case ID_EDIT_NEW_BINARYVALUE:
931 valueType = REG_BINARY;
932 goto create_value;
933 case ID_EDIT_NEW_DWORDVALUE:
934 valueType = REG_DWORD;
935 /* fall through */
936 create_value:
938 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
939 WCHAR newKey[MAX_NEW_KEY_LEN];
940 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey))
941 StartValueRename(g_pChildWnd->hListWnd);
942 heap_free(keyPath);
944 break;
945 case ID_EDIT_RENAME:
947 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
948 if (keyPath == 0 || *keyPath == 0) {
949 MessageBeep(MB_ICONHAND);
950 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
951 StartKeyRename(g_pChildWnd->hTreeWnd);
952 } else if (GetFocus() == g_pChildWnd->hListWnd) {
953 StartValueRename(g_pChildWnd->hListWnd);
955 heap_free(keyPath);
956 break;
958 case ID_TREE_EXPAND_COLLAPSE:
960 HTREEITEM selected = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
961 SendMessageW(g_pChildWnd->hTreeWnd, TVM_EXPAND, TVE_TOGGLE, (LPARAM)selected);
962 break;
964 case ID_REGISTRY_PRINTERSETUP:
965 /*PRINTDLG pd;*/
966 /*PrintDlg(&pd);*/
967 /*PAGESETUPDLG psd;*/
968 /*PageSetupDlg(&psd);*/
969 break;
970 case ID_REGISTRY_OPENLOCAL:
971 break;
972 case ID_REGISTRY_EXIT:
973 DestroyWindow(hWnd);
974 break;
975 case ID_FAVORITES_ADDTOFAVORITES:
977 HKEY hKey;
978 LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
979 if (lpKeyPath) {
980 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
981 if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
982 0, NULL, 0,
983 KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
984 RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
985 RegCloseKey(hKey);
988 heap_free(lpKeyPath);
990 break;
992 case ID_FAVORITES_REMOVEFAVORITE:
994 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
995 HKEY hKey;
996 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
997 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
998 RegDeleteValueW(hKey, favoriteName);
999 RegCloseKey(hKey);
1002 break;
1004 case ID_VIEW_REFRESH:
1006 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
1007 RefreshTreeView(g_pChildWnd->hTreeWnd);
1008 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
1009 heap_free(keyPath);
1011 break;
1012 /*case ID_OPTIONS_TOOLBAR:*/
1013 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
1014 /* break;*/
1015 case ID_VIEW_STATUSBAR:
1016 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
1017 break;
1018 case ID_HELP_HELPTOPICS:
1020 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
1021 WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
1022 break;
1024 case ID_HELP_ABOUT:
1025 ShowAboutBox(hWnd);
1026 break;
1027 case ID_VIEW_SPLIT: {
1028 RECT rt;
1029 POINT pt, pts;
1030 GetClientRect(g_pChildWnd->hWnd, &rt);
1031 pt.x = rt.left + g_pChildWnd->nSplitPos;
1032 pt.y = (rt.bottom / 2);
1033 pts = pt;
1034 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
1035 SetCursorPos(pts.x, pts.y);
1036 SetCursor(LoadCursorW(0, (LPCWSTR)IDC_SIZEWE));
1037 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
1039 return TRUE;
1041 default:
1042 return FALSE;
1045 return TRUE;
1048 /********************************************************************************
1050 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
1052 * PURPOSE: Processes messages for the main frame window.
1054 * WM_COMMAND - process the application menu
1055 * WM_DESTROY - post a quit message and return
1059 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1061 static const WCHAR captionW[] = {'r','e','g','e','d','i','t',' ','c','h','i','l','d',' ','w','i','n','d','o','w',0};
1063 switch (message) {
1064 case WM_CREATE:
1065 CreateWindowExW(0, szChildClass, captionW, WS_CHILD | WS_VISIBLE,
1066 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1067 hWnd, NULL, hInst, 0);
1068 LoadStringW(hInst, IDS_EXPAND, expandW, COUNT_OF(expandW));
1069 LoadStringW(hInst, IDS_COLLAPSE, collapseW, COUNT_OF(collapseW));
1070 LoadStringW(hInst, IDS_EDIT_MODIFY, modifyW, COUNT_OF(modifyW));
1071 LoadStringW(hInst, IDS_EDIT_MODIFY_BIN, modify_binaryW, COUNT_OF(modify_binaryW));
1072 break;
1073 case WM_COMMAND:
1074 if (!_CmdWndProc(hWnd, message, wParam, lParam))
1075 return DefWindowProcW(hWnd, message, wParam, lParam);
1076 break;
1077 case WM_ACTIVATE:
1078 if (LOWORD(hWnd))
1079 SetFocus(g_pChildWnd->hWnd);
1080 break;
1081 case WM_SIZE:
1082 resize_frame_client(hWnd);
1083 break;
1084 case WM_TIMER:
1085 break;
1086 case WM_ENTERMENULOOP:
1087 OnEnterMenuLoop(hWnd);
1088 break;
1089 case WM_EXITMENULOOP:
1090 OnExitMenuLoop(hWnd);
1091 break;
1092 case WM_INITMENUPOPUP:
1093 if (!HIWORD(lParam))
1094 OnInitMenuPopup(hWnd, (HMENU)wParam);
1095 break;
1096 case WM_MENUSELECT:
1097 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
1098 break;
1099 case WM_DESTROY:
1101 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
1102 WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
1103 PostQuitMessage(0);
1105 default:
1106 return DefWindowProcW(hWnd, message, wParam, lParam);
1108 return 0;