システムトレイにアイコンを持つC#WPF .NET 4アプリケーションがあります。私は現在よく議論されているWPF NotifyIconを使用していますが、私が持っている問題はこのコントロールに依存していません。問題は、.NET 4ではWPF ContextMenuオブジェクトがWindows 7のタスクバーの上部に表示されないことです(ほとんどの場合)。この例は、問題を完全に示しています。WPFアプリケーションのトレーアイコンコンテキストメニューの配置
XAML:
<Window x:Class="TrayIconTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="100" Width="400">
<Window.Resources>
<ContextMenu x:Key="TrayContextMenu" Placement="MousePoint">
<MenuItem Header="First Menu Item" />
<MenuItem Header="Second Menu Item" />
</ContextMenu>
<Popup x:Key="TrayPopup" Placement="MousePoint">
<Border Width="100" Height="100" Background="White" BorderBrush="Orange" BorderThickness="4">
<Button Content="Close" Click="ButtonClick"></Button>
</Border>
</Popup>
</Window.Resources>
<StackPanel Orientation="Horizontal">
<Label Target="{Binding ElementName=UseWinFormsMenu}" VerticalAlignment="Center">
<AccessText>Use WinForms context menu for tray menu:</AccessText>
</Label>
<CheckBox Name="UseWinFormsMenu" IsChecked="False" Click="UseWinFormsMenuClicked" VerticalAlignment="Center" />
</StackPanel>
</Window>
コード:
using System.Drawing;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Forms;
using ContextMenu = System.Windows.Controls.ContextMenu;
namespace TrayIconTesting
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ContextMenuStrip winFormsContextMenu;
public MainWindow()
{
InitializeComponent();
this.TrayIcon = new NotifyIcon
{
Icon = new Icon("Bulb.ico"),
Visible = true
};
this.TrayIcon.MouseClick += (sender, args) =>
{
switch (args.Button)
{
case MouseButtons.Left:
this.TrayPopup.IsOpen = true;
break;
case MouseButtons.Right:
if (!this.UseWinFormsMenu.IsChecked.GetValueOrDefault())
{
this.TrayContextMenu.IsOpen = true;
}
break;
}
};
}
private void ButtonClick(object sender, RoutedEventArgs e)
{
this.TrayPopup.IsOpen = false;
}
private void UseWinFormsMenuClicked(object sender, RoutedEventArgs e)
{
this.TrayIcon.ContextMenuStrip = this.UseWinFormsMenu.IsChecked.GetValueOrDefault() ? this.WinFormsContextMenu : null;
}
private ContextMenu TrayContextMenu
{
get
{
return (ContextMenu)this.FindResource("TrayContextMenu");
}
}
private Popup TrayPopup
{
get
{
return (Popup)this.FindResource("TrayPopup");
}
}
private NotifyIcon TrayIcon
{
get;
set;
}
private ContextMenuStrip WinFormsContextMenu
{
get
{
if (this.winFormsContextMenu == null)
{
this.winFormsContextMenu = new ContextMenuStrip();
this.winFormsContextMenu.Items.AddRange(new[] { new ToolStripMenuItem("Item 1"), new ToolStripMenuItem("Item 2") });
}
return this.winFormsContextMenu;
}
}
}
}
問題を表示するには、トレイアイコンが常に表示し、そのWin7のトレイアイコンのポップアップ事のない部分であることを確認してください。トレイアイコンを右クリックすると、コンテキストメニューがタスクバーの上で開きます。次に、標準のWindowsトレイアイコンの1つを右クリックし、その違いを確認します。
ここで、アイコンを左クリックして、マウスカーソルがあるところでカスタムポップアップを右に開くことができることに注意してください。
"WinFormsを使用..."チェックボックスをオンにすると、Windows.Formsアセンブリ内の古いContextMenuStripコンテキストメニューを使用するようにアプリが切り替わります。これにより明らかに正しい場所にメニューが表示されますが、外観はデフォルトのWindows 7のメニューと一致しません。具体的には、行の強調表示が異なります。
HorizontalとVerticalOffsetプロパティで再生していますが、 "右"の値では、画面の右下にコンテキストメニューのポップアップを作成できますが、これは悪いことです。カーソルがどこにあるかはまだ決して決して開きません。
実際のキッカーは、.NET 3.5をターゲットにして同じサンプルを作成した場合、期待どおりに動作するということです。残念ながら、私の実際のアプリケーションでは.NET 4の多くの機能が使用されているため、元に戻すことは選択肢にはなりません。
誰でもコンテキストメニューを実際にカーソルが開いている場所にする方法はありますか?
ターゲットアイコン.NET 3.5を実行する別のアセンブリにすべての通知アイコンロジックを配置して、それを実際のプロジェクト内で使用することはできませんか? – SwissCoder
残念ながらそれは動作しません。この問題は、3.5をターゲットとする別のアセンブリに通知アイコンとコンテキストメニューが存在する場合でも引き続き発生します。実行可能なターゲット4.0の問題が存在する限りはそうです。 – EricTheRed
問題の解決策ではありませんが、WinFormsメニューを使用します。最終的に別のアセンブリで、WinFormsとWPFの間をきれいにする。そうすれば、NotifyIconのContext-Menuは通常のアプリのように見えるはずです。 – SwissCoder