// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ModalWindowHelper.cs" company="Catel development team">
// Copyright (c) 2008 - 2011 Catel development team. All rights reserved.
// </copyright>
// <summary>
// Modal window helper class
// </summary>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace Catel.Windows
{
/// <summary>
/// Modal window helper class
/// </summary>
public class ModalWindowHelper : IDisposable
{
#region Win32 Imports
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll")]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
/// <summary>
/// Win32 RECT structure.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
/// <summary>
/// Left.
/// </summary>
public int Left;
/// <summary>
/// Top.
/// </summary>
public int Top;
/// <summary>
/// Right.
/// </summary>
public int Right;
/// <summary>
/// Bottom.
/// </summary>
public int Bottom;
}
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
static readonly IntPtr HWND_TOP = new IntPtr(0);
static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
#endregion
#region Variables
private bool _succeeded = false;
private IntPtr _parentWindow = IntPtr.Zero;
private string _className = string.Empty;
private string _windowTitle = string.Empty;
private Thread _thread = null;
private DateTime _threadStopTime = DateTime.Now;
#endregion
#region Constructor & destructor
/// <summary>
/// Initializes a new instance of the <see cref="ModalWindowHelper"/> class.
/// </summary>
/// <param name="parentWindow">Handle of the window to set as parent.</param>
/// <param name="className">Class name of the window to make modal.</param>
/// <param name="windowTitle">Title of the window to make modal.</param>
public ModalWindowHelper(IntPtr parentWindow, string className, string windowTitle)
{
_parentWindow = parentWindow;
_className = className;
_windowTitle = windowTitle;
StartSearch();
}
/// <summary>
/// Finalizes an instance of the <see cref="ModalWindowHelper"/> class.
/// </summary>
~ModalWindowHelper()
{
Dispose();
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
_succeeded = false;
if (_thread != null)
{
_thread.Abort();
_thread = null;
}
}
#endregion
#region Properties
/// <summary>
/// Gets whether the window was found and its state is set to model.
/// </summary>
public bool IsSucceeded
{
get { return _succeeded; }
private set { _succeeded = value; }
}
#endregion
#region Methods
/// <summary>
/// Starts the search for the window
/// </summary>
private void StartSearch()
{
Dispose();
_thread = new Thread(FindWindowAndSetModal);
_thread.Start();
_threadStopTime = DateTime.Now.AddSeconds(30);
}
/// <summary>
/// Tries to find the window and set its state to modal.
/// </summary>
private void FindWindowAndSetModal()
{
while (!_succeeded && (_threadStopTime > DateTime.Now))
{
IntPtr windowHandle = IntPtr.Zero;
if (string.IsNullOrEmpty(_windowTitle))
{
windowHandle = FindWindowEx(IntPtr.Zero, IntPtr.Zero, _className, IntPtr.Zero);
}
else
{
windowHandle = FindWindowEx(IntPtr.Zero, IntPtr.Zero, _className, _windowTitle);
}
if (windowHandle != IntPtr.Zero)
{
if (_parentWindow != IntPtr.Zero)
{
SetParent(windowHandle, _parentWindow);
_succeeded = true;
}
else
{
RECT rect;
GetWindowRect(windowHandle, out rect);
// Set the state to system modal
SetWindowPos(windowHandle, HWND_TOPMOST, rect.Left, rect.Top,
rect.Right - rect.Left, rect.Bottom - rect.Top, 0);
_succeeded = true;
}
}
Thread.Sleep(500);
}
}
#endregion
}
}