448 lines
16 KiB
C++
448 lines
16 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
// File: PICKICON.CPP
|
|
//
|
|
// Support code for the Change Icon dialog.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include "rc.h"
|
|
#include "pickicon.h"
|
|
|
|
#define MAX_ICONS 500 // that is a lot 'o icons
|
|
|
|
#define ARRAYSIZE(s) (sizeof(s) / sizeof((s)[0]))
|
|
|
|
typedef struct
|
|
{
|
|
LPSTR pszIconPath; // input/output
|
|
int cbIconPath; // input
|
|
int iIconIndex; // input/output
|
|
// private state variables
|
|
HWND hDlg;
|
|
BOOL fFirstPass;
|
|
char szPathField[MAX_PATH];
|
|
char szBuffer[MAX_PATH];
|
|
} PICKICON_DATA, FAR *LPPICKICON_DATA;
|
|
|
|
extern HINSTANCE g_hInst;
|
|
|
|
// Checks if the file exists, if it doesn't it tries tagging on .exe and if that
|
|
// fails it reports an error. The given path is environment expanded. If it needs
|
|
// to put up an error box, it changes the cursor back. Path's assumed to be
|
|
// MAXITEMPATHLEN long. The main reason for moving this out of the DlgProc was
|
|
// because we're running out of stack space on the call to the comm dlg.
|
|
BOOL NEAR PASCAL IconFileExists( LPPICKICON_DATA lppid )
|
|
{
|
|
TCHAR szTitle[128];
|
|
TCHAR szInvPath[ 64 ];
|
|
TCHAR szText[MAX_PATH+40];
|
|
TCHAR szPath[MAX_PATH];
|
|
LPTSTR psz;
|
|
DWORD dwRet;
|
|
|
|
if( lppid->szBuffer[0] == 0 )
|
|
return FALSE;
|
|
|
|
// Use the Win32 version instead of the shell version. The shell version
|
|
// is/was really only there for 16-bit apps. (RickTu)
|
|
//
|
|
// DoEnvironmentSubst( lppid->szBuffer, sizeof(lppid->szBuffer) );
|
|
//
|
|
|
|
dwRet = ExpandEnvironmentStrings( lppid->szBuffer, szPath, MAX_PATH );
|
|
if (dwRet > 0 && dwRet <= MAX_PATH)
|
|
{
|
|
lstrcpy( lppid->szBuffer, szPath );
|
|
}
|
|
|
|
// PathUnquoteSpaces( lppid->szBuffer ); // JER
|
|
|
|
// if( PathResolve( lppid->szBuffer, NULL, PRF_VERIFYEXISTS | PRF_TRYPROGRAMEXTENSIONS ) ) // JER
|
|
if (SearchPath(NULL, lppid->szBuffer, NULL, ARRAYSIZE(szPath), szPath, &psz) != 0)
|
|
return TRUE;
|
|
|
|
LoadString( g_hInst, IDS_BADPATHMSG, szTitle, ARRAYSIZE(szTitle) );
|
|
LoadString( g_hInst, IDS_INVALIDPATH, szInvPath, ARRAYSIZE(szInvPath) );
|
|
wsprintf( szText, szTitle, lppid->szBuffer );
|
|
GetWindowText( lppid->hDlg, szTitle, sizeof(szTitle) );
|
|
lstrcat( szTitle, szInvPath );
|
|
MessageBox( GetDesktopWindow(), szText, szTitle , MB_OK | MB_ICONEXCLAMATION );
|
|
return FALSE;
|
|
}
|
|
|
|
void NEAR PASCAL PutIconsInList( LPPICKICON_DATA lppid )
|
|
{
|
|
HICON *rgIcons;
|
|
int iTempIcon;
|
|
int cIcons;
|
|
HWND hDlg = lppid->hDlg;
|
|
//HCURSOR hOldCursor;
|
|
|
|
SendDlgItemMessage( hDlg, IDD_ICON, LB_RESETCONTENT, 0, 0L );
|
|
|
|
GetDlgItemText( hDlg, IDD_PATH, lppid->szPathField, sizeof(lppid->szPathField) );
|
|
|
|
lstrcpy( lppid->szBuffer, lppid->szPathField );
|
|
|
|
if( !IconFileExists(lppid) )
|
|
{
|
|
if( lppid->fFirstPass )
|
|
{
|
|
// Icon File doesn't exist, use progman
|
|
lppid->fFirstPass = FALSE; // Only do this bit once.
|
|
GetModuleFileName( g_hInst, lppid->szBuffer, ARRAYSIZE(lppid->szBuffer) );
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
lstrcpy( lppid->szPathField, lppid->szBuffer );
|
|
SetDlgItemText( hDlg, IDD_PATH, lppid->szPathField );
|
|
|
|
// hOldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
|
|
|
|
rgIcons = (HICON *)LocalAlloc(LPTR, MAX_ICONS*sizeof(HICON));
|
|
|
|
if( rgIcons != NULL )
|
|
cIcons = (int)ExtractIconEx( lppid->szBuffer, 0, rgIcons, NULL, MAX_ICONS );
|
|
else
|
|
cIcons = 0;
|
|
|
|
// SetCursor( hOldCursor );
|
|
if( !cIcons )
|
|
{
|
|
char szText[256];
|
|
char szTitle[40];
|
|
|
|
GetWindowText( lppid->hDlg, szTitle, sizeof(szTitle) );
|
|
if( lppid->fFirstPass )
|
|
{
|
|
lppid->fFirstPass = FALSE; // Only do this bit once.
|
|
LoadString( g_hInst, IDS_NOICONSMSG1, szText, 256 );
|
|
MessageBox( GetDesktopWindow(), szText, szTitle, MB_OK | MB_ICONEXCLAMATION );
|
|
|
|
// No icons here - change the path do somewhere where we
|
|
// know there are icons. Get the path to progman.
|
|
// GetModuleFileName( g_hInst, lppid->szPathField, sizeof(lppid->szPathField) );
|
|
GetSystemDirectory( lppid->szPathField, sizeof(lppid->szPathField) );
|
|
lstrcat( lppid->szPathField, "\\shell32.dll" );
|
|
SetDlgItemText( hDlg, IDD_PATH, lppid->szPathField );
|
|
PutIconsInList( lppid );
|
|
}
|
|
else
|
|
{
|
|
LoadString( g_hInst, IDS_NOICONSMSG, szText, 256 );
|
|
MessageBox( GetDesktopWindow(), szText, szTitle, MB_OK | MB_ICONEXCLAMATION );
|
|
return;
|
|
}
|
|
}
|
|
// hOldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
|
|
|
|
SendDlgItemMessage( hDlg, IDD_ICON, WM_SETREDRAW, FALSE, 0L );
|
|
|
|
if( rgIcons )
|
|
{
|
|
for( iTempIcon = 0; iTempIcon < cIcons; iTempIcon++ )
|
|
{
|
|
SendDlgItemMessage( hDlg, IDD_ICON, LB_ADDSTRING, 0, (LPARAM)(UINT)rgIcons[iTempIcon] );
|
|
}
|
|
LocalFree((HLOCAL)rgIcons);
|
|
}
|
|
|
|
if( SendDlgItemMessage( hDlg, IDD_ICON, LB_SETCURSEL, lppid->iIconIndex, 0L ) == LB_ERR )
|
|
{
|
|
// select the first.
|
|
SendDlgItemMessage( hDlg, IDD_ICON, LB_SETCURSEL, 0, 0L );
|
|
}
|
|
|
|
SendDlgItemMessage( hDlg, IDD_ICON, WM_SETREDRAW, TRUE, 0L );
|
|
InvalidateRect( GetDlgItem(hDlg, IDD_ICON), NULL, TRUE );
|
|
|
|
// SetCursor( hOldCursor );
|
|
}
|
|
|
|
void NEAR PASCAL InitPickIconDlg( HWND hDlg, LPPICKICON_DATA lppid )
|
|
{
|
|
RECT rc;
|
|
UINT cy;
|
|
HWND hwndIcons;
|
|
|
|
// init state variables
|
|
lppid->hDlg = hDlg;
|
|
lstrcpyn( lppid->szPathField, lppid->pszIconPath, sizeof(lppid->szPathField) );
|
|
|
|
// this first pass stuff is so that the first time something bogus happens
|
|
// (file not found, no icons) we give the user a list of icons from progman.
|
|
lppid->fFirstPass = TRUE;
|
|
|
|
// init the dialog controls
|
|
SetDlgItemText( hDlg, IDD_PATH, lppid->pszIconPath );
|
|
SendDlgItemMessage( hDlg, IDD_PATH, EM_LIMITTEXT, lppid->cbIconPath, 0L );
|
|
|
|
SendDlgItemMessage( hDlg, IDD_ICON, LB_SETCOLUMNWIDTH, GetSystemMetrics(SM_CXICON) + 12, 0L );
|
|
|
|
hwndIcons = GetDlgItem( hDlg, IDD_ICON );
|
|
|
|
// compute the height of the listbox based on icon dimensions
|
|
GetClientRect( hwndIcons, &rc );
|
|
|
|
cy = GetSystemMetrics( SM_CYICON ) + GetSystemMetrics( SM_CYHSCROLL ) + GetSystemMetrics( SM_CYEDGE ) * 3;
|
|
|
|
SetWindowPos( hwndIcons, NULL, 0, 0, rc.right, cy, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
|
|
|
|
// REVIEW, explicitly position this dialog?
|
|
|
|
cy = rc.bottom - cy;
|
|
|
|
GetWindowRect( hDlg, &rc );
|
|
rc.bottom -= rc.top;
|
|
rc.right -= rc.left;
|
|
rc.bottom = rc.bottom - cy;
|
|
|
|
SetWindowPos( hDlg, NULL, 0, 0, rc.right, rc.bottom, SWP_NOMOVE | SWP_NOACTIVATE );
|
|
|
|
PutIconsInList( lppid );
|
|
}
|
|
|
|
// call the common browse code for this
|
|
BOOL NEAR PASCAL BrowseForIconFile( LPPICKICON_DATA lppid )
|
|
{
|
|
OPENFILENAME ofn;
|
|
CHAR szFilter[256] = TEXT("Icon Files\0*.ico;*.exe;*.dll\0Programs (*.exe)\0*.exe\0Libraries (*.dll)\0*.dll\0Icons (*.ico)\0*.ico\0All Files (*.*)\0*.*\0\0");
|
|
char szTitle[40];
|
|
|
|
ZeroMemory(&ofn, sizeof(ofn));
|
|
|
|
if (LoadString( g_hInst, IDS_ICONFILTER, szFilter, ARRAYSIZE(szFilter) ) != 0) {
|
|
LPTSTR psz;
|
|
|
|
for( psz = szFilter; *psz != TEXT('\0'); psz++ ) {
|
|
#ifdef DBCS
|
|
if ( IsDBCSLeadByte(*psz) ) {
|
|
psz = CharNext(psz) - 1;
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
if (*psz == TEXT('\1')) {
|
|
*psz = TEXT('\0');
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
GetWindowText( lppid->hDlg, szTitle, sizeof(szTitle) );
|
|
GetDlgItemText( lppid->hDlg, IDD_PATH, lppid->szBuffer, sizeof(lppid->szBuffer) );
|
|
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.hwndOwner = lppid->hDlg;
|
|
ofn.lpstrFilter = szFilter;
|
|
// ofn.lpstrCustomFilter = (LPSTR)NULL;
|
|
// ofn.nMaxCustFilter = 0L;
|
|
ofn.nFilterIndex = 1L;
|
|
ofn.lpstrFile = lppid->szBuffer;
|
|
ofn.nMaxFile = sizeof(lppid->szBuffer);
|
|
// ofn.lpstrFileTitle = (LPSTR)NULL;
|
|
// ofn.lpstrInitialDir = NULL;
|
|
ofn.lpstrTitle = szTitle;
|
|
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
|
|
// ofn.nFileOffset = 0;
|
|
// ofn.nFileExtension = 0;
|
|
// ofn.lCustData = 0;
|
|
|
|
if( GetOpenFileName( &ofn ) )
|
|
{
|
|
// PathQuoteSpaces( lppid->szBuffer ); // JER
|
|
SetDlgItemText( lppid->hDlg, IDD_PATH, lppid->szBuffer );
|
|
// Set default button to OK.
|
|
SendMessage( lppid->hDlg, DM_SETDEFID, IDOK, 0 );
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
// test if the name field is different from the last file we looked at
|
|
BOOL NEAR PASCAL NameChange( LPPICKICON_DATA lppid )
|
|
{
|
|
GetDlgItemText( lppid->hDlg, IDD_PATH, lppid->szBuffer, sizeof(lppid->szBuffer) );
|
|
return lstrcmpi(lppid->szBuffer, lppid->szPathField);
|
|
}
|
|
|
|
|
|
//
|
|
// dialog procedure for picking an icon (ala progman change icon)
|
|
// uses DLG_PICKICON template
|
|
//
|
|
// in:
|
|
// pszIconFile
|
|
// cbIconFile
|
|
// iIndex
|
|
//
|
|
// out:
|
|
// pszIconFile
|
|
// iIndex
|
|
//
|
|
INT_PTR CALLBACK PickIconDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
LPPICKICON_DATA lppid = (LPPICKICON_DATA)GetWindowLong(hDlg, DWL_USER);
|
|
|
|
// Array for context help:
|
|
/*static DWORD aPickIconHelpIDs[] = { // JER
|
|
IDD_PATH, IDH_FCAB_LINK_ICONNAME,
|
|
IDD_ICON, IDH_FCAB_LINK_CURRENT_ICON,
|
|
IDD_BROWSE, IDH_BROWSE,
|
|
0, 0
|
|
};
|
|
*/
|
|
switch( wMsg )
|
|
{
|
|
case WM_INITDIALOG:
|
|
SetWindowLong( hDlg, DWL_USER, lParam );
|
|
InitPickIconDlg( hDlg, (LPPICKICON_DATA)lParam );
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch( GET_WM_COMMAND_ID(wParam, lParam) )
|
|
{
|
|
case IDHELP: // not wired
|
|
break;
|
|
|
|
case IDD_BROWSE:
|
|
if( BrowseForIconFile( lppid ) )
|
|
PutIconsInList( lppid );
|
|
break;
|
|
|
|
case IDD_PATH:
|
|
if( NameChange( lppid ) )
|
|
SendDlgItemMessage( hDlg, IDD_ICON, LB_SETCURSEL, (WPARAM)-1, 0 );
|
|
break;
|
|
|
|
case IDD_ICON:
|
|
if( NameChange( lppid ) )
|
|
{
|
|
PutIconsInList( lppid );
|
|
break;
|
|
}
|
|
if( GET_WM_COMMAND_CMD(wParam, lParam) != LBN_DBLCLK )
|
|
break;
|
|
|
|
/*** FALL THRU on double click ***/
|
|
|
|
case IDOK:
|
|
if( NameChange( lppid ) )
|
|
{
|
|
PutIconsInList( lppid );
|
|
}
|
|
else
|
|
{
|
|
int iIconIndex = (int)SendDlgItemMessage( hDlg, IDD_ICON, LB_GETCURSEL, 0, 0L );
|
|
if( iIconIndex < 0 )
|
|
iIconIndex = 0;
|
|
lppid->iIconIndex = iIconIndex;
|
|
lstrcpy( lppid->pszIconPath, lppid->szPathField );
|
|
|
|
EndDialog( hDlg, TRUE );
|
|
}
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
EndDialog( hDlg, FALSE );
|
|
break;
|
|
|
|
default:
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
// owner draw messages for icon listbox
|
|
case WM_DRAWITEM:
|
|
#define lpdi ((DRAWITEMSTRUCT FAR *)lParam)
|
|
|
|
if( lpdi->itemState & ODS_SELECTED )
|
|
SetBkColor( lpdi->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
|
|
else
|
|
SetBkColor( lpdi->hDC, GetSysColor( COLOR_WINDOW ) );
|
|
|
|
/* repaint the selection state */
|
|
ExtTextOut( lpdi->hDC, 0, 0, ETO_OPAQUE, &lpdi->rcItem, NULL, 0, NULL );
|
|
|
|
/* draw the icon */
|
|
if( (int)lpdi->itemID >= 0 )
|
|
DrawIcon(lpdi->hDC, (lpdi->rcItem.left + lpdi->rcItem.right - GetSystemMetrics(SM_CXICON)) / 2,
|
|
(lpdi->rcItem.bottom + lpdi->rcItem.top - GetSystemMetrics(SM_CYICON)) / 2, (HICON)lpdi->itemData);
|
|
|
|
// InflateRect(&lpdi->rcItem, -1, -1);
|
|
|
|
/* if it has the focus, draw the focus */
|
|
if( lpdi->itemState & ODS_FOCUS )
|
|
DrawFocusRect( lpdi->hDC, &lpdi->rcItem );
|
|
|
|
#undef lpdi
|
|
break;
|
|
|
|
case WM_MEASUREITEM:
|
|
#define lpmi ((MEASUREITEMSTRUCT FAR *)lParam)
|
|
|
|
lpmi->itemWidth = GetSystemMetrics( SM_CXICON ) + 12;
|
|
lpmi->itemHeight = GetSystemMetrics( SM_CYICON ) + 4;
|
|
|
|
#undef lpmi
|
|
break;
|
|
|
|
case WM_DELETEITEM:
|
|
#define lpdi ((DELETEITEMSTRUCT FAR *)lParam)
|
|
|
|
DestroyIcon( (HICON)lpdi->itemData );
|
|
|
|
#undef lpdi
|
|
break;
|
|
|
|
case WM_HELP:
|
|
// WinHelp( ((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (DWORD)(LPSTR) aPickIconHelpIDs ); // JER
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
// WinHelp( (HWND) wParam, NULL, HELP_CONTEXTMENU, (DWORD)(LPVOID)aPickIconHelpIDs ); // JER
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// puts up the pick icon dialog
|
|
int WINAPI PickIconDlg( HWND hwnd, LPSTR pszIconPath, UINT cbIconPath, int FAR *piIconIndex )
|
|
{
|
|
PICKICON_DATA *pid;
|
|
int iResult;
|
|
|
|
// if we are coming up from a 16->32 thunk. it is possible that SHELL32 will
|
|
// not be loaded in this context, so we will load ourself if we are not loaded.
|
|
// IsDllLoaded( g_hInst, "SHELL32" ); // JER
|
|
|
|
pid = (PICKICON_DATA *)LocalAlloc( LPTR, sizeof(PICKICON_DATA) );
|
|
|
|
if( pid == NULL )
|
|
return 0;
|
|
|
|
pid->pszIconPath = pszIconPath;
|
|
pid->cbIconPath = cbIconPath;
|
|
pid->iIconIndex = *piIconIndex;
|
|
|
|
iResult = DialogBoxParam( g_hInst, MAKEINTRESOURCE(DLG_PICKICON), hwnd, PickIconDlgProc, (LPARAM)(LPPICKICON_DATA)pid );
|
|
|
|
*piIconIndex = pid->iIconIndex;
|
|
|
|
LocalFree( pid );
|
|
|
|
return iResult;
|
|
}
|