[SHELL32] Fixes and improvements for PickIconDlg().

- Deal with expanded paths only when loading icons. If the user specifies
  an unexpanded path to a module containing icons, this unexpanded path
  is returned to the caller!

- Perform the dialog cleanup in WM_DESTROY message handler.

- When pressing ENTER/OK in the dialog box, retrieve the selected icon and
  close the dialog *ONLY WHEN* the user actually has selected an icon.
  If the user modified manually the module path, pressing ENTER/OK instead
  reloads the icons list.
This commit is contained in:
Hermès Bélusca-Maïto 2018-09-30 21:22:50 +02:00
parent ae9ec94240
commit ccde12483f
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0

View file

@ -48,7 +48,6 @@ typedef struct
HMODULE hLibrary; HMODULE hLibrary;
HWND hDlgCtrl; HWND hDlgCtrl;
WCHAR szPath[MAX_PATH]; WCHAR szPath[MAX_PATH];
WCHAR szExpandedPath[MAX_PATH];
INT Index; INT Index;
INT nIcons; INT nIcons;
HICON *phIcons; HICON *phIcons;
@ -90,19 +89,21 @@ DestroyIconList(HWND hDlgCtrl, PPICK_ICON_CONTEXT pIconContext)
} }
static BOOL static BOOL
DoLoadIcons(HWND hwndDlg, PICK_ICON_CONTEXT *pIconContext, LPCWSTR pszFile) DoLoadIcons(HWND hwndDlg, PPICK_ICON_CONTEXT pIconContext, LPCWSTR pszFile)
{ {
WCHAR szExpandedPath[MAX_PATH];
// Destroy previous icons // Destroy previous icons
DestroyIconList(pIconContext->hDlgCtrl, pIconContext); DestroyIconList(pIconContext->hDlgCtrl, pIconContext);
SendMessageW(pIconContext->hDlgCtrl, LB_RESETCONTENT, 0, 0); SendMessageW(pIconContext->hDlgCtrl, LB_RESETCONTENT, 0, 0);
delete[] pIconContext->phIcons; delete[] pIconContext->phIcons;
// Store the paths // Store the path
StringCchCopyW(pIconContext->szPath, _countof(pIconContext->szPath), pszFile); StringCchCopyW(pIconContext->szPath, _countof(pIconContext->szPath), pszFile);
ExpandEnvironmentStringsW(pszFile, pIconContext->szExpandedPath, _countof(pIconContext->szExpandedPath)); ExpandEnvironmentStringsW(pszFile, szExpandedPath, _countof(szExpandedPath));
// Load the module if possible // Load the module if possible
HMODULE hLibrary = LoadLibraryExW(pIconContext->szExpandedPath, NULL, LOAD_LIBRARY_AS_DATAFILE); HMODULE hLibrary = LoadLibraryExW(szExpandedPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (pIconContext->hLibrary) if (pIconContext->hLibrary)
FreeLibrary(pIconContext->hLibrary); FreeLibrary(pIconContext->hLibrary);
pIconContext->hLibrary = hLibrary; pIconContext->hLibrary = hLibrary;
@ -110,10 +111,10 @@ DoLoadIcons(HWND hwndDlg, PICK_ICON_CONTEXT *pIconContext, LPCWSTR pszFile)
if (pIconContext->hLibrary) if (pIconContext->hLibrary)
{ {
// Load the icons from the module // Load the icons from the module
pIconContext->nIcons = ExtractIconExW(pIconContext->szExpandedPath, -1, NULL, NULL, 0); pIconContext->nIcons = ExtractIconExW(szExpandedPath, -1, NULL, NULL, 0);
pIconContext->phIcons = new HICON[pIconContext->nIcons]; pIconContext->phIcons = new HICON[pIconContext->nIcons];
if (ExtractIconExW(pIconContext->szExpandedPath, 0, pIconContext->phIcons, NULL, pIconContext->nIcons)) if (ExtractIconExW(szExpandedPath, 0, pIconContext->phIcons, NULL, pIconContext->nIcons))
{ {
EnumResourceNamesW(pIconContext->hLibrary, RT_GROUP_ICON, EnumPickIconResourceProc, (LPARAM)pIconContext); EnumResourceNamesW(pIconContext->hLibrary, RT_GROUP_ICON, EnumPickIconResourceProc, (LPARAM)pIconContext);
} }
@ -128,7 +129,7 @@ DoLoadIcons(HWND hwndDlg, PICK_ICON_CONTEXT *pIconContext, LPCWSTR pszFile)
pIconContext->nIcons = 1; pIconContext->nIcons = 1;
pIconContext->phIcons = new HICON[1]; pIconContext->phIcons = new HICON[1];
if (ExtractIconExW(pIconContext->szExpandedPath, 0, pIconContext->phIcons, NULL, pIconContext->nIcons)) if (ExtractIconExW(szExpandedPath, 0, pIconContext->phIcons, NULL, pIconContext->nIcons))
{ {
SendMessageW(pIconContext->hDlgCtrl, LB_ADDSTRING, 0, 0); SendMessageW(pIconContext->hDlgCtrl, LB_ADDSTRING, 0, 0);
} }
@ -138,8 +139,9 @@ DoLoadIcons(HWND hwndDlg, PICK_ICON_CONTEXT *pIconContext, LPCWSTR pszFile)
} }
} }
// Set the text // Set the text and reset the edit control's modification flag
SetDlgItemTextW(hwndDlg, IDC_EDIT_PATH, pIconContext->szPath); SetDlgItemTextW(hwndDlg, IDC_EDIT_PATH, pIconContext->szPath);
SendDlgItemMessage(hwndDlg, IDC_EDIT_PATH, EM_SETMODIFY, FALSE, 0);
if (pIconContext->nIcons == 0) if (pIconContext->nIcons == 0)
{ {
@ -147,12 +149,12 @@ DoLoadIcons(HWND hwndDlg, PICK_ICON_CONTEXT *pIconContext, LPCWSTR pszFile)
pIconContext->phIcons = NULL; pIconContext->phIcons = NULL;
} }
return pIconContext->nIcons > 0; return (pIconContext->nIcons > 0);
} }
static const LPCWSTR s_pszDefaultPath = L"%SystemRoot%\\system32\\shell32.dll"; static const LPCWSTR s_pszDefaultPath = L"%SystemRoot%\\system32\\shell32.dll";
static void NoIconsInFile(HWND hwndDlg, PICK_ICON_CONTEXT *pIconContext) static void NoIconsInFile(HWND hwndDlg, PPICK_ICON_CONTEXT pIconContext)
{ {
// Show an error message // Show an error message
CStringW strText, strTitle(MAKEINTRESOURCEW(IDS_PICK_ICON_TITLE)); CStringW strText, strTitle(MAKEINTRESOURCEW(IDS_PICK_ICON_TITLE));
@ -221,22 +223,45 @@ INT_PTR CALLBACK PickIconProc(
return TRUE; return TRUE;
} }
case WM_DESTROY:
{
DestroyIconList(pIconContext->hDlgCtrl, pIconContext);
delete[] pIconContext->phIcons;
if (pIconContext->hLibrary)
FreeLibrary(pIconContext->hLibrary);
break;
}
case WM_COMMAND: case WM_COMMAND:
switch(LOWORD(wParam)) switch(LOWORD(wParam))
{ {
case IDOK: case IDOK:
index = SendMessageW(pIconContext->hDlgCtrl, LB_GETCURSEL, 0, 0); {
pIconContext->Index = index; /* Check whether the path edit control has been modified; if so load the icons instead of validating */
if (SendDlgItemMessage(hwndDlg, IDC_EDIT_PATH, EM_GETMODIFY, 0, 0))
{
/* Reset the edit control's modification flag and retrieve the text */
SendDlgItemMessage(hwndDlg, IDC_EDIT_PATH, EM_SETMODIFY, FALSE, 0);
GetDlgItemTextW(hwndDlg, IDC_EDIT_PATH, szText, _countof(szText));
// Load the icons
if (!DoLoadIcons(hwndDlg, pIconContext, szText))
NoIconsInFile(hwndDlg, pIconContext);
// Set the selection
SendMessageW(pIconContext->hDlgCtrl, LB_SETCURSEL, 0, 0);
break;
}
/* The path edit control has not been modified, return the selection */
pIconContext->Index = (INT)SendMessageW(pIconContext->hDlgCtrl, LB_GETCURSEL, 0, 0);
GetDlgItemTextW(hwndDlg, IDC_EDIT_PATH, pIconContext->szPath, _countof(pIconContext->szPath)); GetDlgItemTextW(hwndDlg, IDC_EDIT_PATH, pIconContext->szPath, _countof(pIconContext->szPath));
ExpandEnvironmentStringsW(pIconContext->szPath, pIconContext->szExpandedPath, _countof(pIconContext->szExpandedPath));
DestroyIconList(pIconContext->hDlgCtrl, pIconContext);
delete[] pIconContext->phIcons;
EndDialog(hwndDlg, 1); EndDialog(hwndDlg, 1);
break; break;
}
case IDCANCEL: case IDCANCEL:
DestroyIconList(pIconContext->hDlgCtrl, pIconContext);
delete[] pIconContext->phIcons;
EndDialog(hwndDlg, 0); EndDialog(hwndDlg, 0);
break; break;
@ -293,9 +318,7 @@ INT_PTR CALLBACK PickIconProc(
{ {
lpdis = (LPDRAWITEMSTRUCT)lParam; lpdis = (LPDRAWITEMSTRUCT)lParam;
if (lpdis->itemID == (UINT)-1) if (lpdis->itemID == (UINT)-1)
{
break; break;
}
switch (lpdis->itemAction) switch (lpdis->itemAction)
{ {
case ODA_SELECT: case ODA_SELECT:
@ -331,17 +354,18 @@ BOOL WINAPI PickIconDlg(
INT* lpdwIconIndex) INT* lpdwIconIndex)
{ {
int res; int res;
WCHAR szExpandedPath[MAX_PATH];
// Initialize the dialog // Initialize the dialog
PICK_ICON_CONTEXT IconContext = { NULL }; PICK_ICON_CONTEXT IconContext = { NULL };
IconContext.Index = *lpdwIconIndex; IconContext.Index = *lpdwIconIndex;
StringCchCopyW(IconContext.szPath, _countof(IconContext.szPath), lpstrFile); StringCchCopyW(IconContext.szPath, _countof(IconContext.szPath), lpstrFile);
ExpandEnvironmentStringsW(lpstrFile, IconContext.szExpandedPath, _countof(IconContext.szExpandedPath)); ExpandEnvironmentStringsW(lpstrFile, szExpandedPath, _countof(szExpandedPath));
if (!IconContext.szExpandedPath[0] || if (!szExpandedPath[0] ||
GetFileAttributesW(IconContext.szExpandedPath) == INVALID_FILE_ATTRIBUTES) GetFileAttributesW(szExpandedPath) == INVALID_FILE_ATTRIBUTES)
{ {
if (IconContext.szExpandedPath[0]) if (szExpandedPath[0])
{ {
// No such file // No such file
CStringW strText, strTitle(MAKEINTRESOURCEW(IDS_PICK_ICON_TITLE)); CStringW strText, strTitle(MAKEINTRESOURCEW(IDS_PICK_ICON_TITLE));
@ -351,7 +375,6 @@ BOOL WINAPI PickIconDlg(
// Set the default value // Set the default value
StringCchCopyW(IconContext.szPath, _countof(IconContext.szPath), s_pszDefaultPath); StringCchCopyW(IconContext.szPath, _countof(IconContext.szPath), s_pszDefaultPath);
ExpandEnvironmentStringsW(s_pszDefaultPath, IconContext.szPath, _countof(IconContext.szPath));
} }
// Show the dialog // Show the dialog
@ -359,12 +382,10 @@ BOOL WINAPI PickIconDlg(
if (res) if (res)
{ {
// Store the selected icon // Store the selected icon
StringCchCopyW(lpstrFile, nMaxFile, IconContext.szExpandedPath); StringCchCopyW(lpstrFile, nMaxFile, IconContext.szPath);
*lpdwIconIndex = IconContext.Index; *lpdwIconIndex = IconContext.Index;
} }
if (IconContext.hLibrary)
FreeLibrary(IconContext.hLibrary);
return res; return res;
} }