zoukankan      html  css  js  c++  java
  • 判断一个窗体是否被完全遮挡(比较有意思,但这招有什么用呢?)

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        Text = e.ClipRectangle.Width.ToString();
    }

    在窗体的Paint事件中,有一个ClipRectangle的属性,解释为“获取要在其中进行绘画的矩形”
    这个属性的作用就是:窗体在刷新的时候,为提高效率一些被遮挡的区域就不用再绘制。
    那么判断窗体是否被完全遮挡,只需要判断刷新时是否产生有效绘制。

    bool windowPaint = false;

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        windowPaint = e.ClipRectangle.Width > 0 && e.ClipRectangle.Height > 0; // 存在刷新的区域
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        windowPaint = false;
        Invalidate();
        if (windowPaint)
            Text = "客户区可见";
        else Text = "客户区不可见";
    }


    根据这个思路写出如上代码。测试的结果是对客户区判断有效,对标题栏判断失效。
    联想到Delphi中OnPaint中没有参数,这个刷新区域能通过Canvas.ClipRect属性获得。
    分析VCL源代码
    function TCanvas.GetClipRect: TRect;
    begin
      RequiredState([csHandleValid]);
      GetClipBox(FHandle, Result);
    end;
    找到GetClipBox函数。
    按经验GetWindowDC可以取得整个窗体的画布(包括客户区和非客户区);
    这样就有了线索,二话不说动手测试吧。
    ---Delphi----
    function WindowPall(AHandle: THandle): Boolean; // 窗体是否被遮住
    var
      vDC: THandle;
      vRect: TRect;
    begin
      Result := False;
      if not IsWindowVisible(AHandle) then Exit;
      vDC := GetWindowDC(AHandle);
      try
        GetClipBox(vDC, vRect);
        Result := (vRect.Right - vRect.Left <= 0) and (vRect.Bottom - vRect.Top <= 0);
      finally
        ReleaseDC(AHandle, vDC);
      end;
    end; { WindowPall }

    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      Application.Title := BoolToStr(WindowPall(Handle), True);
    end;
    达到理想效果。翻译成C#。
     

    using System.Runtime.InteropServices;

    [DllImport("user32.dll")]
    public static extern bool IsWindowVisible(IntPtr hWnd);

    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowDC(IntPtr hWnd);

    [DllImport("user32.dll")]
    public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

    [DllImport("gdi32.dll")]
    public static extern int GetClipBox(IntPtr hDC, ref Rectangle lpRect);

    /// <summary>
    /// 判断窗体是否被遮挡
    /// </summary>
    /// <param name="hWnd">窗体句柄</param>
    /// <returns>返回窗体是否被完全遮挡</returns>
    public bool WindowPall(IntPtr AHandle)
    {
        if (!IsWindowVisible(AHandle)) return false; // 窗体不可见
        IntPtr vDC = GetWindowDC(AHandle);
        try
        {
            Rectangle vRect = new Rectangle();
            GetClipBox(vDC, ref vRect);
            return vRect.Width - vRect.Left <= 0 && vRect.Height - vRect.Top <= 0;
            // 特别说明:Rectangle.Width对应API中RECT.Right、Rectangle.Height为RECT.Bottom
        }
        finally
        {
            ReleaseDC(AHandle, vDC);
        }
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        Text = WindowPall(Handle).ToString();
    }


    这个解决方案没有考虑不规则窗体的情况,可能和GetClipRgn有关,有兴趣的朋友可以自己做做,做出来别忘记和大家分享一下。

    http://blog.csdn.net/zswang/article/details/2056199

  • 相关阅读:
    MODBUS 数据格式相关记录
    STM32Cube基础工程配置
    QT5学习记录(一)
    求最大值
    算法训练方格取数
    传纸条
    分组背包
    混合背包
    二维背包
    多重背包
  • 原文地址:https://www.cnblogs.com/findumars/p/6347907.html
Copyright © 2011-2022 走看看