请教下:怎么判断窗口是否被别的窗口挡住

xwy2258588 2008-01-20 01:39:21
我有个应用程序,有多个窗口,可能被自己应用窗口挡住,或者被别的应用程序的窗口挡住即窗口被遮挡.我怎么判定窗口被遮挡.
谢谢
...全文
2349 30 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
巨应打字员 2011-07-26
  • 打赏
  • 举报
回复 1
个人认为 Form.ContainsFocus;就搞定了,楼上的牛人们意下如何?
xwy2258588 2008-01-21
  • 打赏
  • 举报
回复
谢谢,上面的各位。
我试下。
Optione 2008-01-21
  • 打赏
  • 举报
回复
尝试:GetForegroundWindow
shrinerain 2008-01-21
  • 打赏
  • 举报
回复
1. 取出当前活动窗体
2. 用GetClientRect获取各个窗体在屏幕上的位置.
3. 检查是否有重合
4. 如果有重合, 取得重合部分中心点, 用GetWindowFromPoint, 获取重合点的top窗体, 检查是否是你的窗体, 如果不是, 说明被遮挡.

Alex_MagicBoy 2008-01-21
  • 打赏
  • 举报
回复
api Getwindowrect 获取 窗口 X Y 高宽长度.. 是否少与 其他窗口的 X Y 高宽长度 可以吗? 我也不太懂..只是感觉

当你打开你的 窗口 Getwindowrect 信息保存起来.. 然后 当你打开其他窗口的时候 用那窗口的信息 对比你应用程序的窗口信息..
我的愚见.. 有空帮我顶下贴.. 我也有个大困难

http://topic.csdn.net/u/20080119/13/fc2a2576-e924-4cf0-a185-e67853afab91.html

http://topic.csdn.net/u/20080119/11/0d1b8aec-b349-4699-b837-fdeac8ab22a8.html
王集鹄 2008-01-21
  • 打赏
  • 举报
回复
一个更好的解决方案,不用加事件,也可以判断标题;
没有考虑不规则窗体的情况。
参考如下代码:
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();
}
王集鹄 2008-01-21
  • 打赏
  • 举报
回复
这个问题我以前也问过,想到的办法就是Invalidate刷新一下,看看Paint事件是否触发或者刷新区域无效。
缺点就是不能判断窗体标题栏是否也被遮挡。
参考如下代码:
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 = "客户区不可见";
}
gxingmin 2008-01-21
  • 打赏
  • 举报
回复
如果你不想让用户看到这个mnuWindows(窗口)菜单,你可以隐藏它,只在你判断代码里用到它就可以了
gxingmin 2008-01-21
  • 打赏
  • 举报
回复
你可以在你程序的主窗体上加个菜单项,比如:mnuWindows(窗口),把这个菜单的MdiList属性设为True,每次打开一个子窗体,该菜单项会增加这个窗体标题的子菜单项,通过子菜单项的Checked属性来判断当前激活的子窗体和非激活的子窗体了
下面这段代码是VB.Net的,你可以参考一下
   
For Each mnu As MenuItem In mnuWindows.MenuItems
If mnu.Checked Then
MessageBox.Show(mnu.Text & "窗口是激活状态!")
Else
MessageBox.Show(mnu.Text & "窗口是非激活状态!")
End If
Next
xwy2258588 2008-01-21
  • 打赏
  • 举报
回复
uscool
小小风
等 级:
发表于:2008-01-21 09:20:2916楼 得分:0
定时刷新,将窗口为TopMost,也就是说,你失去焦点将会自动获得焦点~~~

=============================================
这个不现实,我程序里的所有窗口都有可能吸附在一起,把所有窗口设置TopMost等于没设置。

jupiter911 2008-01-21
  • 打赏
  • 举报
回复
重写OnPaint(),如果失去焦点的时候重绘就肯定是被遮盖了.然后获取当前具有焦点的窗体就行了
uscool 2008-01-21
  • 打赏
  • 举报
回复
定时刷新,将窗口为TopMost,也就是说,你失去焦点将会自动获得焦点~~~
jianojian 2008-01-21
  • 打赏
  • 举报
回复
找自己的窗口容易点,找别的难啊
sknice 2008-01-21
  • 打赏
  • 举报
回复
每生成一个对象都放进哈希表里面,遍历一下哈希表就知道了
xwy2258588 2008-01-21
  • 打赏
  • 举报
回复
Optione
昵称非法
等 级:
发表于:2008-01-21 00:42:5812楼 得分:0
尝试:GetForegroundWindow

===========================
应该不行,这个函数只能获取活动窗口,屏幕上能挡住别的窗口的窗口一般都不是激活窗口。
我也试过gettopwindow只能取得最顶层的窗口。都不能判断出窗口是否被挡住。
各位高手还有别的方法能判断下吗?取巧的方法也行。
xwy2258588 2008-01-21
  • 打赏
  • 举报
回复
谢谢各位
to zswang
你的方法可以判断全部遮挡,但是不能判断,部分遮挡。不过还是谢谢。

to shrinerain
你的方法还没试,等晚上慢慢搞。谢谢

各位还有好的方法吗?不胜感激。

lioiwowiqkd 2008-01-21
  • 打赏
  • 举报
回复
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有关,有兴趣的朋友可以自己做做,做出来别忘记和大家分享一下。



主页上的某文章。。。下次提问先找找多好。。。哎。。。 orz,服了楼主
阿非 2008-01-21
  • 打赏
  • 举报
回复
友情UP~
xwy2258588 2008-01-20
  • 打赏
  • 举报
回复
GetWindowPlacement涵数返回的WINDOWPLACEMENT
我全部跟踪了下,发现只能取得它的大小,或者最大话,最小话,另外没什么发现.
各位高手再帮忙看看啊,我以前做b/s比较多,winform编程不太搞,很多不熟悉.
xwy2258588 2008-01-20
  • 打赏
  • 举报
回复
VirtualAS 虚拟艾非
看窗口有没有焦点
==========================
看焦点没用的,窗口没挡住,也有可能失去焦点

请教下`GetWindowPlacement涵数返回的WINDOWPLACEMENT具体参数说明能详细说明下吗?
加载更多回复(9)

111,113

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧