How to check if window is really visible in Windows Forms?

后端 未结 9 1240
小蘑菇
小蘑菇 2020-12-30 09:59

Normally you use Form.Visible to check if Window is visible at all. But sometimes on the screen window is below other windows so it\'s really invisible.

So how to ch

相关标签:
9条回答
  • 2020-12-30 10:10

    You can call the Activate method on the form to bring it to the front if it isn't already.

    However, note that if a different program is active, it will usually simply flash the desktop button (depending where you call it from). This is Windows' standard protection against focus-stealing and you should not try to work around it.

    0 讨论(0)
  • 2020-12-30 10:14

    To answer the question as asked, you could try calling the WindowFromPoint API function to find the window at various points on your form, and check whether it returns the handle of whatever you expect to be at that point.

    0 讨论(0)
  • 2020-12-30 10:18

    Simply set the Form.AlwaysOnTop property to true.

    0 讨论(0)
  • 2020-12-30 10:25

    You also could.. :) get the ClickablePoint property from the AutomationElement corresponding to the window. I am not 100%ly sure whether this is completely accurate though.. it has worked in 99% of the cases for me and I am still checking on the other 1%, where the problem lies (might be on my side or bad user handling, or.)

    0 讨论(0)
  • 2020-12-30 10:25

    I aktually tried to implement SLaks suggestion. Although I wrote it in VB.NET, not C#

    Friend Structure PointStruct
        Public x As Int32
        Public y As Int32
    End Structure
    
    <System.Runtime.InteropServices.DllImport("user32.dll")> _
    Friend Function WindowFromPoint(ByVal Point As PointStruct) As IntPtr
    End Function
    
    ''' <summary>
    ''' Checks if a control is actually visible to the user completely
    ''' </summary>
    ''' <param name="control">The control to check.</param>
    ''' <returns>True, if the control is completely visible, false else.</returns>
    ''' <remarks>This is not 100% accurate, but feasible enough for my purpose.</remarks>
    Public Function IsControlVisibleToUser(ByVal control As Windows.Forms.Control) As Boolean
        If Not control.Visible Then Return False
    
        Dim bAllPointsVisible As Boolean = True
        Dim lPointsToCheck As New List(Of Point)
        'Add the points to check. In this case add the edges and some border points
        'between the edges.
        'Strangely, the exact edge points always return the false handle.
        'So we add a pixel into the control.
        lPointsToCheck.Add(New Point(control.Left + 1, control.Top + 1))
        lPointsToCheck.Add(New Point(control.Right - 1, control.Top + 1))
        lPointsToCheck.Add(New Point(control.Right - 1, control.Bottom - 1))
        lPointsToCheck.Add(New Point(control.Left + 1, control.Bottom - 1))
        lPointsToCheck.Add(New Point(control.Left + control.Width / 2, control.Top + 1))
        lPointsToCheck.Add(New Point(control.Right - 1, control.Top + control.Height / 2))
        lPointsToCheck.Add(New Point(control.Right - control.Width / 2, control.Bottom - 1))
        lPointsToCheck.Add(New Point(control.Left + 1, control.Bottom - control.Height / 2))
        'lPointsToCheck.Add(New Point(control.Left + control.Width / 2, control.Top + control.Height / 2))
    
        'Check each point. If all points return the handle of the control,
        'the control should be visible to the user.
        For Each oPoint In lPointsToCheck
            Dim sPoint As New PointStruct() With {
                .x = oPoint.X, _
                .y = oPoint.Y _
            }
            bAllPointsVisible = bAllPointsVisible And ( _
                (WindowFromPoint(sPoint) = control.Handle) _
            )
        Next
    
        Return bAllPointsVisible
    End Function
    
    0 讨论(0)
  • 2020-12-30 10:25

    You should be able to find out if your window is visible by overriding the OnPaint method. You'll want to pass control to the base class in order to do the actual painting, but you'll be able to detect whether a paint message is received. Update: no, this doesn't work, Sorry!

    In principle, the Activate method should bring your window to the foreground, but in practice I've always found this problematic if other processes have the input focus. If you really want someone to see a window, set the topmost bit, but expect them to be annoyed! One surefire way to get some attention for a window is to close it and reopen it, if you can get away with that.

    One way to achieve what you're looking for is to use a notify icon, this will get the user's attention in a way that is compliant with Windows UI guidelines.

    0 讨论(0)
提交回复
热议问题