UI.cs :  » GUI » Paint.net » PaintDotNet » SystemLayer » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » GUI » Paint.net 
Paint.net » PaintDotNet » SystemLayer » UI.cs
/////////////////////////////////////////////////////////////////////////////////
// Paint.NET                                                                   //
// Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors.     //
// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.          //
// See src/Resources/Files/License.txt for full licensing and attribution      //
// details.                                                                    //
// .                                                                           //
/////////////////////////////////////////////////////////////////////////////////

using PaintDotNet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

namespace PaintDotNet.SystemLayer{
    /// <summary>
    /// Contains static methods related to the user interface.
    /// </summary>
    public static class UI
    {
        private static bool initScales = false;
        private static float xScale;
        private static float yScale;

        public static void FlashForm(Form form)
        {
            IntPtr hWnd = form.Handle;
            SafeNativeMethods.FlashWindow(hWnd, false);
            SafeNativeMethods.FlashWindow(hWnd, false);
            GC.KeepAlive(form);
        }

        /// <summary>
        /// In some circumstances, the window manager will draw the window larger than it reports
        /// its size to be. You can use this function to retrieve the size of this extra border
        /// padding.
        /// </summary>
        /// <param name="window"></param>
        /// <returns>
        /// An integer greater than or equal to zero that describes the size of the border padding
        /// which is not reported via the window's Size or Bounds property.
        /// </returns>
        /// <remarks>
        /// Note to implementors: This method may simply return 0. It is provided for use in Windows
        /// Vista when DWM+Aero is enabled in which case sizable FloatingToolForm windows do not
        /// visibly dock to the correct locations.
        /// </remarks>
        public static int GetExtendedFrameBounds(Form window)
        {
            int returnVal;

            if (OS.IsVistaOrLater)
            {
                unsafe
                {
                    int* rcVal = stackalloc int[4];

                    int hr = SafeNativeMethods.DwmGetWindowAttribute(
                        window.Handle,
                        NativeConstants.DWMWA_EXTENDED_FRAME_BOUNDS,
                        (void*)rcVal,
                        4 * (uint)sizeof(int));

                    if (hr >= 0)
                    {
                        returnVal = -rcVal[0];
                    }
                    else
                    {
                        returnVal = 0;
                    }
                }
            }
            else
            {
                returnVal = 0;
            }

            GC.KeepAlive(window);
            return Math.Max(0, returnVal);
        }

        private static void InitScaleFactors(Control c)
        {
            if (c == null)
            {
                xScale = 1.0f;
                yScale = 1.0f;
            }
            else
            {
                using (Graphics g = c.CreateGraphics())
                {
                    xScale = g.DpiX / 96.0f;
                    yScale = g.DpiY / 96.0f;
                }
            }

            initScales = true;
        }

        public static void InitScaling(Control c)
        {
            if (!initScales)
            {
                InitScaleFactors(c);
            }
        }

        public static float ScaleWidth(float width)
        {
            return (float)Math.Round(width * GetXScaleFactor());
        }

        public static int ScaleWidth(int width)
        {
            return (int)Math.Round((float)width * GetXScaleFactor());
        }

        public static int ScaleHeight(int height)
        {
            return (int)Math.Round((float)height * GetYScaleFactor());
        }

        public static float ScaleHeight(float height)
        {
            return (float)Math.Round(height * GetYScaleFactor());
        }

        public static Size ScaleSize(Size size)
        {
            return new Size(ScaleWidth(size.Width), ScaleHeight(size.Height));
        }

        public static Point ScalePoint(Point pt)
        {
            return new Point(ScaleWidth(pt.X), ScaleHeight(pt.Y));
        }

        public static float GetXScaleFactor()
        {
            if (!initScales)
            {
                throw new InvalidOperationException("Must call InitScaling() first");
            }

            return xScale;
        }

        public static float GetYScaleFactor()
        {
            if (!initScales)
            {
                throw new InvalidOperationException("Must call InitScaling() first");
            }

            return yScale;
        }

        public static void DrawCommandButton(
            Graphics g, 
            PushButtonState state, 
            Rectangle rect, 
            Color backColor,
            Control childControl)
        {
            VisualStyleElement element = null;
            int alpha = 255;
            
            if (OS.IsVistaOrLater)
            {
                const string className = "BUTTON";
                const int partID = NativeConstants.BP_COMMANDLINK;
                int stateID;

                switch (state)
                {
                    case PushButtonState.Default:
                        stateID = NativeConstants.CMDLS_DEFAULTED;
                        break;

                    case PushButtonState.Disabled:
                        stateID = NativeConstants.CMDLS_DISABLED;
                        break;
                        
                    case PushButtonState.Hot:
                        stateID = NativeConstants.CMDLS_HOT;
                        break;

                    case PushButtonState.Normal:
                        stateID = NativeConstants.CMDLS_NORMAL;
                        break;

                    case PushButtonState.Pressed:
                        stateID = NativeConstants.CMDLS_PRESSED;
                        break;

                    default:
                        throw new InvalidEnumArgumentException();
                }

                try
                {
                    element = VisualStyleElement.CreateElement(className, partID, stateID);

                    if (!VisualStyleRenderer.IsElementDefined(element))
                    {
                        element = null;
                    }
                }

                catch (InvalidOperationException)
                {
                    element = null;
                }
            }

            if (element == null)
            {
                switch (state)
                {
                    case PushButtonState.Default:
                        element = VisualStyleElement.Button.PushButton.Default;
                        alpha = 95;
                        break;

                    case PushButtonState.Disabled:
                        element = VisualStyleElement.Button.PushButton.Disabled;
                        break;

                    case PushButtonState.Hot:
                        element = VisualStyleElement.Button.PushButton.Hot;
                        break;

                    case PushButtonState.Normal:
                        alpha = 0;
                        element = VisualStyleElement.Button.PushButton.Normal;
                        break;
                    case PushButtonState.Pressed:
                        element = VisualStyleElement.Button.PushButton.Pressed;
                        break;

                    default:
                        throw new InvalidEnumArgumentException();
                }
            }

            if (element != null)
            {
                try
                {
                    VisualStyleRenderer renderer = new VisualStyleRenderer(element);
                    renderer.DrawParentBackground(g, rect, childControl);
                    renderer.DrawBackground(g, rect);
                }

                catch (Exception)
                {
                    element = null;
                }
            }

            if (element == null)
            {
                ButtonRenderer.DrawButton(g, rect, state);
            }

            if (alpha != 255)
            {
                using (Brush backBrush = new SolidBrush(Color.FromArgb(255 - alpha, backColor)))
                {
                    CompositingMode oldCM = g.CompositingMode;

                    try
                    {
                        g.CompositingMode = CompositingMode.SourceOver;
                        g.FillRectangle(backBrush, rect);
                    }

                    finally
                    {
                        g.CompositingMode = oldCM;
                    }
                }
            }
        }
       
        /// <summary>
        /// Sets the control's redraw state.
        /// </summary>
        /// <param name="control">The control whose state should be modified.</param>
        /// <param name="enabled">The new state for redrawing ability.</param>
        /// <remarks>
        /// Note to implementors: This method is used by SuspendControlPainting() and ResumeControlPainting().
        /// This may be implemented as a no-op.
        /// </remarks>
        private static void SetControlRedrawImpl(Control control, bool enabled)
        {
            SafeNativeMethods.SendMessageW(control.Handle, NativeConstants.WM_SETREDRAW, enabled ? new IntPtr(1) : IntPtr.Zero, IntPtr.Zero);
            GC.KeepAlive(control);
        }

        private static Dictionary<Control, int> controlRedrawStack = new Dictionary<Control, int>();

        /// <summary>
        /// Suspends the control's ability to draw itself.
        /// </summary>
        /// <param name="control">The control to suspend drawing for.</param>
        /// <remarks>
        /// When drawing is suspended, any painting performed in the control's WM_PAINT, OnPaint(),
        /// WM_ERASEBKND, or OnPaintBackground() handlers is completely ignored. Invalidation rectangles
        /// are not accumulated during this period, so when drawing is resumed (with 
        /// ResumeControlPainting()), it is usually a good idea to call Invalidate(true) on the control.
        /// This method must be matched at a later time by a corresponding call to ResumeControlPainting().
        /// If you call SuspendControlPainting() multiple times for the same control, then you must
        /// call ResumeControlPainting() once for each call.
        /// Note to implementors: Do not modify this method. Instead, modify SetControlRedrawImpl(),
        /// which may be implemented as a no-op.
        /// </remarks>
        public static void SuspendControlPainting(Control control)
        {
            int pushCount;

            if (controlRedrawStack.TryGetValue(control, out pushCount))
            {
                ++pushCount;
            }
            else
            {
                pushCount = 1;
            }

            if (pushCount == 1)
            {
                SetControlRedrawImpl(control, false);
            }

            controlRedrawStack[control] = pushCount;
        }

        /// <summary>
        /// Resumes the control's ability to draw itself.
        /// </summary>
        /// <param name="control">The control to suspend drawing for.</param>
        /// <remarks>
        /// This method must be matched by a preceding call to SuspendControlPainting(). If that method
        /// was called multiple times, then this method must be called a corresponding number of times
        /// in order to enable drawing.
        /// This method must be matched at a later time by a corresponding call to ResumeControlPainting().
        /// If you call SuspendControlPainting() multiple times for the same control, then you must
        /// call ResumeControlPainting() once for each call.
        /// Note to implementors: Do not modify this method. Instead, modify SetControlRedrawImpl(),
        /// which may be implemented as a no-op.
        /// </remarks>        
        public static void ResumeControlPainting(Control control)
        {
            int pushCount;

            if (controlRedrawStack.TryGetValue(control, out pushCount))
            {
                --pushCount;
            }
            else
            {
                throw new InvalidOperationException("There was no previous matching SuspendControlPainting() for this control");
            }

            if (pushCount == 0)
            {
                SetControlRedrawImpl(control, true);
                controlRedrawStack.Remove(control);
            }
            else
            {
                controlRedrawStack[control] = pushCount;
            }
        }

        /// <summary>
        /// Queries whether painting is enabled for the given control.
        /// </summary>
        /// <param name="control">The control to query suspension for.</param>
        /// <returns>
        /// false if the control's painting has been suspended via a call to SuspendControlPainting(),
        /// otherwise true.
        /// </returns>
        /// <remarks>
        /// You may use the return value of this method to optimize away painting. If this
        /// method returns false, then you may skip your entire OnPaint() method. This saves
        /// processor time by avoiding all of the non-painting drawing and resource initialization
        /// and destruction that is typically contained in OnPaint().
        /// This method assumes painting suspension is being exclusively managed with Suspend-
        /// and ResumeControlPainting().
        /// </remarks>
        public static bool IsControlPaintingEnabled(Control control)
        {
            int pushCount;

            if (!controlRedrawStack.TryGetValue(control, out pushCount))
            {
                pushCount = 0;
            }

            return (pushCount == 0);
        }

        private static IntPtr hRgn = SafeNativeMethods.CreateRectRgn(0, 0, 1, 1);

        /// <summary>
        /// This method retrieves the update region of a control.
        /// </summary>
        /// <param name="control">The control to retrieve the update region for.</param>
        /// <returns>
        /// An array of rectangles specifying the area that has been invalidated, or 
        /// null if this could not be determined.
        /// </returns>
        /// <remarks>
        /// This method is not thread safe.
        /// Note to implementors: This method may be implemented as a no-op. In this case, just return null.
        /// </remarks>
        public static Rectangle[] GetUpdateRegion(Control control)
        {
            SafeNativeMethods.GetUpdateRgn(control.Handle, hRgn, false);
            Rectangle[] scans;
            int area;
            PdnGraphics.GetRegionScans(hRgn, out scans, out area);
            GC.KeepAlive(control);
            return scans;
        }

        /// <summary>
        /// Sets a form's opacity.
        /// </summary>
        /// <param name="form"></param>
        /// <param name="opacity"></param>
        /// <remarks>
        /// Note to implementors: This may be implemented as just "form.Opacity = opacity".
        /// This method works around some visual clumsiness in .NET 2.0 related to
        /// transitioning between opacity == 1.0 and opacity != 1.0.</remarks>
        public static void SetFormOpacity(Form form, double opacity)
        {
            if (opacity < 0.0 || opacity > 1.0)
            {
                throw new ArgumentOutOfRangeException("opacity", "must be in the range [0, 1]");
            }

            uint exStyle = SafeNativeMethods.GetWindowLongW(form.Handle, NativeConstants.GWL_EXSTYLE);

            byte bOldAlpha = 255;

            if ((exStyle & NativeConstants.GWL_EXSTYLE) != 0)
            {
                uint dwOldKey;
                uint dwOldFlags;
                bool result = SafeNativeMethods.GetLayeredWindowAttributes(form.Handle, out dwOldKey, out bOldAlpha, out dwOldFlags);
            }

            byte bNewAlpha = (byte)(opacity * 255.0);
            uint newExStyle = exStyle;

            if (bNewAlpha != 255)
            {
                newExStyle |= NativeConstants.WS_EX_LAYERED;
            }

            if (newExStyle != exStyle || (newExStyle & NativeConstants.WS_EX_LAYERED) != 0)
            {
                if (newExStyle != exStyle)
                {
                    SafeNativeMethods.SetWindowLongW(form.Handle, NativeConstants.GWL_EXSTYLE, newExStyle);
                }

                if ((newExStyle & NativeConstants.WS_EX_LAYERED) != 0)
                {
                    SafeNativeMethods.SetLayeredWindowAttributes(form.Handle, 0, bNewAlpha, NativeConstants.LWA_ALPHA);
                }
            }

            GC.KeepAlive(form);
        }

        /// <summary>
        /// This WndProc implements click-through functionality. Some controls (MenuStrip, ToolStrip) will not
        /// recognize a click unless the form they are hosted in is active. So the first click will activate the
        /// form and then a second is required to actually make the click happen.
        /// </summary>
        /// <param name="m">The Message that was passed to your WndProc.</param>
        /// <returns>true if the message was processed, false if it was not</returns>
        /// <remarks>
        /// You should first call base.WndProc(), and then call this method. This method is only intended to
        /// change a return value, not to change actual processing before that.
        /// </remarks>
        internal static bool ClickThroughWndProc(ref Message m)
        {
            bool returnVal = false;

            if (m.Msg == NativeConstants.WM_MOUSEACTIVATE)
            {
                if (m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT)
                {
                    m.Result = (IntPtr)NativeConstants.MA_ACTIVATE;
                    returnVal = true;
                }
            }

            return returnVal;
        }

        public static bool IsOurAppActive
        {
            get
            {
                foreach (Form form in Application.OpenForms)
                {
                    if (form == Form.ActiveForm)
                    {
                        return true;
                    }
                }

                return false;
            }
        }

        private static VisualStyleClass DetermineVisualStyleClass()
        {
            return Do.TryCatch(DetermineVisualStyleClassImpl, ex => VisualStyleClass.Other);
        }

        private static VisualStyleClass DetermineVisualStyleClassImpl()
        {
            VisualStyleClass vsClass;

            if (!VisualStyleInformation.IsSupportedByOS)
            {
                vsClass = VisualStyleClass.Classic;
            }
            else if (!VisualStyleInformation.IsEnabledByUser)
            {
                vsClass = VisualStyleClass.Classic;
            }
            else if (0 == string.Compare(VisualStyleInformation.Author, "MSX", StringComparison.InvariantCulture) &&
                     0 == string.Compare(VisualStyleInformation.DisplayName, "Aero style", StringComparison.InvariantCulture))
            {
                vsClass = VisualStyleClass.Aero;
            }
            else if (0 == string.Compare(VisualStyleInformation.Company, "Microsoft Corporation", StringComparison.InvariantCulture) &&
                     0 == string.Compare(VisualStyleInformation.Author, "Microsoft Design Team", StringComparison.InvariantCulture))
            {
                if (0 == string.Compare(VisualStyleInformation.DisplayName, "Windows XP style", StringComparison.InvariantCulture) ||  // Luna
                    0 == string.Compare(VisualStyleInformation.DisplayName, "Zune Style", StringComparison.InvariantCulture) ||        // Zune
                    0 == string.Compare(VisualStyleInformation.DisplayName, "Media Center style", StringComparison.InvariantCulture))  // Royale
                {
                    vsClass = VisualStyleClass.Luna;
                }
                else
                {
                    vsClass = VisualStyleClass.Other;
                }
            }
            else
            {
                vsClass = VisualStyleClass.Other;
            }

            return vsClass;
        }

        public static VisualStyleClass VisualStyleClass
        {
            get
            {
                return DetermineVisualStyleClass();
            }
        }

        public static void EnableShield(Button button, bool enableShield)
        {
            IntPtr hWnd = button.Handle;

            SafeNativeMethods.SendMessageW(
                hWnd,
                NativeConstants.BCM_SETSHIELD,
                IntPtr.Zero,
                enableShield ? new IntPtr(1) : IntPtr.Zero);

            GC.KeepAlive(button);
        }

        // TODO: get rid of this somehow! (this will happen when Layers window is rewritten, post-3.0)
        public static bool HideHorizontalScrollBar(Control c)
        {
            return SafeNativeMethods.ShowScrollBar(c.Handle, NativeConstants.SB_HORZ, false);
        }

        public static void RestoreWindow(IWin32Window window)
        {
            IntPtr hWnd = window.Handle;
            SafeNativeMethods.ShowWindow(hWnd, NativeConstants.SW_RESTORE);
            GC.KeepAlive(window);
        }

        public static void ShowComboBox(ComboBox comboBox, bool show)
        {
            IntPtr hWnd = comboBox.Handle;

            SafeNativeMethods.SendMessageW(
                hWnd,
                NativeConstants.CB_SHOWDROPDOWN,
                show ? new IntPtr(1) : IntPtr.Zero,
                IntPtr.Zero);

            GC.KeepAlive(comboBox);
        }

        /// <summary>
        /// Disables the system menu "Close" menu command, as well as the "X" close button on the window title bar.
        /// </summary>
        /// <remarks>
        /// Note to implementors: This method may *not* be implemented as a no-op. The purpose is to make it so that
        /// calling the Close() method is the only way to close a dialog, which is something that can only be done
        /// programmatically.
        /// </remarks>
        public static void DisableCloseBox(IWin32Window window)
        {
            IntPtr hWnd = window.Handle;
            IntPtr hMenu = SafeNativeMethods.GetSystemMenu(hWnd, false);

            if (hMenu == IntPtr.Zero)
            {
                NativeMethods.ThrowOnWin32Error("GetSystemMenu() returned NULL");
            }

            int result = SafeNativeMethods.EnableMenuItem(
                hMenu, 
                NativeConstants.SC_CLOSE, 
                NativeConstants.MF_BYCOMMAND | NativeConstants.MF_GRAYED);

            bool bResult = SafeNativeMethods.DrawMenuBar(hWnd);
            if (!bResult)
            {
                NativeMethods.ThrowOnWin32Error("DrawMenuBar returned FALSE");
            }

            GC.KeepAlive(window);
        }

        internal static void InvokeThroughModalTrampoline(IWin32Window owner, Procedure<IWin32Window> invokeMe)
        {
            using (Form modalityFix = new Form())
            {
                modalityFix.ShowInTaskbar = false;
                modalityFix.TransparencyKey = modalityFix.BackColor;
                UI.SetFormOpacity(modalityFix, 0);
                modalityFix.ControlBox = false;
                modalityFix.FormBorderStyle = FormBorderStyle.None;

                Control ownerAsControl = owner as Control;
                if (ownerAsControl != null)
                {
                    Form ownerForm = ownerAsControl.FindForm();

                    if (ownerForm != null)
                    {
                        Rectangle clientRect = ownerForm.RectangleToScreen(ownerForm.ClientRectangle);

                        modalityFix.Icon = ownerForm.Icon;
                        modalityFix.Location = clientRect.Location;
                        modalityFix.Size = clientRect.Size;
                        modalityFix.StartPosition = FormStartPosition.Manual;
                    }
                }

                modalityFix.Shown +=
                    delegate(object sender, EventArgs e)
                    {
                        invokeMe(modalityFix);
                        modalityFix.Close();
                    };

                modalityFix.ShowDialog(owner);
                GC.KeepAlive(modalityFix);
            }
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.