private IntPtr CreateCompatibleDIB(IntPtr hdc, IntPtr hpal, int ulWidth, int ulHeight, ref IntPtr ppvBits) { if (hdc == IntPtr.Zero) { throw new ArgumentNullException("hdc"); } IntPtr hbmRet = IntPtr.Zero; NativeMethods.BITMAPINFO_FLAT pbmi = new NativeMethods.BITMAPINFO_FLAT(); // // Validate hdc. // int objType = UnsafeNativeMethods.GetObjectType(new HandleRef(null, hdc)); switch (objType) { case NativeMethods.OBJ_DC: case NativeMethods.OBJ_METADC: case NativeMethods.OBJ_MEMDC: case NativeMethods.OBJ_ENHMETADC: break; default: throw new ArgumentException(SR.GetString(SR.DCTypeInvalid)); } if (bFillBitmapInfo(hdc, hpal, ref pbmi)) { // // Change bitmap size to match specified dimensions. // pbmi.bmiHeader_biWidth = ulWidth; pbmi.bmiHeader_biHeight = ulHeight; if (pbmi.bmiHeader_biCompression == NativeMethods.BI_RGB) { pbmi.bmiHeader_biSizeImage = 0; } else { if (pbmi.bmiHeader_biBitCount == 16) { pbmi.bmiHeader_biSizeImage = ulWidth * ulHeight * 2; } else if (pbmi.bmiHeader_biBitCount == 32) { pbmi.bmiHeader_biSizeImage = ulWidth * ulHeight * 4; } else { pbmi.bmiHeader_biSizeImage = 0; } } pbmi.bmiHeader_biClrUsed = 0; pbmi.bmiHeader_biClrImportant = 0; // // Create the DIB section. Let Win32 allocate the memory and return // a pointer to the bitmap surface. // hbmRet = SafeNativeMethods.CreateDIBSection(new HandleRef(null, hdc), ref pbmi, NativeMethods.DIB_RGB_COLORS, ref ppvBits, IntPtr.Zero, 0); Win32Exception ex = null; if (hbmRet == IntPtr.Zero) { ex = new Win32Exception(Marshal.GetLastWin32Error()); #if DEBUG DumpBitmapInfo(ref pbmi); #endif } #if DEBUG if (DoubleBuffering.TraceVerbose) { DumpBitmapInfo(ref pbmi); } #endif if (ex != null) { throw ex; } } return(hbmRet); }
private static Icon GetIcon(ref Icon icon, int iconId) { return(icon ?? (icon = new Icon(SafeNativeMethods.LoadIcon(NativeMethods.NullHandleRef, iconId)))); }
private Bitmap BmpFrame() { Bitmap bitmap = null; if (_iconData != null && _bestBitDepth == 32) { // GDI+ doesnt handle 32 bpp icons with alpha properly // we load the icon ourself from the byte table bitmap = new Bitmap(Size.Width, Size.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); Debug.Assert(_bestImageOffset >= 0 && (_bestImageOffset + _bestBytesInRes) <= _iconData.Length, "Illegal offset/length for the Icon data"); unsafe { BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, Size.Width, Size.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); try { uint *pixelPtr = (uint *)bmpdata.Scan0.ToPointer(); // jumping the image header int newOffset = _bestImageOffset + Marshal.SizeOf(typeof(SafeNativeMethods.BITMAPINFOHEADER)); // there is no color table that we need to skip since we're 32bpp int lineLength = Size.Width * 4; int width = Size.Width; for (int j = (Size.Height - 1) * 4; j >= 0; j -= 4) { Marshal.Copy(_iconData, newOffset + j * width, (IntPtr)pixelPtr, lineLength); pixelPtr += width; } // note: we ignore the mask that's available after the pixel table } finally { bitmap.UnlockBits(bmpdata); } } } else if (_bestBitDepth == 0 || _bestBitDepth == 32) { // This may be a 32bpp icon or an icon without any data. var info = new SafeNativeMethods.ICONINFO(); SafeNativeMethods.GetIconInfo(new HandleRef(this, _handle), info); var bmp = new SafeNativeMethods.BITMAP(); try { if (info.hbmColor != IntPtr.Zero) { SafeNativeMethods.GetObject(new HandleRef(null, info.hbmColor), Marshal.SizeOf(typeof(SafeNativeMethods.BITMAP)), bmp); if (bmp.bmBitsPixel == 32) { Bitmap tmpBitmap = null; BitmapData bmpData = null; BitmapData targetData = null; try { tmpBitmap = Image.FromHbitmap(info.hbmColor); // In GDI+ the bits are there but the bitmap was created with no alpha channel // so copy the bits by hand to a new bitmap // we also need to go around a limitation in the way the ICON is stored (ie if it's another bpp // but stored in 32bpp all pixels are transparent and not opaque) // (Here you mostly need to remain calm....) bmpData = tmpBitmap.LockBits(new Rectangle(0, 0, tmpBitmap.Width, tmpBitmap.Height), ImageLockMode.ReadOnly, tmpBitmap.PixelFormat); // we need do the following if the image has alpha because otherwise the image is fully transparent even though it has data if (BitmapHasAlpha(bmpData)) { bitmap = new Bitmap(bmpData.Width, bmpData.Height, PixelFormat.Format32bppArgb); targetData = bitmap.LockBits(new Rectangle(0, 0, bmpData.Width, bmpData.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); CopyBitmapData(bmpData, targetData); } } finally { if (tmpBitmap != null && bmpData != null) { tmpBitmap.UnlockBits(bmpData); } if (bitmap != null && targetData != null) { bitmap.UnlockBits(targetData); } } tmpBitmap.Dispose(); } } } finally { if (info.hbmColor != IntPtr.Zero) { SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmColor)); } if (info.hbmMask != IntPtr.Zero) { SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmMask)); } } } if (bitmap == null) { // last chance... all the other cases (ie non 32 bpp icons coming from a handle or from the bitmapData) // we have to do this rather than just return Bitmap.FromHIcon because // the bitmap returned from that, even though it's 32bpp, just paints where the mask allows it // seems like another GDI+ weirdness. might be interesting to investigate further. In the meantime // this looks like the right thing to do and is not more expansive that what was present before. Size size = Size; bitmap = new Bitmap(size.Width, size.Height); // initialized to transparent Graphics graphics = null; using (graphics = Graphics.FromImage(bitmap)) { try { using (Bitmap tmpBitmap = Bitmap.FromHicon(Handle)) { graphics.DrawImage(tmpBitmap, new Rectangle(0, 0, size.Width, size.Height)); } } catch (ArgumentException) { // Sometimes FromHicon will crash with no real reason. // The backup plan is to just draw the image like we used to. // NOTE: FromHIcon is also where we have the buffer overrun // if width and height are mismatched. Draw(graphics, new Rectangle(0, 0, size.Width, size.Height)); } } // GDI+ fills the surface with a sentinel color for GetDC, but does // not correctly clean it up again, so we have to do it. Color fakeTransparencyColor = Color.FromArgb(0x0d, 0x0b, 0x0c); bitmap.MakeTransparent(fakeTransparencyColor); } Debug.Assert(bitmap != null, "Bitmap cannot be null"); return(bitmap); }
private bool bFillBitmapInfo(IntPtr hdc, IntPtr hpal, ref NativeMethods.BITMAPINFO_FLAT pbmi) { IntPtr hbm = IntPtr.Zero; bool bRet = false; try { // // Create a dummy bitmap from which we can query color format info // about the device surface. // hbm = SafeNativeMethods.CreateCompatibleBitmap(new HandleRef(null, hdc), 1, 1); if (hbm == IntPtr.Zero) { throw new OutOfMemoryException(SR.GetString(SR.GraphicsBufferQueryFail)); } pbmi.bmiHeader_biSize = Marshal.SizeOf(typeof(NativeMethods.BITMAPINFOHEADER)); pbmi.bmiColors = new byte[NativeMethods.BITMAPINFO_MAX_COLORSIZE * 4]; // // Call first time to fill in BITMAPINFO header. // SafeNativeMethods.GetDIBits(new HandleRef(null, hdc), new HandleRef(null, hbm), 0, 0, IntPtr.Zero, ref pbmi, NativeMethods.DIB_RGB_COLORS); if (pbmi.bmiHeader_biBitCount <= 8) { bRet = bFillColorTable(hdc, hpal, ref pbmi); } else { if (pbmi.bmiHeader_biCompression == NativeMethods.BI_BITFIELDS) { // // Call a second time to get the color masks. // It's a GetDIBits Win32 "feature". // SafeNativeMethods.GetDIBits(new HandleRef(null, hdc), new HandleRef(null, hbm), 0, pbmi.bmiHeader_biHeight, IntPtr.Zero, ref pbmi, NativeMethods.DIB_RGB_COLORS); } bRet = true; } } finally { if (hbm != IntPtr.Zero) { SafeNativeMethods.DeleteObject(new HandleRef(null, hbm)); hbm = IntPtr.Zero; } } return(bRet); }
// Draws this image to a graphics object. The drawing command originates on the graphics // object, but a graphics object generally has no idea how to render a given image. So, // it passes the call to the actual image. This version crops the image to the given // dimensions and allows the user to specify a rectangle within the image to draw. private void DrawIcon(IntPtr dc, Rectangle imageRect, Rectangle targetRect, bool stretch) { int imageX = 0; int imageY = 0; int imageWidth; int imageHeight; int targetX = 0; int targetY = 0; int targetWidth = 0; int targetHeight = 0; Size cursorSize = Size; // Compute the dimensions of the icon if needed. if (!imageRect.IsEmpty) { imageX = imageRect.X; imageY = imageRect.Y; imageWidth = imageRect.Width; imageHeight = imageRect.Height; } else { imageWidth = cursorSize.Width; imageHeight = cursorSize.Height; } if (!targetRect.IsEmpty) { targetX = targetRect.X; targetY = targetRect.Y; targetWidth = targetRect.Width; targetHeight = targetRect.Height; } else { targetWidth = cursorSize.Width; targetHeight = cursorSize.Height; } int drawWidth, drawHeight; int clipWidth, clipHeight; if (stretch) { drawWidth = cursorSize.Width * targetWidth / imageWidth; drawHeight = cursorSize.Height * targetHeight / imageHeight; clipWidth = targetWidth; clipHeight = targetHeight; } else { drawWidth = cursorSize.Width; drawHeight = cursorSize.Height; clipWidth = targetWidth < imageWidth ? targetWidth : imageWidth; clipHeight = targetHeight < imageHeight ? targetHeight : imageHeight; } // The ROP is SRCCOPY, so we can be simple here and take // advantage of clipping regions. Drawing the cursor // is merely a matter of offsetting and clipping. IntPtr hSaveRgn = SafeNativeMethods.SaveClipRgn(dc); try { SafeNativeMethods.IntersectClipRect(new HandleRef(this, dc), targetX, targetY, targetX + clipWidth, targetY + clipHeight); SafeNativeMethods.DrawIconEx(new HandleRef(null, dc), targetX - imageX, targetY - imageY, new HandleRef(this, _handle), drawWidth, drawHeight, 0, NativeMethods.NullHandleRef, SafeNativeMethods.DI_NORMAL); } finally { SafeNativeMethods.RestoreClipRgn(dc, hSaveRgn); } }
// 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)); } int icondirSize = Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIR)); if (_iconData.Length < icondirSize) { 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 *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", nameof(Icon))); } SafeNativeMethods.ICONDIRENTRY EntryTemp; byte bestWidth = 0; byte bestHeight = 0; byte *pbIconDirEntry = unchecked (pbIconData + 6); int icondirEntrySize = Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIRENTRY)); if ((icondirEntrySize * (idCount - 1) + icondirSize) > _iconData.Length) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(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; } // 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(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; } if (_bestImageOffset < 0) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(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", 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 = 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(); } } }
public LOGFONT(SafeNativeMethods.LOGFONT lf) { this.lfHeight = lf.lfHeight; this.lfWidth = lf.lfWidth; this.lfEscapement = lf.lfEscapement; this.lfOrientation = lf.lfOrientation; this.lfWeight = lf.lfWeight; this.lfItalic = lf.lfItalic; this.lfUnderline = lf.lfUnderline; this.lfStrikeOut = lf.lfStrikeOut; this.lfCharSet = lf.lfCharSet; this.lfOutPrecision = lf.lfOutPrecision; this.lfClipPrecision = lf.lfClipPrecision; this.lfQuality = lf.lfQuality; this.lfPitchAndFamily = lf.lfPitchAndFamily; this.lfFaceName = lf.lfFaceName; }
/// <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(); } } }
private static int SystemColorToArgb(int index) { return(FromWin32Value(SafeNativeMethods.GetSysColor(index))); }
private System.Drawing.Printing.PrinterResolution PrinterResolutionFromMode(SafeNativeMethods.DEVMODE mode) { System.Drawing.Printing.PrinterResolution[] resolutionArray = this.printerSettings.Get_PrinterResolutions(); for (int i = 0; i < resolutionArray.Length; i++) { if (((mode.dmPrintQuality >= 0) && ((mode.dmFields & 0x400) == 0x400)) && ((mode.dmFields & 0x2000) == 0x2000)) { if ((resolutionArray[i].X == mode.dmPrintQuality) && (resolutionArray[i].Y == mode.dmYResolution)) { return resolutionArray[i]; } } else if (((mode.dmFields & 0x400) == 0x400) && (resolutionArray[i].Kind == ((PrinterResolutionKind) mode.dmPrintQuality))) { return resolutionArray[i]; } } return new System.Drawing.Printing.PrinterResolution(PrinterResolutionKind.Custom, mode.dmPrintQuality, mode.dmYResolution); }
private System.Drawing.Printing.PaperSource PaperSourceFromMode(SafeNativeMethods.DEVMODE mode) { System.Drawing.Printing.PaperSource[] sourceArray = this.printerSettings.Get_PaperSources(); if ((mode.dmFields & 0x200) == 0x200) { for (int i = 0; i < sourceArray.Length; i++) { if (((short) sourceArray[i].RawKind) == mode.dmDefaultSource) { return sourceArray[i]; } } } return new System.Drawing.Printing.PaperSource((PaperSourceKind) mode.dmDefaultSource, "unknown"); }
private System.Drawing.Printing.PaperSize PaperSizeFromMode(SafeNativeMethods.DEVMODE mode) { System.Drawing.Printing.PaperSize[] sizeArray = this.printerSettings.Get_PaperSizes(); if ((mode.dmFields & 2) == 2) { for (int i = 0; i < sizeArray.Length; i++) { if (sizeArray[i].RawKind == mode.dmPaperSize) { return sizeArray[i]; } } } return new System.Drawing.Printing.PaperSize(PaperKind.Custom, "custom", PrinterUnitConvert.Convert((int) mode.dmPaperWidth, PrinterUnit.TenthsOfAMillimeter, PrinterUnit.Display), PrinterUnitConvert.Convert((int) mode.dmPaperLength, PrinterUnit.TenthsOfAMillimeter, PrinterUnit.Display)); }
// 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(); } } }