pickicon.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 17k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //---------------------------------------------------------------------------
  2. //
  3. //      File: PICKICON.CPP
  4. //
  5. //      Support code for the Change Icon dialog.
  6. //
  7. //---------------------------------------------------------------------------
  8. #include <windows.h>
  9. #include <windowsx.h>
  10. #include "rc.h"
  11. #include "pickicon.h"
  12. #define MAX_ICONS   500             // that is a lot 'o icons
  13. #define ARRAYSIZE(s)                (sizeof(s) / sizeof((s)[0]))
  14. typedef struct
  15. {
  16.         LPSTR pszIconPath;              // input/output
  17.         int cbIconPath;                 // input
  18.         int iIconIndex;             // input/output
  19.         // private state variables
  20.         HWND hDlg;
  21.         BOOL fFirstPass;
  22.         char szPathField[MAX_PATH];
  23.         char szBuffer[MAX_PATH];
  24. } PICKICON_DATA, FAR *LPPICKICON_DATA;
  25. extern HINSTANCE g_hInst;
  26. // Checks if the file exists, if it doesn't it tries tagging on .exe and if that
  27. // fails it reports an error. The given path is environment expanded.  If it needs
  28. // to put up an error box, it changes the cursor back.  Path's assumed to be
  29. // MAXITEMPATHLEN long.  The main reason for moving this out of the DlgProc was
  30. // because we're running out of stack space on the call to the comm dlg.
  31. BOOL NEAR PASCAL IconFileExists( LPPICKICON_DATA lppid )
  32. {
  33. TCHAR szTitle[128];
  34. TCHAR szInvPath[ 64 ];
  35. TCHAR szText[MAX_PATH+40];
  36. TCHAR szPath[MAX_PATH];
  37. LPTSTR psz;
  38. DWORD dwRet;
  39.         if( lppid->szBuffer[0] == 0 )
  40.                 return FALSE;
  41.         // Use the Win32 version instead of the shell version.  The shell version
  42.         // is/was really only there for 16-bit apps.  (RickTu)
  43.         //
  44.         // DoEnvironmentSubst( lppid->szBuffer, sizeof(lppid->szBuffer) );
  45.         //
  46.         dwRet = ExpandEnvironmentStrings( lppid->szBuffer, szPath, MAX_PATH );
  47.         if (dwRet > 0 && dwRet <= MAX_PATH)
  48.         {
  49.             lstrcpy( lppid->szBuffer, szPath );
  50.         }
  51. //      PathUnquoteSpaces( lppid->szBuffer );   // JER
  52. //      if( PathResolve( lppid->szBuffer, NULL, PRF_VERIFYEXISTS | PRF_TRYPROGRAMEXTENSIONS ) ) // JER
  53.         if (SearchPath(NULL, lppid->szBuffer, NULL, ARRAYSIZE(szPath), szPath, &psz) != 0)
  54.                 return TRUE;
  55.         LoadString( g_hInst, IDS_BADPATHMSG, szTitle, ARRAYSIZE(szTitle) );
  56.         LoadString( g_hInst, IDS_INVALIDPATH, szInvPath, ARRAYSIZE(szInvPath) );
  57.         wsprintf( szText, szTitle, lppid->szBuffer );
  58.         GetWindowText( lppid->hDlg, szTitle, sizeof(szTitle) );
  59.         lstrcat( szTitle, szInvPath );
  60.         MessageBox( GetDesktopWindow(), szText, szTitle , MB_OK | MB_ICONEXCLAMATION );
  61.         return FALSE;
  62. }
  63. void NEAR PASCAL PutIconsInList( LPPICKICON_DATA lppid )
  64. {
  65. HICON  *rgIcons;
  66. int      iTempIcon;
  67. int  cIcons;
  68. HWND hDlg = lppid->hDlg;
  69. //HCURSOR hOldCursor;
  70.         SendDlgItemMessage( hDlg, IDD_ICON, LB_RESETCONTENT, 0, 0L );
  71.         GetDlgItemText( hDlg, IDD_PATH, lppid->szPathField, sizeof(lppid->szPathField) );
  72.         lstrcpy( lppid->szBuffer, lppid->szPathField );
  73.         if( !IconFileExists(lppid) )
  74.         {
  75.                 if( lppid->fFirstPass )
  76.                 {
  77.                         // Icon File doesn't exist, use progman
  78.                         lppid->fFirstPass = FALSE;  // Only do this bit once.
  79.                         GetModuleFileName( g_hInst, lppid->szBuffer, ARRAYSIZE(lppid->szBuffer) );
  80.                 }
  81.                 else
  82.                 {
  83.                         return;
  84.                 }
  85.         }
  86.         lstrcpy( lppid->szPathField, lppid->szBuffer );
  87.         SetDlgItemText( hDlg, IDD_PATH, lppid->szPathField );
  88. //      hOldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  89.         rgIcons = (HICON *)LocalAlloc(LPTR, MAX_ICONS*sizeof(HICON));
  90.         if( rgIcons != NULL )
  91.                 cIcons = (int)ExtractIconEx( lppid->szBuffer, 0, rgIcons, NULL, MAX_ICONS );
  92.         else
  93.                 cIcons = 0;
  94. //      SetCursor( hOldCursor );
  95.     if( !cIcons )
  96.     {
  97.         char szText[256];
  98.         char szTitle[40];
  99.                 GetWindowText( lppid->hDlg, szTitle, sizeof(szTitle) );
  100.                 if( lppid->fFirstPass )
  101.                 {
  102.                         lppid->fFirstPass = FALSE;  // Only do this bit once.
  103.                         LoadString( g_hInst, IDS_NOICONSMSG1, szText, 256 );
  104.                         MessageBox( GetDesktopWindow(), szText, szTitle, MB_OK | MB_ICONEXCLAMATION );
  105.                         // No icons here - change the path do somewhere where we
  106.                         // know there are icons. Get the path to progman.
  107. //                      GetModuleFileName( g_hInst, lppid->szPathField, sizeof(lppid->szPathField) );
  108.                         GetSystemDirectory( lppid->szPathField, sizeof(lppid->szPathField) );
  109.                         lstrcat( lppid->szPathField, "\shell32.dll" );
  110.                         SetDlgItemText( hDlg, IDD_PATH, lppid->szPathField );
  111.                         PutIconsInList( lppid );
  112.                 }
  113.                 else
  114.                 {
  115.                         LoadString( g_hInst, IDS_NOICONSMSG, szText, 256 );
  116.                         MessageBox( GetDesktopWindow(), szText, szTitle, MB_OK | MB_ICONEXCLAMATION );
  117.                         return;
  118.                 }
  119.         }
  120. //      hOldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  121.         SendDlgItemMessage( hDlg, IDD_ICON, WM_SETREDRAW, FALSE, 0L );
  122.     if( rgIcons )
  123.     {
  124.                 for( iTempIcon = 0; iTempIcon < cIcons; iTempIcon++ )
  125.                 {
  126.                         SendDlgItemMessage( hDlg, IDD_ICON, LB_ADDSTRING, 0, (LPARAM)(UINT)rgIcons[iTempIcon] );
  127.                 }
  128.                 LocalFree((HLOCAL)rgIcons);
  129.         }
  130.         if( SendDlgItemMessage( hDlg, IDD_ICON, LB_SETCURSEL, lppid->iIconIndex, 0L ) == LB_ERR )
  131.         {
  132.                 // select the first.
  133.                 SendDlgItemMessage( hDlg, IDD_ICON, LB_SETCURSEL, 0, 0L );
  134.         }
  135.         SendDlgItemMessage( hDlg, IDD_ICON, WM_SETREDRAW, TRUE, 0L );
  136.         InvalidateRect( GetDlgItem(hDlg, IDD_ICON), NULL, TRUE );
  137. //      SetCursor( hOldCursor );
  138. }
  139. void NEAR PASCAL InitPickIconDlg( HWND hDlg, LPPICKICON_DATA lppid )
  140. {
  141. RECT rc;
  142. UINT cy;
  143. HWND hwndIcons;
  144.         // init state variables
  145.         lppid->hDlg = hDlg;
  146.         lstrcpyn( lppid->szPathField, lppid->pszIconPath, sizeof(lppid->szPathField) );
  147.         // this first pass stuff is so that the first time something bogus happens
  148.         // (file not found, no icons) we give the user a list of icons from progman.
  149.         lppid->fFirstPass = TRUE;
  150.         // init the dialog controls
  151.         SetDlgItemText( hDlg, IDD_PATH, lppid->pszIconPath );
  152.         SendDlgItemMessage( hDlg, IDD_PATH, EM_LIMITTEXT, lppid->cbIconPath, 0L );
  153.         SendDlgItemMessage( hDlg, IDD_ICON, LB_SETCOLUMNWIDTH, GetSystemMetrics(SM_CXICON) + 12, 0L );
  154.         hwndIcons = GetDlgItem( hDlg, IDD_ICON );
  155.         // compute the height of the listbox based on icon dimensions
  156.         GetClientRect( hwndIcons, &rc );
  157.         cy = GetSystemMetrics( SM_CYICON ) + GetSystemMetrics( SM_CYHSCROLL ) + GetSystemMetrics( SM_CYEDGE ) * 3;
  158.         SetWindowPos( hwndIcons, NULL, 0, 0, rc.right, cy, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
  159.         // REVIEW, explicitly position this dialog?
  160.         cy = rc.bottom - cy;
  161.         GetWindowRect( hDlg, &rc );
  162.         rc.bottom -= rc.top;
  163.         rc.right -= rc.left;
  164.         rc.bottom = rc.bottom - cy;
  165.         SetWindowPos( hDlg, NULL, 0, 0, rc.right, rc.bottom, SWP_NOMOVE | SWP_NOACTIVATE );
  166.         PutIconsInList( lppid );
  167. }
  168. // call the common browse code for this
  169. BOOL NEAR PASCAL BrowseForIconFile( LPPICKICON_DATA lppid )
  170. {
  171. OPENFILENAME  ofn;
  172. CHAR szFilter[256] = TEXT("Icon Files*.ico;*.exe;*.dllPrograms (*.exe)*.exeLibraries (*.dll)*.dllIcons (*.ico)*.icoAll Files (*.*)*.*");
  173. char szTitle[40];
  174.         ZeroMemory(&ofn, sizeof(ofn));
  175.         if (LoadString( g_hInst, IDS_ICONFILTER, szFilter, ARRAYSIZE(szFilter) ) != 0) {
  176.             LPTSTR psz;
  177.             for( psz = szFilter; *psz != TEXT(''); psz++ ) {
  178. #ifdef DBCS
  179.                 if ( IsDBCSLeadByte(*psz) ) {
  180.                     psz = CharNext(psz) - 1;
  181.                     continue;
  182.                 }
  183. #endif
  184.                 if (*psz == TEXT('1')) {
  185.                     *psz = TEXT('');
  186.                 }
  187.             }
  188.         }
  189.         GetWindowText( lppid->hDlg, szTitle, sizeof(szTitle) );
  190.         GetDlgItemText( lppid->hDlg, IDD_PATH, lppid->szBuffer, sizeof(lppid->szBuffer) );
  191.         ofn.lStructSize                 = sizeof(OPENFILENAME);
  192.         ofn.hwndOwner                   = lppid->hDlg;
  193.         ofn.lpstrFilter                 = szFilter;
  194. //      ofn.lpstrCustomFilter   = (LPSTR)NULL;
  195. //      ofn.nMaxCustFilter              = 0L;
  196.         ofn.nFilterIndex                = 1L;
  197.         ofn.lpstrFile                   = lppid->szBuffer;
  198.         ofn.nMaxFile                    = sizeof(lppid->szBuffer);
  199. //      ofn.lpstrFileTitle              = (LPSTR)NULL;
  200. //      ofn.lpstrInitialDir             = NULL;
  201.         ofn.lpstrTitle                  = szTitle;
  202.         ofn.Flags                               = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
  203. //      ofn.nFileOffset                 = 0;
  204. //      ofn.nFileExtension              = 0;
  205. //      ofn.lCustData                   = 0;
  206.         if( GetOpenFileName( &ofn ) )
  207.         {
  208. //              PathQuoteSpaces( lppid->szBuffer );     // JER
  209.                 SetDlgItemText( lppid->hDlg, IDD_PATH, lppid->szBuffer );
  210.                 // Set default button to OK.
  211.                 SendMessage( lppid->hDlg, DM_SETDEFID, IDOK, 0 );
  212.                 return TRUE;
  213.         }
  214.         else
  215.                 return FALSE;
  216. }
  217. // test if the name field is different from the last file we looked at
  218. BOOL NEAR PASCAL NameChange( LPPICKICON_DATA lppid )
  219. {
  220.         GetDlgItemText( lppid->hDlg, IDD_PATH, lppid->szBuffer, sizeof(lppid->szBuffer) );
  221.         return lstrcmpi(lppid->szBuffer, lppid->szPathField);
  222. }
  223. //
  224. // dialog procedure for picking an icon (ala progman change icon)
  225. // uses DLG_PICKICON template
  226. //
  227. // in:
  228. //      pszIconFile
  229. //      cbIconFile
  230. //      iIndex
  231. //
  232. // out:
  233. //      pszIconFile
  234. //      iIndex
  235. //
  236. BOOL CALLBACK PickIconDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
  237. {
  238. LPPICKICON_DATA lppid = (LPPICKICON_DATA)GetWindowLong(hDlg, DWL_USER);
  239. // Array for context help:
  240. /*static DWORD aPickIconHelpIDs[] = {           // JER
  241.         IDD_PATH,   IDH_FCAB_LINK_ICONNAME,
  242.         IDD_ICON,   IDH_FCAB_LINK_CURRENT_ICON,
  243.         IDD_BROWSE, IDH_BROWSE,
  244.         0, 0
  245.         };
  246. */
  247.         switch( wMsg )
  248.         {
  249.                 case WM_INITDIALOG:
  250.                         SetWindowLong( hDlg, DWL_USER, lParam );
  251.                         InitPickIconDlg( hDlg, (LPPICKICON_DATA)lParam );
  252.                         break;
  253.                 case WM_COMMAND:
  254.                         switch( GET_WM_COMMAND_ID(wParam, lParam) )
  255.                         {
  256.                                 case IDHELP:        // BUGBUG, not wired
  257.                                         break;
  258.                                 case IDD_BROWSE:
  259.                                         if( BrowseForIconFile( lppid ) )
  260.                                                 PutIconsInList( lppid );
  261.                                         break;
  262.                                 case IDD_PATH:
  263.                                         if( NameChange( lppid ) )
  264.                                                 SendDlgItemMessage( hDlg, IDD_ICON, LB_SETCURSEL, (WPARAM)-1, 0 );
  265.                                         break;
  266.                                 case IDD_ICON:
  267.                                         if( NameChange( lppid ) )
  268.                                         {
  269.                                                 PutIconsInList( lppid );
  270.                                                 break;
  271.                                         }
  272.                                         if( GET_WM_COMMAND_CMD(wParam, lParam) != LBN_DBLCLK )
  273.                                                 break;
  274.                                         /*** FALL THRU on double click ***/
  275.                                 case IDOK:
  276.                                         if( NameChange( lppid ) )
  277.                                         {
  278.                                                 PutIconsInList( lppid );
  279.                                         }
  280.                                         else
  281.                                         {
  282.                                         int iIconIndex = (int)SendDlgItemMessage( hDlg, IDD_ICON, LB_GETCURSEL, 0, 0L );
  283.                                                 if( iIconIndex < 0 )
  284.                                                         iIconIndex = 0;
  285.                                                 lppid->iIconIndex = iIconIndex;
  286.                                                 lstrcpy( lppid->pszIconPath, lppid->szPathField );
  287.                                                 EndDialog( hDlg, TRUE );
  288.                                         }
  289.                                         break;
  290.                                 case IDCANCEL:
  291.                                         EndDialog( hDlg, FALSE );
  292.                                         break;
  293.                                 default:
  294.                                         return( FALSE );
  295.                         }
  296.                         break;
  297.                 // owner draw messages for icon listbox
  298.                 case WM_DRAWITEM:
  299.                         #define lpdi ((DRAWITEMSTRUCT FAR *)lParam)
  300.                         if( lpdi->itemState & ODS_SELECTED )
  301.                                 SetBkColor( lpdi->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
  302.                         else
  303.                                 SetBkColor( lpdi->hDC, GetSysColor( COLOR_WINDOW ) );
  304.                         /* repaint the selection state */
  305.                         ExtTextOut( lpdi->hDC, 0, 0, ETO_OPAQUE, &lpdi->rcItem, NULL, 0, NULL );
  306.                         /* draw the icon */
  307.                         if( (int)lpdi->itemID >= 0 )
  308.                                 DrawIcon(lpdi->hDC, (lpdi->rcItem.left + lpdi->rcItem.right - GetSystemMetrics(SM_CXICON)) / 2,
  309.                                         (lpdi->rcItem.bottom + lpdi->rcItem.top - GetSystemMetrics(SM_CYICON)) / 2, (HICON)lpdi->itemData);
  310.                         // InflateRect(&lpdi->rcItem, -1, -1);
  311.                         /* if it has the focus, draw the focus */
  312.                         if( lpdi->itemState & ODS_FOCUS )
  313.                                 DrawFocusRect( lpdi->hDC, &lpdi->rcItem );
  314.                         #undef lpdi
  315.                         break;
  316.                 case WM_MEASUREITEM:
  317.                         #define lpmi ((MEASUREITEMSTRUCT FAR *)lParam)
  318.                         lpmi->itemWidth = GetSystemMetrics( SM_CXICON ) + 12;
  319.                         lpmi->itemHeight = GetSystemMetrics( SM_CYICON ) + 4;
  320.                         #undef lpmi
  321.                         break;
  322.                 case WM_DELETEITEM:
  323.                         #define lpdi ((DELETEITEMSTRUCT FAR *)lParam)
  324.                         DestroyIcon( (HICON)lpdi->itemData );
  325.                         #undef lpdi
  326.                         break;
  327.                 case WM_HELP:
  328. //                      WinHelp( ((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (DWORD)(LPSTR) aPickIconHelpIDs ); // JER
  329.                         break;
  330.                 case WM_CONTEXTMENU:
  331. //                      WinHelp( (HWND) wParam, NULL, HELP_CONTEXTMENU, (DWORD)(LPVOID)aPickIconHelpIDs ); // JER
  332.                         break;
  333.                 default:
  334.                         return FALSE;
  335.         }
  336.         return TRUE;
  337. }
  338. // puts up the pick icon dialog
  339. int WINAPI PickIconDlg( HWND hwnd, LPSTR pszIconPath, UINT cbIconPath, int FAR *piIconIndex )
  340. {
  341. PICKICON_DATA *pid;
  342. int iResult;
  343.         // if we are coming up from a 16->32 thunk.  it is possible that SHELL32 will
  344.         // not be loaded in this context, so we will load ourself if we are not loaded.
  345. //      IsDllLoaded( g_hInst, "SHELL32" );      // JER
  346.         pid = (PICKICON_DATA *)LocalAlloc( LPTR, sizeof(PICKICON_DATA) );
  347.         if( pid == NULL )
  348.                 return 0;
  349.         pid->pszIconPath = pszIconPath;
  350.         pid->cbIconPath = cbIconPath;
  351.         pid->iIconIndex = *piIconIndex;
  352.         iResult = DialogBoxParam( g_hInst, MAKEINTRESOURCE(DLG_PICKICON), hwnd, (DLGPROC)PickIconDlgProc, (LPARAM)(LPPICKICON_DATA)pid );
  353.         *piIconIndex = pid->iIconIndex;
  354.         LocalFree( pid );
  355.         return iResult;
  356. }