コード例 #1
0
ファイル: Form.cs プロジェクト: johnsewell/APE
        /// <summary>
        /// Closes the form by click the 'x' in the top right hand corner of the form
        /// </summary>
        public void Close()
        {
            if (NM.IsWindow(Identity.Handle))
            {
                if (NM.IsWindowVisible(Identity.Handle))
                {
                    if (NM.IsIconic(Identity.Handle))
                    {
                        throw new Exception("Can not close the window as it is minimised");
                    }

                    GUI.m_APE.AddFirstMessageGetTitleBarItemRectangle(Identity.Handle, NM.TitleBarStateElement.Close);
                    GUI.m_APE.SendMessages(EventSet.APE);
                    GUI.m_APE.WaitForMessages(EventSet.APE);
                    //Get the value(s) returned MUST be done straight after the WaitForMessages call
                    NM.StateSystem State  = (NM.StateSystem)GUI.m_APE.GetValueFromMessage();
                    int            Top    = GUI.m_APE.GetValueFromMessage();
                    int            Left   = GUI.m_APE.GetValueFromMessage();
                    int            Bottom = GUI.m_APE.GetValueFromMessage();
                    int            Right  = GUI.m_APE.GetValueFromMessage();

                    // Check the close button is actually displayed
                    if (State != NM.StateSystem.STATE_SYSTEM_NORMAL && State != NM.StateSystem.STATE_SYSTEM_PRESSED)
                    {
                        throw new Exception("Can not close the window as the close button is in state '" + State.ToString() + "'");
                    }

                    NM.tagRect WindowRect;
                    NM.GetWindowRect(Identity.Handle, out WindowRect);

                    int X = Left + ((Right - Left) / 2) - WindowRect.left;
                    int Y = Top + ((Bottom - Top) / 2) - WindowRect.top;

                    Input.Block(Identity.ParentHandle, Identity.Handle);
                    try
                    {
                        GUI.Log("Close the " + Identity.Description, LogItemType.Action);
                        base.SingleClickInternal(X, Y, MouseButton.Left, MouseKeyModifier.None);

                        //Wait for the window to disappear
                        base.WaitForControlToNotBeVisible();
                    }
                    finally
                    {
                        Input.Unblock();
                    }
                }
            }
        }
コード例 #2
0
ファイル: FormHelper.cs プロジェクト: robguyoncourt/APE
        private unsafe void GetToolTip(Message *ptrMessage, int messageNumber)
        {
            //must be first message
            if (messageNumber != 1)
            {
                throw new Exception("GetToolTip must be first message");
            }

            // p1  = handle
            IntPtr handle = GetParameterIntPtr(ptrMessage, 0);

            CleanUpMessage(ptrMessage);

            NM.EnumWindowsProc windowsToGetToolTipsCallback = new NM.EnumWindowsProc(EnumWindowsToGetToolTips);

            m_ToolTipWindows = new List <IntPtr>();
            NM.EnumWindows(windowsToGetToolTipsCallback, IntPtr.Zero);

            IntPtr    toolTipHandle    = IntPtr.Zero;
            string    toolTipTitle     = null;
            Rectangle toolTipRectangle = new Rectangle(0, 0, 0, 0);

            foreach (IntPtr hWnd in m_ToolTipWindows)
            {
                NM.ToolInfo info = NM.GetToolInfo(hWnd, TimeOut);

                if (info.hWnd == handle)
                {
                    //we have the tooltip so return infomation about it
                    toolTipHandle = hWnd;
                    toolTipTitle  = GetWindowTextViaWindowMessage(toolTipHandle);

                    NM.tagRect windowPosition;
                    NM.tagRect windowSize;
                    NM.GetWindowRect(toolTipHandle, out windowPosition);
                    windowSize = NM.GetClipBox(toolTipHandle);

                    toolTipRectangle = new Rectangle(windowPosition.left, windowPosition.top, windowSize.right, windowSize.bottom);
                    break;
                }
            }

            AddReturnValue(new Parameter(this, toolTipHandle));
            AddReturnValue(new Parameter(this, toolTipTitle));
            AddReturnValue(new Parameter(this, toolTipRectangle.X));
            AddReturnValue(new Parameter(this, toolTipRectangle.Y));
            AddReturnValue(new Parameter(this, toolTipRectangle.Width));
            AddReturnValue(new Parameter(this, toolTipRectangle.Height));
        }
コード例 #3
0
ファイル: Form.cs プロジェクト: johnsewell/APE
        /// <summary>
        /// Moves the specified window to the specified location by clicking at the specified point to drag the form
        /// </summary>
        /// <param name="MouseDownX">The x coordinate inside the form to perform a mouse down at</param>
        /// <param name="MouseDownY">The y coordinate inside the form to perform a mouse down at</param>
        /// <param name="DestinationUpperLeftX">The new location for the left side of the form</param>
        /// <param name="DestinationUpperLeftY">The new location for the top of the form</param>
        public void Move(int MouseDownX, int MouseDownY, int DestinationUpperLeftX, int DestinationUpperLeftY)
        {
            GUI.Log("Move the " + Identity.Description + " window to " + DestinationUpperLeftX.ToString() + ", " + DestinationUpperLeftY.ToString(), LogItemType.Action);

            NM.tagRect WindowRect;
            NM.GetWindowRect(Identity.Handle, out WindowRect);

            Input.Block(Identity.ParentHandle, Identity.Handle);
            try
            {
                base.MouseDownInternal(MouseDownX, MouseDownY, MouseButton.Left, MouseKeyModifier.None);
                base.MouseUpInternal(DestinationUpperLeftX + MouseDownX - WindowRect.left, DestinationUpperLeftY + MouseDownY - WindowRect.top, MouseButton.Left, MouseKeyModifier.None);
            }
            finally
            {
                Input.Unblock();
            }
        }
コード例 #4
0
        public static NM.tagPoint MouseMove(IntPtr Handle, int x, int y, bool PerformCheck = true)
        {
            NM.tagRect  WindowRect;
            NM.tagRect  ClientRect;
            NM.tagPoint thePoint;
            int         xOffset;
            int         yOffset;

            Stopwatch timer = Stopwatch.StartNew();

            while (true)
            {
                NM.GetWindowRect(Handle, out WindowRect);
                NM.GetClientRect(Handle, out ClientRect);

                //TODO fix this as -1 might be a valid move,,, maybe 0 instead or...
                if (x == -1)
                {
                    xOffset = ClientRect.right / 2;
                }
                else
                {
                    xOffset = x;
                }

                if (y == -1)
                {
                    yOffset = ClientRect.bottom / 2;
                }
                else
                {
                    yOffset = y;
                }

                //Convert the window area to screen point
                thePoint.x = WindowRect.left + xOffset;
                thePoint.y = WindowRect.top + yOffset;

                if (NM.MonitorFromPoint(thePoint, NM.MonitorOptions.MONITOR_DEFAULTTONULL) == null)
                {
                    throw new Exception("coordinate appears to be offscreen");
                }

                if (PerformCheck)
                {
                    IntPtr ChildHandle;

                    thePoint.x = xOffset + WindowRect.left;
                    thePoint.y = yOffset + WindowRect.top;

                    ChildHandle = NM.WindowFromPoint(thePoint);

                    //Make sure we are inside the controls window area
                    if (Handle == ChildHandle)
                    {
                        break;
                    }
                    else
                    {
                        //Try to scroll it into view
                        GUI.m_APE.AddFirstMessageScrollControlIntoView(Handle);
                        GUI.m_APE.SendMessages(EventSet.APE);
                        GUI.m_APE.WaitForMessages(EventSet.APE);

                        if (timer.ElapsedMilliseconds > GUI.GetTimeOut())
                        {
                            throw new Exception("Coordinates are not inside the controls area");
                        }
                    }
                }
                else
                {
                    break;
                }
            }

            //Get the current mouse location
            NM.tagPoint currentPoint;
            NM.GetCursorPos(out currentPoint);

            //X direction
            int DirectionX;

            if (currentPoint.x <= WindowRect.left + xOffset)
            {
                DirectionX = 1;     //right
            }
            else
            {
                DirectionX = -1;    //left
            }

            //Y direction
            int DirectionY;

            if (currentPoint.y <= WindowRect.top + yOffset)
            {
                DirectionY = 1;     //down
            }
            else
            {
                DirectionY = -1;    //up
            }

            int MoveX = currentPoint.x;
            int MoveY = currentPoint.y;

            while (MoveX != WindowRect.left + xOffset || MoveY != WindowRect.top + yOffset)
            {
                if (MoveX != WindowRect.left + xOffset)
                {
                    if (DirectionX == 1)
                    {
                        if (MoveX + MoveSize > WindowRect.left + xOffset)
                        {
                            MoveX = MoveX + 1;
                        }
                        else
                        {
                            MoveX = MoveX + MoveSize;
                        }
                    }
                    else
                    {
                        if (MoveX - MoveSize < WindowRect.left + xOffset)
                        {
                            MoveX = MoveX - 1;
                        }
                        else
                        {
                            MoveX = MoveX - MoveSize;
                        }
                    }
                }

                if (MoveY != WindowRect.top + yOffset)
                {
                    if (DirectionY == 1)
                    {
                        if (MoveY + MoveSize > WindowRect.top + yOffset)
                        {
                            MoveY = MoveY + 1;
                        }
                        else
                        {
                            MoveY = MoveY + MoveSize;
                        }
                    }
                    else
                    {
                        if (MoveY - MoveSize < WindowRect.top + yOffset)
                        {
                            MoveY = MoveY - 1;
                        }
                        else
                        {
                            MoveY = MoveY - MoveSize;
                        }
                    }
                }

                MoveMouse(MoveX, MoveY);
            }

            return(thePoint);
        }
コード例 #5
0
        public static void MouseUp(IntPtr ParentHandle, IntPtr Handle, int x, int y, MouseButton Button, MouseKeyModifier Keys)
        {
            bool hooked = false;

            WaitToBeVisibleAndEnabled(Handle);
            Block(ParentHandle, Handle);
            try
            {
                NM.tagPoint thePoint = new NM.tagPoint();
                thePoint.x = x;
                thePoint.y = y;
                IntPtr TopLevelHandle = NM.ChildWindowFromPoint(NM.GetDesktopWindow(), thePoint);

                NM.tagRect WindowSize;
                NM.GetWindowRect(Handle, out WindowSize);

                thePoint.x = x + WindowSize.left;
                thePoint.y = y + WindowSize.top;
                IntPtr ChildHandle = NM.WindowFromPoint(thePoint);

                if (!WaitForInputIdle(ChildHandle, GUI.m_APE.TimeOut))
                {
                    throw new Exception("Window did not go idle within timeout");
                }

                IntPtr ActualParent;

                if (ParentHandle == IntPtr.Zero)
                {
                    ActualParent = Handle;
                }
                else
                {
                    ActualParent = ParentHandle;
                }

                TimerResolution.SetMaxTimerResolution();

                //TODO this looks wrong should use clickcommon only for this
                if (ChildHandle == ActualParent)
                {
                    ClickCommon(ParentHandle, Handle, x, y);
                }
                else
                {
                    MouseMove(Handle, x, y, false);
                }

                if (Handle == ActualParent)
                {
                    GUI.m_APE.AddFirstMessageAddMouseHook(Handle);
                    GUI.m_APE.SendMessages(EventSet.APE);
                    GUI.m_APE.WaitForMessages(EventSet.APE);
                    hooked = true;
                }

                MouseClick(Button, false, true, 1, Keys.HasFlag(MouseKeyModifier.Control), Keys.HasFlag(MouseKeyModifier.Shift));

                if (Handle == ActualParent)
                {
                    GUI.m_APE.AddFirstMessageWaitForMouseState((APEIPC.MouseButton)Button, false, true);
                    GUI.m_APE.SendMessages(EventSet.APE);
                    GUI.m_APE.WaitForMessages(EventSet.APE);
                }
            }
            catch
            {
                Reset();    //Reset the mouse blocking
                throw;
            }
            finally
            {
                try
                {
                    if (hooked)
                    {
                        GUI.m_APE.AddFirstMessageRemoveMouseHook(Handle);
                        GUI.m_APE.SendMessages(EventSet.APE);
                        GUI.m_APE.WaitForMessages(EventSet.APE);
                    }
                }
                finally
                {
                    TimerResolution.UnsetMaxTimerResolution();
                    Unblock();
                    IsMouseDown = false;
                }
            }
        }
コード例 #6
0
        internal void MouseDownInternal(int X, int Y, MouseButton button, MouseKeyModifier keys, int preClickDelay, int intraClickDelay)
        {
            Input.MouseDown(Identity.ParentHandle, Identity.Handle, Identity.Description, X, Y, button, keys, this, preClickDelay, intraClickDelay);
            if (!Input.WaitForInputIdle(Identity.Handle, GUI.m_APE.TimeOut))
            {
                throw GUI.ApeException(Identity.Description + " did not go idle within timeout");
            }

            //get the current location
            NM.GetCursorPos(out NM.tagPoint currentPoint);

            // If we are doing separate calls to mouse down and up then its very likely we want to drag so make sure we are in dragmode
            NM.tagRect WindowRect;
            NM.tagRect ClientRect;
            NM.GetWindowRect(Handle, out WindowRect);
            NM.GetClientRect(Handle, out ClientRect);

            int middleOfClientAreaX = (ClientRect.right / 2);
            int middleOfClientAreaY = (ClientRect.bottom / 2);

            int dragTriggerHeight = SystemInformation.DragSize.Height;
            int dragTriggerWidth  = SystemInformation.DragSize.Width;

            if (middleOfClientAreaX < dragTriggerWidth || middleOfClientAreaY < dragTriggerHeight)
            {
                throw GUI.ApeException(Description + " is to small to reliably enter drag mode");
            }

            // Move the mouse a few times to make sure we are in drag mode
            Rectangle workingArea;
            int       moveX1 = WindowRect.left;
            int       moveY1 = WindowRect.top;
            int       moveX2 = WindowRect.left + middleOfClientAreaX;
            int       moveY2 = WindowRect.top + middleOfClientAreaY;

            workingArea = Screen.GetWorkingArea(new Point(moveX1, moveY1));
            if (moveX1 < workingArea.Left + 3)
            {
                moveX1 = workingArea.Left + 3;
            }
            if (moveX1 > workingArea.Right - 3)
            {
                moveX1 = workingArea.Right - 3;
            }
            if (moveY1 < workingArea.Top + 3)
            {
                moveY1 = workingArea.Top + 3;
            }
            if (moveY1 > workingArea.Bottom - 3)
            {
                moveY1 = workingArea.Bottom - 3;
            }

            workingArea = Screen.GetWorkingArea(new Point(moveX2, moveY2));
            if (moveX2 < workingArea.Left + 3)
            {
                moveX2 = workingArea.Left + 3;
            }
            if (moveX2 > workingArea.Right - 3)
            {
                moveX2 = workingArea.Right - 3;
            }
            if (moveY2 < workingArea.Top + 3)
            {
                moveY2 = workingArea.Top + 3;
            }
            if (moveY2 > workingArea.Bottom - 3)
            {
                moveY2 = workingArea.Bottom - 3;
            }

            for (int i = 0; i < 10; i++)
            {
                Input.MoveMouse(moveX1, moveY1);
                Input.MoveMouse(moveY2, moveY2);
            }
            if (!Input.WaitForInputIdle(Identity.Handle, GUI.m_APE.TimeOut))
            {
                throw GUI.ApeException(Identity.Description + " did not go idle within timeout");
            }

            //Move back to where we were before the above drag block of code
            Input.MoveMouse(currentPoint.x, currentPoint.y);
            if (!Input.WaitForInputIdle(Identity.Handle, GUI.m_APE.TimeOut))
            {
                throw GUI.ApeException(Identity.Description + " did not go idle within timeout");
            }
        }
コード例 #7
0
ファイル: Form.cs プロジェクト: johnsewell/APE
        /// <summary>
        /// Restores the window back clicking the restore button in the top right corner of the form
        /// Note if the window is minimised then a non-gui method is used to restore the form
        /// </summary>
        public void Restore()
        {
            GUI.Log("Restore the " + Identity.Description, LogItemType.Action);

            string windowState = FormWindowState();

            if (windowState == "Normal")
            {
                throw new Exception("Can not restore the window as it already is");
            }

            if (windowState == "Minimized")
            {
                Input.Block(Identity.ParentHandle, Identity.Handle);
                try
                {
                    NM.ShowWindow(Identity.Handle, NM.SW_RESTORE);

                    //Bring it to the front (can sometimes get restored to the background using the api)
                    SetFocus();

                    // Wait for the animation to finish
                    base.WaitForAnimation(Identity.Handle, true, AnimationUtils.WaitForAnimationSource.Form);

                    // Check the window is now normal
                    Stopwatch timer = Stopwatch.StartNew();
                    do
                    {
                        GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
                        GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "WindowState", MemberTypes.Property);
                        GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store2, "ToString", MemberTypes.Method);
                        GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store2);
                        GUI.m_APE.SendMessages(EventSet.APE);
                        GUI.m_APE.WaitForMessages(EventSet.APE);
                        //Get the value(s) returned MUST be done straight after the WaitForMessages call
                        windowState = GUI.m_APE.GetValueFromMessage();

                        if (timer.ElapsedMilliseconds > GUI.m_APE.TimeOut)
                        {
                            timer.Stop();
                            throw new Exception("Failed to restore the window");
                        }

                        Thread.Sleep(15);
                    }while (windowState != "Normal");
                    timer.Stop();
                }
                finally
                {
                    Input.Unblock();
                }
            }
            else
            {
                GUI.m_APE.AddFirstMessageGetTitleBarItemRectangle(Identity.Handle, NM.TitleBarStateElement.Maximize);
                GUI.m_APE.SendMessages(EventSet.APE);
                GUI.m_APE.WaitForMessages(EventSet.APE);
                //Get the value(s) returned MUST be done straight after the WaitForMessages call
                NM.StateSystem State  = (NM.StateSystem)GUI.m_APE.GetValueFromMessage();
                int            Top    = GUI.m_APE.GetValueFromMessage();
                int            Left   = GUI.m_APE.GetValueFromMessage();
                int            Bottom = GUI.m_APE.GetValueFromMessage();
                int            Right  = GUI.m_APE.GetValueFromMessage();

                // Check the maximise button is actually displayed
                if (State != NM.StateSystem.STATE_SYSTEM_NORMAL && State != NM.StateSystem.STATE_SYSTEM_PRESSED)
                {
                    throw new Exception("Can not restore the window as the restore button is in state '" + State.ToString() + "'");
                }

                NM.tagRect WindowRect;
                NM.GetWindowRect(Identity.Handle, out WindowRect);

                int X = Left + ((Right - Left) / 2) - WindowRect.left;
                int Y = Top + ((Bottom - Top) / 2) - WindowRect.top;

                Input.Block(Identity.ParentHandle, Identity.Handle);
                try
                {
                    base.SingleClickInternal(X, Y, MouseButton.Left, MouseKeyModifier.None);

                    // Wait for the animation to finish
                    base.WaitForAnimation(Identity.Handle, true, AnimationUtils.WaitForAnimationSource.Form);

                    // Check the window is now minimised
                    Stopwatch timer = Stopwatch.StartNew();
                    do
                    {
                        GUI.m_APE.AddFirstMessageFindByHandle(DataStores.Store0, Identity.ParentHandle, Identity.Handle);
                        GUI.m_APE.AddQueryMessageReflect(DataStores.Store0, DataStores.Store1, "WindowState", MemberTypes.Property);
                        GUI.m_APE.AddQueryMessageReflect(DataStores.Store1, DataStores.Store2, "ToString", MemberTypes.Method);
                        GUI.m_APE.AddRetrieveMessageGetValue(DataStores.Store2);
                        GUI.m_APE.SendMessages(EventSet.APE);
                        GUI.m_APE.WaitForMessages(EventSet.APE);
                        //Get the value(s) returned MUST be done straight after the WaitForMessages call
                        windowState = GUI.m_APE.GetValueFromMessage();

                        if (timer.ElapsedMilliseconds > GUI.m_APE.TimeOut)
                        {
                            timer.Stop();
                            throw new Exception("Failed to restore the window");
                        }

                        Thread.Sleep(15);
                    }while (windowState != "Normal");
                    timer.Stop();
                }
                finally
                {
                    Input.Unblock();
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Moves the specified window to the specified location by clicking at the specified point to drag the form
        /// </summary>
        /// <param name="mouseDownX">The x coordinate inside the form to perform a mouse down at</param>
        /// <param name="mouseDownY">The y coordinate inside the form to perform a mouse down at</param>
        /// <param name="destinationUpperLeftX">The new location for the left side of the form</param>
        /// <param name="destinationUpperLeftY">The new location for the top of the form</param>
        /// <param name="checkMoveCompleted">Whether to check if the form is now in the location specified</param>
        public void Move(int mouseDownX, int mouseDownY, int destinationUpperLeftX, int destinationUpperLeftY, bool checkMoveCompleted)
        {
            if (mouseDownX < 3)
            {
                mouseDownX = 3;
            }
            if (mouseDownY < 3)
            {
                mouseDownY = 3;
            }

            Rectangle workingArea = Screen.GetWorkingArea(new Point(destinationUpperLeftX, destinationUpperLeftY));

            if (destinationUpperLeftX < workingArea.Left)
            {
                destinationUpperLeftX = workingArea.Left;
            }
            if (destinationUpperLeftY < workingArea.Top)
            {
                destinationUpperLeftY = workingArea.Top;
            }
            if (destinationUpperLeftX > workingArea.Right - mouseDownX - 3)
            {
                destinationUpperLeftX = workingArea.Right - mouseDownX - 3;
            }
            if (destinationUpperLeftY > workingArea.Bottom - mouseDownY - 3)
            {
                destinationUpperLeftY = workingArea.Bottom - mouseDownY - 3;
            }

            GUI.Log("Move the " + Identity.Description + " window to " + destinationUpperLeftX.ToString() + ", " + destinationUpperLeftY.ToString(), LogItemType.Action);

            NM.tagRect windowRect;
            NM.GetWindowRect(Identity.Handle, out windowRect);

            Input.Block();
            try
            {
                base.MouseDownInternal(mouseDownX, mouseDownY, MouseButton.Left, MouseKeyModifier.None, 32, 32);
                base.MouseUpInternal(destinationUpperLeftX + mouseDownX - windowRect.left, destinationUpperLeftY + mouseDownY - windowRect.top, MouseButton.Left, MouseKeyModifier.None);

                if (checkMoveCompleted)
                {
                    Stopwatch timer = Stopwatch.StartNew();
                    while (true)
                    {
                        NM.GetWindowRect(Identity.Handle, out windowRect);

                        //if we are in the right place +/- 2 pixel then break the loop
                        if (windowRect.left > destinationUpperLeftX - 3 && windowRect.left < destinationUpperLeftX + 3)
                        {
                            if (windowRect.top > destinationUpperLeftY - 3 && windowRect.top < destinationUpperLeftY + 3)
                            {
                                break;
                            }
                        }

                        if (timer.ElapsedMilliseconds > GUI.m_APE.TimeOut)
                        {
                            throw GUI.ApeException("Failed to move the form");
                        }

                        Thread.Sleep(15);
                    }
                }
            }
            catch when(Input.ResetInputFilter())
            {
                // Will never be reached as ResetInputFilter always returns false
            }
            finally
            {
                Input.Unblock();
            }
        }
コード例 #9
0
        /// <summary>
        /// Minimises the form by clicking the minimise button in the top right hand corner of the form
        /// </summary>
        public void Minimise()
        {
            GUI.Log("Minimise the " + Identity.Description, LogItemType.Action);

            string windowState = FormWindowState();

            if (windowState == "Minimized")
            {
                throw GUI.ApeException("Can not minimise the window as it already is");
            }

            GUI.m_APE.AddFirstMessageGetTitleBarItemRectangle(Identity.Handle, NM.TitleBarStateElement.Minimize);
            GUI.m_APE.SendMessages(EventSet.APE);
            GUI.m_APE.WaitForMessages(EventSet.APE);
            //Get the value(s) returned MUST be done straight after the WaitForMessages call
            NM.StateSystem State  = (NM.StateSystem)GUI.m_APE.GetValueFromMessage();
            int            Top    = GUI.m_APE.GetValueFromMessage();
            int            Left   = GUI.m_APE.GetValueFromMessage();
            int            Bottom = GUI.m_APE.GetValueFromMessage();
            int            Right  = GUI.m_APE.GetValueFromMessage();

            // Check the maximise button is actually displayed
            if (State != NM.StateSystem.STATE_SYSTEM_NORMAL && State != NM.StateSystem.STATE_SYSTEM_PRESSED)
            {
                throw GUI.ApeException("Can not minimise the window as the minimised button is in state '" + State.ToString() + "'");
            }

            NM.tagRect WindowRect;
            NM.GetWindowRect(Identity.Handle, out WindowRect);

            int X = Left + ((Right - Left) / 2) - WindowRect.left;
            int Y = Top + ((Bottom - Top) / 2) - WindowRect.top;

            Input.Block();
            try
            {
                base.SingleClickInternal(X, Y, MouseButton.Left, MouseKeyModifier.None, 32, 32);

                // Wait for the animation to finish
                base.WaitForAnimation(Identity.Handle, true, AnimationUtils.WaitForAnimationSource.Form);

                // Check the window is now minimised
                Stopwatch timer = Stopwatch.StartNew();
                do
                {
                    windowState = FormWindowState();

                    if (timer.ElapsedMilliseconds > GUI.m_APE.TimeOut)
                    {
                        timer.Stop();
                        throw GUI.ApeException("Failed to minimise the window");
                    }

                    Thread.Sleep(15);
                }while (windowState != "Minimized");
                timer.Stop();
            }
            catch when(Input.ResetInputFilter())
            {
                // Will never be reached as ResetInputFilter always returns false
            }
            finally
            {
                Input.Unblock();
            }
        }