2016-08-11 181 views
0

我編寫了一個程序來可視化鍵盤的狀態。當我調整窗口大小時,繪製矩形的畫布保持其大小,但我希望將其調整爲窗口大小。我試圖爲窗口和畫布添加一個SizeChanged事件處理程序,但那不起作用。固定初始大小的可調整大小的WPF窗口

我也嘗試在窗口的SizeChanged事件中設置Lights畫布的大小,但窗口在啓動時幾乎填滿了整個屏幕。

那麼我怎樣才能達到以下目標?

  • 最初,窗口的客戶區是256×256。
  • 窗口是可調整大小。
  • 窗口大小調整後,其內容會隨之縮放。

MainWindow.xaml

<Window x:Class="KeyMonitor.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Key Monitor" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen" ResizeMode="CanResize"> 
    <Grid> 
     <Canvas x:Name="Lights" Width="256" Height="256" /> 
    </Grid> 
</Window> 

MainWindow.xaml.cs

using System; 
using System.Runtime.InteropServices; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 
using System.Windows.Shapes; 
using System.Windows.Threading; 

namespace KeyMonitor 
{ 
    public partial class MainWindow : Window 
    { 
     private Rectangle[] indicators = new Rectangle[256]; 

     public MainWindow() 
     { 
      InitializeComponent(); 

      for (int i = 0; i < 256; i++) 
       Lights.Children.Add(indicators[i] = new Rectangle { Fill = Brushes.Transparent }); 

      Lights.SizeChanged += Lights_SizeChanged; 

      var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(100) }; 
      timer.Tick += Timer_Tick; 
      timer.Start(); 
     } 

     private void Lights_SizeChanged(object sender, SizeChangedEventArgs e) 
     { 
      //Lights.Width = e.NewSize.Width; 
      //Lights.Height = e.NewSize.Height; 
      for (int y = 0; y < 16; y++) 
      { 
       var sy = (int)(e.NewSize.Height * y/16); 
       var sy1 = (int)(e.NewSize.Height * (y + 1)/16); 

       for (int x = 0; x < 16; x++) 
       { 
        var sx = (int)(e.NewSize.Width * x/16); 
        var sx1 = (int)(e.NewSize.Width * (x + 1)/16); 

        var indicator = indicators[16 * y + x]; 
        indicator.Width = 1 + sx1 - sx; 
        indicator.Height = 1 + sy1 - sy; 
        Canvas.SetLeft(indicator, sx); 
        Canvas.SetTop(indicator, sy); 
       } 
      } 
     } 

     void Timer_Tick(object sender, EventArgs e) 
     { 
      var keys = new byte[256]; 
      if (User32.GetKeyboardState(keys) != 0) 
      { 
       for (int i = 0; i < 256; i++) 
       { 
        var r = (byte)((keys[i] & 0x7E) != 0 ? 0xFF : 0x00); 
        var g = (byte)((keys[i] & 0x01) != 0 ? 0xFF : 0x00); 
        var b = (byte)((keys[i] & 0x80) != 0 ? 0xFF : 0x00); 
        indicators[i].Fill = new SolidColorBrush(Color.FromRgb(r, g, b)); 
       } 
      } 
     } 
    } 

    static class User32 
    { 
     [DllImport("user32")] 
     public static extern int GetKeyboardState(byte[] lpKeyState); 
    } 
} 

回答

1

我將設置Window的尺寸爲初始256 * 256,讓Canvas拉伸其中:

<Window x:Class="KeyMonitor.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Key Monitor" Width="256" Height="256" 
     WindowStartupLocation="CenterScreen" > 
    <!-- Grid is not necessary--> 
    <Canvas x:Name="Lights" /> 
</Window> 

HorizointalAlignmentVerticalAlignment的默認值爲Stretch,因此不需要設置其他屬性。

默認的調整大小模式已經是CanResize,所以它不是必需的。此外,我刪除SizeToContent值,因爲默認值爲Manual,這是您在此處需要的值。

編輯:我發現一個初始大小的問題。在xaml中設置WidthHeight表示包含Windows添加的邊框的大小。所以如果Height=Width的內容大小不是一個正方形。
我在SO上發現了一個解決方案:How to set WPF window's startup ClientSize?。這是不是最好的總是使用代碼背後,但我認爲這是一個合理的解決方法。這只是初始大小。

+0

這幾乎就是我想要的。唯一缺少的是窗口_client area_的初始大小。奇怪的是,在Visual Studio設計器中,包含標題欄和邊框的窗口爲256×256,但是當我運行該應用程序時,該窗口僅爲242×249. –

+0

@RolandIllig您說得對,我能夠重現此問題。我花了一點研究,並找到另一個SO線程的工作解決方案。我在我的答案中將其鏈接到它。 – Koopakiller

+0

@RolandIllig你可以設置內容大小_and_使用'SizeToContent'屬性。 – heltonbiker

1

要縮放內容,請將畫布置於視圖框內。這將適當地縮放內容。

<ViewBox> 
<Canvas x:Name="Lights" /> 
</ViewBox> 
+0

這很好地解決了我的一半問題,即調整畫布大小。但它不能解決初始窗口大小。初始窗口大約填滿了一半的屏幕,而不是256×256的區域。 –