gpt4 book ai didi

.net - WPF 任务栏图标上下文菜单

转载 作者:行者123 更新时间:2023-12-02 04:51:20 30 4
gpt4 key购买 nike

我正在尝试使用 TaskbarIcon 创建一个 WPF 应用程序,我想如果我点击托盘栏中的图标,它会弹出一个上下文菜单,如果我选择“退出”,那么它会显示一个消息框,询问我是否要关闭此应用程序。

这就是问题所在,MessageBox 显示正确,但它在我单击任何按钮之前立即消失,我使用调试器检查“结果”值,我发现它始终为“否”。有没有人遇到过这个问题?任何线索将不胜感激!!

这是我的 .xaml 代码:

<tb:TaskbarIcon x:Name="WpfTaskIcon" IconSource="/Themes/Images/TimeSync.ico"
ToolTipText="Hello world" >
<tb:TaskbarIcon.ContextMenu>
<ContextMenu Background="LightCoral">
<MenuItem Header="Exit" Click="Exit_Click" />
<MenuItem Header="Second menu Item" />
</ContextMenu>
</tb:TaskbarIcon.ContextMenu>

这是我的 C# 代码:

private void Exit_Click(object sender, RoutedEventArgs e)
{
MessageBoxResult result = System.Windows.MessageBox.Show(
"Message_ConfirmationOfExit",
"Title_Confirmation",
MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
this.Close();
}
}

编辑:我添加了这个来初始化 MainWindow 的可见性:

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
this.Visibility = System.Windows.Visibility.Visible;
MessageBox.Show("MainWindow loaded");
MessageBoxResult result = System.Windows.MessageBox.Show(
"Message_ConfirmationOfExit",
"Title_Confirmation",
MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
this.Close();
}
}

最佳答案

可能来的有点晚了,不过我可能已经找到这个问题的原因了:

MessageBox 使用 WindowAPI。

引用:http://pinvoke.net/default.aspx/user32/MessageBox.html

[DllImport("user32.dll", SetLastError = true, CharSet= CharSet.Auto)]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

参数包括IntPtr类型的hWnd

在 WPF 中调用 MessageBox.Show() 时,ShowCore() 方法在 MessageBox 类内部被调用,该类内部处理这个参数。

引用:https://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/MessageBox.cs在第 483 行

...


if ( (options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) ! = 0)
{
// Demand UnmangedCode permissions if using ServiceNotification/DefaultDesktopOnly.
// Details in DevDiv 163043.
SecurityHelper.DemandUnmanagedCode()
if (owner ! = IntPtr.Zero)
{
throw new ArgumentException(SR.Get(SRID.CantShowMBServiceWithOwner));
}
}
else
{
if (owner == IntPtr.Zero)
{
owner = UnsafeNativeMethods.GetActiveWindow();
}
}

...

我认为,在 WPF 中使用 MessageBox 时,当前事件窗口被自动选择为 hWnd,并且由于没有窗口,ContextMenu 用作窗口。

我们可以使用 API 证明这一点:

[DllImport("user32.dll")]
static extern IntPtr GetActiveWindow();

并在点击事件中使用它:

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
var t = GetActiveWindow();
}

然后在spy++中找到t的值,就是ContextMenu

ContextMenu上的MenuItem被点击时,ContextMenu会被关闭,此时MessageBox<的所有者 消失,MessageBox 被强制关闭。

基于以上研究,我得到了以下解决方案。

1.延迟 MessageBox 的出现,使其在 ContextMenu 关闭后显示。

await Task.Delay(200); 
MessageBox.Show("Hello, world!");

2.调用API本身并将hWnd设置为IntPtr.Zero。

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MessageBox(IntPtr.Zero, "Hello, world!", "Test", 0);
}

3.根据WPF中MessageBox源码修改MessageBoxOptions的值。

MessageBox.Show(
"Hello, world!",
"Test",
MessageBoxButton.OK,
MessageBoxImage.Error,
MessageBoxResult.OK,
MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly);

也许这可以为大家提供一些帮助。

==================

我觉得这样比较好:

向 App.xaml.cs 添加一个变量:

bool isNeedShowMessageBox = false;

当按下 MenuItem 时:

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
isNeedShowMessageBox = true;
}

为上下文菜单添加事件:

<ContextMenu Closed="ContextMenu_Closed">

然后:

private void ContextMenu_Closed(object sender, RoutedEventArgs e)
{
if (isNeedShowMessageBox)
{
MessageBox.Show();
isNeedShowMessageBox=false;
}
}

这似乎工作得很好。

在后续的尝试中我发现不仅是MessageBox,OpenFileDialog或者其他类似的窗口也会有同样的强制关闭,但是如果这样处理应该可以避免这个问题。

关于.net - WPF 任务栏图标上下文菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28017576/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com