[SHELL32] Split dialogs/folder_options.cpp (#582)

The dialogs/folder_options.cpp source file in shell32 is too big to manage. We will split it to smaller files.
CORE-12906
This commit is contained in:
Katayama Hirofumi MZ 2018-06-06 21:04:50 +09:00 committed by Hermès BÉLUSCA - MAÏTO
parent f215f394d8
commit 698cbc6184
41 changed files with 3137 additions and 2994 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,55 @@
/*
* Folder Options
*
* Copyright 2007 Johannes Anderwald <johannes.anderwald@reactos.org>
* Copyright 2016-2018 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
// IDD_FOLDER_OPTIONS_GENERAL
INT_PTR
CALLBACK
FolderOptionsGeneralDlg(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
// IDD_FOLDER_OPTIONS_VIEW
INT_PTR CALLBACK
FolderOptionsViewDlg(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
// IDD_FOLDER_OPTIONS_FILETYPES
INT_PTR CALLBACK
FolderOptionsFileTypesDlg(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
HBITMAP Create24BppBitmap(HDC hDC, INT cx, INT cy);
HBITMAP BitmapFromIcon(HICON hIcon, INT cx, INT cy);
HBITMAP CreateCheckImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE);
HBITMAP CreateCheckMask(HDC hDC);
HBITMAP CreateRadioImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE);
HBITMAP CreateRadioMask(HDC hDC);
extern LPCWSTR g_pszShell32;
extern LPCWSTR g_pszSpace;

View file

@ -0,0 +1,147 @@
/*
* 'General' tab property sheet of Folder Options
*
* Copyright 2007 Johannes Anderwald <johannes.anderwald@reactos.org>
* Copyright 2016-2018 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "precomp.h"
WINE_DEFAULT_DEBUG_CHANNEL (fprop);
static VOID
GeneralDlg_UpdateIcons(HWND hDlg)
{
HICON hTaskIcon = NULL, hFolderIcon = NULL, hClickIcon = NULL;
LPTSTR lpTaskIconName = NULL, lpFolderIconName = NULL, lpClickIconName = NULL;
// Show task setting icon.
if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_COMMONTASKS) == BST_CHECKED)
lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_SHOW_COMMON_TASKS);
else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_CLASSICFOLDERS) == BST_CHECKED)
lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_CLASSIC_FOLDERS);
if (lpTaskIconName)
{
hTaskIcon = (HICON)LoadImage(shell32_hInstance, lpTaskIconName,
IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
if (hTaskIcon)
{
HWND hwndTaskIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_TASKICON);
SendMessage(hwndTaskIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hTaskIcon);
}
}
// Show Folder setting icons
if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW) == BST_CHECKED)
lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_SOME_WINDOW);
else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_OWNWINDOW) == BST_CHECKED)
lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_NEW_WINDOW);
if (lpFolderIconName)
{
hFolderIcon = (HICON)LoadImage(shell32_hInstance, lpFolderIconName,
IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
if (hFolderIcon)
{
HWND hwndFolderIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_FOLDERICON);
SendMessage(hwndFolderIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hFolderIcon);
}
}
// Show click setting icon
if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SINGLECLICK) == BST_CHECKED)
lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_SINGLE_CLICK_TO_OPEN);
else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_DOUBLECLICK) == BST_CHECKED)
lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_DOUBLE_CLICK_TO_OPEN);
if (lpClickIconName)
{
hClickIcon = (HICON)LoadImage(shell32_hInstance, lpClickIconName,
IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
if (hClickIcon)
{
HWND hwndClickIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_CLICKICON);
SendMessage(hwndClickIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hClickIcon);
}
}
// Clean up
if (hTaskIcon)
DeleteObject(hTaskIcon);
if (hFolderIcon)
DeleteObject(hFolderIcon);
if (hClickIcon)
DeleteObject(hClickIcon);
}
INT_PTR CALLBACK
FolderOptionsGeneralDlg(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
// FIXME
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_FOLDER_OPTIONS_COMMONTASKS:
case IDC_FOLDER_OPTIONS_CLASSICFOLDERS:
case IDC_FOLDER_OPTIONS_SAMEWINDOW:
case IDC_FOLDER_OPTIONS_OWNWINDOW:
case IDC_FOLDER_OPTIONS_SINGLECLICK:
case IDC_FOLDER_OPTIONS_DOUBLECLICK:
if (HIWORD(wParam) == BN_CLICKED)
{
GeneralDlg_UpdateIcons(hwndDlg);
// Enable the 'Apply' button
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
}
break;
}
break;
case WM_NOTIFY:
{
LPNMHDR pnmh = (LPNMHDR)lParam;
switch (pnmh->code)
{
case PSN_SETACTIVE:
break;
case PSN_APPLY:
break;
}
break;
}
case WM_DESTROY:
break;
default:
return FALSE;
}
return FALSE;
}

View file

@ -0,0 +1,985 @@
/*
* 'View' tab property sheet of Folder Options
*
* Copyright 2007 Johannes Anderwald <johannes.anderwald@reactos.org>
* Copyright 2016-2018 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "precomp.h"
WINE_DEFAULT_DEBUG_CHANNEL (fprop);
/////////////////////////////////////////////////////////////////////////////
// View Tree
// predefined icon IDs (See ViewDlg_CreateTreeImageList function below)
#define I_CHECKED 0
#define I_UNCHECKED 1
#define I_CHECKED_DISABLED 2
#define I_UNCHECKED_DISABLED 3
#define I_RADIO_CHECKED 4
#define I_RADIO_UNCHECKED 5
#define I_RADIO_CHECKED_DISABLED 6
#define I_RADIO_UNCHECKED_DISABLED 7
#define PREDEFINED_ICON_COUNT 8
// uniquely-defined icon entry for View Advanced Settings
typedef struct VIEWTREE_ICON
{
WCHAR szPath[MAX_PATH];
UINT nIconIndex;
} VIEWTREE_ICON, *PVIEWTREE_ICON;
// types of View Advanced Setting entry
typedef enum VIEWTREE_ENTRY_TYPE
{
AETYPE_GROUP,
AETYPE_CHECKBOX,
AETYPE_RADIO,
} VIEWTREE_ENTRY_TYPE, *PVIEWTREE_ENTRY_TYPE;
// an entry info of View Advanced Settings
typedef struct VIEWTREE_ENTRY
{
DWORD dwID; // entry ID
DWORD dwParentID; // parent entry ID
DWORD dwResourceID; // resource ID
WCHAR szKeyName[64]; // entry key name
DWORD dwType; // VIEWTREE_ENTRY_TYPE
WCHAR szText[MAX_PATH]; // text
INT nIconID; // icon ID (See VIEWTREE_ICON)
HKEY hkeyRoot; // registry root key
WCHAR szRegPath[MAX_PATH]; // registry path
WCHAR szValueName[64]; // registry value name
DWORD dwCheckedValue; // checked value
DWORD dwUncheckedValue; // unchecked value
DWORD dwDefaultValue; // defalut value
BOOL bHasUncheckedValue; // If FALSE, UncheckedValue is invalid
HTREEITEM hItem; // for TreeView
BOOL bGrayed; // disabled?
BOOL bChecked; // checked?
} VIEWTREE_ENTRY, *PVIEWTREE_ENTRY;
// definition of view advanced entries
static PVIEWTREE_ENTRY s_ViewTreeEntries = NULL;
static INT s_ViewTreeEntryCount = 0;
// definition of icon stock
static PVIEWTREE_ICON s_ViewTreeIcons = NULL;
static INT s_ViewTreeIconCount = 0;
static HIMAGELIST s_hTreeImageList = NULL;
static INT
ViewTree_FindIcon(LPCWSTR pszPath, UINT nIconIndex)
{
for (INT i = PREDEFINED_ICON_COUNT; i < s_ViewTreeIconCount; ++i)
{
PVIEWTREE_ICON pIcon = &s_ViewTreeIcons[i];
if (pIcon->nIconIndex == nIconIndex &&
lstrcmpiW(pIcon->szPath, pszPath) == 0)
{
return i; // icon ID
}
}
return -1; // not found
}
static INT
ViewTree_AddIcon(LPCWSTR pszPath, UINT nIconIndex)
{
PVIEWTREE_ICON pAllocated;
// return the ID if already existed
INT nIconID = ViewTree_FindIcon(pszPath, nIconIndex);
if (nIconID != -1)
return nIconID; // already exists
// extract a small icon
HICON hIconSmall = NULL;
ExtractIconExW(pszPath, nIconIndex, NULL, &hIconSmall, 1);
if (hIconSmall == NULL)
return -1; // failure
// resize s_ViewTreeIcons
size_t Size = (s_ViewTreeIconCount + 1) * sizeof(VIEWTREE_ICON);
pAllocated = (PVIEWTREE_ICON)realloc(s_ViewTreeIcons, Size);
if (pAllocated == NULL)
return -1; // failure
else
s_ViewTreeIcons = pAllocated;
// save icon information
PVIEWTREE_ICON pIcon = &s_ViewTreeIcons[s_ViewTreeIconCount];
lstrcpynW(pIcon->szPath, pszPath, _countof(pIcon->szPath));
pIcon->nIconIndex = nIconIndex;
// add the icon to the image list
ImageList_AddIcon(s_hTreeImageList, hIconSmall);
// increment the counter
nIconID = s_ViewTreeIconCount;
++s_ViewTreeIconCount;
DestroyIcon(hIconSmall);
return nIconID; // newly-added icon ID
}
static PVIEWTREE_ENTRY
ViewTree_GetItem(DWORD dwID)
{
if (dwID == DWORD(-1))
return NULL;
for (INT i = 0; i < s_ViewTreeEntryCount; ++i)
{
PVIEWTREE_ENTRY pEntry = &s_ViewTreeEntries[i];
if (pEntry->dwID == dwID)
return pEntry;
}
return NULL; // failure
}
static INT
ViewTree_GetImage(PVIEWTREE_ENTRY pEntry)
{
switch (pEntry->dwType)
{
case AETYPE_GROUP:
return pEntry->nIconID;
case AETYPE_CHECKBOX:
if (pEntry->bGrayed)
{
if (pEntry->bChecked)
return I_CHECKED_DISABLED;
else
return I_UNCHECKED_DISABLED;
}
else
{
if (pEntry->bChecked)
return I_CHECKED;
else
return I_UNCHECKED;
}
case AETYPE_RADIO:
if (pEntry->bGrayed)
{
if (pEntry->bChecked)
return I_RADIO_CHECKED_DISABLED;
else
return I_RADIO_UNCHECKED_DISABLED;
}
else
{
if (pEntry->bChecked)
return I_RADIO_CHECKED;
else
return I_RADIO_UNCHECKED;
}
}
return -1; // failure
}
static VOID
ViewTree_InsertEntry(HWND hwndTreeView, PVIEWTREE_ENTRY pEntry)
{
PVIEWTREE_ENTRY pParent = ViewTree_GetItem(pEntry->dwParentID);
HTREEITEM hParent = TVI_ROOT;
if (pParent)
hParent = pParent->hItem;
TV_INSERTSTRUCT Insertion;
ZeroMemory(&Insertion, sizeof(Insertion));
Insertion.hParent = hParent;
Insertion.hInsertAfter = TVI_LAST;
Insertion.item.mask =
TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
Insertion.item.pszText = pEntry->szText;
INT iImage = ViewTree_GetImage(pEntry);
Insertion.item.iImage = Insertion.item.iSelectedImage = iImage;
Insertion.item.lParam = pEntry->dwID;
pEntry->hItem = TreeView_InsertItem(hwndTreeView, &Insertion);
}
static VOID
ViewTree_InsertAll(HWND hwndTreeView)
{
TreeView_DeleteAllItems(hwndTreeView);
// insert the entries
PVIEWTREE_ENTRY pEntry;
for (INT i = 0; i < s_ViewTreeEntryCount; ++i)
{
pEntry = &s_ViewTreeEntries[i];
ViewTree_InsertEntry(hwndTreeView, pEntry);
}
// expand all
for (INT i = 0; i < s_ViewTreeEntryCount; ++i)
{
pEntry = &s_ViewTreeEntries[i];
if (pEntry->dwType == AETYPE_GROUP)
{
TreeView_Expand(hwndTreeView, pEntry->hItem, TVE_EXPAND);
}
}
}
static BOOL
ViewTree_LoadTree(HKEY hKey, LPCWSTR pszKeyName, DWORD dwParentID)
{
DWORD dwIndex;
WCHAR szKeyName[64], szText[MAX_PATH], *pch;
DWORD Size, Value;
PVIEWTREE_ENTRY pAllocated;
// resize s_ViewTreeEntries
Size = (s_ViewTreeEntryCount + 1) * sizeof(VIEWTREE_ENTRY);
pAllocated = (PVIEWTREE_ENTRY)realloc(s_ViewTreeEntries, Size);
if (pAllocated == NULL)
return FALSE; // failure
else
s_ViewTreeEntries = pAllocated;
PVIEWTREE_ENTRY pEntry = &s_ViewTreeEntries[s_ViewTreeEntryCount];
// dwID, dwParentID, szKeyName
pEntry->dwID = s_ViewTreeEntryCount;
pEntry->dwParentID = dwParentID;
lstrcpynW(pEntry->szKeyName, pszKeyName, _countof(pEntry->szKeyName));
// Text, ResourceID
pEntry->szText[0] = 0;
pEntry->dwResourceID = 0;
szText[0] = 0;
Size = sizeof(szText);
RegQueryValueExW(hKey, L"Text", NULL, NULL, LPBYTE(szText), &Size);
if (szText[0] == L'@')
{
pch = wcsrchr(szText, L',');
if (pch)
{
*pch = 0;
dwIndex = abs(_wtoi(pch + 1));
pEntry->dwResourceID = dwIndex;
}
HINSTANCE hInst = LoadLibraryW(&szText[1]);
LoadStringW(hInst, dwIndex, szText, _countof(szText));
FreeLibrary(hInst);
}
else
{
pEntry->dwResourceID = DWORD(-1);
}
lstrcpynW(pEntry->szText, szText, _countof(pEntry->szText));
// Type
szText[0] = 0;
RegQueryValueExW(hKey, L"Type", NULL, NULL, LPBYTE(szText), &Size);
if (lstrcmpiW(szText, L"checkbox") == 0)
pEntry->dwType = AETYPE_CHECKBOX;
else if (lstrcmpiW(szText, L"radio") == 0)
pEntry->dwType = AETYPE_RADIO;
else if (lstrcmpiW(szText, L"group") == 0)
pEntry->dwType = AETYPE_GROUP;
else
return FALSE; // failure
pEntry->nIconID = -1;
if (pEntry->dwType == AETYPE_GROUP)
{
// Bitmap (Icon)
UINT nIconIndex = 0;
Size = sizeof(szText);
szText[0] = 0;
RegQueryValueExW(hKey, L"Bitmap", NULL, NULL, LPBYTE(szText), &Size);
WCHAR szExpanded[MAX_PATH];
ExpandEnvironmentStringsW(szText, szExpanded, _countof(szExpanded));
pch = wcsrchr(szExpanded, L',');
if (pch)
{
*pch = 0;
nIconIndex = abs(_wtoi(pch + 1));
}
pEntry->nIconID = ViewTree_AddIcon(szExpanded, nIconIndex);
}
if (pEntry->dwType == AETYPE_GROUP)
{
pEntry->hkeyRoot = NULL;
pEntry->szRegPath[0] = 0;
pEntry->szValueName[0] = 0;
pEntry->dwCheckedValue = 0;
pEntry->bHasUncheckedValue = FALSE;
pEntry->dwUncheckedValue = 0;
pEntry->dwDefaultValue = 0;
pEntry->hItem = NULL;
pEntry->bGrayed = FALSE;
pEntry->bChecked = FALSE;
}
else
{
// HKeyRoot
Value = DWORD(HKEY_CURRENT_USER);
Size = sizeof(Value);
RegQueryValueExW(hKey, L"HKeyRoot", NULL, NULL, LPBYTE(&Value), &Size);
pEntry->hkeyRoot = HKEY(Value);
// RegPath
pEntry->szRegPath[0] = 0;
Size = sizeof(szText);
RegQueryValueExW(hKey, L"RegPath", NULL, NULL, LPBYTE(szText), &Size);
lstrcpynW(pEntry->szRegPath, szText, _countof(pEntry->szRegPath));
// ValueName
pEntry->szValueName[0] = 0;
Size = sizeof(szText);
RegQueryValueExW(hKey, L"ValueName", NULL, NULL, LPBYTE(szText), &Size);
lstrcpynW(pEntry->szValueName, szText, _countof(pEntry->szValueName));
// CheckedValue
Size = sizeof(Value);
Value = 0x00000001;
RegQueryValueExW(hKey, L"CheckedValue", NULL, NULL, LPBYTE(&Value), &Size);
pEntry->dwCheckedValue = Value;
// UncheckedValue
Size = sizeof(Value);
Value = 0x00000000;
pEntry->bHasUncheckedValue = TRUE;
if (RegQueryValueExW(hKey, L"UncheckedValue", NULL,
NULL, LPBYTE(&Value), &Size) != ERROR_SUCCESS)
{
pEntry->bHasUncheckedValue = FALSE;
}
pEntry->dwUncheckedValue = Value;
// DefaultValue
Size = sizeof(Value);
Value = 0x00000001;
RegQueryValueExW(hKey, L"DefaultValue", NULL, NULL, LPBYTE(&Value), &Size);
pEntry->dwDefaultValue = Value;
// hItem
pEntry->hItem = NULL;
// bGrayed, bChecked
HKEY hkeyTarget;
Value = pEntry->dwDefaultValue;
pEntry->bGrayed = TRUE;
if (RegOpenKeyExW(HKEY(pEntry->hkeyRoot), pEntry->szRegPath, 0,
KEY_READ, &hkeyTarget) == ERROR_SUCCESS)
{
Size = sizeof(Value);
if (RegQueryValueExW(hkeyTarget, pEntry->szValueName, NULL, NULL,
LPBYTE(&Value), &Size) == ERROR_SUCCESS)
{
pEntry->bGrayed = FALSE;
}
RegCloseKey(hkeyTarget);
}
pEntry->bChecked = (Value == pEntry->dwCheckedValue);
}
// Grayed (ReactOS extension)
Size = sizeof(Value);
Value = FALSE;
RegQueryValueExW(hKey, L"Grayed", NULL, NULL, LPBYTE(&Value), &Size);
if (!pEntry->bGrayed)
pEntry->bGrayed = Value;
BOOL bIsGroup = (pEntry->dwType == AETYPE_GROUP);
dwParentID = pEntry->dwID;
++s_ViewTreeEntryCount;
if (!bIsGroup)
return TRUE; // success
// load the children
dwIndex = 0;
while (RegEnumKeyW(hKey, dwIndex, szKeyName,
_countof(szKeyName)) == ERROR_SUCCESS)
{
HKEY hkeyChild;
if (RegOpenKeyExW(hKey, szKeyName, 0, KEY_READ,
&hkeyChild) != ERROR_SUCCESS)
{
++dwIndex;
continue; // failure
}
ViewTree_LoadTree(hkeyChild, szKeyName, dwParentID);
RegCloseKey(hkeyChild);
++dwIndex;
}
return TRUE; // success
}
static BOOL ViewTree_LoadAll(VOID)
{
static const WCHAR s_szAdvanced[] =
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced";
// free if already existed
if (s_ViewTreeEntries)
{
free(s_ViewTreeEntries);
s_ViewTreeEntries = NULL;
}
s_ViewTreeEntryCount = 0;
HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szAdvanced, 0,
KEY_READ, &hKey) != ERROR_SUCCESS)
{
return FALSE; // failure
}
// load the children
WCHAR szKeyName[64];
DWORD dwIndex = 0;
while (RegEnumKeyW(hKey, dwIndex, szKeyName,
_countof(szKeyName)) == ERROR_SUCCESS)
{
HKEY hkeyChild;
if (RegOpenKeyExW(hKey, szKeyName, 0, KEY_READ,
&hkeyChild) != ERROR_SUCCESS)
{
++dwIndex;
continue; // failure
}
ViewTree_LoadTree(hkeyChild, szKeyName, DWORD(-1));
RegCloseKey(hkeyChild);
++dwIndex;
}
RegCloseKey(hKey);
return TRUE; // success
}
static int ViewTree_Compare(const void *x, const void *y)
{
PVIEWTREE_ENTRY pEntry1 = (PVIEWTREE_ENTRY)x;
PVIEWTREE_ENTRY pEntry2 = (PVIEWTREE_ENTRY)y;
DWORD dwParentID1 = pEntry1->dwParentID;
DWORD dwParentID2 = pEntry2->dwParentID;
if (dwParentID1 == dwParentID2)
return lstrcmpi(pEntry1->szText, pEntry2->szText);
DWORD i, m, n;
const UINT MAX_DEPTH = 32;
PVIEWTREE_ENTRY pArray1[MAX_DEPTH];
PVIEWTREE_ENTRY pArray2[MAX_DEPTH];
// Make ancestor lists
for (i = m = n = 0; i < MAX_DEPTH; ++i)
{
PVIEWTREE_ENTRY pParent1 = ViewTree_GetItem(dwParentID1);
PVIEWTREE_ENTRY pParent2 = ViewTree_GetItem(dwParentID2);
if (!pParent1 && !pParent2)
break;
if (pParent1)
{
pArray1[m++] = pParent1;
dwParentID1 = pParent1->dwParentID;
}
if (pParent2)
{
pArray2[n++] = pParent2;
dwParentID2 = pParent2->dwParentID;
}
}
UINT k = min(m, n);
for (i = 0; i < k; ++i)
{
INT nCompare = lstrcmpi(pArray1[m - i - 1]->szText, pArray2[n - i - 1]->szText);
if (nCompare < 0)
return -1;
if (nCompare > 0)
return 1;
}
if (m < n)
return -1;
if (m > n)
return 1;
return lstrcmpi(pEntry1->szText, pEntry2->szText);
}
static VOID
ViewTree_SortAll(VOID)
{
qsort(s_ViewTreeEntries, s_ViewTreeEntryCount, sizeof(VIEWTREE_ENTRY), ViewTree_Compare);
}
/////////////////////////////////////////////////////////////////////////////
// ViewDlg
static HIMAGELIST
ViewDlg_CreateTreeImageList(VOID)
{
HIMAGELIST hImageList;
hImageList = ImageList_Create(16, 16, ILC_COLOR24 | ILC_MASK, 9, 1);
if (hImageList == NULL)
return NULL; // failure
// free if existed
if (s_ViewTreeIcons)
{
free(s_ViewTreeIcons);
s_ViewTreeIcons = NULL;
}
s_ViewTreeIconCount = 0;
// allocate now
PVIEWTREE_ICON pAllocated;
size_t Size = PREDEFINED_ICON_COUNT * sizeof(VIEWTREE_ICON);
pAllocated = (PVIEWTREE_ICON)calloc(1, Size);
if (pAllocated == NULL)
return NULL; // failure
s_ViewTreeIconCount = PREDEFINED_ICON_COUNT;
s_ViewTreeIcons = pAllocated;
// add the predefined icons
HDC hDC = CreateCompatibleDC(NULL);
HBITMAP hbmMask = CreateCheckMask(hDC);
HBITMAP hbmChecked, hbmUnchecked;
hbmChecked = CreateCheckImage(hDC, TRUE);
ImageList_Add(hImageList, hbmChecked, hbmMask);
DeleteObject(hbmChecked);
hbmUnchecked = CreateCheckImage(hDC, FALSE);
ImageList_Add(hImageList, hbmUnchecked, hbmMask);
DeleteObject(hbmUnchecked);
hbmChecked = CreateCheckImage(hDC, TRUE, FALSE);
ImageList_Add(hImageList, hbmChecked, hbmMask);
DeleteObject(hbmChecked);
hbmUnchecked = CreateCheckImage(hDC, FALSE, FALSE);
ImageList_Add(hImageList, hbmUnchecked, hbmMask);
DeleteObject(hbmUnchecked);
DeleteObject(hbmMask);
hbmMask = CreateRadioMask(hDC);
hbmChecked = CreateRadioImage(hDC, TRUE);
ImageList_Add(hImageList, hbmChecked, hbmMask);
DeleteObject(hbmChecked);
hbmUnchecked = CreateRadioImage(hDC, FALSE);
ImageList_Add(hImageList, hbmUnchecked, hbmMask);
DeleteObject(hbmUnchecked);
hbmChecked = CreateRadioImage(hDC, TRUE, FALSE);
ImageList_Add(hImageList, hbmChecked, hbmMask);
DeleteObject(hbmChecked);
hbmUnchecked = CreateRadioImage(hDC, FALSE, FALSE);
ImageList_Add(hImageList, hbmUnchecked, hbmMask);
DeleteObject(hbmUnchecked);
DeleteObject(hbmMask);
return hImageList;
}
static BOOL
ViewDlg_OnInitDialog(HWND hwndDlg)
{
HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW);
s_hTreeImageList = ViewDlg_CreateTreeImageList();
TreeView_SetImageList(hwndTreeView, s_hTreeImageList, TVSIL_NORMAL);
ViewTree_LoadAll();
ViewTree_SortAll();
ViewTree_InsertAll(hwndTreeView);
return TRUE; // set focus
}
static BOOL
ViewDlg_ToggleCheckItem(HWND hwndDlg, HTREEITEM hItem)
{
HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW);
// get the item
TV_ITEM Item;
INT i;
ZeroMemory(&Item, sizeof(Item));
Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_PARAM;
Item.hItem = hItem;
if (!TreeView_GetItem(hwndTreeView, &Item))
return FALSE; // no such item
VIEWTREE_ENTRY *pEntry = ViewTree_GetItem(Item.lParam);
if (pEntry == NULL)
return FALSE; // no such item
if (pEntry->bGrayed)
return FALSE; // disabled
// toggle check mark
Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
switch (pEntry->dwType)
{
case AETYPE_CHECKBOX:
pEntry->bChecked = !pEntry->bChecked;
break;
case AETYPE_RADIO:
// reset all the entries of the same parent
for (i = 0; i < s_ViewTreeEntryCount; ++i)
{
VIEWTREE_ENTRY *pEntry2 = &s_ViewTreeEntries[i];
if (pEntry->dwParentID == pEntry2->dwParentID)
{
pEntry2->bChecked = FALSE;
Item.hItem = pEntry2->hItem;
INT iImage = ViewTree_GetImage(pEntry2);
Item.iImage = Item.iSelectedImage = iImage;
TreeView_SetItem(hwndTreeView, &Item);
}
}
pEntry->bChecked = TRUE;
break;
default:
return FALSE; // failure
}
Item.iImage = Item.iSelectedImage = ViewTree_GetImage(pEntry);
Item.hItem = hItem;
TreeView_SetItem(hwndTreeView, &Item);
// redraw the item
RECT rcItem;
TreeView_GetItemRect(hwndTreeView, hItem, &rcItem, FALSE);
InvalidateRect(hwndTreeView, &rcItem, TRUE);
return TRUE; // success
}
static VOID
ViewDlg_OnTreeViewClick(HWND hwndDlg)
{
HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW);
// do hit test to get the clicked item
TV_HITTESTINFO HitTest;
ZeroMemory(&HitTest, sizeof(HitTest));
DWORD dwPos = GetMessagePos();
HitTest.pt.x = LOWORD(dwPos);
HitTest.pt.y = HIWORD(dwPos);
ScreenToClient(hwndTreeView, &HitTest.pt);
HTREEITEM hItem = TreeView_HitTest(hwndTreeView, &HitTest);
// toggle the check mark if possible
if (ViewDlg_ToggleCheckItem(hwndDlg, hItem))
{
// property sheet was changed
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
}
}
static void
ViewDlg_OnTreeViewKeyDown(HWND hwndDlg, TV_KEYDOWN *KeyDown)
{
HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW);
if (KeyDown->wVKey == VK_SPACE)
{
// [Space] key was pressed
HTREEITEM hItem = TreeView_GetSelection(hwndTreeView);
if (ViewDlg_ToggleCheckItem(hwndDlg, hItem))
{
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
}
}
}
static INT_PTR
ViewDlg_OnTreeCustomDraw(HWND hwndDlg, NMTVCUSTOMDRAW *Draw)
{
NMCUSTOMDRAW& nmcd = Draw->nmcd;
switch (nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW; // for CDDS_ITEMPREPAINT
case CDDS_ITEMPREPAINT:
if (!(nmcd.uItemState & CDIS_SELECTED)) // not selected
{
LPARAM lParam = nmcd.lItemlParam;
VIEWTREE_ENTRY *pEntry = ViewTree_GetItem(lParam);
if (pEntry && pEntry->bGrayed) // disabled
{
// draw as grayed
Draw->clrText = GetSysColor(COLOR_GRAYTEXT);
Draw->clrTextBk = GetSysColor(COLOR_WINDOW);
return CDRF_NEWFONT;
}
}
break;
default:
break;
}
return CDRF_DODEFAULT;
}
static VOID
ViewDlg_RestoreDefaults(HWND hwndDlg)
{
HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW);
for (INT i = 0; i < s_ViewTreeEntryCount; ++i)
{
// ignore if the type is group
VIEWTREE_ENTRY *pEntry = &s_ViewTreeEntries[i];
if (pEntry->dwType == AETYPE_GROUP)
continue;
// set default value on registry
HKEY hKey;
if (RegOpenKeyExW(HKEY(pEntry->hkeyRoot), pEntry->szRegPath,
0, KEY_WRITE, &hKey) != ERROR_SUCCESS)
{
continue;
}
RegSetValueExW(hKey, pEntry->szValueName, 0, REG_DWORD,
LPBYTE(pEntry->dwDefaultValue), sizeof(DWORD));
RegCloseKey(hKey);
// update check status
pEntry->bChecked = (pEntry->dwCheckedValue == pEntry->dwDefaultValue);
// update the image
TV_ITEM Item;
ZeroMemory(&Item, sizeof(Item));
Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
Item.hItem = pEntry->hItem;
Item.iImage = Item.iSelectedImage = ViewTree_GetImage(pEntry);
TreeView_SetItem(hwndTreeView, &Item);
}
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
}
static VOID
ScanAdvancedSettings(SHELLSTATE *pSS, DWORD *pdwMask)
{
for (INT i = 0; i < s_ViewTreeEntryCount; ++i)
{
const VIEWTREE_ENTRY *pEntry = &s_ViewTreeEntries[i];
if (pEntry->dwType == AETYPE_GROUP || pEntry->bGrayed)
continue;
BOOL bChecked = pEntry->bChecked;
// FIXME: Add more items
if (lstrcmpiW(pEntry->szKeyName, L"SuperHidden") == 0)
{
pSS->fShowSuperHidden = !bChecked ? 1 : 0;
*pdwMask |= SSF_SHOWSUPERHIDDEN;
continue;
}
if (lstrcmpiW(pEntry->szKeyName, L"DesktopProcess") == 0)
{
pSS->fSepProcess = bChecked ? 1 : 0;
*pdwMask |= SSF_SEPPROCESS;
continue;
}
if (lstrcmpiW(pEntry->szKeyName, L"SHOWALL") == 0)
{
pSS->fShowAllObjects = !bChecked ? 1 : 0;
*pdwMask |= SSF_SHOWALLOBJECTS;
continue;
}
if (lstrcmpiW(pEntry->szKeyName, L"HideFileExt") == 0)
{
pSS->fShowExtensions = !bChecked ? 1 : 0;
*pdwMask |= SSF_SHOWEXTENSIONS;
continue;
}
if (lstrcmpiW(pEntry->szKeyName, L"ShowCompColor") == 0)
{
pSS->fShowCompColor = bChecked ? 1 : 0;
*pdwMask |= SSF_SHOWCOMPCOLOR;
continue;
}
if (lstrcmpiW(pEntry->szKeyName, L"ShowInfoTip") == 0)
{
pSS->fShowInfoTip = bChecked ? 1 : 0;
*pdwMask |= SSF_SHOWINFOTIP;
continue;
}
}
}
static BOOL CALLBACK
RefreshBrowsersCallback(HWND hWnd, LPARAM msg)
{
WCHAR ClassName[100];
if (GetClassNameW(hWnd, ClassName, _countof(ClassName)))
{
if (!wcscmp(ClassName, L"Progman") ||
!wcscmp(ClassName, L"CabinetWClass") ||
!wcscmp(ClassName, L"ExploreWClass"))
{
PostMessage(hWnd, WM_COMMAND, FCIDM_DESKBROWSER_REFRESH, 0);
}
}
return TRUE;
}
static VOID
ViewDlg_Apply(HWND hwndDlg)
{
for (INT i = 0; i < s_ViewTreeEntryCount; ++i)
{
// ignore the entry if the type is group or the entry is grayed
VIEWTREE_ENTRY *pEntry = &s_ViewTreeEntries[i];
if (pEntry->dwType == AETYPE_GROUP || pEntry->bGrayed)
continue;
// open the registry key
HKEY hkeyTarget;
if (RegOpenKeyExW(HKEY(pEntry->hkeyRoot), pEntry->szRegPath, 0,
KEY_WRITE, &hkeyTarget) != ERROR_SUCCESS)
{
continue;
}
// checked or unchecked?
DWORD dwValue, dwSize;
if (pEntry->bChecked)
{
dwValue = pEntry->dwCheckedValue;
}
else
{
if (pEntry->bHasUncheckedValue)
{
dwValue = pEntry->dwUncheckedValue;
}
else
{
// there is no unchecked value
RegCloseKey(hkeyTarget);
continue; // ignore
}
}
// set the value
dwSize = sizeof(dwValue);
RegSetValueExW(hkeyTarget, pEntry->szValueName, 0, REG_DWORD,
LPBYTE(&dwValue), dwSize);
// close now
RegCloseKey(hkeyTarget);
}
// scan advanced settings for user's settings
DWORD dwMask = 0;
SHELLSTATE ShellState;
ZeroMemory(&ShellState, sizeof(ShellState));
ScanAdvancedSettings(&ShellState, &dwMask);
// update user's settings
SHGetSetSettings(&ShellState, dwMask, TRUE);
// notify all
SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0);
EnumWindows(RefreshBrowsersCallback, NULL);
}
// IDD_FOLDER_OPTIONS_VIEW
INT_PTR CALLBACK
FolderOptionsViewDlg(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
INT_PTR Result;
NMTVCUSTOMDRAW *Draw;
switch (uMsg)
{
case WM_INITDIALOG:
return ViewDlg_OnInitDialog(hwndDlg);
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_VIEW_RESTORE_DEFAULTS: // Restore Defaults
ViewDlg_RestoreDefaults(hwndDlg);
break;
}
break;
case WM_NOTIFY:
switch (LPNMHDR(lParam)->code)
{
case NM_CLICK: // clicked on treeview
ViewDlg_OnTreeViewClick(hwndDlg);
break;
case NM_CUSTOMDRAW: // custom draw (for graying)
Draw = (NMTVCUSTOMDRAW *)lParam;
Result = ViewDlg_OnTreeCustomDraw(hwndDlg, Draw);
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, Result);
return Result;
case TVN_KEYDOWN: // key is down
ViewDlg_OnTreeViewKeyDown(hwndDlg, (TV_KEYDOWN *)lParam);
break;
case PSN_APPLY: // [Apply] is clicked
ViewDlg_Apply(hwndDlg);
break;
default:
break;
}
break;
}
return FALSE;
}