//Copyright (C) 2010 Jonathan Preece
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using VistaControls.ThemeText;
using WindowsAeroWizardControl.Properties;
namespace WindowsAeroWizardControl
{
///<summary>
/// Creates a Windows form that has all the properties necessary to create a Windows Aero enabled experience
///</summary>
public class JPWizardForm : Form
{
#region Events
///<summary>
/// Raised when the DWM notifies the form that Windows Aero has been disabled
///</summary>
/// <remarks><para>DWM: Desktop Windows Manager</para></remarks>
public event AeroGlassCompositionChanged DesktopCompositionChanged;
/// <summary>
/// Raised when the user clicks the "Next" button
/// </summary>
public event Generic Next;
/// <summary>
/// Raised when the user clicks the "Previous" button
/// </summary>
public event Generic Previous;
/// <summary>
/// Raised when the user clicks the "Cancel" button
/// </summary>
public event Generic CancelRequest;
#endregion
#region WindowThemeAttributeType enum
///<summary>
/// WindowThemeAttributeType
///</summary>
public enum WindowThemeAttributeType
{
///<summary>
/// WTA_NONCLIENT
///</summary>
WTA_NONCLIENT = 1
}
#endregion
#region External Methods
///<summary>
/// Extends the window frame behind the client area.
///</summary>
///<param name="hWnd">The handle to the window for which the frame is extended into the client area.</param>
///<param name="Margins">A pointer to a MARGINS structure that describes the margins to use when extending the frame into the client area.</param>
[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern void DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS Margins);
///<summary>
/// Obtains a value that indicates whether Desktop Window Manager (DWM) composition is enabled. Applications can listen for composition state changes by handling the WM_DWMCOMPOSITIONCHANGED notification.
///</summary>
///<returns>If desktop composition is enabled, returns true, otherwise false</returns>
[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern bool DwmIsCompositionEnabled();
///<summary>
/// Sets attributes to control how visual styles are applied to a specified window.
///</summary>
///<param name="hWnd">Handle to a window to apply changes to.</param>
///<param name="wtype"></param>
///<param name="attributes"></param>
///<param name="size"></param>
///<returns>If the function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns>
[DllImport("UxTheme.dll")]
public static extern int SetWindowThemeAttribute(IntPtr hWnd, WindowThemeAttributeType wtype,
ref WTA_OPTIONS attributes, uint size);
#endregion
private const int WM_DWMCOMPOSITIONCHANGED = 0x031E;
private const int WM_DWMNCRENDERINGCHANGED = 0x031F;
private const uint WTNCA_NODRAWCAPTION = 0x1;
private const uint WTNCA_NODRAWICON = 0x2;
private const string spaces = " ";
private Button CancelRequestButton;
private Panel FooterPanel;
private Panel HeaderPanel;
private PictureBox NavigationButton;
private Button NextButton;
private Label NoDWMLabel;
private ThemedLabel WindowTitle;
private PictureBox WizardIconPictureBox;
private bool enablePreviousButton;
#region Constructor
///<summary>
/// Constructs the JPAeroForm class
///</summary>
public JPWizardForm()
{
Load += JPAeroForm_Load;
Resize += JPAeroForm_Resize;
}
private void JPAeroForm_Load(object sender, EventArgs e)
{
Color headerDefault = SystemColors.GradientActiveCaption;
if (DwmIsCompositionEnabled() && !DesignMode)
{
var Margins = new MARGINS { Top = 41, Left = 0, Right = 0, Bottom = 0 };
DwmExtendFrameIntoClientArea(Handle, ref Margins);
var ops = new WTA_OPTIONS { Flags = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON, Mask = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON };
SetWindowThemeAttribute(Handle, WindowThemeAttributeType.WTA_NONCLIENT, ref ops, (uint)Marshal.SizeOf(typeof(WTA_OPTIONS)));
headerDefault = Color.Black;
#region Set Window Title
WindowTitle = new ThemedLabel { ShadowEnabled = true, TextAlignVertical = VerticalAlignment.Center, GlowSize = 6, Location = new Point(0, 1), Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right), Font = new Font("Corbel", 9.75f, FontStyle.Regular, GraphicsUnit.Point, 0), Size = new Size(602, 37), Text = spaces + Text, TabIndex = 5, Visible = true };
Controls.Add(WindowTitle);
#endregion
}
#region Create Panels
HeaderPanel = new Panel { BackColor = headerDefault, Height = 41, Dock = DockStyle.Top };
Controls.Add(HeaderPanel);
HeaderPanel.SendToBack();
FooterPanel = new Panel { BackColor = SystemColors.Control, Height = 45, Dock = DockStyle.Bottom };
Controls.Add(FooterPanel);
FooterPanel.SendToBack();
#endregion
#region 3D Lines
var _3DLine1 = new JPLine { Dock = DockStyle.Top, ForeColor = Color.Gainsboro, Location = new Point(0, 0), Name = "_3DLine2", Size = new Size(544, 1), TabIndex = 8, Text = "_3DLine2" };
FooterPanel.Controls.Add(_3DLine1);
#endregion
#region Buttons
NextButton = new Button { DialogResult = DialogResult.OK, Location = new Point(381, 9), Name = "NextButton", Size = new Size(66, 26), TabIndex = 7, Text = "&Next", UseVisualStyleBackColor = true };
NextButton.Click += NextButton_Click;
FooterPanel.Controls.Add(NextButton);
NextButton.BringToFront();
CancelRequestButton = new Button { DialogResult = DialogResult.Cancel, Location = new Point(456, 9), Name = "CancelRequestButton", Size = new Size(66, 26), TabIndex = 7, Text = "&Cancel", UseVisualStyleBackColor = true };
CancelRequestButton.Click += CancelRequestButton_Click;
FooterPanel.Controls.Add(CancelRequestButton);
CancelRequestButton.BringToFront();
NavigationButton = new PictureBox { Image = Resources.disabled2, Location = new Point(2, 7), Name = "NavigationButton", Size = new Size(25, 25), SizeMode = PictureBoxSizeMode.Zoom, TabIndex = 6, TabStop = false, Tag = "disabled", BackColor = headerDefault };
NavigationButton.MouseLeave += NavigationButton_MouseLeave;
NavigationButton.Click += NavigationButton_Click;
NavigationButton.MouseDown += NavigationButton_MouseDown;
NavigationButton.MouseUp += NavigationButton_MouseUp;
NavigationButton.MouseEnter += NavigationButton_MouseEnter;
#endregion
#region Other Visual Elements
NoDWMLabel = new Label { AutoSize = true, BackColor = headerDefault, BorderStyle = BorderStyle.None, Font = new Font("Segoe UI", 8.75F), ForeColor = Color.Black, Location = new Point(66, 13), Name = "NoDWMLabel", Size = new Size(115, 17), TabIndex = 10, Text = "My Windows Aero Wizard" };
WizardIconPictureBox = new PictureBox { BackColor = headerDefault, BorderStyle = BorderStyle.None, Location = new Point(39, 12), Name = "WizardIconPictureBox", Size = new Size(16, 16), SizeMode = PictureBoxSizeMode.Zoom, TabIndex = 9, TabStop = false, Image = Resources.wizard1616 };
MinimumSize = new Size(455, 367);
MaximizeBox = false;
ShowIcon = false;
BackColor = Color.White;
if (!DwmIsCompositionEnabled() || DesignMode)
Controls.Add(NoDWMLabel);
Controls.Add(WizardIconPictureBox);
Controls.Add(NavigationButton);
NoDWMLabel.BringToFront();
WizardIconPictureBox.BringToFront();
NavigationButton.BringToFront();
NavButtonStatusChanged();
#endregion
}
#endregion
#region Public Properties
///<summary>
/// Gets a value representing whether or not Windows Aero is supported.
///</summary>
/// <returns>True if Windows Aero is supported, otherwise, false</returns>
[Browsable(true)]
[Category("Appearance")]
[Description("Gets a value representing whether or not Windows Aero is supported.")]
public bool isAeroEnabled
{
get { return Environment.OSVersion.Version.Major > 5 && DwmIsCompositionEnabled() && !DesignMode; }
}
/// <summary>
/// Gets or sets a value that determines whether or not the previous button is enabled
/// </summary>
[Browsable(true)]
[Category("Appearance")]
[Description("Gets a value that determines whether or not the previous button is enabled")]
public bool EnablePreviousButton
{
get { return enablePreviousButton; }
set
{
enablePreviousButton = value;
if (NavigationButton != null) NavButtonStatusChanged();
}
}
/// <summary>
/// Gets or sets the icon being displayed on the form
/// </summary>
[Browsable(true)]
[Category("Appearance")]
[Description("Gets or sets the icon being displayed on the form")]
public Image WizardIcon
{
get { return WizardIconPictureBox.Image; }
set { if (WizardIconPictureBox != null) WizardIconPictureBox.Image = value; }
}
#endregion
#region Protected Methods
public override string Text
{
get { return base.Text; }
set
{
if (WindowTitle != null) WindowTitle.Text = spaces + value;
base.Text = value;
}
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_DWMCOMPOSITIONCHANGED || m.Msg == WM_DWMNCRENDERINGCHANGED)
{
if (DesktopCompositionChanged != null)
{
var args = new CompositionChangedEventArgs(DwmIsCompositionEnabled());
DesktopCompositionChanged.Invoke(this, args);
}
}
base.WndProc(ref m);
}
#endregion
#region Nested type: MARGINS
///<summary>
/// MARGINS struct
///</summary>
[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
///<summary>
/// Left
///</summary>
public int Left;
/// <summary>
/// Right
/// </summary>
public int Right;
/// <summary>
/// Top
/// </summary>
public int Top;
/// <summary>
/// Bottom
/// </summary>
public int Bottom;
}
#endregion
#region Nested type: WTA_OPTIONS
///<summary>
/// Defines options that are used to set window visual style attributes.
///</summary>
[StructLayout(LayoutKind.Sequential)]
public struct WTA_OPTIONS
{
/// <summary>
/// Flags
/// </summary>
public uint Flags;
/// <summary>
/// Mask
/// </summary>
public uint Mask;
}
#endregion
#region Private Methods
private void InvokeNextEvent()
{
if (Next != null) Next.Invoke(this, new EventArgs());
}
private void InvokePreviousEvent()
{
if (Previous != null) Previous.Invoke(this, new EventArgs());
}
private void InvokeCancelRequestEvent()
{
if (CancelRequest != null) CancelRequest.Invoke(this, new EventArgs());
}
private void NextButton_Click(object sender, EventArgs e)
{
InvokeNextEvent();
}
private void CancelRequestButton_Click(object sender, EventArgs e)
{
InvokeCancelRequestEvent();
}
private void JPAeroForm_Resize(object sender, EventArgs e)
{
if (CancelRequestButton != null) CancelRequestButton.Location = new Point(Width - 94, 9);
if (NextButton != null) NextButton.Location = new Point(Width - 169, 9);
}
private void NavigationButton_Click(object sender, EventArgs e)
{
if ((NAV_BACKBUTTONSTATES)NavigationButton.Tag != NAV_BACKBUTTONSTATES.NAV_BB_DISABLED)
{
InvokePreviousEvent();
}
}
private void NavButtonStatusChanged()
{
if (EnablePreviousButton)
{
NavigationButton.Tag = NAV_BACKBUTTONSTATES.NAV_BB_NORMAL;
NavigationButton.Image = Resources.normal;
}
else
{
NavigationButton.Tag = NAV_BACKBUTTONSTATES.NAV_BB_DISABLED;
NavigationButton.Image = Resources.disabled2;
}
}
private void NavigationButton_MouseUp(object sender, MouseEventArgs e)
{
NavigationButton.Image = (NAV_BACKBUTTONSTATES)NavigationButton.Tag == NAV_BACKBUTTONSTATES.NAV_BB_NORMAL ? Resources.hot : Resources.disabled2;
}
private void NavigationButton_MouseEnter(object sender, EventArgs e)
{
NavigationButton.Image = (NAV_BACKBUTTONSTATES)NavigationButton.Tag == NAV_BACKBUTTONSTATES.NAV_BB_NORMAL ? Resources.hot : Resources.disabled2;
}
private void NavigationButton_MouseDown(object sender, MouseEventArgs e)
{
NavigationButton.Image = (NAV_BACKBUTTONSTATES)NavigationButton.Tag == NAV_BACKBUTTONSTATES.NAV_BB_NORMAL ? Resources.pressed5 : Resources.disabled2;
}
private void NavigationButton_MouseLeave(object sender, EventArgs e)
{
NavigationButton.Image = (NAV_BACKBUTTONSTATES)NavigationButton.Tag == NAV_BACKBUTTONSTATES.NAV_BB_NORMAL ? Resources.normal : Resources.disabled2;
}
#endregion
private enum NAV_BACKBUTTONSTATES
{
NAV_BB_NORMAL = 1,
NAV_BB_HOT = 2,
NAV_BB_PRESSED = 3,
NAV_BB_DISABLED = 4,
};
}
#region EventArgs
/// <summary>
/// Raised when the DWM composition state is changed
/// </summary>
public class CompositionChangedEventArgs : EventArgs
{
#region Private Variables
private readonly bool availability;
#endregion
#region Constructor
///<summary>
/// Constructs the CompositionChangedEventArgs class
///</summary>
///<param name="Availability">Availability of Windows Aero styles</param>
public CompositionChangedEventArgs(bool Availability)
{
availability = Availability;
}
#endregion
#region Public Properties
/// <summary>
/// Gets the new DWM state
/// </summary>
public bool IsGlassAvailable
{
get { return availability; }
}
#endregion
}
#endregion
}