[.net3.5] extension methods: progressbar et vista

Description

Je rappel pour ceux qui ne connaissent pas les "extensions methods" qu'il s'agit d'une nouveauté de c#3. Elles permettent d'étendre les méthodes sur des classes existantes. Ceci peut s'avérer pratique dans le cas ou l'on souhaite ajouter des méthodes sur une classe dont on a pas les sources et/ou on ne peut pas en hériter.

J'ai mis en application cette nouveauté sur le contrôle ProgressBar en y ajoutant des méthodes propres à des fonctionnalités de Vista. (voir la capture)

Le code est commenté bien que la source soit simple.

Source / Exemple :


using System;
using System.Runtime.InteropServices;

namespace ExtensionMethods
{
    public static class Progressbar
    {
        #region "Native methods"

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", EntryPoint = "GetWindowLong", SetLastError = true)]
        private static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
        private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        const int WM_USER = 0x400;
        const int GWL_STYLE = (-16);
        const int PBM_SETPOS = (WM_USER + 2);
        const int PBM_SETSTATE = (WM_USER + 16);
        const int PBM_GETSTATE = (WM_USER + 17);
        const int PBS_SMOOTH = 0x01;
        const int PBS_SMOOTHREVERSE = 0x10;

        #endregion

        /// <summary>
        /// Etat de la barre de progression.
        /// </summary>
        public enum PBM_STATE : int
        {
            NORMAL = 0x1,
            ERROR,
            PAUSE
        }

        /// <summary>
        /// Obtient l'état de la barre de progression.
        /// </summary>
        /// <param name="pb"><see cref="System.Windows.Forms.ProgressBar"/></param>
        /// <returns>L'état <see cref="PBM_STATE"/>.</returns>
        public static PBM_STATE GetState(this System.Windows.Forms.ProgressBar pb)
        {
            if (Environment.OSVersion.Version.Major >= 6)
            {
                IntPtr pValue = SendMessage(pb.Handle, PBM_GETSTATE, IntPtr.Zero, IntPtr.Zero);

                int iVal = pValue.ToInt32();
                return (PBM_STATE)iVal;
            }
            else
                throw new Exception("Supported on Vista or later only !.");
        }

        /// <summary>
        /// Définit l'état de la barre de progression.
        /// </summary>
        /// <param name="pb"><see cref="System.Windows.Forms.ProgressBar"/></param>
        /// <param name="state">Nouvel état <see cref="PBM_STATE"/>.</param>
        public static void SetState(this System.Windows.Forms.ProgressBar pb, PBM_STATE state)
        {
            if (Environment.OSVersion.Version.Major >= 6)
            {
                SendMessage(pb.Handle, PBM_SETSTATE, new IntPtr((int)state), IntPtr.Zero);
            }
            else
                throw new Exception("Supported on Vista or later only !.");
        }

        /// <summary>
        /// Change la manière dont la décrémentation de la valeur de la progress bar se fait.
        /// </summary>
        /// <param name="pb"><see cref="System.Windows.Forms.ProgressBar"/></param>
        /// <param name="turnOn"><b>True</b> pour décrémentation fluide; <b>False</b> pour décrémentation direct.</param>
        public static void SmoothReverse(this System.Windows.Forms.ProgressBar pb, bool turnOn)
        {
            if (Environment.OSVersion.Version.Major >= 6)
            {
                //Récupère le style.
                IntPtr pStyle = GetWindowLong(pb.Handle, GWL_STYLE);

                //Garde la valeur actuelle pour redéfinir celle de la progress bar une fois la modification de style effectué.
                int iOldVal = pb.Value;

                if (turnOn)
                {
                    //Si pas activé?
                    //On active.
                    if ((pStyle.ToInt32() & PBS_SMOOTHREVERSE) != PBS_SMOOTHREVERSE)
                    {
                        SetWindowLong(pb.Handle, GWL_STYLE, new IntPtr((pStyle.ToInt32() | PBS_SMOOTHREVERSE)));
                        SendMessage(pb.Handle, PBM_SETPOS, new IntPtr(iOldVal), IntPtr.Zero);
                    }
                }
                else
                {
                    //Si activé?
                    //On désactive.
                    if ((pStyle.ToInt32() & PBS_SMOOTHREVERSE) == PBS_SMOOTHREVERSE)
                    {
                        SetWindowLong(pb.Handle, GWL_STYLE, new IntPtr((pStyle.ToInt32() - PBS_SMOOTHREVERSE)));
                        SendMessage(pb.Handle, PBM_SETPOS, new IntPtr(iOldVal), IntPtr.Zero);
                    }
                }
            }
            else
                throw new Exception("Supported on Vista or later only !.");
        }

        /// <summary>
        /// GetWindowLong avec support 32 et 64 bits.
        /// </summary>
        private static IntPtr GetWindowLong(IntPtr hWnd, int nIndex)
        {
            if (IntPtr.Size == 8)
                return GetWindowLongPtr(hWnd, nIndex);
            else
                return GetWindowLong32(hWnd, nIndex);
        }

        /// <summary>
        /// SetWindowLong avec support 32 et 64 bits.
        /// </summary>
        private static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
        {
            if (IntPtr.Size == 8)
                return SetWindowLongPtr(hWnd, nIndex, dwNewLong);
            else
                return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
        }
    }
}

Conclusion :


Bon dév à tous ^^

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.