//********************************************************************* //* Microsoft Windows ** //* Copyright(c) Microsoft Corp., 1996 ** //********************************************************************* // // ADVANCED.C - "Advanced" Property Sheet // // // This is a registry driven UI that walk through the part of the // registry tree and convert it into a tree view list. // Note that registry values can be localized, so internation versions // have to localize the INF file so that setup will set the registry // with the right text. // // Here is how the registry key looks like, // // HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\AdvancedOptions\ // GroupKey1\ // Type="group" // Text="text to display" // DefaultImage="somedll.dll,icon_index", (optional). // // RadioKey1.1\ // Type="radio" // Text="text to display" // (optional) HKeyRoot=any one of the pre-defined root HKEY in DWORD, // ; default to HKEY_CURRENT_USER. // (optional) RegPath="path to the key where the setting value is stored." // ; default to Software\Microsoft\Windows\CurrentVersion\Explorer\AdvancedOptions // ValueName="reg value name." // CheckedValue=... ; value for this radio button, // ; if the value is platform dependent, use one of the following two instead // CheckedValueNT=... ; if the value is platform dependent // CheckedValueW95=... ; if the value is platform dependent // DefaultValue=... // (optional) SPIAction=uiAction param to SystemParametersInfo in DWORD // (optional) SPIParamON=uiParam param to SystemParametersInfo for this radio button in DWORD // (optional) Mask=... ; mask for the bitfield 1's for the bits we want to be able to set/clear // // RadioKey1.2\ // Type="radio" // Text="text to display" // (optional) HKeyRoot=any one of the pre-defined root HKEY in DWORD, // ; default to HKEY_CURRENT_USER. // (optional) RegPath="path to the key where the setting value is stored." // ; default to Software\Microsoft\Windows\CurrentVersion\Explorer\AdvancedOptions // ValueName="reg value name." // CheckedValue=... ; value for this checkbox if it's checked // ; if the value is platform dependent, use one of the following two instead // CheckedValueNT=... ; if the value is platform dependent // CheckedValueW95=... ; if the value is platform dependent // UncheckedValue=... ; value for this checkbox if it's unchecked // DefaultValue=... // (optional) SPIAction=uiAction param to SystemParametersInfo in DWORD // (optional) SPIParamON=uiParam param to SystemParametersInfo if checked in DWORD // (optional) SPIParamOFF=uiParam param to SystemParametersInfo if checked in DWORD // (optional) Mask=... ; mask for the bitfield 1's for the bits we want to be able to set/clear // // CheckBoxKey1.1\ // ... // GroupKey1.1\ // ... // GroupKey2\ // ... // CheckBoxKey2.1\ // ... // CheckBoxKey2.2\ // ... // // // Notes: // 1. All the settings are store in HKCU\...\Explorer\Settings key, // code can be added to support any random absolute reg path for // the settings. // #include "stdafx.h" #include "utils.h" #pragma hdrstop void Cabinet_StateChanged(void); // // Private Calls and structures // // typedef struct { HWND hDlg; // handle of our dialog HWND hwndTree; // handle to the treeview IRegTreeOptions *pTO; // pointer to RegTreeOptions interface CFolderOptionsPsx *ppsx; // to talk to our propsheet sibling BOOL fDirty; // Dirty bit to detect if anything changed. } ADVANCEDPAGE, *LPADVANCEDPAGE; #define ENABLEAPPLY(hDlg) SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L) // // Initializes Advanced property sheet // // History: void Install_AdvancedShellSettings(SHELLSTATE * pss); BOOL AdvancedDlgInit(HWND hDlg, LPARAM lParam) { HRESULT hr; LPADVANCEDPAGE pAdv = (LPADVANCEDPAGE)LocalAlloc(LPTR, sizeof(*pAdv)); if (!pAdv) { EndDialog(hDlg, 0); return FALSE; // no memory? } // We expose some of SHGetSetSettings in the advanced settings section, // so we need to migrate these PER-USER settings from the SHELLSTATE // structure into the registry tree structure once per user. Since we // don't have a per-user install section, do it here on demand. // We don't have to do it every time, but that's easier... Install_AdvancedShellSettings(NULL); // tell dialog where to get info SetWindowPtr(hDlg, DWLP_USER, pAdv); PROPSHEETPAGE *pps = (PROPSHEETPAGE *)lParam; pAdv->ppsx = (CFolderOptionsPsx *)pps->lParam; //Check if we have pointer to Shell Browser if (!pAdv->ppsx->HasBrowserService()) { //Hey ! we dont have pointer to Shell Browser so we must have been //invoked through a global Folder Options . In this case it doesn't //make sense to say "You can make all your folders look the same Like Current Folder" //because we dont have a current folder so let just disable the button "Like Current Folder" EnableWindow(GetDlgItem(hDlg, IDC_ADVO_USECURRENTFOLDER), FALSE); } // save dialog handle pAdv->hDlg = hDlg; pAdv->hwndTree = GetDlgItem(pAdv->hDlg, IDC_ADVO_ADVANCEDTREE); DWORD dwServerType = CLSCTX_INPROC_SERVER; hr = CoCreateInstance(CLSID_CRegTreeOptions, NULL, dwServerType, IID_IRegTreeOptions, (LPVOID *)&(pAdv->pTO)); if (SUCCEEDED(hr)) { // HACK - IRegTreeOptions is ANSI, so we temporarily turn off UNICODE #undef TEXT #define TEXT(s) s hr = pAdv->pTO->InitTree(pAdv->hwndTree, HKEY_LOCAL_MACHINE, REGSTR_EXPLORER_ADVANCED, NULL); #undef TEXT #define TEXT(s) __TEXT(s) } // find the first root and make sure that it is visible TreeView_EnsureVisible(pAdv->hwndTree, TreeView_GetRoot(pAdv->hwndTree)); return SUCCEEDED(hr) ? TRUE : FALSE; } void Tree_OnNotify(LPADVANCEDPAGE pAdv) { TV_HITTESTINFO ht; GetCursorPos(&ht.pt); // get where we were hit ScreenToClient(pAdv->hwndTree, &ht.pt); // translate it to our window // retrieve the item hit // IRegTreeOptions might fail to cocreate under stress conditions and // low memory, in which case we would fault here if we dont check for // pTO. Bug # 211108 - ramkumar if (pAdv->pTO) { pAdv->pTO->ToggleItem(TreeView_HitTest(pAdv->hwndTree, &ht)); ENABLEAPPLY(pAdv->hDlg); pAdv->fDirty = TRUE; } } // Tree_OnNotify // // AdvancedDlgOnNotify() // // Handles Advanced property sheets WM_NOTIFY messages // // void AdvancedDlgOnNotify(LPADVANCEDPAGE pAdv, LPNMHDR psn) { SetWindowLongPtr(pAdv->hDlg, DWLP_MSGRESULT, 0); // handled switch (psn->code) { case TVN_KEYDOWN: { TV_KEYDOWN *pnm = (TV_KEYDOWN*)psn; if (pnm->wVKey == VK_SPACE) { pAdv->pTO->ToggleItem((HTREEITEM)SendMessage(pAdv->hwndTree, TVM_GETNEXTITEM, TVGN_CARET, NULL)); ENABLEAPPLY(pAdv->hDlg); pAdv->fDirty = TRUE; // Specify that we handled the key, so we don't beep SetWindowLongPtr(pAdv->hDlg, DWLP_MSGRESULT, TRUE); } break; } case NM_CLICK: case NM_DBLCLK: // is this click in our tree? if (psn->idFrom == IDC_ADVO_ADVANCEDTREE) { // yes... Tree_OnNotify(pAdv); } break; case PSN_APPLY: if (pAdv->fDirty) //We will save these only if something changed. { pAdv->pTO->WalkTree(WALK_TREE_SAVE); CABINETSTATE cs; ReadCabinetState(&cs, sizeof(cs)); // refresh the global CABINETSTATE WriteCabinetState(&cs); // and make sure we commit to the bitfield. // We should only notify if needed. SHRefreshSettings(); // refresh the SHELLSTATE structure SHSettingsChanged(0, 0); // invalidate the restrictions // Let everybody know about the new settings SendNotifyMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0); // Okay now tell all Cabinets to refresh Cabinet_RefreshAll(Cabinet_RefreshEnum, (LPARAM)0L); } break; } } const static DWORD aAdvOptsHelpIDs[] = { // Context Help IDs IDC_ADVO_GROUPBOX, IDH_COMM_GROUPBOX, IDC_ADVO_ADVANCEDTEXT, IDH_GROUPBOX, IDC_ADVO_ADV_RESTORE_DEF, IDH_RESTORE_DEFAULT, IDC_ADVO_RESETTOORIGINAL, IDH_RESET_TO_ORIGINAL, IDC_ADVO_USECURRENTFOLDER, IDH_USE_CURRENT_FOLDER, IDC_ADVO_IMAGEFOLDER, -1, //Suppress help for this item. IDC_ADVO_STATICTEXT, -1, //Suppress help for this item. 0, 0 }; // // AdvancedDlgProc // // History: // // BOOL_PTR CALLBACK AdvancedOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { LPADVANCEDPAGE pAdv = (LPADVANCEDPAGE)GetWindowPtr(hDlg, DWLP_USER); if (uMsg == WM_INITDIALOG) { // Initialize Dialog controls return AdvancedDlgInit(hDlg, lParam); } if (pAdv) { switch (uMsg) { case WM_NOTIFY: AdvancedDlgOnNotify(pAdv, (LPNMHDR)lParam); return TRUE; break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDC_ADVO_ADV_RESTORE_DEF: pAdv->pTO->WalkTree(WALK_TREE_RESTORE); ENABLEAPPLY(hDlg); pAdv->fDirty = TRUE; break; case IDC_ADVO_USECURRENTFOLDER: if (ShellMessageBox(HINST_THISDLL, hDlg, MAKEINTRESOURCE(IDS_LIKECURRENT_TEXT), MAKEINTRESOURCE(IDS_FOLDERVIEWS), MB_YESNO | MB_ICONINFORMATION) == IDYES) { pAdv->ppsx->SetAsDefFolderSettings(); pAdv->ppsx->SetNeedRefresh(TRUE); pAdv->fDirty = TRUE; } break; case IDC_ADVO_RESETTOORIGINAL: if (ShellMessageBox(HINST_THISDLL, hDlg, MAKEINTRESOURCE(IDS_RESETALL_TEXT), MAKEINTRESOURCE(IDS_FOLDERVIEWS), MB_YESNO | MB_ICONINFORMATION) == IDYES) { pAdv->ppsx->ResetDefFolderSettings(); pAdv->ppsx->SetNeedRefresh(TRUE); pAdv->fDirty = TRUE; } break; } break; case WM_HELP: // F1 { HELPINFO *phi = (HELPINFO *)lParam; //if the help is for one of the command buttons then call winhelp if (phi->iCtrlId != IDC_ADVO_ADVANCEDTREE) { WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, TEXT(SHELL_HLP), HELP_WM_HELP, (DWORD_PTR)(LPSTR)aAdvOptsHelpIDs); } else { //Help is for the tree item so we need to do some special processing HTREEITEM hItem; // Is this help invoked throught F1 key if (GetAsyncKeyState(VK_F1) < 0) { // Yes. WE need to give help for the currently selected item hItem = TreeView_GetSelection(pAdv->hwndTree); } else { //No, We need to give help for the item at the cursor position TV_HITTESTINFO ht; ht.pt = phi->MousePos; ScreenToClient(pAdv->hwndTree, &ht.pt); // Translate it to our window hItem = TreeView_HitTest(pAdv->hwndTree, &ht); } if (FAILED(pAdv->pTO->ShowHelp(hItem, HELP_WM_HELP))) { WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR)(LPSTR)aAdvOptsHelpIDs); } } break; } case WM_CONTEXTMENU: // right mouse click { HTREEITEM hti; if ((LPARAM)-1 == lParam) { hti = TreeView_GetSelection(pAdv->hwndTree); } else { TV_HITTESTINFO ht; ht.pt.x = GET_X_LPARAM(lParam); ht.pt.y = GET_Y_LPARAM(lParam); ScreenToClient(pAdv->hwndTree, &ht.pt); hti = TreeView_HitTest(pAdv->hwndTree, &ht); } // retrieve the item hit if (FAILED(pAdv->pTO->ShowHelp(hti, HELP_CONTEXTMENU))) { WinHelp((HWND) wParam, TEXT(SHELL_HLP), HELP_CONTEXTMENU, (ULONG_PTR)(LPSTR)aAdvOptsHelpIDs); } break; } case WM_DESTROY: // free the tree if (pAdv->pTO) { pAdv->pTO->WalkTree(WALK_TREE_DELETE); ATOMICRELEASE(pAdv->pTO); } LocalFree(pAdv); // make sure we don't re-enter SetWindowPtr(hDlg, DWLP_USER, NULL); break; // WM_DESTORY } } return FALSE; // not handled }