2010-08-02 24 views
7

Tôi có một cửa sổ không có thanh tiêu đề (WindowStyle == WindowStyle.None). Toàn bộ cửa sổ sử dụng hiệu ứng kính Aero. Khi tôi làm cho cửa sổ không thể thay đổi (ResizeMode == ResizeMode.NoResize), hiệu ứng kính biến mất và các điều khiển của tôi chỉ treo trong không trung. (Về cơ bản, bản thân cửa sổ biến mất nhưng để lại nội dung của nó.)WPF: Tạo cửa sổ không thể thay đổi, nhưng giữ khung?

Có cách nào để tôi làm cho cửa sổ không thể thay đổi được mà không phải loại bỏ khung cửa sổ?


Tôi đã đọc câu hỏi Enable Vista glass effect on a borderless WPF window, nhưng đó không phải là điều tôi muốn - tôi muốn giữ đường viền cửa sổ. Ví dụ về những gì tôi muốn cửa sổ của tôi trông giống như, nhấn Alt + Tab với Aero được kích hoạt.


Để làm rõ, tôi làm không muốn con trỏ thay đổi kích thước để hiển thị lên ở tất cả khi lơ lửng trên biên giới cửa sổ. Đây thực chất là những gì tôi muốn cửa sổ của tôi trông giống như:

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

Các giải pháp không phải là nghiêm WPF - Tôi tốt với hacking xung quanh với các API Win32 để đạt được điều này.

Trả lời

9

Bạn có thể móc wndproc và chặn thông báo WM_WINDOWPOSCHANGING. Không đúng WPF, nhưng có lẽ là đặt cược tốt nhất của bạn.

Nếu bạn muốn ẩn con trỏ thay đổi kích thước, thì tốt nhất bạn nên đánh chặn WM_NCHITTEST. Gọi DefWindowProc (để có được hành vi mặc định), và kiểm tra giá trị trả về; nếu đó là HTBOTTOM, HTBOTTOMLEFT, HTBOTTOMRIGHT, HTTOP, HTTOPLEFT hoặc HTTOPRIGHT, hãy thay đổi giá trị trả về thành HTBORDER.

+0

Bạn vẫn sẽ có con trỏ thay đổi kích thước, và OP cho biết (trong một bình luận khác) rằng những người không mong muốn. –

+0

Làm việc như một sự quyến rũ! Cảm ơn! Thưởng thức thêm 275 đại diện. :) –

1

Một cách hackish để làm điều đó là đặt thuộc tính MinWidth/MaxWidth và MinHeight/MaxHeight để làm cho nó không thể thực hiện được một cách hiệu quả. Tất nhiên, vấn đề là bạn vẫn sẽ nhận được con trỏ thay đổi kích thước qua biên giới.

+0

Vâng toàn bộ vấn đề là để thoát khỏi con trỏ thay đổi kích thước, do đó sẽ không giúp đỡ, không may. –

1

Tại sao bạn không chỉ tạo đường viền cửa sổ này cho cửa sổ? Nó đang sử dụng bù đắp để đặt màu của cửa sổ. Vì vậy, một cách dễ dàng là chỉ để quấn toàn bộ đường viền quanh cửa sổ của bạn và trên hết là bạn sẽ có được màu sắc của riêng mình!

+0

Một khi tôi có nghĩa là quấn nó xung quanh cửa sổ, tôi có nghĩa quấn cơ bản Kevin

+0

Nhưng sau đó tôi không thể làm cho nó phù hợp với chủ đề hiện tại của người dùng. Tôi có thể làm cho một biên giới tùy chỉnh trông giống hệt như chủ đề Aero mặc định, nhưng nếu người dùng đã tùy chỉnh nó (hoặc đang sử dụng một chủ đề khác), thì cửa sổ sẽ không khớp. –

+0

Tôi sẽ không trả lời câu trả lời này, tuy nhiên, tôi có thể phải làm điều này. –

9

Dựa trên câu trả lời Erics.

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

Tôi sẽ đưa ra câu trả lời cho Eric là công bằng, kể từ khi ông lần đầu tiên đăng ý tưởng, nhưng cảm ơn bạn cho ví dụ làm việc. :) –

+1

Đó là lý do tại sao tôi đề cập đến nó. Tôi chỉ muốn xem liệu tôi có thể làm cho nó hoạt động được không. –

+1

Không nên gọi DefWindowProc trong mọi trường hợp? Trong mã này, bạn chỉ gọi hàm gốc nếu msg là WM_NCHITTEST. Tôi tưởng tượng rằng để ghi đè chính xác, bất kỳ thông báo nào khác chỉ cần trả lại kết quả được đưa ra bởi hàm ban đầu. – Nyerguds

Các vấn đề liên quan