2012-02-12 2 views
1

시스템 트레이에 아이콘이있는 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 트레이 아이콘 중 하나를 마우스 오른쪽 버튼으로 클릭하고 차이점을 확인하십시오.

이제 아이콘을 마우스 왼쪽 버튼으로 클릭하고 마우스 커서가있는 곳에서 맞춤 팝업을 열 수 있음을 확인하십시오.

"WinForms 사용 ..."확인란을 선택하면 Windows.Forms 어셈블리의 이전 ContextMenuStrip 컨텍스트 메뉴를 사용하도록 응용 프로그램이 전환됩니다. 이렇게하면 분명히 올바른 위치에 메뉴가 열리지 만 모양이 기본 Windows 7 메뉴와 일치하지 않습니다. 특히 행 강조 표시가 다릅니다.

Horizontal 및 VerticalOffset 속성을 사용하여 연주했으며 "오른쪽"값을 사용하면 화면 오른쪽 하단에서 컨텍스트 메뉴 팝업을 끝까지 볼 수 있지만 이는 나쁘게도 마찬가지입니다. 커서가있는 곳에서는 절대로 열리지 않습니다.

.NET 3.5를 대상으로 동일한 샘플을 빌드하면 예상대로 작동합니다. 불행히도, 제 실제 응용 프로그램은 많은 .NET 4 기능을 사용하므로 되돌릴 수 없습니다.

누구나 커서가있는 곳에서 컨텍스트 메뉴를 실제로 여는 방법을 알고 계십니까?

+0

.NET 3.5를 대상으로하는 별도의 어셈블리에 알림 아이콘 로직을 모두 넣을 수 없으며 실제 프로젝트에서 사용하십시오. – SwissCoder

+0

아쉽게도 작동하지 않습니다. 알림 아이콘과 컨텍스트 메뉴가 3.5를 대상으로하는 별도의 어셈블리에 존재하는 경우에도 문제가 계속 발생합니다. 실행 가능한 타겟 4.0이 문제가 존재하는 한 그렇게 보인다. – EricTheRed

+0

문제의 해결책은 아니지만 WinForms 메뉴를 사용합니다. 궁극적으로 별도의 어셈블리에서 WinForms와 WPF 사이를 깨끗하게 잘라냅니다. 그런 식으로 NotifyIcon의 Context-Menu는 일반 앱용으로 표시되어야합니다. – SwissCoder

답변

0

글쎄, 나는 나를 위해 약간 더 나은 옵션을 발견했기 때문에 이것을 대답으로 표시하지 않았기 때문에 기쁩니다. this article은 System.Windows.Forms.MenuItem 개체에 아이콘을 추가하는 방법을 자세히 설명합니다. 이제 약간의 코드로 시스템 컨텍스트 메뉴와 완벽하게 일치하는 메뉴를 갖게되었습니다!

0

조금 더 검색 한 후에 나는 question & answer을 우연히 발견했습니다. NotifyIcon에서 ContextMenu 속성을 사용해 본적이 없습니다. 이상적이지는 않지만 WPF가 시스템 트레이가 응용 프로그램의 유용한 부분이라는 사실을 알릴 때까지는 충분히 잘 작동합니다. WPF ContextMenu에서 제공하는 모든 바인딩 및 명령 라우팅 기능을 잃어 버리는 것은 정말 수치 스럽습니다.

내 자신의 대답을 받아들이는 것은 잘못 되었기 때문에 앞으로 며칠 동안이 질문을 공개하겠습니다.

관련 문제