문제

256 x 256 Windows Vista 아이콘을 만든 응용 프로그램이 있습니다.

응용 프로그램 아이콘으로 사용 된 ICO 파일에서 256x256 PNG 파일을 어떻게 사용하고 양식의 사진 상자에 표시 할 수 있는지 궁금했습니다.

vb.net을 사용하고 있지만 C#의 답변은 괜찮습니다. 나는 반사를 사용해야 할 수도 있다고 생각합니다.

Windows XP에서 이것이 가능하고 Windows Vista API가 필요할 수 있는지 확실하지 않습니다.

도움이 되었습니까?

해결책

오늘, 나는 아주 좋은 기능을했습니다 Vista 아이콘에서 256x256 비트 맵을 추출합니다.

당신처럼, Nathan W, 나는 그것을 사용하여 큰 아이콘을 "About"Box의 비트 맵으로 표시합니다. 예를 들어이 코드는 Vista 아이콘을 PNG 이미지로 가져오고 256x256 PictureBox에 표시합니다.

picboxAppLogo.Image = ExtractVistaIcon(myIcon);

이 함수는 아이콘 객체를 매개 변수로 간주합니다. 따라서 아이콘과 함께 사용할 수 있습니다. 자원에서, 파일, 스트림 등의. (EXE 아이콘 추출에 대해 아래를 읽으십시오).

그것은 계속됩니다 모든 OS, 그렇기 때문에 ~ 아니다 Win32 API를 사용하십시오 100% 관리 코드 :-)

// Based on: http://www.codeproject.com/KB/cs/IconExtractor.aspx
// And a hint from: http://www.codeproject.com/KB/cs/IconLib.aspx

Bitmap ExtractVistaIcon(Icon icoIcon)
{
    Bitmap bmpPngExtracted = null;
    try
    {
        byte[] srcBuf = null;
        using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
            { icoIcon.Save(stream); srcBuf = stream.ToArray(); }
        const int SizeICONDIR = 6;
        const int SizeICONDIRENTRY = 16;
        int iCount = BitConverter.ToInt16(srcBuf, 4);
        for (int iIndex=0; iIndex<iCount; iIndex++)
        {
            int iWidth  = srcBuf[SizeICONDIR + SizeICONDIRENTRY * iIndex];
            int iHeight = srcBuf[SizeICONDIR + SizeICONDIRENTRY * iIndex + 1];
            int iBitCount   = BitConverter.ToInt16(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 6);
            if (iWidth == 0 && iHeight == 0 && iBitCount == 32)
            {
                int iImageSize   = BitConverter.ToInt32(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 8);
                int iImageOffset = BitConverter.ToInt32(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 12);
                System.IO.MemoryStream destStream = new System.IO.MemoryStream();
                System.IO.BinaryWriter writer = new System.IO.BinaryWriter(destStream);
                writer.Write(srcBuf, iImageOffset, iImageSize);
                destStream.Seek(0, System.IO.SeekOrigin.Begin);
                bmpPngExtracted = new Bitmap(destStream); // This is PNG! :)
                break;
            }
        }
    }
    catch { return null; }
    return bmpPngExtracted;
}

중요한! 이 아이콘을 EXE 파일에서 직접로드하려면 캔트 사용 icon.extractAssociatedIcon (Application.ExecutablePath) 매개 변수로서 .NET 함수 extractAssociatedIcon ()가 너무 어리 석으므로 32x32 아이콘 만 추출합니다!

대신 전체를 더 잘 사용하는 것이 좋습니다 Iconextractor Tsuda Kageyu가 만든 클래스 (http://www.codeproject.com/kb/cs/iconextractor.aspx). 이 클래스를 약간 단순화하여 더 작게 만들 수 있습니다. 사용 Iconextractor 이 방법:

// Getting FILL icon set from EXE, and extracting 256x256 version for logo...
using (TKageyu.Utils.IconExtractor IconEx = new TKageyu.Utils.IconExtractor(Application.ExecutablePath))
{
    Icon icoAppIcon = IconEx.GetIcon(0); // Because standard System.Drawing.Icon.ExtractAssociatedIcon() returns ONLY 32x32.
    picboxAppLogo.Image = ExtractVistaIcon(icoAppIcon);
}

참고 : 나는 아직도 내 ExtractVistaicon () 기능을 사용하고 있습니다. Iconextractor 이 작업을 처리합니다. 먼저 IcOnextractor.spliticon (icoappicon)을 사용하여 모든 아이콘 형식을 추출한 다음 원하는 Vista -Icon을 얻으려면 정확한 256x256 아이콘 색인을 알아야합니다. 따라서 내 ExtractVistaicon ()을 사용하여 여기에 훨씬 빠르고 단순한 방법이 있습니다 :)

다른 팁

발견 된 정보 여기. 큰 Vista 아이콘을 얻으려면 Shell32의 Shgetfileinfo 메소드를 사용해야합니다. 아래의 관련 텍스트를 아래에 복사했습니다. 물론 파일 이름 변수를 "assembly.getexecutingAsembly (). 위치"로 바꾸려고합니다.

using System.Runtime.InteropServices;

검색하려는 아이콘의 크기를 지정하기 위해 ShgetFileInfo ()를 호출하는 데 사용할 수있는 상수도 있습니다.

// Constants that we need in the function call
private const int SHGFI_ICON = 0x100;
private const int SHGFI_SMALLICON = 0x1;
private const int SHGFI_LARGEICON = 0x0;

Shfileinfo 구조는 다양한 파일 정보를 처리 할 것이므로 그래픽 아이콘입니다.

// This structure will contain information about the file
public struct SHFILEINFO
{
    // Handle to the icon representing the file
    public IntPtr hIcon;
    // Index of the icon within the image list
    public int iIcon;
    // Various attributes of the file
    public uint dwAttributes;
    // Path to the file
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string szDisplayName;
    // File type
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
    public string szTypeName;
};

관리되지 않는 코드에 대한 최종 준비는 인기있는 Shell32.dll에 위치한 Shgetfileinfo의 서명을 정의하는 것입니다.

// The signature of SHGetFileInfo (located in Shell32.dll)
[DllImport("Shell32.dll")]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, uint uFlags);

이제 모든 것을 준비 했으므로 이제 기능을 호출하고 검색 한 아이콘을 표시 할 때입니다. 검색 될 객체는 아이콘 유형 (System.Drawing.icon)이지만 그림 상자에 표시하여 TobitMap () 메소드를 사용하여 아이콘을 비트 맵으로 변환하려고합니다.

그러나 먼저 양식에 추가 해야하는 3 가지 컨트롤, 텍스트 속성에 대한 "아이콘 추출", 그림 상자 인 PiciconLarge 인 PiciconLarge가있는 버튼 Btnextract가 있습니다. 그것은 우리가 두 개의 아이콘 크기를 얻을 것이기 때문입니다. 이제 Visual Studio의 디자인보기에서 btnextract를 두 번 클릭하면 클릭 이벤트에 도달합니다. 내부에는 나머지 코드가 있습니다.

private void btnExtract_Click(object sender, EventArgs e)
{
    // Will store a handle to the small icon
    IntPtr hImgSmall;
    // Will store a handle to the large icon
    IntPtr hImgLarge;

    SHFILEINFO shinfo = new SHFILEINFO();

    // Open the file that we wish to extract the icon from
    if(openFile.ShowDialog() == DialogResult.OK)
    {
        // Store the file name
        string FileName = openFile.FileName;
        // Sore the icon in this myIcon object
        System.Drawing.Icon myIcon;

        // Get a handle to the small icon
        hImgSmall = SHGetFileInfo(FileName, 0, ref shinfo, Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_SMALLICON);
        // Get the small icon from the handle
        myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
        // Display the small icon
        picIconSmall.Image = myIcon.ToBitmap();

        // Get a handle to the large icon
        hImgLarge = SHGetFileInfo(FileName, 0, ref shinfo, Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_LARGEICON);
        // Get the large icon from the handle
        myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
        // Display the large icon
        picIconLarge.Image = myIcon.ToBitmap();

    }
}

업데이트 : 더 많은 정보를 찾았습니다 여기.

위의 답변 중 어느 것도 Vista 아이콘을 처리하지 않습니다 - 소형 (32x32) 및 큰 (48x48)

Vista 아이콘을 처리하는 라이브러리가 있습니다 여기

... 듀얼 PNG 알파 채널 형식으로 인해 상당히 복잡해 보입니다.

VB .NET에서 간결한 답변을 만들려고하지만 시간이 걸릴 수 있습니다.

사진 상자의 ICO 파일에서 256*256*32 이미지를 표시하는 것과 동일한 문제가 있기 때문에 SAL80의 솔루션이 가장 효율적인 솔루션 (및 거의 작동)을 발견했습니다. 그러나 원래 코드는 BMP로 저장된 이미지를 지원하지 않습니다 (큰 아이콘은 일반적으로 PNG이지만 항상 그런 것은 아닙니다).

다음은 향후 참조를위한 내 버전입니다. 비트 맵을 만들기위한 코드도 약간 더 간단합니다.

    /// <summary>
    /// Extracts  the large Vista icon from a ICO file 
    /// </summary>
    /// <param name="srcBuf">Bytes of the ICO file</param>
    /// <returns>The large icon or null if not found</returns>
    private static Bitmap ExtractVistaIcon(byte[] srcBuf)
    {
        const int SizeIcondir = 6;
        const int SizeIcondirentry = 16;

        // Read image count from ICO header
        int iCount = BitConverter.ToInt16(srcBuf, 4);

        // Search for a large icon
        for (int iIndex = 0; iIndex < iCount; iIndex++)
        {
            // Read image information from image directory entry
            int iWidth = srcBuf[SizeIcondir + SizeIcondirentry * iIndex];
            int iHeight = srcBuf[SizeIcondir + SizeIcondirentry * iIndex + 1];
            int iBitCount = BitConverter.ToInt16(srcBuf, SizeIcondir + SizeIcondirentry * iIndex + 6);

            // If Vista icon
            if (iWidth == 0 && iHeight == 0 && iBitCount == 32)
            {
                // Get image data position and length from directory
                int iImageSize = BitConverter.ToInt32(srcBuf, SizeIcondir + SizeIcondirentry * iIndex + 8);
                int iImageOffset = BitConverter.ToInt32(srcBuf, SizeIcondir + SizeIcondirentry * iIndex + 12);

                // Check if the image has a PNG signature
                if (srcBuf[iImageOffset] == 0x89 && srcBuf[iImageOffset+1] == 0x50 && srcBuf[iImageOffset+2] == 0x4E && srcBuf[iImageOffset+3] == 0x47)
                {
                    // the PNG data is stored directly in the file
                    var x = new MemoryStream(srcBuf, iImageOffset, iImageSize, false, false);
                    return new Bitmap(x); 
                }

                // Else it's bitmap data with a partial bitmap header
                // Read size from partial header
                int w = BitConverter.ToInt32(srcBuf, iImageOffset + 4);
                // Create a full header
                var b = new Bitmap(w, w, PixelFormat.Format32bppArgb);
                // Copy bits into bitmap
                BitmapData bmpData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.WriteOnly, b.PixelFormat);
                Marshal.Copy(srcBuf, iImageOffset + Marshal.SizeOf(typeof(Bitmapinfoheader)), bmpData.Scan0, b.Width*b.Height*4);
                b.UnlockBits(bmpData);
                return b;
            }
        }

        return null;
    }

창문을 살펴보십시오 아이콘 기능 사용 가능합니다. 또한 있습니다 개요 다른 아이콘 크기에 대한 쿼리를 언급합니다. 거기에 dream.in.code C#에서 API를 사용하기위한 포럼 스레드 및 pinvoke.net 참조.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top