ブログ

割とコンピュータよりの情報をお届けします。

Windows Forms

Windows Embedded でのMessageBoxの扱いの注意

Windows Embedded Standard向けのアプリを開発していたら,.NETで64bitでも32bitでもどちらでもアプリが動かしるようにしていたところ,32bitでの動作では普通にMessageBoxが開くのに...

組み込み用のWindowsではWindows標準のMessageBoxの動作を変更することができる.すべてOKを応答させてダイアログを表示させないようにするのだ.

.NET Frameworkで開発したアプリで特に64bitで動かしたときにできるらしい.
この機能は開発時にMessageBoxを出させておいて,展開時にはMessageBoxを抑制するというという使い方になる.
知らなかったのでダイアログが出ない理由を一週間かけて探した.

≫ Read More

2019/10/19 コンピュータ   TakeMe

Windows FormsのDockプロパティFillはダブルバッファリングと相性が悪い

今回は,Windows Formsのアプリケーションを作成していた.
DataBindingを設定して,更新してみていたが どうもちらつく.原因はDockプロパティだった.
「Windows FormsのDockプロパティFillはダブルバッファリングと相性が悪い」ではなく「Windows FormsのDockプロパティFillはダブルバッファリングと相性が悪いかったかも」が正しいのかもしれない.実行環境を新しくしていくと問題が消えていく...

そもそも,本題の更新時のちらつきについて話を進める前に,
WPFのデータバインディングの場合には,バックグラウンドスレッドで更新しても普通に更新がかかるのだが,Windows Formsの場合にはUIスレッドで意図的にプロパティ変更イベントを出さないといけないようだ.
さて本題だが,Windows FormsのLabelは標準でダブルバッファリングが有効になったコントロールである.
しかし,DockプロパティをFillにしているとちらつく(ことがある).
ただし,Windows 10では問題ないように見える.例えば以下のようなコードはWindows 10で問題ない(っぽい)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private Timer timer = new Timer();
        private Label label = new Label();
        private Label label2 = new Label();
        private TableLayoutPanel tableLayoutPanel = new TableLayoutPanel();
        private Int64 count = 0;

        private ViewModel vm = new ViewModel();

        public Form1()
        {
            InitializeComponent();

            this.Controls.Add(tableLayoutPanel);
            tableLayoutPanel.Dock = DockStyle.Fill;
            tableLayoutPanel.ColumnCount = 2;
            tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
            tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
            tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
            tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
            tableLayoutPanel.RowCount = 2;
            tableLayoutPanel.Controls.Add(label);
            tableLayoutPanel.SetColumn(label, 0);
            tableLayoutPanel.SetRow(label, 0);

            tableLayoutPanel.Controls.Add(label2);
            tableLayoutPanel.SetColumn(label2, 1);
            tableLayoutPanel.SetRow(label2, 1);

            this.label.DataBindings.Add(new Binding("Text", this.vm, "Text1", false));
            this.label2.DataBindings.Add(new Binding("Text", this.vm, "Text2", false));

            label.Font = new Font("MS Gothic", 40);
            label.Height = 50;
            label.Text = count.ToString();
            label.TextAlign = ContentAlignment.MiddleCenter;
            label.Dock = DockStyle.Fill;

            label2.Font = new Font("MS Gothic", 40);
            label2.Height = 50;
            label2.Text = count.ToString();
            label2.TextAlign = ContentAlignment.MiddleCenter;
            label2.Dock = DockStyle.Fill;

            timer.Interval = 100;
            timer.Tick += timer_Tick;
            timer.Start();
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            count++;
            this.vm.Text1 = count.ToString();
            this.vm.Text2 = (-count).ToString();
        }
    }
}
using System;
using System.ComponentModel;

namespace WindowsFormsApp1
{
    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private string _text1 = "test";
        public string Text1
        {
            set
            {
                _text1 = value;
                RaisePropertyChanged("Text1");
            }
            get
            {
                return _text1;
            }
        }

        private string _text2 = "test";
        public string Text2
        {
            set
            {
                _text2 = value;
                RaisePropertyChanged("Text2");
            }
            get
            {
                return _text2;
            }
        }
    }
}

環境によってちらつきが発生する難しいバグ発生となった.
このバグが発生する場合には「コントロールのダブルバッファリングを有効にして、ちらつきを防止する」を実施しても関係ないようだ.
難しい.

≫ Read More

2019/04/14 コンピュータ   TakeMe