Click here to Skip to main content
15,893,401 members
Articles / Desktop Programming / WPF

Catel - Part 4 of n: Unit testing with Catel

Rate me:
Please Sign up or sign in to vote.
4.55/5 (10 votes)
28 Jan 2011CPOL11 min read 49.1K   572   11  
This article explains how to write unit tests for MVVM using Catel.
// --------------------------------------------------------------------------------------------------------------------
// <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
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Netherlands Netherlands
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions