さて、前回「次回からはこれ(注)をもっと詳しく見て(get more details)行きましょう。」と書きましたが、思い付きで他の話題を取り上げてしまうのが、このブログの作法です。(笑)
注:複数コントロールの使い方、です。
前回WPFでウィンドウ(Windowクラス)のContentに文字列、画像、コントロールを入れてみましたが、
(1)文字列は普通に表示される
(2)画像はそのサイズにより、縦か横一杯に表示される
(3)コントロールはクライアントエリア(ページエリア?)いっぱいに表示される
ことに気が付きました。
では、コントロールにサイズを指定するとどうなるのか?また実験です。
【Window04.cs(注)】
注:このプログラムはWPFと格闘を始めて比較的初期に書いたSimple_Window.csを書き換えたものです。イベント処理なども確認しているので、私自身の備忘の為に色々と書き込み(コメント)がありますが、皆様の参考にもなると思います。
///////////////
// Window04.cs
///////////////
using System;
using System.Windows;
using System.Windows.Controls;
/* WPFの場合に参照すべきDLL
C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\WindowsBase.dll
C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationCore.dll
C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Xaml.dll //Xaml使用のみならず↑のdllで参照される
*/
namespace Window04
{
///////////////////////////
//エントリーポイントクラス
///////////////////////////
class MainApp
{
[STAThread]
public static void Main()
{
/* Windows.Formでは問題が無かった次の書式、
"Application.Run(new MainWindow());"
が"CS0120: 静的でないフィールド、メソッド、またはプロパティでオブジェクト参照が必要です"
というエラーになるので注意。
解説:前にやった話です。WPFを調べ始めた当時は「へぇ~」という感じでした。*/
MainWindow mwnd = new MainWindow();
Application ap = new Application(); //明示的にインスタンスを作らなければならない
ap.Run(mwnd);
}
}
public partial class MainWindow : Window //派生元が"Form"から"Window"となる
{
public MainWindow()
{
//this.Loaded += new RoutedEventHandler(Window_Loaded);
//this.ContentRendered += new EventHandler(Window_ContentRendered);
//解説:RoutedEventとEventの違いはこれが参考になります。まだ私も完全に理解していませんが...(笑)
this.Loaded += Window_Loaded;
this.ContentRendered += Window_ContentRendered;
//this.Activated += new EventHandler(Window_Activated); //これを有効にするとMopuseDownとButton Clickイベントがsupersedeされる
this.MouseDown += Window_MouseDown;
this.Closing += Window_Closing;
InitControl();
}
public void InitControl()
{
//Windowのプロパティ:https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.window?view=windowsdesktop-8.0
//this.Text = "WPF サンプル"; //TextからTitleになった
this.Title = "WPF サンプル";
//this.Size = new Size(640, 480); //Sizeは無くなった
this.Width = 640;
this.Height = 480;
//this.StartPosition = FormStartPosition.CenterScreen; //StartPositionは廃止された
//this.Location = new Point(100, 100); //Locationも廃止された
this.WindowStartupLocation = WindowStartupLocation.CenterScreen; //Manual, CenterOwnerもある(Manualの場合、LeftとTopプロパティの値)
//this.BackColor = SystemColors.Window; //Color BackColorからBrush Backgroundになった
//WPFのSystemColors-https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.systemcolors?view=windowsdesktop-8.0
this.Background = SystemColors.WindowBrush;
/* 解説:以下ボタンコントロールにを一つ作り、サイズを絶対値で指定し、
クライアントエリアの中央に余白(Thickness)50で配置します。
*/
Button btn = new Button();
btn.Width = 240; //解説:これはWinFormにありますが、Sizeは無くなりました。
btn.Height = 80;
btn.HorizontalAlignment = HorizontalAlignment.Center; //解説:これはWinFormにはないものです。
btn.VerticalAlignment = VerticalAlignment.Center; //解説:これはWinFormにはないものです。
//解説:WinFormでは次のようになります。
//btn.Location = new Point((ClientSize.Width - btn.Width) / 2, (ClientSize.Height - btn.Height) / 2);
btn.Margin = new Thickness(50, 50, 50, 50); //構造体 Thickness(左, 上, 右, 下)
btn.Content = "I am a button."; //解説:Textではなく、Contentとして文字列を受け付けます。
btn.Click += Button_Click; //解説:この記述方法は基本的に変わりませんね。
this.Content = btn; //解説:WinFormでは"this.Controls.Add(btn);"でしたね。
}
private void Window_Loaded(object sender, EventArgs e)
{
MessageBox.Show("プログラムがロードされました。", "Loadedイベント", MessageBoxButton.OK, MessageBoxImage.Information); //解説:細かいですが、WinFormではMessageBoxButtons、MessageBoxIconでした。以下同じ。
}
private void Window_ContentRendered(object sender, EventArgs e)
{
MessageBox.Show("ウィンドウが完成しました。", "ContentRenderedイベント", MessageBoxButton.OK, MessageBoxImage.Information);
}
private void Window_Activated(object sender, EventArgs e)
{
MessageBoxResult result = MessageBox.Show("ウィンドウがアクティブになりました。\r\n終了しますか?", "Activatedイベント", MessageBoxButton.YesNo, MessageBoxImage.Question);
if(result == MessageBoxResult.Yes)
Close();
}
void Window_MouseDown(object sender, EventArgs e)
{
MessageBox.Show("ウィンドウがクリックされました。", "Clickイベント", MessageBoxButton.OK, MessageBoxImage.Information);
}
void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
MessageBoxResult result =
MessageBox.Show("ウィンドウを閉じようとしています。\r\nよろしいですか?", "Closingイベント", MessageBoxButton.YesNo, MessageBoxImage.Question);
if(result == MessageBoxResult.No)
e.Cancel = true;
}
void Button_Click(object sender, RoutedEventArgs e) //解説:引数形式が変わりました。Routingについては↑参照。
{
MessageBox.Show("ボタンがクリックされました。", "Button Clickイベント", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}
/* 参考-Visual Studioが作成するInitializeComponent()を含む自動作成コード
「どういうことだろうか。」とありますが、記事の中でラベルのタイ
トル"Label"が変わらないのは、Xamlコードの方が"Label"になっていて、
ビルドすると自動生成コードが更新されてまた"Label"になってしまうか
らです。自動生成コードでコンテンツを文字列"ABC"にするのではなく、
Xamlコードを"ABC"としておけば "ABC"と表示されるはずです。
*/
// SampleWpfApplication
using System.Windows;
using System.Windows.Markup;
namespace SampleWpfApplication
{
public partial class MainWindow : Window, IComponentConnector
{
private bool _contentLoaded; //解説:コンテントがロードされているか否かのフラグですね。
public void InitializeComponent()
{
if (_contentLoaded) return;
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri(
//解説:ウィンドウやコンテンツを定義したXamlファイルへのパスですね。
"/SampleWpfApplication;component/mainwindow.xaml",
System.UriKind.Relative);
System.Windows.Application.LoadComponent(
this, resourceLocater); //解説:Xamlファイルをバイナリーに変換して実装するのでしょう。
}
void IComponentConnector.Connect(int connectionId, object target)
{
//解説:この後、MSBuildによってswitch分を使ったコントロールのコードが追加されます。
【追加されるコード例】
switch (connectionId)
{
case 1:
this.text1 = ((System.Windows.Controls.TextBlock)(target));
return;
case 2:
this.button1 = ((System.Windows.Controls.Button)(target));
this.button1.Click +=
new System.Windows.RoutedEventHandler(this.Button_Click);
return;
}
this._contentLoaded = true;
}
}
}
*/
【対比用Form04.cs】-↑のファイルと(同等とまではいきませんが)似たような動作をするWinFormのコードです。見た目が大分違いますね。
///////////////
// Form04.cs
///////////////
using System;
using System.Windows.Forms;
using System.Drawing; //SystemColorsを使う為
namespace Window04
{
///////////////////////////
//エントリーポイントクラス
///////////////////////////
class MainApp
{
[STAThread]
public static void Main()
{
Application.Run(new MainWindow());
}
}
public partial class MainWindow : Form
{
Button btn;
public MainWindow()
{
InitControl();
this.Load += Window_Loaded;
this.Shown += Window_ContentRendered;
//this.Activated += new EventHandler(Window_Activated); //これを有効にするとWindow_MouseDownとButton Clickイベントがsupersedeされる
this.SizeChanged += On_SizeChanged;
this.MouseDown += Window_MouseDown;
this.Closing += Window_Closing;
}
public void InitControl()
{
this.Text = "Form サンプル";
this.Size = new Size(640, 480);
this.StartPosition = FormStartPosition.CenterScreen;
this.BackColor = SystemColors.Window;
btn = new Button();
btn.Size = new Size(240, 80);
btn.Location = new Point((ClientSize.Width - btn.Width) / 2, (ClientSize.Height - btn.Height) / 2);
btn.Text = "I am a button.";
btn.Click += Button_Click;
this.Controls.Add(btn);
}
private void On_SizeChanged(object sender, EventArgs e)
{
btn.Location = new Point((ClientSize.Width - btn.Width) / 2, (ClientSize.Height - btn.Height) / 2);
}
private void Window_Loaded(object sender, EventArgs e)
{
MessageBox.Show("プログラムがロードされました。", "Loadedイベント", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void Window_ContentRendered(object sender, EventArgs e)
{
MessageBox.Show("ウィンドウが完成しました。", "ContentRenderedイベント", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
DialogResult result =
MessageBox.Show("ウィンドウを閉じようとしています。\r\nよろしいですか?", "Closingイベント", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if(result == DialogResult.No)
e.Cancel = true;
}
private void Window_Activated(object sender, EventArgs e)
{
DialogResult result = MessageBox.Show("ウィンドウがアクティブになりました。\r\n終了しますか?", "Activatedイベント", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if(result == DialogResult.Yes)
Close();
}
void Window_MouseDown(object sender, EventArgs e)
{
MessageBox.Show("ウィンドウがクリックされました。", "Clickイベント", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
void Button_Click(object sender, EventArgs e)
{
MessageBox.Show("ボタンがクリックされました。", "Button Clickイベント", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}