Winform :判断是否为顶层窗口
今天遇到一个需求,就像MSN提示信息一样,如果窗口未当前,则需闪烁提醒用户
好久没动笔了,写一写记下来吧,嘿嘿
引用:http://www.codeproject.com/KB/dialog/Is_My_Application_on_Top_.aspx
以上图是从copeproject copy下来的,从此图可以看出一个流程吧,但是作者用的是一个GetTopWindow的函数,感觉并不正确,尽管做出来的效果是跟讲的一样,但是。。。。有兴趣的朋友可以看一下,以下是他判断是否当前窗口为最顶层的函数,VB。NET代码
Private Function IsOnTop(ByVal hwnd As Integer) As Boolean
Dim i As Integer = GetTopWindow(0) 'Initialize
Dim x As Integer = 1
Dim s As String
' Enumeration
Do
i = GetNextWindow(i, 2) ' Find next window in Z-order
If i = hwnd Then
Exit Do
Else
If i = 0 Then ' Never find any window match the input handle
Return False
End If
End If
If IsWindowVisible(i) = True Then
s = Space(256)
If GetWindowText(i, s, 255) <> 0 Then
' Very important to prevent confusing
' of BalloonTips and ContextMenuStrips
x += 1
End If
End If
Loop
' x is Z-order number
If x = 1 Then
Return True
Else
Return False
End If
End Function
但通过console打印出自已当前处于最顶层窗口句柄时,也打印出GetTopWindow获得的句柄,再用SPY++查看,并不一致,那里出错呢,对这函数的理解出错了么?
幸好忽闪过一个函数:
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
再与当前自已处于顶层的窗口句柄比较了一下,是一致的,就直接采用了
查了一下MSDN
GetForegroundWindow Function
The GetForegroundWindow function returns a handle to the foreground window (the window with which the user is currently working). The system assigns a slightly higher priority to the thread that creates the foreground window than it does to other threads.
GetTopWindow Function
The GetTopWindow function examines the Z order of the child windows associated with the specified parent window and retrieves a handle to the child window at the top of the Z order.
自已英语很菜,但这gettopwindow的意思是获取子窗口的顶层窗口的句柄,但网上别人说:传0进去是获得WINDOWS当前顶层窗口?
而闪烁则是通过flashwindow函数,这大多C++ coder都清楚的,嘿嘿,就能跟MSN一样,当用户并未操作当前消息窗口时能提示
顺便写写这个例中过程中曾用过的几个API
[DllImport("user32", EntryPoint = "GetTopWindow", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int GetTopWindow(int hwnd);
[DllImport("user32", EntryPoint = "GetWindow", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int GetNextWindow(int hwnd, int wFlag);
[DllImport("user32", EntryPoint = "IsWindowVisible", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern bool IsWindowVisible(int hwnd);
[DllImport("user32", EntryPoint = "GetWindowTextA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int GetWindowText(int hwnd, string lpString, int cch);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
也记一下一篇文章,很好的介结了WINDOWS窗口机制,改天好好验证一下每个函数
http://blog.csdn.net/chenshaoying/archive/2008/04/24/2324304.aspx
其实上面主要涉及到的,还是一个Z轴的问题,老的WIN32 coder是很熟啦,通过Z轴,能做出一些很漂亮的效果哦,最明显的就是一个OUTLOOK的控件,codeproject上有好几个介绍的,一个是作者自已写的,好长好长的代码呀,另一个,则是作者通过设置Z轴达到的效果,很好很强大
以下是其设置Z轴的一段代码
void ButtonClick(object sender, System.EventArgs e)
{
// Get the clicked button...
Button clickedButton = (Button)sender;
// ... and it's tabindex
int clickedButtonTabIndex = clickedButton.TabIndex;
// Send each button to top or bottom as appropriate
foreach (Control ctl in panel1.Controls)
{
if (ctl is Button)
{
Button btn = (Button)ctl;
if (btn.TabIndex > clickedButtonTabIndex)
{
if (btn.Dock != DockStyle.Bottom)
{
btn.Dock = DockStyle.Bottom;
// This is vital to preserve the correct order
btn.BringToFront();
}
}
else
{
if (btn.Dock != DockStyle.Top)
{
btn.Dock = DockStyle.Top;
// This is vital to preserve the correct order
btn.BringToFront();
}
}
}
}
// Determine which button was clicked.
switch (clickedButton.Text)
{
case "Cars":
CreateCarList();
break;
case "Outlook Shortcuts":
CreateOutlookList();
break;
case "Zip Files":
CreateZipList();
break;
}
listView1.BringToFront(); // Without this, the buttons will hide the items.
}
很简单地设置一个Z轴就达到OUTLook效果了,给自已标志一下,加油
别告诉我那种VS效果是怎么做出来的哦,那要说的话可以写好长好长的一篇文章了,CODEPROJECT上就有一个开源的控件做,嘿嘿,很佩服作者的精神,坚持下去。。。。。。。。。