判断一个窗体是否被完全遮挡

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

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

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


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

根据这个思路写出如上代码。测试的结果是对客户区判断有效,对标题栏判断失效。
联想到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(IntPtrhWnd);

[DllImport(
" user32.dll " )]
public static extern IntPtrGetWindowDC(IntPtrhWnd);

[DllImport(
" user32.dll " )]
public static extern int ReleaseDC(IntPtrhWnd,IntPtrhDC);

[DllImport(
" gdi32.dll " )]
public static extern int GetClipBox(IntPtrhDC, ref RectanglelpRect);

/**/ ///<summary>
///判断窗体是否被遮挡
///</summary>
///<paramname="hWnd">窗体句柄</param>
///<returns>返回窗体是否被完全遮挡</returns>

public bool WindowPall(IntPtrAHandle)
... {
if(!IsWindowVisible(AHandle))returnfalse;//窗体不可见
IntPtrvDC=GetWindowDC(AHandle);
try
...{
RectanglevRect
=newRectangle();
GetClipBox(vDC,
refvRect);
returnvRect.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,EventArgse)
... {
Text
=WindowPall(Handle).ToString();
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值