2013-10-16 63 views
5

Uygulamanın simgesine tıkladığınızda veya uygulamanın başlık çubuğuna sağ tıklandığında ContextMenu numaralı telefonu aramak istiyorum.Özel pencerede Başlat penceresinin Sistem Menüsü

Bu ContextMenu Yani: Ben pencere gibi davranan özel denetim yapılmış çünkü

enter image description here

buna ihtiyacım var.
Denetimimi tamamlamak için bu davranışa ihtiyacım var.

DÜZENLEME:

https://skydrive.live.com/?cid=c3392940f5cf5f74&id=C3392940F5CF5F74%21107&authkey=!APd2X3tDxWRfpL4

ya:

Benim MainWindow.xaml:

<!--<Grid> 
     <Border Name="TopBorder" BorderThickness="0.5,0,0,0" BorderBrush="Blue"/> 
     <Border Name="RightBorder" BorderThickness="0,0.5,0,0" BorderBrush="Red"/> 
     <Border Name="BottomBorder" BorderThickness="0,0,0.5,0" BorderBrush="Green"/> 
     <Border Name="LeftBorder" BorderThickness="0,0,0,0.5" BorderBrush="Orange"/> 
     <Grid Margin="0.5"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition Height="*"/> 
      </Grid.RowDefinitions> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="*"/> 
        <ColumnDefinition Width="Auto"/> 
       </Grid.ColumnDefinitions> 
       <StatusBar Background="Transparent" MouseDoubleClick="TriggerMaximize" MouseDown="StatusBar_MouseDown"> 
        <Image Margin="5,0,0,0" VerticalAlignment="Center" Width="16" Height="16" Source="{Binding Icon, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" RenderOptions.BitmapScalingMode="NearestNeighbor" RenderOptions.EdgeMode="Aliased"/> 
        <Label VerticalAlignment="Center" FontSize="14" Content="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/> 
       </StatusBar> 
       <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Column="1"> 
        <Button x:Name="Minimize" ToolTip="Minimize" Content="0" Style="{DynamicResource TitleBarButton}" Click="TriggerMinimize"/> 
        <Button x:Name="Restore" ToolTip="Restore" Content="2" Style="{DynamicResource TitleBarButton}" Visibility="Collapsed" Click="TriggerMaximize"/> 
        <Button x:Name="Maximize" ToolTip="Maximize" Content="1" Style="{DynamicResource TitleBarButton}" Click="TriggerMaximize"/> 
        <Button x:Name="Close" ToolTip="Close" Content="r" Style="{DynamicResource TitleBarButton}" Click="TriggerClose"/> 
       </StackPanel> 
      </Grid> 
     </Grid> 
    </Grid>--> 

    <DockPanel LastChildFill="true"> 
     <Border Name="TopBorder" DockPanel.Dock="Top" BorderBrush ="#007ACC" BorderThickness="0.5"/> 
     <Border Name="RightBorder" DockPanel.Dock="Right" BorderBrush ="#007ACC" BorderThickness="0.5"/> 
     <Border Name="BottomBorder" DockPanel.Dock="Bottom" BorderBrush ="#007ACC" BorderThickness="0.5"/> 
     <Border Name="LeftBorder" DockPanel.Dock="Left" BorderBrush="#007ACC" BorderThickness="0.5"/> 
     <Grid> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition Height="*"/> 
      </Grid.RowDefinitions> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="*"/> 
        <ColumnDefinition Width="Auto"/> 
       </Grid.ColumnDefinitions> 
       <StatusBar Background="Transparent" MouseDoubleClick="TriggerMaximize" MouseDown="StatusBar_MouseDown"> 
        <Image Margin="5,0,0,0" Width="16" Height="16" Source="{Binding Icon, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" RenderOptions.BitmapScalingMode="NearestNeighbor" RenderOptions.EdgeMode="Aliased"/> 
        <Label VerticalAlignment="Center" FontSize="14" Content="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/> 
       </StatusBar> 
       <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Column="1"> 
        <Button x:Name="Minimize" ToolTip="Minimize" Content="0" Style="{DynamicResource TitleBarButton}" Click="TriggerMinimize"/> 
        <Button x:Name="Restore" ToolTip="Restore" Content="2" Style="{DynamicResource TitleBarButton}" Visibility="Collapsed" Click="TriggerMaximize"/> 
        <Button x:Name="Maximize" ToolTip="Maximize" Content="1" Style="{DynamicResource TitleBarButton}" Click="TriggerMaximize"/> 
        <Button x:Name="Close" ToolTip="Close" Content="r" Style="{DynamicResource TitleBarButton}" Click="TriggerClose"/> 
       </StackPanel> 
      </Grid> 
     </Grid> 
    </DockPanel> 
</Window> 

Benim MainWindow.cs
Leo Lorenzo Luis kod beni istedi (Kod-Arkasında):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.InteropServices; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Windows.Interop; 
using System.Windows.Forms; 

namespace WpfApplication16 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      this.SourceInitialized += new EventHandler(win_SourceInitialized); 
     } 

     private void TriggerMaximize(object sender, MouseButtonEventArgs e) 
     { 
      TriggerMaximize(); 
     } 

     private void TriggerMaximize(object sender, RoutedEventArgs e) 
     { 
      TriggerMaximize(); 
     } 

     private void TriggerMaximize() 
     { 
      if (WindowState == System.Windows.WindowState.Maximized) 
      { 
       WindowState = System.Windows.WindowState.Normal; 
       Restore.Visibility = Visibility.Collapsed; 
       Maximize.Visibility = Visibility.Visible; 
      } 
      else if (WindowState == System.Windows.WindowState.Normal) 
      { 
       WindowState = System.Windows.WindowState.Maximized; 
       Maximize.Visibility = Visibility.Collapsed; 
       Restore.Visibility = Visibility.Visible; 
      } 
     } 

     private void Window_LocationChanged(object sender, EventArgs e) 
     { 
      TriggerBorderChanges(); 
     } 


     private void Window_SizeChanged(object sender, SizeChangedEventArgs e) 
     { 
      TriggerBorderChanges(); 
     } 

     private void TriggerBorderChanges() 
     { 
      TopBorder.BorderThickness = new Thickness(0.5); 
      RightBorder.BorderThickness = new Thickness(0.5); 
      BottomBorder.BorderThickness = new Thickness(0.5); 
      LeftBorder.BorderThickness = new Thickness(0.5); 

      if (Top == 0) 
      { 
       TopBorder.BorderThickness = new Thickness(0); 
       BottomBorder.BorderThickness = new Thickness(0); 
      } 

      if (Left == 0) 
      { 
       LeftBorder.BorderThickness = new Thickness(0); 
      } 

      // need to test in dual view -if not needed, remove drawing and windows.forms (from refereance and from the using) 
      //Screen currentScreen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); 
      //if (Left == (currentScreen.WorkArea.Width - Width)) 
      if (Left == (System.Windows.SystemParameters.WorkArea.Width - 1 - Width)) 
      { 
       RightBorder.BorderThickness = new Thickness(0); 
      } 
     } 

     private void TriggerClose(object sender, RoutedEventArgs e) 
     { 
      Close(); 
     } 

     private void TriggerMinimize(object sender, RoutedEventArgs e) 
     { 
      WindowState = System.Windows.WindowState.Minimized; 
     } 


     private void StatusBar_MouseDown(object sender, MouseButtonEventArgs e) 
     { 
      if (e.ChangedButton == MouseButton.Left) 
       this.DragMove(); 
     } 


     void win_SourceInitialized(object sender, EventArgs e) 
     { 
      System.IntPtr handle = (new WindowInteropHelper(this)).Handle; 
      HwndSource.FromHwnd(handle).AddHook(new HwndSourceHook(WindowProc)); 
     } 

     /// <summary> 
     /// POINT aka POINTAPI 
     /// </summary>5 
     [StructLayout(LayoutKind.Sequential)] 
     public struct POINT 
     { 
      /// <summary> 
      /// x coordinate of point. 
      /// </summary> 
      public int x; 
      /// <summary> 
      /// y coordinate of point. 
      /// </summary> 
      public int y; 

      /// <summary> 
      /// Construct a point of coordinates (x,y). 
      /// </summary> 
      public POINT(int x, int y) 
      { 
       this.x = x; 
       this.y = y; 
      } 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct MINMAXINFO 
     { 
      public POINT ptReserved; 
      public POINT ptMaxSize; 
      public POINT ptMaxPosition; 
      public POINT ptMinTrackSize; 
      public POINT ptMaxTrackSize; 
     }; 

     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
     public class MONITORINFO 
     { 
      /// <summary> 
      /// </summary>    
      public int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); 

      /// <summary> 
      /// </summary>    
      public RECT rcMonitor = new RECT(); 

      /// <summary> 
      /// </summary>    
      public RECT rcWork = new RECT(); 

      /// <summary> 
      /// </summary>    
      public int dwFlags = 0; 
     } 

     /// <summary> Win32 </summary> 
     [StructLayout(LayoutKind.Sequential, Pack = 0)] 
     public struct RECT 
     { 
      /// <summary> Win32 </summary> 
      public int left; 
      /// <summary> Win32 </summary> 
      public int top; 
      /// <summary> Win32 </summary> 
      public int right; 
      /// <summary> Win32 </summary> 
      public int bottom; 

      /// <summary> Win32 </summary> 
      public static readonly RECT Empty = new RECT(); 

      /// <summary> Win32 </summary> 
      public int Width 
      { 
       get { return Math.Abs(right - left); } // Abs needed for BIDI OS 
      } 

      /// <summary> Win32 </summary> 
      public int Height 
      { 
       get { return bottom - top; } 
      } 

      /// <summary> Win32 </summary> 
      public RECT(int left, int top, int right, int bottom) 
      { 
       this.left = left; 
       this.top = top; 
       this.right = right; 
       this.bottom = bottom; 
      } 

      /// <summary> Win32 </summary> 
      public RECT(RECT rcSrc) 
      { 
       this.left = rcSrc.left; 
       this.top = rcSrc.top; 
       this.right = rcSrc.right; 
       this.bottom = rcSrc.bottom; 
      } 

      /// <summary> Win32 </summary> 
      public bool IsEmpty 
      { 
       get 
       { 
        // BUGBUG : On Bidi OS (hebrew arabic) left > right 
        return left >= right || top >= bottom; 
       } 
      } 

      /// <summary> Return a user friendly representation of this struct </summary> 
      public override string ToString() 
      { 
       if (this == RECT.Empty) { return "RECT {Empty}"; } 
       return "RECT { left : " + left + "/top : " + top + "/right : " + right + "/bottom : " + bottom + " }"; 
      } 

      /// <summary> Determine if 2 RECT are equal (deep compare) </summary> 
      public override bool Equals(object obj) 
      { 
       if (!(obj is Rect)) { return false; } 
       return (this == (RECT)obj); 
      } 

      /// <summary>Return the HashCode for this struct (not garanteed to be unique)</summary> 
      public override int GetHashCode() 
      { 
       return left.GetHashCode() + top.GetHashCode() + right.GetHashCode() + bottom.GetHashCode(); 
      } 

      /// <summary> Determine if 2 RECT are equal (deep compare)</summary> 
      public static bool operator ==(RECT rect1, RECT rect2) 
      { 
       return (rect1.left == rect2.left && rect1.top == rect2.top && rect1.right == rect2.right && rect1.bottom == rect2.bottom); 
      } 

      /// <summary> Determine if 2 RECT are different(deep compare)</summary> 
      public static bool operator !=(RECT rect1, RECT rect2) 
      { 
       return !(rect1 == rect2); 
      } 
     } 

     [DllImport("user32")] 
     internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi); 

     [DllImport("User32")] 
     internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags); 

     private static System.IntPtr WindowProc(
       System.IntPtr hwnd, 
       int msg, 
       System.IntPtr wParam, 
       System.IntPtr lParam, 
       ref bool handled) 
     { 
      switch (msg) 
      { 
       case 0x0024: 
        WmGetMinMaxInfo(hwnd, lParam); 
        handled = true; 
        break; 
      } 

      return (System.IntPtr)0; 
     } 

     private static void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam) 
     { 
      MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); 

      // Adjust the maximized size and position to fit the work area of the correct monitor 
      int MONITOR_DEFAULTTONEAREST = 0x00000002; 
      System.IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); 

      if (monitor != System.IntPtr.Zero) 
      { 

       MONITORINFO monitorInfo = new MONITORINFO(); 
       GetMonitorInfo(monitor, monitorInfo); 
       RECT rcWorkArea = monitorInfo.rcWork; 
       RECT rcMonitorArea = monitorInfo.rcMonitor; 
       mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left); 
       mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top); 
       mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left); 
       mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top); 
      } 

      Marshal.StructureToPtr(mmi, lParam, true); 
     } 
    } 
} 

Benim App.xaml:

<Application 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" x:Class="WpfApplication16.App" 
      StartupUri="MainWindow.xaml"> 
    <Application.Resources> 


     <Style x:Key="TitleBarButton" TargetType="Button"> 
      <Setter Property="Foreground" Value="Black"/> 
      <Setter Property="Background" Value="Transparent"/> 
      <Setter Property="BorderThickness" Value="0"/> 
      <Setter Property="Padding" Value="12,7"/> 
      <Setter Property="FocusVisualStyle" Value="{x:Null}"/> 
      <Setter Property="FontFamily" Value="Marlett"/> 
      <Setter Property="FontSize" Value="12"/> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="Button"> 
         <Border BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"> 
          <Grid> 
           <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" TextBlock.FontFamily="{TemplateBinding FontFamily}" TextBlock.FontSize="{TemplateBinding FontSize}" /> 
          </Grid> 
         </Border> 
         <ControlTemplate.Triggers> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter Property="Background" Value="#EFEFF2" /> 
          </Trigger> 
          <Trigger Property="IsPressed" Value="True"> 
           <Setter Property="Background" Value="#007ACC"/> 
           <Setter Property="Foreground" Value="White"/> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

    </Application.Resources> 
</Application> 

yardımına seviniriz.

+0

Paylaştığınız görüntü gibi özel denetiminizde, Visual Studio'yu (simge) bir düğmeyi yapabilir ve tıklatıldığında ContextMenu'nu oradan gösterebilir misiniz? –

+0

Evet. Sadece belirli ContextMenu'yu nasıl arayacağımı bilmem gerek. Bir tane kendim mi yapmalıyım yoksa bunu doğrudan arayabilir miyim?(kontrolüm pencere kontrolüne dayanıyor) – Ron

+0

lütfen sorunuzdan ekstra kodu kaldırın. Bu, başkalarının soruyu hızlı bir şekilde almasına yardımcı olacaktır – Nitin

cevap

7

Göstermek istediğiniz menü sistem ContextMenu'dur. Bununla çalışmak için aşağıdaki kodda gösterildiği gibi bazı user32 işlevlerini almanız gerekir. Sistem menüsünü buton tıklaması ile başlattım. Herhangi bir eylemde başlatabilirsiniz, sağ fare tıklatması vb.

GetSystemMenu sistem menüsünü alır ve görüntülemek için TrackPopupMenuEx kullanılır. PostMessage, menü adımı tıklatıldığında gönder sistemidir.

public partial class Window3 : Window 
{ 

    private const int WM_SYSCOMMAND = 0x112; 
    uint TPM_LEFTALIGN = 0x0000; 
    uint TPM_RETURNCMD = 0x0100; 
    const UInt32 MF_ENABLED = 0x00000000; 
    const UInt32 MF_GRAYED = 0x00000001; 
    internal const UInt32 SC_MAXIMIZE = 0xF030; 
    internal const UInt32 SC_RESTORE = 0xF120; 

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); 

    [DllImport("user32.dll")] 
    static extern int TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, 
     int x, int y, IntPtr hwnd, IntPtr lptpm); 

    [DllImport("user32.dll")] 
    public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 

    [DllImport("user32.dll")] 
    static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, 
     uint uEnable); 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     WindowInteropHelper helper = new WindowInteropHelper(this); 
     IntPtr callingWindow = helper.Handle; 
     IntPtr wMenu = GetSystemMenu(callingWindow, false); 
     // Display the menu 
     if (this.WindowState == System.Windows.WindowState.Maximized) 
     { 
      EnableMenuItem(wMenu, SC_MAXIMIZE, MF_GRAYED); 
     } 
     else 
     { 
      EnableMenuItem(wMenu, SC_MAXIMIZE, MF_ENABLED); 
     } 

     int command = TrackPopupMenuEx(wMenu, TPM_LEFTALIGN | TPM_RETURNCMD, 100, 100, callingWindow, IntPtr.Zero); 
     if (command == 0) 
      return; 

     PostMessage(callingWindow, WM_SYSCOMMAND, new IntPtr(command), IntPtr.Zero); 
    } 
+0

İstediğim şeye çok yaklaşıyorum. Bir sorunum var - pencere en üst düzeye çıkarıldığında bile en üst düzeye çıkarılabilir, geri yükleme hakkında aynı (en üst düzeye gelmediğinde) - gerektiği gibi davranmayı nasıl zorlayabilirim? – Ron

+0

maxit menuitem etkinleştirme/devre dışı bırakma için güncellenmiş bir cevap ... benzer şekilde diğer öğelerin üstesinden gelmeniz gerekecek – Nitin

+0

İşler harika, ancak otomatik olarak algılayacağını umduğum halde çalışır. Çok teşekkür ederim! – Ron

0

Paylaştığınız görüntü gibi özel denetiminizde, Visual Studio'yu (simge) bir görüntü düğmesine/düğmesine getirin ve tıklatıldığında ContextMenu'yu buradan gösterin.

<Button Click="SomeEventHandler"> 
    <Button.ContextMenu> 
    <ContextMenu> 
     <!-- DO WHATEVER --> 
    </ContextMenu> 
    </Button.ContextMenu> 
</Button> 

Sonra tıklayın işleyicisi üzerine, sadece söylemek buttonName.ContextMenu.IsOpen = truehere

zaten bağımlılık özelliği vardır bulunabilir Eğer bunu başarabilirsiniz nasıl

Bundan da bağlam menüsünü gösterecek şekilde ayarlayabilirsiniz. Ne demek ne olduğundan emin değilim Düzenleme

"Eğer bu bir doğrudan arayabilecek tek kendin yapmak gerekir veya Do": Anlamıyorum neden Pencere davranışı yeniden yerine sizin özel devralan olsa Pencere sınıfına pencere ve özelleştirmeniz gerekenlerin üzerine yaz.

+0

Evet, beni doğru anlamadığınızı görebiliyorum. ContextMenu'nun nasıl yapılacağını ve nasıl çağırılacağını biliyorum. Kendi ContextMenu yapmak istemiyorum ama Window ContextMenu (geri yükleme, taşıma, boyut vb ... öğeleri ile) kullanmak istiyorum - Ben bir yolu var ama emin değilim ne olduğunu biliyorum .. – Ron

+0

Sadece cevabımı düzenledim. –

+0

Gördün mü, 1 Eminim nasıl kaldığını biliyorum. 2. Tüm tasarımın üzerine yazdım (Windows 8 Tasarım http://stackoverflow.com/questions/19335343/wpf-net-framework-3-5-window-metro-style adresinden yapılan Pencere, önceden yapılmış bir şey alır hedef çerçeve 4 + bu yüzden kendi yapmak zorunda kaldım) + bazı fonksiyonların üzerine yazdım (örneğin: maksimize edilmediğinde sınırları ekle) – Ron

İlgili konular