// this code is adapted from Icon.GetIconSize please take this into account when changing this private Size GetIconSize(IntPtr iconHandle) { Size iconSize = Size; NativeMethods.ICONINFO info = default; SafeNativeMethods.GetIconInfo(new HandleRef(this, iconHandle), ref info); NativeMethods.BITMAP bmp = new NativeMethods.BITMAP(); if (info.hbmColor != IntPtr.Zero) { UnsafeNativeMethods.GetObject(new HandleRef(null, info.hbmColor), Marshal.SizeOf <NativeMethods.BITMAP>(), bmp); Interop.Gdi32.DeleteObject(info.hbmColor); iconSize = new Size(bmp.bmWidth, bmp.bmHeight); } else if (info.hbmMask != IntPtr.Zero) { UnsafeNativeMethods.GetObject(new HandleRef(null, info.hbmMask), Marshal.SizeOf <NativeMethods.BITMAP>(), bmp); iconSize = new Size(bmp.bmWidth, bmp.bmHeight / 2); } if (info.hbmMask != IntPtr.Zero) { Interop.Gdi32.DeleteObject(info.hbmMask); } return(iconSize); }
// this code is adapted from Icon.GetIconSize please take this into account when changing this private Size GetIconSize(IntPtr iconHandle) { Size iconSize = Size; NativeMethods.ICONINFO info = new NativeMethods.ICONINFO(); SafeNativeMethods.GetIconInfo(new HandleRef(this, iconHandle), info); NativeMethods.BITMAP bmp = new NativeMethods.BITMAP(); if (info.hbmColor != IntPtr.Zero) { UnsafeNativeMethods.GetObject(new HandleRef(null, info.hbmColor), Marshal.SizeOf(typeof(NativeMethods.BITMAP)), bmp); SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmColor)); iconSize = new Size(bmp.bmWidth, bmp.bmHeight); } else if (info.hbmMask != IntPtr.Zero) { UnsafeNativeMethods.GetObject(new HandleRef(null, info.hbmMask), Marshal.SizeOf(typeof(NativeMethods.BITMAP)), bmp); iconSize = new Size(bmp.bmWidth, bmp.bmHeight / 2); } if (info.hbmMask != IntPtr.Zero) { SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmMask)); } return(iconSize); }
// ported form VB6 (Ctls\PortUtil\StdCtl.cpp:6176) private unsafe bool DICopy(HandleRef hdcDest, IntPtr hdcSrc, RECT rect, bool bStretch) { long i; // Get the bitmap from the DC by selecting in a 1x1 pixel temp bitmap IntPtr hNullBitmap = SafeNativeMethods.CreateBitmap(1, 1, 1, 1, IntPtr.Zero); if (hNullBitmap == IntPtr.Zero) { return(false); } try { IntPtr hBitmap = Gdi32.SelectObject(hdcSrc, hNullBitmap); if (hBitmap == IntPtr.Zero) { return(false); } // Restore original bitmap Gdi32.SelectObject(hdcSrc, hBitmap); NativeMethods.BITMAP bmp = new NativeMethods.BITMAP(); if (UnsafeNativeMethods.GetObject(new HandleRef(null, hBitmap), Marshal.SizeOf(bmp), bmp) == 0) { return(false); } NativeMethods.BITMAPINFO_FLAT lpbmi = new NativeMethods.BITMAPINFO_FLAT { bmiHeader_biSize = Marshal.SizeOf <NativeMethods.BITMAPINFOHEADER>(), bmiHeader_biWidth = bmp.bmWidth, bmiHeader_biHeight = bmp.bmHeight, bmiHeader_biPlanes = 1, bmiHeader_biBitCount = bmp.bmBitsPixel, bmiHeader_biCompression = NativeMethods.BI_RGB, bmiHeader_biSizeImage = 0, //Not needed since using BI_RGB bmiHeader_biXPelsPerMeter = 0, bmiHeader_biYPelsPerMeter = 0, bmiHeader_biClrUsed = 0, bmiHeader_biClrImportant = 0, bmiColors = new byte[NativeMethods.BITMAPINFO_MAX_COLORSIZE * 4] }; // Include the palette for 256 color bitmaps long iColors = 1 << (bmp.bmBitsPixel * bmp.bmPlanes); if (iColors <= 256) { byte[] aj = new byte[Marshal.SizeOf <NativeMethods.PALETTEENTRY>() * 256]; SafeNativeMethods.GetSystemPaletteEntries(hdcSrc, 0, (int)iColors, aj); fixed(byte *pcolors = lpbmi.bmiColors) { fixed(byte *ppal = aj) { NativeMethods.RGBQUAD * prgb = (NativeMethods.RGBQUAD *)pcolors; NativeMethods.PALETTEENTRY *lppe = (NativeMethods.PALETTEENTRY *)ppal; // Convert the palette entries to RGB quad entries for (i = 0; i < (int)iColors; i++) { prgb[i].rgbRed = lppe[i].peRed; prgb[i].rgbBlue = lppe[i].peBlue; prgb[i].rgbGreen = lppe[i].peGreen; } } } } // Allocate memory to hold the bitmap bits long bitsPerScanLine = bmp.bmBitsPixel * (long)bmp.bmWidth; long bytesPerScanLine = (bitsPerScanLine + 7) / 8; long totalBytesReqd = bytesPerScanLine * bmp.bmHeight; byte[] lpBits = new byte[totalBytesReqd]; // Get the bitmap bits int diRet = SafeNativeMethods.GetDIBits(hdcSrc, hBitmap, 0, bmp.bmHeight, lpBits, ref lpbmi, NativeMethods.DIB_RGB_COLORS); if (diRet == 0) { return(false); } // Set the destination coordiates depending on whether stretch-to-fit was chosen int xDest, yDest, cxDest, cyDest; if (bStretch) { xDest = rect.left; yDest = rect.top; cxDest = rect.right - rect.left; cyDest = rect.bottom - rect.top; } else { xDest = rect.left; yDest = rect.top; cxDest = bmp.bmWidth; cyDest = bmp.bmHeight; } // Paint the bitmap int iRet = SafeNativeMethods.StretchDIBits(hdcDest, xDest, yDest, cxDest, cyDest, 0, 0, bmp.bmWidth, bmp.bmHeight, lpBits, ref lpbmi, NativeMethods.DIB_RGB_COLORS, NativeMethods.SRCCOPY); if (iRet == NativeMethods.GDI_ERROR) { return(false); } } finally { Gdi32.DeleteObject(hNullBitmap); } return(true); }
private static void GetMouseCursorSize(out int width, out int height, out int hotX, out int hotY) { /* The code for this function is based upon shell\comctl32\v6\tooltips.cpp _GetHcursorPdy3 ------------------------------------------------------------------------- With the current mouse drivers that allow you to customize the mouse pointer size, GetSystemMetrics returns useless values regarding that pointer size. Assumption: 1. The pointer's width is equal to its height. We compute its height and infer its width. This function looks at the mouse pointer bitmap to find out the dimensions of the mouse pointer and the hot spot location. ------------------------------------------------------------------------- */ // If there is no mouse cursor, these should be 0 width = height = hotX = hotY = 0; // First, retrieve the mouse cursor IntPtr hCursor = SafeNativeMethods.GetCursor(); if (hCursor != IntPtr.Zero) { // In case we can't figure out the dimensions, this is a best guess width = height = 16; // Get the cursor information NativeMethods.ICONINFO iconInfo = new NativeMethods.ICONINFO(); bool gotIconInfo = true; try { UnsafeNativeMethods.GetIconInfo(new HandleRef(null, hCursor), out iconInfo); } catch(Win32Exception) { gotIconInfo = false; } if(gotIconInfo) { // Get a handle to the bitmap NativeMethods.BITMAP bm = new NativeMethods.BITMAP(); int resultOfGetObject=0; new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); //Blessed Assert try { resultOfGetObject = UnsafeNativeMethods.GetObject(iconInfo.hbmMask.MakeHandleRef(null), Marshal.SizeOf(typeof(NativeMethods.BITMAP)), bm); } finally { SecurityPermission.RevertAssert(); } if (resultOfGetObject != 0) { // Extract the bitmap bits int max = (bm.bmWidth * bm.bmHeight / 8); byte[] curMask = new byte[max * 2]; // Enough space for the mask and the xor mask if (UnsafeNativeMethods.GetBitmapBits(iconInfo.hbmMask.MakeHandleRef(null), curMask.Length, curMask) != 0) { bool hasXORMask = false; if (iconInfo.hbmColor.IsInvalid) { // if no color bitmap, then the hbmMask is a double height bitmap // with the cursor and the mask stacked. hasXORMask = true; max /= 2; } // Go through the bitmap looking for the bottom of the image and/or mask bool empty = true; int bottom = max; for (bottom--; bottom >= 0; bottom--) { if (curMask[bottom] != 0xFF || (hasXORMask && (curMask[bottom + max] != 0))) { empty = false; break; } } if (!empty) { // Go through the bitmap looking for the top of the image and/or mask int top; for (top = 0; top < max; top++) { if (curMask[top] != 0xFF || (hasXORMask && (curMask[top + max] != 0))) break; } // Calculate the left, right, top, bottom points // byteWidth = bytes per row AND bytes per vertical pixel int byteWidth = bm.bmWidth / 8; int right /*px*/ = (bottom /*bytes*/ % byteWidth) * 8 /*px/byte*/; bottom /*px*/ = bottom /*bytes*/ / byteWidth /*bytes/px*/; int left /*px*/ = top /*bytes*/ % byteWidth * 8 /*px/byte*/; top /*px*/ = top /*bytes*/ / byteWidth /*bytes/px*/; // (Final value) Convert LRTB to Width and Height width = right - left + 1; height = bottom - top + 1; // (Final value) Calculate the hotspot relative to top/left hotX = iconInfo.xHotspot - left; hotY = iconInfo.yHotspot - top; } else { // (Final value) We didn't find anything in the bitmap. // So, we'll make a guess with the information that we have. // Note: This seems to happen on I-Beams and Cross-hairs -- cursors that // are all inverted. Strangely, their hbmColor is non-null. width = bm.bmWidth; height = bm.bmHeight; hotX = iconInfo.xHotspot; hotY = iconInfo.yHotspot; } } } iconInfo.hbmColor.Dispose(); iconInfo.hbmMask.Dispose(); } } }