Windows 8系统托盘通知漏洞

9

我正在尝试在Windows 8上创建一个简单的PowerShell脚本,该脚本将通过系统托盘通知气球来通知我。代码非常简单:

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon

$objNotifyIcon.Icon = "D:\1.ico"
$objNotifyIcon.BalloonTipIcon = "Info"
$objNotifyIcon.BalloonTipText = "I'm there"
$objNotifyIcon.BalloonTipTitle = "Hello!"

$objNotifyIcon.Visible = $True
$objNotifyIcon.ShowBalloonTip(10000)

1.ico是真正存在于磁盘上的自定义图标。

它可以正常工作,除了一个小问题:我更喜欢将任务栏放在窗口顶部,这似乎给气球带来了麻烦:它会被绘制在任务栏下方(屏幕截图:https://dl.dropbox.com/u/1138313/systraybug.PNG)。我用C#制作了一个测试应用程序,使用notifyIcon得到了同样的结果。但是像Dropbox或Skydrive等其他应用程序没有这样的问题,我的任务栏在底部的脚本也能完美地运行。

我在NotifyIcon文档中没有找到任何样式选项。这是一个令人恼火的错误吗?还是我可以修复它?

谢谢。

更新:看起来,即使Dropbox应用程序也有同样的问题(可耻的是,第一次没看到)。所以我想这是系统的错。


请您能否发布完整的代码,这样我们就可以测试并告知您是否这个错误只出现在您的电脑上了? - Victor Zakharov
气球应该在任务栏下面绘制,而不是在其后面,我这样看。某些类型的气球就是这样工作的,但我无法弄清楚具体情况。 - Bohdan Ivanov
表单通常具有“始终置顶”属性,将其设置为true是否可以解决您的问题? - MDMoore313
Dropbox气球在这里(win8)完美运行。我发现有趣的是,“安全删除硬件”和“Dropbox”等都使用“现代”的方形气球,而我只能获得像图片中那样的圆形气球,就像我们用notifyicon创建的那个一样。所有方形的“新”气球都可以正常工作(不会被切断),而我们用notifyicon创建的圆形“xp-style”气球则会被切断。我们如何获得现代风格?[System.Windows.Forms.Application] :: EnableVisualStyles()没有帮助。 - Frode F.
这不是因为他们正在使用 XAML 而不是 WinForms 吗? - Patrick Magee
我尝试了MakeTopMost,但无论是我没有理解它在Powershell脚本中的工作方式还是它本身没有效果。 - Bohdan Ivanov
2个回答

2

这是Windows中已知的一个bug。您可能能够覆盖任务栏的行为的唯一方法是找到气球的句柄,然后使用SetWindowPos将其置于最顶层:

BOOL WINAPI SetWindowPos(
  _In_      HWND hWnd,
  _In_opt_  HWND hWndInsertAfter,
  _In_      int X,
  _In_      int Y,
  _In_      int cx,
  _In_      int cy,
  _In_      UINT uFlags
);

MSDN:“可以通过将hWndInsertAfter参数设置为HWND_TOPMOST并确保未设置SWP_NOZORDER标志,或通过将窗口的位置设置在Z顺序中,使其位于任何现有的最顶级窗口之上,使窗口成为最顶级窗口。当非最顶级窗口变为最顶级窗口时,它的所有拥有窗口也都变为了最顶级窗口。但是它的所有者不会改变。”更多信息请参见SetWindowPos

另一个策略是降低任务栏的优先级。使用此代码查找最顶层的窗口:

HWND FindMyTopMostWindow()
{
    DWORD dwProcID = GetCurrentProcessId();
    HWND hWnd = GetTopWindow(GetDesktopWindow());
    while(hWnd)
    {
        DWORD dwWndProcID = 0;
        GetWindowThreadProcessId(hWnd, &dwWndProcID);
        if(dwWndProcID == dwProcID)
            return hWnd;            
        hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
    }
    return NULL;
 }

然后降低窗口优先级或将您的窗口Z轴顺序设置得更高。

哦,听起来很有趣。从现在开始我会尝试在ps中轻松实现这个。谢谢。 - Bohdan Ivanov

0

我曾经遇到过同样的问题,并发现气球的形状取决于消息正文的大小。 也就是说,如果您的消息正文长度不超过60个字符,则会显示圆形气球;对于更长的消息,则会使用新的标准方形气球。

我没有使用PowerShell与系统托盘进行交互,而是使用WPF NiotifyIcon库在WPF应用程序中显示托盘图标。

希望对您有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接