ResizeImageWithAspect() статический приватный Метод

/// Grabs a snapshot of a WPF UIElement and returns the image as Bitmap. /// Resizes the given bitmap while maintaining the aspect ratio.
static private ResizeImageWithAspect ( IntPtr originalHBitmap, int newWidth, int maxHeight, bool resizeIfWider ) : Bitmap
originalHBitmap System.IntPtr Original/source bitmap
newWidth int Maximum width for the new image
maxHeight int Maximum height for the new image
resizeIfWider bool If true and requested image is wider than the source, the new image is resized accordingly.
Результат System.Drawing.Bitmap
Пример #1
0
        private static bool DispatchSendIconThumbnailMessage(ref System.Windows.Forms.Message m, TaskbarWindow taskbarWindow)
        {
            if (m.Msg == (int)TaskbarNativeMethods.WmDwmSendIconThumbnail)
            {
                int  width         = (int)((long)m.LParam >> 16);
                int  height        = (int)(((long)m.LParam) & (0xFFFF));
                Size requestedSize = new Size(width, height);

                // Fire an event to let the user update their bitmap
                taskbarWindow.TabbedThumbnail.OnTabbedThumbnailBitmapRequested();

                IntPtr hBitmap = IntPtr.Zero;

                // Default size for the thumbnail
                Size realWindowSize = new Size(200, 200);

                // Get the size of teh control or UIElement
                if (taskbarWindow.TabbedThumbnail.WindowHandle != IntPtr.Zero)
                {
                    TabbedThumbnailNativeMethods.GetClientSize(taskbarWindow.TabbedThumbnail.WindowHandle, out realWindowSize);
                }
                else if (taskbarWindow.TabbedThumbnail.WindowsControl != null)
                {
                    realWindowSize = new Size(
                        Convert.ToInt32(taskbarWindow.TabbedThumbnail.WindowsControl.RenderSize.Width),
                        Convert.ToInt32(taskbarWindow.TabbedThumbnail.WindowsControl.RenderSize.Height));
                }

                if (realWindowSize.Height == -1 && realWindowSize.Width == -1)
                {
                    realWindowSize.Width = realWindowSize.Height = 199;
                }

                // capture the bitmap for the given control
                // If the user has already specified us a bitmap to use, use that.
                if (taskbarWindow.TabbedThumbnail.ClippingRectangle != null &&
                    taskbarWindow.TabbedThumbnail.ClippingRectangle.Value != Rectangle.Empty)
                {
                    if (taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero)
                    {
                        hBitmap = GrabBitmap(taskbarWindow, realWindowSize);
                    }
                    else
                    {
                        hBitmap = taskbarWindow.TabbedThumbnail.CurrentHBitmap;
                    }

                    // Clip the bitmap we just got.
                    Bitmap bmp = Bitmap.FromHbitmap(hBitmap);

                    Rectangle clippingRectangle = taskbarWindow.TabbedThumbnail.ClippingRectangle.Value;

                    // If our clipping rect is out of bounds, update it
                    if (clippingRectangle.Height > requestedSize.Height)
                    {
                        clippingRectangle.Height = requestedSize.Height;
                    }
                    if (clippingRectangle.Width > requestedSize.Width)
                    {
                        clippingRectangle.Width = requestedSize.Width;
                    }

                    // NOTE: Is this a memory leak?
                    bmp = bmp.Clone(clippingRectangle, bmp.PixelFormat);

                    // Make sure we dispose the bitmap before assigning, otherwise we'll have a memory leak
                    if (hBitmap != IntPtr.Zero && taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero)
                    {
                        ShellNativeMethods.DeleteObject(hBitmap);
                    }
                    hBitmap = bmp.GetHbitmap();
                    bmp.Dispose();
                }
                else
                {
                    // Else, user didn't want any clipping, if they haven't provided us a bitmap,
                    // use the screencapture utility and capture it.

                    hBitmap = taskbarWindow.TabbedThumbnail.CurrentHBitmap;

                    // If no bitmap, capture one using the utility
                    if (hBitmap == IntPtr.Zero)
                    {
                        hBitmap = GrabBitmap(taskbarWindow, realWindowSize);
                    }
                }

                // Only set the thumbnail if it's not null.
                // If it's null (either we didn't get the bitmap or size was 0),
                // let DWM handle it
                if (hBitmap != IntPtr.Zero)
                {
                    Bitmap temp = TabbedThumbnailScreenCapture.ResizeImageWithAspect(
                        hBitmap, requestedSize.Width, requestedSize.Height, true);

                    if (taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero)
                    {
                        ShellNativeMethods.DeleteObject(hBitmap);
                    }

                    hBitmap = temp.GetHbitmap();
                    TabbedThumbnailNativeMethods.SetIconicThumbnail(taskbarWindow.WindowToTellTaskbarAbout, hBitmap);
                    temp.Dispose();
                }

                // If the bitmap we have is not coming from the user (i.e. we created it here),
                // then make sure we delete it as we don't need it now.
                if (taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero)
                {
                    ShellNativeMethods.DeleteObject(hBitmap);
                }

                return(true);
            }
            return(false);
        }
        /// <summary>
        /// Dispatches a window message so that the appropriate events
        /// can be invoked. This is used for the Taskbar's thumbnail toolbar feature.
        /// </summary>
        /// <param name="m">The window message, typically obtained
        /// from a Windows Forms or WPF window procedure.</param>
        /// <param name="taskbarWindow">Taskbar window for which we are intercepting the messages</param>
        /// <returns>Returns true if this method handles the window message</returns>
        internal bool DispatchMessage(ref Message m, TaskbarWindow taskbarWindow)
        {
            if (taskbarWindow.EnableThumbnailToolbars)
            {
                if (m.Msg == (int)TaskbarNativeMethods.WM_TASKBARBUTTONCREATED)
                {
                    AddButtons(taskbarWindow);
                }
                else
                {
                    if (!buttonsAdded)
                    {
                        AddButtons(taskbarWindow);
                    }

                    switch (m.Msg)
                    {
                    case TaskbarNativeMethods.WM_COMMAND:
                        if (CoreNativeMethods.HIWORD(m.WParam.ToInt64(), 16) == THUMBBUTTON.THBN_CLICKED)
                        {
                            int buttonId = CoreNativeMethods.LOWORD(m.WParam.ToInt64());

                            var buttonsFound =
                                from b in taskbarWindow.ThumbnailButtons
                                where b.Id == buttonId
                                select b;

                            foreach (ThumbnailToolbarButton button in buttonsFound)
                            {
                                button.FireClick(taskbarWindow);
                            }
                        }
                        break;
                    } // End switch
                }     // End else
            }         // End if


            // If we are removed from the taskbar, ignore all the messages
            if (taskbarWindow.EnableTabbedThumbnails)
            {
                if (taskbarWindow.TabbedThumbnail.RemovedFromTaskbar)
                {
                    return(false);
                }
                else if (m.Msg == (int)TabbedThumbnailNativeMethods.WM_ACTIVATE)
                {
                    // Raise the event
                    taskbarWindow.TabbedThumbnail.OnTabbedThumbnailActivated();

                    SetActiveTab(taskbarWindow);

                    return(true);
                }
                else if (m.Msg == (int)TaskbarNativeMethods.WM_DWMSENDICONICTHUMBNAIL)
                {
                    int  width         = (int)((long)m.LParam >> 16);
                    int  height        = (int)(((long)m.LParam) & (0xFFFF));
                    Size requestedSize = new Size(width, height);

                    // Fire an event to let the user update their bitmap
                    // Raise the event
                    taskbarWindow.TabbedThumbnail.OnTabbedThumbnailBitmapRequested();

                    IntPtr hBitmap = IntPtr.Zero;

                    // Default size for the thumbnail
                    Size realWindowSize = new Size(200, 200);

                    if (taskbarWindow.TabbedThumbnail.WindowHandle != IntPtr.Zero)
                    {
                        TabbedThumbnailNativeMethods.GetClientSize(taskbarWindow.TabbedThumbnail.WindowHandle, out realWindowSize);
                    }
                    else if (taskbarWindow.TabbedThumbnail.WindowsControl != null)
                    {
                        realWindowSize = new Size(
                            Convert.ToInt32(taskbarWindow.TabbedThumbnail.WindowsControl.RenderSize.Width),
                            Convert.ToInt32(taskbarWindow.TabbedThumbnail.WindowsControl.RenderSize.Height));
                    }

                    if ((realWindowSize.Height == -1) && (realWindowSize.Width == -1))
                    {
                        realWindowSize.Width = realWindowSize.Height = 199;
                    }

                    // capture the bitmap for the given control
                    // If the user has already specified us a bitmap to use, use that.
                    if (taskbarWindow.TabbedThumbnail.ClippingRectangle != null && taskbarWindow.TabbedThumbnail.ClippingRectangle.Value != Rectangle.Empty)
                    {
                        if (taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero)
                        {
                            hBitmap = GrabBitmap(taskbarWindow, realWindowSize);
                        }
                        else
                        {
                            hBitmap = taskbarWindow.TabbedThumbnail.CurrentHBitmap;
                        }

                        // Clip the bitmap we just got
                        Bitmap bmp = Bitmap.FromHbitmap(hBitmap);

                        Rectangle clippingRectangle = taskbarWindow.TabbedThumbnail.ClippingRectangle.Value;

                        // If our clipping rect is out of bounds, update it
                        if (clippingRectangle.Height > requestedSize.Height)
                        {
                            clippingRectangle.Height = requestedSize.Height;
                        }
                        if (clippingRectangle.Width > requestedSize.Width)
                        {
                            clippingRectangle.Width = requestedSize.Width;
                        }

                        bmp = bmp.Clone(clippingRectangle, bmp.PixelFormat);

                        // Make sure we dispose the bitmap before assigning, otherwise we'll have a memory leak
                        if (hBitmap != IntPtr.Zero && taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero)
                        {
                            ShellNativeMethods.DeleteObject(hBitmap);
                        }
                        hBitmap = bmp.GetHbitmap();
                    }
                    else
                    {
                        // Else, user didn't want any clipping, if they haven't provided us a bitmap,
                        // use the screencapture utility and capture it.

                        hBitmap = taskbarWindow.TabbedThumbnail.CurrentHBitmap;

                        // If no bitmap, capture one using the utility
                        if (hBitmap == IntPtr.Zero)
                        {
                            hBitmap = GrabBitmap(taskbarWindow, realWindowSize);
                        }
                    }

                    // Only set the thumbnail if it's not null.
                    // If it's null (either we didn't get the bitmap or size was 0),
                    // let DWM handle it
                    if (hBitmap != IntPtr.Zero)
                    {
                        Bitmap temp = TabbedThumbnailScreenCapture.ResizeImageWithAspect(hBitmap, requestedSize.Width, requestedSize.Height, true);

                        if (taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero)
                        {
                            ShellNativeMethods.DeleteObject(hBitmap);
                        }

                        hBitmap = temp.GetHbitmap();
                        TabbedThumbnailNativeMethods.SetIconicThumbnail(taskbarWindow.WindowToTellTaskbarAbout, hBitmap);
                        temp.Dispose();
                    }

                    // If the bitmap we have is not coming from the user (i.e. we created it here),
                    // then make sure we delete it as we don't need it now.
                    if (taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero)
                    {
                        ShellNativeMethods.DeleteObject(hBitmap);
                    }

                    return(true);
                }
                else if (m.Msg == (int)TaskbarNativeMethods.WM_DWMSENDICONICLIVEPREVIEWBITMAP)
                {
                    // Try to get the width/height
                    int width  = (int)(((long)m.LParam) >> 16);
                    int height = (int)(((long)m.LParam) & (0xFFFF));

                    // Default size for the thumbnail
                    Size realWindowSize = new Size(200, 200);

                    if (taskbarWindow.TabbedThumbnail.WindowHandle != IntPtr.Zero)
                    {
                        TabbedThumbnailNativeMethods.GetClientSize(taskbarWindow.TabbedThumbnail.WindowHandle, out realWindowSize);
                    }
                    else if (taskbarWindow.TabbedThumbnail.WindowsControl != null)
                    {
                        realWindowSize = new Size(
                            Convert.ToInt32(taskbarWindow.TabbedThumbnail.WindowsControl.RenderSize.Width),
                            Convert.ToInt32(taskbarWindow.TabbedThumbnail.WindowsControl.RenderSize.Height));
                    }

                    // If we don't have a valid height/width, use the original window's size
                    if (width <= 0)
                    {
                        width = realWindowSize.Width;
                    }
                    if (height <= 0)
                    {
                        height = realWindowSize.Height;
                    }

                    // Fire an event to let the user update their bitmap
                    // Raise the event
                    taskbarWindow.TabbedThumbnail.OnTabbedThumbnailBitmapRequested();

                    // capture the bitmap for the given control
                    // If the user has already specified us a bitmap to use, use that.
                    IntPtr hBitmap = taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero ? GrabBitmap(taskbarWindow, realWindowSize) : taskbarWindow.TabbedThumbnail.CurrentHBitmap;

                    // If we have a valid parent window handle,
                    // calculate the offset so we can place the "peek" bitmap
                    // correctly on the app window
                    if (taskbarWindow.TabbedThumbnail.ParentWindowHandle != IntPtr.Zero && taskbarWindow.TabbedThumbnail.WindowHandle != IntPtr.Zero)
                    {
                        Point offset = new Point();

                        // if we don't have a offset specified already by the user...
                        if (!taskbarWindow.TabbedThumbnail.PeekOffset.HasValue)
                        {
                            offset = WindowUtilities.GetParentOffsetOfChild(taskbarWindow.TabbedThumbnail.WindowHandle, taskbarWindow.TabbedThumbnail.ParentWindowHandle);
                        }
                        else
                        {
                            offset = new Point(Convert.ToInt32(taskbarWindow.TabbedThumbnail.PeekOffset.Value.X),
                                               Convert.ToInt32(taskbarWindow.TabbedThumbnail.PeekOffset.Value.Y));
                        }

                        // Only set the peek bitmap if it's not null.
                        // If it's null (either we didn't get the bitmap or size was 0),
                        // let DWM handle it
                        if (hBitmap != IntPtr.Zero)
                        {
                            if (offset.X >= 0 && offset.Y >= 0)
                            {
                                TabbedThumbnailNativeMethods.SetPeekBitmap(taskbarWindow.WindowToTellTaskbarAbout, hBitmap, offset, taskbarWindow.TabbedThumbnail.DisplayFrameAroundBitmap);
                            }
                        }

                        // If the bitmap we have is not coming from the user (i.e. we created it here),
                        // then make sure we delete it as we don't need it now.
                        if (taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero)
                        {
                            ShellNativeMethods.DeleteObject(hBitmap);
                        }

                        return(true);
                    }
                    // Else, we don't have a valid window handle from the user. This is mostly likely because
                    // we have a WPF UIElement control. If that's the case, use a different screen capture method
                    // and also couple of ways to try to calculate the control's offset w.r.t it's parent.
                    else if (taskbarWindow.TabbedThumbnail.ParentWindowHandle != IntPtr.Zero &&
                             taskbarWindow.TabbedThumbnail.WindowsControl != null)
                    {
                        System.Windows.Point offset;

                        if (!taskbarWindow.TabbedThumbnail.PeekOffset.HasValue)
                        {
                            // Calculate the offset for a WPF UIElement control
                            // For hidden controls, we can't seem to perform the transform.
                            GeneralTransform objGeneralTransform = taskbarWindow.TabbedThumbnail.WindowsControl.TransformToVisual(taskbarWindow.TabbedThumbnail.WindowsControlParentWindow);
                            offset = objGeneralTransform.Transform(new System.Windows.Point(0, 0));
                        }
                        else
                        {
                            offset = new System.Windows.Point(taskbarWindow.TabbedThumbnail.PeekOffset.Value.X, taskbarWindow.TabbedThumbnail.PeekOffset.Value.Y);
                        }

                        // Only set the peek bitmap if it's not null.
                        // If it's null (either we didn't get the bitmap or size was 0),
                        // let DWM handle it
                        if (hBitmap != IntPtr.Zero)
                        {
                            if (offset.X >= 0 && offset.Y >= 0)
                            {
                                TabbedThumbnailNativeMethods.SetPeekBitmap(taskbarWindow.WindowToTellTaskbarAbout, hBitmap, new Point((int)offset.X, (int)offset.Y), taskbarWindow.TabbedThumbnail.DisplayFrameAroundBitmap);
                            }
                            else
                            {
                                TabbedThumbnailNativeMethods.SetPeekBitmap(taskbarWindow.WindowToTellTaskbarAbout, hBitmap, taskbarWindow.TabbedThumbnail.DisplayFrameAroundBitmap);
                            }
                        }

                        // If the bitmap we have is not coming from the user (i.e. we created it here),
                        // then make sure we delete it as we don't need it now.
                        if (taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero)
                        {
                            ShellNativeMethods.DeleteObject(hBitmap);
                        }

                        return(true);
                    }
                    else
                    {
                        // Else (no parent specified), just set the bitmap. It would take over the entire
                        // application window (would work only if you are a MDI app)

                        // Only set the peek bitmap if it's not null.
                        // If it's null (either we didn't get the bitmap or size was 0),
                        // let DWM handle it
                        if (hBitmap != null)
                        {
                            TabbedThumbnailNativeMethods.SetPeekBitmap(taskbarWindow.WindowToTellTaskbarAbout, hBitmap, taskbarWindow.TabbedThumbnail.DisplayFrameAroundBitmap);
                        }

                        // If the bitmap we have is not coming from the user (i.e. we created it here),
                        // then make sure we delete it as we don't need it now.
                        if (taskbarWindow.TabbedThumbnail.CurrentHBitmap == IntPtr.Zero)
                        {
                            ShellNativeMethods.DeleteObject(hBitmap);
                        }

                        return(true);
                    }
                }
                else if (m.Msg == (int)TabbedThumbnailNativeMethods.WM_DESTROY)
                {
                    TaskbarManager.Instance.TaskbarList.UnregisterTab(taskbarWindow.WindowToTellTaskbarAbout);

                    taskbarWindow.TabbedThumbnail.RemovedFromTaskbar = true;

                    return(true);
                }
                else if (m.Msg == (int)TabbedThumbnailNativeMethods.WM_NCDESTROY)
                {
                    // Raise the event
                    taskbarWindow.TabbedThumbnail.OnTabbedThumbnailClosed();

                    // Remove the taskbar window from our internal list
                    if (taskbarWindowList.Contains(taskbarWindow))
                    {
                        taskbarWindowList.Remove(taskbarWindow);
                    }

                    taskbarWindow.Dispose();
                    taskbarWindow = null;

                    return(true);
                }
                else if (m.Msg == (int)TabbedThumbnailNativeMethods.WM_SYSCOMMAND)
                {
                    if (((int)m.WParam) == TabbedThumbnailNativeMethods.SC_CLOSE)
                    {
                        // Raise the event
                        taskbarWindow.TabbedThumbnail.OnTabbedThumbnailClosed();

                        // Remove the taskbar window from our internal list
                        if (taskbarWindowList.Contains(taskbarWindow))
                        {
                            taskbarWindowList.Remove(taskbarWindow);
                        }

                        taskbarWindow.Dispose();
                        taskbarWindow = null;
                    }
                    else if (((int)m.WParam) == TabbedThumbnailNativeMethods.SC_MAXIMIZE)
                    {
                        // Raise the event
                        taskbarWindow.TabbedThumbnail.OnTabbedThumbnailMaximized();
                    }
                    else if (((int)m.WParam) == TabbedThumbnailNativeMethods.SC_MINIMIZE)
                    {
                        // Raise the event
                        taskbarWindow.TabbedThumbnail.OnTabbedThumbnailMinimized();
                    }

                    return(true);
                }
            }

            return(false);
        }