2010-08-02 10 views
7

Başlık çubuğuna sahip olmayan bir pencerem var (WindowStyle == WindowStyle.None). Tüm pencere Aero cam etkisini kullanır. Pencereyi kararsız hale getirdiğimde (ResizeMode == ResizeMode.NoResize), cam efekti kaybolur ve denetimlerim yalnızca havada asılı kalır. (Aslında, pencerenin kendisi kaybolur, ancak içeriğini kaldırır.)WPF: Pencereyi düzenlenemez hale getirin, ancak çerçeveyi koruyun mu?

Pencerenin çerçevesinden kurtulmadan pencereyi düzenlenemez hale getirmenin bir yolu var mı?


Soruyu Enable Vista glass effect on a borderless WPF window okudum ama benim istediğim oldukça değil - Ben pencere sınırı tutmak istiyorum. Penceremin nasıl görünmesini istediğim bir örnek için, Aero etkinleştirilmiş Alt + Tab'a basın.


netleştirmek için, hiçbir pencere sınırına üzerine gelindiğinde yeniden boyutlandırma imleçleri hiç göstermek istiyoruz. Bunu elde etmek için Win32 API ile etrafında hack ile iyiyim - kesinlikle WPF olmak zorunda değildir

Projector http://i37.tinypic.com/2mg4jty.png

çözüm: Bu benim pencere gibi bakmak istediğim aslında.

cevap

9

wndproc'yi bağlayıp WM_WINDOWPOSCHANGING iletisini engelleyebilirsiniz. Kesinlikle WPF değil, muhtemelen en iyi bahsiniz.

Yeniden boyutlandırma imleçlerini gizlemek istiyorsanız, en iyi seçeneğiniz WM_NCHITTEST kodunu kesmektir. DefWindowProc (varsayılan davranışı almak için) çağrısı yapın ve dönüş değerini test edin; HTBOTTOM, HTBOTTOMLEFT, HTBOTTOMRIGHT, HTTOP, HTTOPLEFT veya HTTOPRIGHT ise, dönüş değerini HTBORDER olarak değiştirin.

+0

Yeniden boyutlandırma imleçlerine sahip olacaksınız ve OP (başka bir yorumda) bunların istenmeyen olduğunu söyledi. –

+0

Bir çekicilik gibi çalıştım! Teşekkürler! 275 daha fazla temsilcinin keyfini çıkarın. :) –

1

Bunu yapmanın en çirkin yolu, MinWidth/MaxWidth ve MinHeight/MaxHeight özelliklerini etkili bir şekilde etkinleştirilememesidir. Tabii ki, orada sorun hala sınırların üzerinde yeniden boyutlandırma imleçleri elde edersiniz.

+0

Eh bütün mesele maalesef, yeniden boyutlandırma imleçler kurtulmak etmektir. –

1

Neden pencere için bu pencere kenarlığını yaratmıyorsunuz? Pencerenin renklerini ayarlamak için bir ofset kullanıyor. Yani, kolay bir yol sadece pencerenizin etrafında bir kenarlık sarmak ve bunun üzerine kendi renkleri olsun!

+0

Bir Ben temelde Kevin

+0

sarmak demek Ama sonra kullanıcının geçerli bir tema maç yapamaz, bir pencere etrafına sarın ifade ederken. Tam olarak varsayılan Aero teması gibi görünen özel bir kenarlık yapabilirdim, ancak kullanıcı özelleştirdiyse (veya farklı bir tema kullanıyorsa), pencere eşleşmez. –

+0

Bu cevabı bir kenara atmama rağmen, bunu yapmak zorunda kalabilirim. –

9

Erics'e göre cevap. Bu yardımcı olmayacak şekilde

Example Image

public partial class MainWindow : Window 
{ 
    [DllImport("DwmApi.dll")] 
    public static extern int DwmExtendFrameIntoClientArea(
     IntPtr hwnd, 
     ref MARGINS pMarInset); 

    [DllImport("user32.dll", CharSet = CharSet.Auto)] 
    public static extern IntPtr DefWindowProc(
     IntPtr hWnd, 
     int msg, 
     IntPtr wParam, 
     IntPtr lParam); 

    private const int WM_NCHITTEST = 0x0084; 
    private const int HTBORDER = 18; 
    private const int HTBOTTOM = 15; 
    private const int HTBOTTOMLEFT = 16; 
    private const int HTBOTTOMRIGHT = 17; 
    private const int HTLEFT = 10; 
    private const int HTRIGHT = 11; 
    private const int HTTOP = 12; 
    private const int HTTOPLEFT = 13; 
    private const int HTTOPRIGHT = 14; 

    public MainWindow() 
    { 
     InitializeComponent(); 

     this.Loaded += new RoutedEventHandler(MainWindow_Loaded); 
    } 

    void MainWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     try 
     { 
      // Obtain the window handle for WPF application 
      IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle; 
      HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr); 
      mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0); 
      mainWindowSrc.AddHook(WndProc); 

      // Set Margins 
      MARGINS margins = new MARGINS(); 
      margins.cxLeftWidth = 10; 
      margins.cxRightWidth = 10; 
      margins.cyBottomHeight = 10; 
      margins.cyTopHeight = 10; 

      int hr = DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins); 
      // 
      if (hr < 0) 
      { 
       //DwmExtendFrameIntoClientArea Failed 
      } 
     } 
     // If not Vista, paint background white. 
     catch (DllNotFoundException) 
     { 
      Application.Current.MainWindow.Background = Brushes.White; 
     } 
    } 

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
    { 
     // Override the window hit test 
     // and if the cursor is over a resize border, 
     // return a standard border result instead. 
     if (msg == WM_NCHITTEST) 
     { 
      handled = true; 
      var htLocation = DefWindowProc(hwnd, msg, wParam, lParam).ToInt32(); 
      switch (htLocation) 
      { 
       case HTBOTTOM: 
       case HTBOTTOMLEFT: 
       case HTBOTTOMRIGHT: 
       case HTLEFT: 
       case HTRIGHT: 
       case HTTOP: 
       case HTTOPLEFT: 
       case HTTOPRIGHT: 
        htLocation = HTBORDER; 
        break; 
      } 

      return new IntPtr(htLocation); 
     } 

     return IntPtr.Zero; 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     this.Close(); 
    } 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct MARGINS 
{ 
    public int cxLeftWidth;  // width of left border that retains its size 
    public int cxRightWidth;  // width of right border that retains its size 
    public int cyTopHeight;  // height of top border that retains its size 
    public int cyBottomHeight; // height of bottom border that retains its size 
}; 

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="150" Width="200" 
    Background="Transparent" 
    WindowStyle="None" 
    ResizeMode="CanResize" 
> 
    <Grid Background="White" Margin="10,10,10,10"> 
     <Button Content="Go Away" Click="Button_Click" Height="20" Width="100" /> 
    </Grid> 
</Window> 
+0

Eric'in adil olması için cevabı vereceğim, çünkü bu fikri ilk kez yayınladı, ama çalışma örneği için teşekkür ederim. :) –

+1

Bu yüzden bundan bahsetmiştim. Sadece çalışıp çalışamayacağımı görmek istedim. –

+1

Tüm durumlarda DefWindowProc çağrılmasın mı? Bu kodda sadece msg WM_NCHITTEST ise orijinal işlevi çağırırsınız. Geçersiz kılma işlemini yapmak için herhangi bir mesajın sadece orijinal işlev tarafından verilen sonucu döndürmesi gerektiğini düşünürdüm. – Nyerguds

İlgili konular