さて、前回「次回からはこれ(注)をもっと詳しく見て(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);
        }
    }
}