public float GetHeight() { IntPtr screenDC = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef); try { using (Graphics graphics = Graphics.FromHdcInternal(screenDC)) { return(GetHeight(graphics)); } } finally { UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, screenDC)); } }
/// <summary> /// Creates a <see cref='System.Drawing.Font'/> from the specified Windows handle. /// </summary> public static Font FromHfont(IntPtr hfont) { var lf = new SafeNativeMethods.LOGFONT(); SafeNativeMethods.GetObject(new HandleRef(null, hfont), lf); IntPtr screenDC = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef); try { return(FromLogFont(lf, screenDC)); } finally { UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, screenDC)); } }
// Operations /// <include file='doc\Font.uex' path='docs/doc[@for="Font.ToLogFont"]/*' /> /// <devdoc> /// <para>[To be supplied.]</para> /// </devdoc> public void ToLogFont(object logFont) { IntPtr screenDC = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef); try { Graphics graphics = Graphics.FromHdcInternal(screenDC); try { this.ToLogFont(logFont, graphics); } finally { graphics.Dispose(); } } finally { UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, screenDC)); } }
/// <include file='doc\Font.uex' path='docs/doc[@for="Font.FromHfont"]/*' /> /// <devdoc> /// Creates a <see cref='System.Drawing.Font'/> from the specified Windows /// handle. /// </devdoc> public static Font FromHfont(IntPtr hfont) { IntSecurity.ObjectFromWin32Handle.Demand(); SafeNativeMethods.LOGFONT lf = new SafeNativeMethods.LOGFONT(); SafeNativeMethods.GetObject(new HandleRef(null, hfont), lf); Font result; IntPtr screenDC = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef); try { result = Font.FromLogFont(lf, screenDC); } finally { UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, screenDC)); } return(result); }
/// <include file='doc\Icon.uex' path='docs/doc[@for="Icon.Initialize"]/*' /> /// <devdoc> /// Initializes this Image object. This is identical to calling the image's /// constructor with picture, but this allows non-constructor initialization, /// which may be necessary in some instances. /// </devdoc> private unsafe void Initialize(int width, int height) { if (_iconData == null || _handle != IntPtr.Zero) { throw new InvalidOperationException(SR.Format(SR.IllegalState, GetType().Name)); } int icondirSize = Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIR)); if (_iconData.Length < icondirSize) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", "Icon")); } // Get the correct width / height // if (width == 0) { width = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CXICON); } if (height == 0) { height = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CYICON); } if (s_bitDepth == 0) { IntPtr dc = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef); s_bitDepth = UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), SafeNativeMethods.BITSPIXEL); s_bitDepth *= UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), SafeNativeMethods.PLANES); UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, dc)); // If the bitdepth is 8, make it 4. Why? Because windows does not // choose a 256 color icon if the display is running in 256 color mode // because of palette flicker. // if (s_bitDepth == 8) { s_bitDepth = 4; } } fixed(byte *pbIconData = _iconData) { short idReserved = GetShort(pbIconData); short idType = GetShort(pbIconData + 2); short idCount = GetShort(pbIconData + 4); if (idReserved != 0 || idType != 1 || idCount == 0) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", "Icon")); } SafeNativeMethods.ICONDIRENTRY EntryTemp; byte bestWidth = 0; byte bestHeight = 0; //int bestBitDepth = 0; byte *pbIconDirEntry = unchecked (pbIconData + 6); int icondirEntrySize = Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIRENTRY)); Debug.Assert((icondirEntrySize * (idCount - 1) + icondirSize) <= _iconData.Length, "Illegal number of ICONDIRENTRIES"); if ((icondirEntrySize * (idCount - 1) + icondirSize) > _iconData.Length) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", "Icon")); } for (int i = 0; i < idCount; i++) { // // Fill in EntryTemp // EntryTemp.bWidth = pbIconDirEntry[0]; EntryTemp.bHeight = pbIconDirEntry[1]; EntryTemp.bColorCount = pbIconDirEntry[2]; EntryTemp.bReserved = pbIconDirEntry[3]; EntryTemp.wPlanes = GetShort(pbIconDirEntry + 4); EntryTemp.wBitCount = GetShort(pbIconDirEntry + 6); EntryTemp.dwBytesInRes = GetInt(pbIconDirEntry + 8); EntryTemp.dwImageOffset = GetInt(pbIconDirEntry + 12); // // // bool fUpdateBestFit = false; int iconBitDepth = 0; if (EntryTemp.bColorCount != 0) { iconBitDepth = 4; if (EntryTemp.bColorCount < 0x10) { iconBitDepth = 1; } } else { iconBitDepth = EntryTemp.wBitCount; } // it looks like if nothing is specified at this point, bpp is 8... if (iconBitDepth == 0) { iconBitDepth = 8; } // Windows rules for specifing an icon: // // 1. The icon with the closest size match. // 2. For matching sizes, the image with the closest bit depth. // 3. If there is no color depth match, the icon with the closest color depth that does not exceed the display. // 4. If all icon color depth > display, lowest color depth is chosen. // 5. color depth of > 8bpp are all equal. // 6. Never choose an 8bpp icon on an 8bpp system. // if (0 == _bestBytesInRes) { fUpdateBestFit = true; } else { int bestDelta = Math.Abs(bestWidth - width) + Math.Abs(bestHeight - height); int thisDelta = Math.Abs(EntryTemp.bWidth - width) + Math.Abs(EntryTemp.bHeight - height); if ((thisDelta < bestDelta) || (thisDelta == bestDelta && (iconBitDepth <= s_bitDepth && iconBitDepth > _bestBitDepth || _bestBitDepth > s_bitDepth && iconBitDepth < _bestBitDepth))) { fUpdateBestFit = true; } } if (fUpdateBestFit) { bestWidth = EntryTemp.bWidth; bestHeight = EntryTemp.bHeight; _bestImageOffset = EntryTemp.dwImageOffset; _bestBytesInRes = EntryTemp.dwBytesInRes; _bestBitDepth = iconBitDepth; } pbIconDirEntry += icondirEntrySize; } Debug.Assert(_bestImageOffset >= 0 && _bestBytesInRes >= 0 && (_bestImageOffset + _bestBytesInRes) <= _iconData.Length, "Illegal offset/length for the Icon data"); if (_bestImageOffset < 0) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", "Icon")); } if (_bestBytesInRes < 0) { throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER); } int endOffset; try { endOffset = checked (_bestImageOffset + _bestBytesInRes); } catch (OverflowException) { throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER); } if (endOffset > _iconData.Length) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", "Icon")); } // See DevDivBugs 17509. Copying bytes into an aligned buffer if needed if ((_bestImageOffset % IntPtr.Size) != 0) { // Beginning of icon's content is misaligned byte[] alignedBuffer = new byte[_bestBytesInRes]; Array.Copy(_iconData, _bestImageOffset, alignedBuffer, 0, _bestBytesInRes); fixed(byte *pbAlignedBuffer = alignedBuffer) { _handle = SafeNativeMethods.CreateIconFromResourceEx(pbAlignedBuffer, _bestBytesInRes, true, 0x00030000, 0, 0, 0); } } else { try { _handle = SafeNativeMethods.CreateIconFromResourceEx(checked (pbIconData + _bestImageOffset), _bestBytesInRes, true, 0x00030000, 0, 0, 0); } catch (OverflowException) { throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER); } } if (_handle == IntPtr.Zero) { throw new Win32Exception(); } } }
// Initializes this Image object. This is identical to calling the image's // constructor with picture, but this allows non-constructor initialization, // which may be necessary in some instances. private unsafe void Initialize(int width, int height) { if (_iconData == null || _handle != IntPtr.Zero) { throw new InvalidOperationException(SR.Format(SR.IllegalState, GetType().Name)); } if (_iconData.Length < sizeof(SafeNativeMethods.ICONDIR)) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(Icon))); } // Get the correct width and height. if (width == 0) { width = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CXICON); } if (height == 0) { height = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CYICON); } if (s_bitDepth == 0) { IntPtr dc = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef); s_bitDepth = UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), SafeNativeMethods.BITSPIXEL); s_bitDepth *= UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), SafeNativeMethods.PLANES); UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, dc)); // If the bitdepth is 8, make it 4 because windows does not // choose a 256 color icon if the display is running in 256 color mode // due to palette flicker. if (s_bitDepth == 8) { s_bitDepth = 4; } } fixed(byte *b = _iconData) { SafeNativeMethods.ICONDIR *dir = (SafeNativeMethods.ICONDIR *)b; if (dir->idReserved != 0 || dir->idType != 1 || dir->idCount == 0) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(Icon))); } byte bestWidth = 0; byte bestHeight = 0; if (sizeof(SafeNativeMethods.ICONDIRENTRY) * (dir->idCount - 1) + sizeof(SafeNativeMethods.ICONDIR) > _iconData.Length) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(Icon))); } var entries = new ReadOnlySpan <SafeNativeMethods.ICONDIRENTRY>(&dir->idEntries, dir->idCount); foreach (SafeNativeMethods.ICONDIRENTRY entry in entries) { bool fUpdateBestFit = false; uint iconBitDepth; if (entry.bColorCount != 0) { iconBitDepth = 4; if (entry.bColorCount < 0x10) { iconBitDepth = 1; } } else { iconBitDepth = entry.wBitCount; } // If it looks like if nothing is specified at this point then set the bits per pixel to 8. if (iconBitDepth == 0) { iconBitDepth = 8; } // Windows rules for specifing an icon: // // 1. The icon with the closest size match. // 2. For matching sizes, the image with the closest bit depth. // 3. If there is no color depth match, the icon with the closest color depth that does not exceed the display. // 4. If all icon color depth > display, lowest color depth is chosen. // 5. color depth of > 8bpp are all equal. // 6. Never choose an 8bpp icon on an 8bpp system. if (_bestBytesInRes == 0) { fUpdateBestFit = true; } else { int bestDelta = Math.Abs(bestWidth - width) + Math.Abs(bestHeight - height); int thisDelta = Math.Abs(entry.bWidth - width) + Math.Abs(entry.bHeight - height); if ((thisDelta < bestDelta) || (thisDelta == bestDelta && (0 <= s_bitDepth && 0 > _bestBitDepth || _bestBitDepth > s_bitDepth && 0 < _bestBitDepth))) { fUpdateBestFit = true; } } if (fUpdateBestFit) { bestWidth = entry.bWidth; bestHeight = entry.bHeight; _bestImageOffset = entry.dwImageOffset; _bestBytesInRes = entry.dwBytesInRes; _bestBitDepth = iconBitDepth; } } if (_bestImageOffset > int.MaxValue) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(Icon))); } if (_bestBytesInRes > int.MaxValue) { throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER); } uint endOffset; try { endOffset = checked (_bestImageOffset + _bestBytesInRes); } catch (OverflowException) { throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER); } if (endOffset > _iconData.Length) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(Icon))); } // Copy the bytes into an aligned buffer if needed. if ((_bestImageOffset % IntPtr.Size) != 0) { // Beginning of icon's content is misaligned. byte[] alignedBuffer = ArrayPool <byte> .Shared.Rent((int)_bestBytesInRes); Array.Copy(_iconData, _bestImageOffset, alignedBuffer, 0, _bestBytesInRes); fixed(byte *pbAlignedBuffer = alignedBuffer) { _handle = SafeNativeMethods.CreateIconFromResourceEx(pbAlignedBuffer, _bestBytesInRes, true, 0x00030000, 0, 0, 0); } ArrayPool <byte> .Shared.Return(alignedBuffer); } else { try { _handle = SafeNativeMethods.CreateIconFromResourceEx(checked (b + _bestImageOffset), _bestBytesInRes, true, 0x00030000, 0, 0, 0); } catch (OverflowException) { throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER); } } if (_handle == IntPtr.Zero) { throw new Win32Exception(); } } }
/// <include file='doc\Icon.uex' path='docs/doc[@for="Icon.Initialize"]/*' /> /// <devdoc> /// Initializes this Image object. This is identical to calling the image's /// constructor with picture, but this allows non-constructor initialization, /// which may be necessary in some instances. /// </devdoc> private unsafe void Initialize(int width, int height) { if (iconData == null || handle != IntPtr.Zero) { throw new InvalidOperationException(SR.GetString(SR.IllegalState, GetType().Name)); } if (iconData.Length < Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIR))) { throw new ArgumentException(SR.GetString(SR.InvalidPictureType, "picture", "Icon")); } // Get the correct width / height // if (width == 0) { width = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CXICON); } if (height == 0) { height = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CYICON); } if (bitDepth == 0) { IntPtr dc = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef); bitDepth = UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), SafeNativeMethods.BITSPIXEL); bitDepth *= UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), SafeNativeMethods.PLANES); UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, dc)); // If the bitdepth is 8, make it 4. Why? Because windows does not // choose a 256 color icon if the display is running in 256 color mode // because of palette flicker. // if (bitDepth == 8) { bitDepth = 4; } } fixed(byte *pbIconData = iconData) { SafeNativeMethods.ICONDIR *pIconDir = (SafeNativeMethods.ICONDIR *)pbIconData; if (pIconDir->idReserved != 0 || pIconDir->idType != 1 || pIconDir->idCount == 0) { throw new ArgumentException(SR.GetString(SR.InvalidPictureType, "picture", "Icon")); } SafeNativeMethods.ICONDIRENTRY *pIconDirEntry = &pIconDir->idEntries; SafeNativeMethods.ICONDIRENTRY *pBestFit = null; int bestBitDepth = 0; int icondirEntrySize = Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIRENTRY)); Debug.Assert((icondirEntrySize * pIconDir->idCount) < iconData.Length, "Illegal number of ICONDIRENTRIES"); if ((icondirEntrySize * pIconDir->idCount) >= iconData.Length) { throw new ArgumentException(SR.GetString(SR.InvalidPictureType, "picture", "Icon")); } for (int i = 0; i < pIconDir->idCount; i++) { int iconBitDepth = pIconDirEntry->wPlanes * pIconDirEntry->wBitCount; if (iconBitDepth == 0) { if (pIconDirEntry->bColorCount == 0) { iconBitDepth = 16; } else { iconBitDepth = 8; if (pIconDirEntry->bColorCount < 0xFF) { iconBitDepth = 4; } if (pIconDirEntry->bColorCount < 0x10) { iconBitDepth = 2; } } } // Windows rules for specifing an icon: // // 1. The icon with the closest size match. // 2. For matching sizes, the image with the closest bit depth. // 3. If there is no color depth match, the icon with the closest color depth that does not exceed the display. // 4. If all icon color depth > display, lowest color depth is chosen. // 5. color depth of > 8bpp are all equal. // 6. Never choose an 8bpp icon on an 8bpp system. // if (pBestFit == null) { pBestFit = pIconDirEntry; bestBitDepth = iconBitDepth; } else { int bestDelta = Math.Abs(pBestFit->bWidth - width) + Math.Abs(pBestFit->bHeight - height); int thisDelta = Math.Abs(pIconDirEntry->bWidth - width) + Math.Abs(pIconDirEntry->bHeight - height); if (thisDelta < bestDelta) { pBestFit = pIconDirEntry; bestBitDepth = iconBitDepth; } else if (thisDelta == bestDelta && (iconBitDepth <= bitDepth && iconBitDepth > bestBitDepth || bestBitDepth > bitDepth && iconBitDepth < bestBitDepth)) { pBestFit = pIconDirEntry; bestBitDepth = iconBitDepth; } } pIconDirEntry++; } Debug.Assert(pBestFit->dwImageOffset >= 0 && (pBestFit->dwImageOffset + pBestFit->dwBytesInRes) <= iconData.Length, "Illegal offset/length for the Icon data"); if (pBestFit->dwImageOffset < 0 || (pBestFit->dwImageOffset + pBestFit->dwBytesInRes) > iconData.Length) { throw new ArgumentException(SR.GetString(SR.InvalidPictureType, "picture", "Icon")); } handle = SafeNativeMethods.CreateIconFromResourceEx(pbIconData + pBestFit->dwImageOffset, pBestFit->dwBytesInRes, true, 0x00030000, 0, 0, 0); if (handle == IntPtr.Zero) { throw new Win32Exception(); } } }