Пример #1
0
        /// <summary>
        /// Creates a handle to a PARGB32 bitmap from an Icon.
        /// </summary>
        /// <param name="iconHandle">The handle to the icon.</param>
        /// <param name="iconSize">The iconSize of the icon.</param>
        /// <returns>A PARGB32 bitmap with the contents of the icon, including transparency.</returns>
        public static IntPtr CreatePARGB32HBitmap(IntPtr iconHandle, Size iconSize)
        {
            //  Make sure we're ready for buffered painting.
            //  TODO: Really we only need to do this once per thread, so an improvement
            //  might be to have a manager create this as required per thread.
            Uxtheme.BufferedPaintInit();

            //  Create a compatible device context to work with.
            var deviceContextHandle = Gdi32.CreateCompatibleDC(IntPtr.Zero);

            if (deviceContextHandle == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }

            //  Now create a 32 bit bitmap of the appropriate size, getting it's bits and handle.
            IntPtr bits;
            IntPtr hBitmap;

            if (!Create32BitHBITMAP(deviceContextHandle, iconSize, out bits, out hBitmap))
            {
                Gdi32.DeleteDC(deviceContextHandle);
                return(IntPtr.Zero);
            }

            //  Select the bitmap, keeping track of the old one. If this fails,
            //  delete the device context and return a null handle.
            var oldBitmapHandle = Gdi32.SelectObject(deviceContextHandle, hBitmap);

            if (oldBitmapHandle == IntPtr.Zero)
            {
                Gdi32.DeleteDC(deviceContextHandle);
                return(IntPtr.Zero);
            }

            //  Create paint params that represent our alpha blending.
            var bfAlpha = new BLENDFUNCTION
            {
                BlendOp             = AC_SRC_OVER,
                BlendFlags          = 0,
                SourceConstantAlpha = 255,
                AlphaFormat         = AC_SRC_ALPHA
            };
            var paintParams = new BP_PAINTPARAMS();

            paintParams.cbSize         = (uint)Marshal.SizeOf(paintParams);
            paintParams.dwFlags        = BPPF_ERASE;
            paintParams.pBlendFunction = Marshal.AllocHGlobal(Marshal.SizeOf(bfAlpha));
            Marshal.StructureToPtr(bfAlpha, paintParams.pBlendFunction, false);

            //  Create the pointer that'll hold the device context to the buffer, set the icon rectangle.
            IntPtr bufferDeviceContextHandle;
            var    iconRect = new RECT(0, 0, iconSize.Width, iconSize.Height);

            //  Create a paint buffer handle.
            var paintBufferHandle = Uxtheme.BeginBufferedPaint(deviceContextHandle, ref iconRect,
                                                               BP_BUFFERFORMAT.BPBF_DIB, ref paintParams, out bufferDeviceContextHandle);

            //  Free the memory we allocated for the blend function.
            Marshal.FreeHGlobal(paintParams.pBlendFunction);

            //  If we created a paint buffer successfully, we can draw the icon into it.
            if (paintBufferHandle != IntPtr.Zero)
            {
                //  Try and draw the icon.
                if (Gdi32.DrawIconEx(bufferDeviceContextHandle, 0, 0, iconHandle, iconSize.Width, iconSize.Height, 0, IntPtr.Zero,
                                     (int)DI_NORMAL))
                {
                    //  Now convert the buffer we've painted into PARGB32, meaning we'll end up
                    //  with a PARGB32 bitmap.
                    ConvertBufferToPARGB32(paintBufferHandle, deviceContextHandle, iconHandle, iconSize);
                }

                // This will write the buffer contents to the destination bitmap.
                Uxtheme.EndBufferedPaint(paintBufferHandle, true);
            }

            //  Select the old bitmpa and delete the device context.
            Gdi32.SelectObject(deviceContextHandle, oldBitmapHandle);
            Gdi32.DeleteDC(deviceContextHandle);

            //  We're done with buffered painting.
            Uxtheme.BufferedPaintUnInit();

            //  Baddabing-baddabom, PARGB32.
            return(hBitmap);
        }