码迷,mamicode.com
首页 > Windows程序 > 详细

判断一个窗体是否被完全遮挡(比较有意思,但这招有什么用呢?)

时间:2017-01-24 22:57:57      阅读:281      评论:0      收藏:0      [点我收藏+]

标签:name   效果   validate   top   try   解决   方案   clip   eve   

技术分享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

判断一个窗体是否被完全遮挡(比较有意思,但这招有什么用呢?)

标签:name   效果   validate   top   try   解决   方案   clip   eve   

原文地址:http://www.cnblogs.com/findumars/p/6347907.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!