- 投稿日:2021-03-21T18:07:24+09:00
C#で特定の日時を過ぎたら開けなくする[WPF]
参照:
https://docs.microsoft.com/ja-jp/dotnet/api/system.datetime.compare
コード
DateTime date1 = DateTime.Now;//現在時刻取得 DateTime date2 = new DateTime(2030, 1, 1, 0, 0, 0);//対象先の日付時刻設定(左から、年、月、日、時、分) int result = DateTime.Compare(date1, date2);//比較 if (result < 0) { //現在時刻が対象先の日付時刻よりも早い場合の処理 } else { //現在時刻が対象先の日付時刻よりも遅い場合の処理 Close();//アプリケーション終了 }注意点
PCの設定で日付を意図的に遅らせた場合は動作しない可能性がありますのでご注意ください。
aapythonはこのコードを使用したことによるいかなる責任を負いません。
- 投稿日:2021-03-21T13:37:42+09:00
[Windows Forms] ボタンに画像を2つ入れる
■概要
■環境
- Windows 10
- Visual Studio 2019 Community Version 16.9.2
- .NET Framework 4.7.2
■プロジェクトの作成
新しいプロジェクトを作成します。
検索条件で絞り込んでWindows フォーム アプリケーション(.NET Framework)
を選択します。
プロジェクト名を入力し、フレームワークを選択します。
ここではプロジェクト名をWindowsFormsApp1
、
フレームワークは4.5~4.8、ここでは.NET Framework 4.7.2
にしました。
■画面コンテンツ枠の追加
プロジェクトを右クリックし、「追加」-「新しい項目」を選択します。
「WPF」-「ユーザーコントロール(WPF)」を選択し、名前に
Form1Child
と入力して追加します。
メニューの「ビルド」-「ソリューションのビルド」でビルドしておきます。
Form1を選択し、ツールボックスの「WPF相互運用機能」の「ElementHost」をForm1にドラッグ&ドロップします。
「ホストするコンテンツの選択」のドロップダウンを開き、
Form1Child
を選択します。
■土台部分作成
デザイナの「Form1Click.xaml」のタブを選択し、メニューの「表示」-「その他のウィンドウ」-「ドキュメントアウトライン」を選択します。
Gridを選択状態にし、デザイナの薄く赤線を引いた部分にマウスポインタを近づけると
+
マークが付きます。
そこでクリックするとGridを分割できます。
ツールボックスから「StackPanel」を行分割したGridの下の行にドラッグ&ドロップします。
StackPanelは既定では中に配置したコントロールを縦並びに整列させます。
これを横並びに変更します。
StackPanelを選択し、プロパティウィンドウの「整列」-「Orientation」でHorizontal
を選択します。
■ボタンの追加
ツールボックスから「Button」を画面のStackPanel上にドラッグ&ドロップします。
続けて2つ、「Button」をStackPanel上にドラッグ&ドロップします。
■画像リソースの読み込み
以下のファイルをダウンロードして
green.png
,orange.png
という名前で保存します。
プロジェクトの「Properties」-「Resources.resx」をダブルクリックし、
「リソースの追加」の▼
をクリックし、「既存のファイルの追加」を選択します。
「Resources」フォルダの「green.png」を選択し、
プロパティウィンドウの「ビルドアクション」でResources
を選択します。
メニューの「ビルド」-「ソリューションのビルド」でビルドしておきます。
■画像付きボタンの作成
◇部品配置
ツールボックスから「StackPanel」を1つめのボタン上にドラッグ&ドロップします。
ドキュメントアウトライン上でStackPanelが選択状態になっていることを確認し、
プロパティウィンドウで「レイアウト」-「Orientation」を先程と同じHorizontal
に設定します。ツールボックスからドキュメントアウトラインの「Button」の中の「StackPanel」上に、
「Image」、「TextBlock」、「Image」の順にドラッグ&ドロップします。
◇画像設定
ドキュメントアウトラインで1つめの「Image」を選択し、
プロパティウィンドウの「共通」-「Source」の▼
を開き、「green.png」を選択します。
「Image」をプロパティウィンドウの「レイアウト」で「Width」と「Height」を
20
に設定します。
もう一つの「Image」も「orange.png」を読み込ませて同様に設定します。
◇余白調整、ボタンテキスト変更
ドキュメントアウトラインで「TextBlock」を選択し、
プロパティウィンドウの「レイアウト」-「Margin」で左右余白8
を設定します。
「共通」-「Text」に押してください
を入力します。
「レイアウト」-「VerticalAlignment」をCenter
に設定します。
◇イベント追加
ドキュメントアウトラインで1つめのボタンを選択し、プロパティウィンドウで稲妻マークを選択し、イベント一覧を表示します。
「Click」横のテキストボックスをダブルクリックします。
メッセージボックスを表示する処理を記述します。
Form1Child.xaml.csprivate void Button_Click(object sender, RoutedEventArgs e) { MessageBox.Show("押された!", "タイトル", MessageBoxButton.OK, MessageBoxImage.Information); }■Gridの行高さ調整
適当に設定していたGridの行高さを調整します。
ドキュメントアウトラインでGridを選択し、デザイナでGridの下の行の左端あたりにマウスポインタを移動します。
■ボタン間隔調整
ボタンがぴったりくっついているので間隔を調整します。
以下をUserControlの開始タグとGridの開始タグの間に記述します。Form1Child.xaml<UserControl.Resources> <Style TargetType="Button"> <Setter Property="Margin" Value="8" /> </Style> </UserControl.Resources>これでこのUserControlの中にあるすべてのボタンの上下左右に余白
8
が設定されました。
ボタンの淵と中身の間隔「Padding」も設定してみます。
<Style TargetType="Button"> <Setter Property="Margin" Value="8" /> <Setter Property="Padding" Value="24,8" /> </Style>ボタンの淵~中身の左右の間隔は
24
、上下間隔は8
に設定しました。
■実行
■おまけ
閉じるボタンを実装します。
3つめのボタンのテキストを閉じる
にし、ClickイベントにCloseButton_Click
を入力してEnterします。
プロパティ
CloseAction
を追加し、CloseButton_Clickの中で呼び出します。Form1Child.xaml.csusing System; using System.Windows; using System.Windows.Controls; namespace WindowsFormsApp1 { /// <summary> /// Form1Child.xaml の相互作用ロジック /// </summary> public partial class Form1Child : UserControl { public Action CloseAction { get; set; } public Form1Child() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { MessageBox.Show("押された!", "タイトル", MessageBoxButton.OK, MessageBoxImage.Information); } private void CloseButton_Click(object sender, RoutedEventArgs e) { CloseAction(); } } }CloseActionにフォームを閉じる処理を設定します。
Form1.csusing System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); var child = elementHost1.Child as Form1Child; child.CloseAction = () => Close(); } } }
- 投稿日:2021-03-21T13:37:42+09:00
[Windows Forms] ボタンに画像を2つ表示
■概要
■環境
- Windows 10
- Visual Studio 2019 Community Version 16.9.2
- .NET Framework 4.7.2
■プロジェクトの作成
新しいプロジェクトを作成します。
検索条件で絞り込んでWindows フォーム アプリケーション(.NET Framework)
を選択します。
プロジェクト名を入力し、フレームワークを選択します。
ここではプロジェクト名をWindowsFormsApp1
、
フレームワークは4.5~4.8、ここでは.NET Framework 4.7.2
にしました。
■画面コンテンツ枠の追加
プロジェクトを右クリックし、「追加」-「新しい項目」を選択します。
「WPF」-「ユーザーコントロール(WPF)」を選択し、名前に
Form1Child
と入力して追加します。
メニューの「ビルド」-「ソリューションのビルド」でビルドしておきます。
Form1を選択し、ツールボックスの「WPF相互運用機能」の「ElementHost」をForm1にドラッグ&ドロップします。
「ホストするコンテンツの選択」のドロップダウンを開き、
Form1Child
を選択します。
■土台部分作成
デザイナの「Form1Child.xaml」のタブを選択し、メニューの「表示」-「その他のウィンドウ」-「ドキュメントアウトライン」を選択します。
Gridを選択状態にし、デザイナの薄く赤線を引いた部分にマウスポインタを近づけると
+
マークが付きます。
そこでクリックするとGridを分割できます。
ツールボックスから「StackPanel」を行分割したGridの下の行にドラッグ&ドロップします。
StackPanelは既定では中に配置したコントロールを縦並びに整列させます。
これを横並びに変更します。
StackPanelを選択し、プロパティウィンドウの「整列」-「Orientation」でHorizontal
を選択します。
■ボタンの追加
ツールボックスから「Button」を画面のStackPanel上にドラッグ&ドロップします。
続けて2つ、「Button」をStackPanel上にドラッグ&ドロップします。
■画像リソースの読み込み
以下のファイルをダウンロードして
green.png
,orange.png
という名前で保存します。
プロジェクトの「Properties」-「Resources.resx」をダブルクリックし、
「リソースの追加」の▼
をクリックし、「既存のファイルの追加」を選択します。
「Resources」フォルダの「green.png」を選択し、
プロパティウィンドウの「ビルドアクション」でResources
を選択します。
メニューの「ビルド」-「ソリューションのビルド」でビルドしておきます。
■画像付きボタンの作成
◇部品配置
ツールボックスから「StackPanel」を1つめのボタン上にドラッグ&ドロップします。
ドキュメントアウトライン上でStackPanelが選択状態になっていることを確認し、
プロパティウィンドウで「レイアウト」-「Orientation」を先程と同じHorizontal
に設定します。ツールボックスからドキュメントアウトラインの「Button」の中の「StackPanel」上に、
「Image」、「TextBlock」、「Image」の順にドラッグ&ドロップします。
◇画像設定
ドキュメントアウトラインで1つめの「Image」を選択し、
プロパティウィンドウの「共通」-「Source」の▼
を開き、「green.png」を選択します。
「Image」をプロパティウィンドウの「レイアウト」で「Width」と「Height」を
20
に設定します。
もう一つの「Image」も「orange.png」を読み込ませて同様に設定します。
◇余白調整、ボタンテキスト変更
ドキュメントアウトラインで「TextBlock」を選択し、
プロパティウィンドウの「レイアウト」-「Margin」で左右余白8
を設定します。
「共通」-「Text」に押してください
を入力します。
「レイアウト」-「VerticalAlignment」をCenter
に設定します。
◇イベント追加
ドキュメントアウトラインで1つめのボタンを選択し、プロパティウィンドウで稲妻マークを選択し、イベント一覧を表示します。
「Click」横のテキストボックスをダブルクリックします。
メッセージボックスを表示する処理を記述します。
Form1Child.xaml.csprivate void Button_Click(object sender, RoutedEventArgs e) { MessageBox.Show("押された!", "タイトル", MessageBoxButton.OK, MessageBoxImage.Information); }■Gridの行高さ調整
適当に設定していたGridの行高さを調整します。
ドキュメントアウトラインでGridを選択し、デザイナでGridの下の行の左端あたりにマウスポインタを移動します。
■ボタン間隔調整
ボタンがぴったりくっついているので間隔を調整します。
以下をUserControlの開始タグとGridの開始タグの間に記述します。Form1Child.xaml<UserControl.Resources> <Style TargetType="Button"> <Setter Property="Margin" Value="8" /> </Style> </UserControl.Resources>これでこのUserControlの中にあるすべてのボタンの上下左右に余白
8
が設定されました。
ボタンの淵と中身の間隔「Padding」も設定してみます。
<Style TargetType="Button"> <Setter Property="Margin" Value="8" /> <Setter Property="Padding" Value="24,8" /> </Style>ボタンの淵~中身の左右の間隔は
24
、上下間隔は8
に設定しました。
■実行
■おまけ
閉じるボタンを実装します。
3つめのボタンのテキストを閉じる
にし、ClickイベントにCloseButton_Click
を入力してEnterします。
プロパティ
CloseAction
を追加し、CloseButton_Clickの中で呼び出します。Form1Child.xaml.csusing System; using System.Windows; using System.Windows.Controls; namespace WindowsFormsApp1 { /// <summary> /// Form1Child.xaml の相互作用ロジック /// </summary> public partial class Form1Child : UserControl { public Action CloseAction { get; set; } public Form1Child() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { MessageBox.Show("押された!", "タイトル", MessageBoxButton.OK, MessageBoxImage.Information); } private void CloseButton_Click(object sender, RoutedEventArgs e) { CloseAction(); } } }CloseActionにフォームを閉じる処理を設定します。
Form1.csusing System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); var child = elementHost1.Child as Form1Child; child.CloseAction = () => Close(); } } }
- 投稿日:2021-03-21T08:19:56+09:00
MaskedTextProviderを利用してみる
はじめに
時刻入力用のTextBoxが必要なことがあり、MaskedTextProviderを使えばいいらしいことは分かったのですが、実装がうまくできませんでした。
欲しかった画面はこんな感じでした。
日付を入力して、そのあと、時間を入力するというもの。
時刻はText(string)で使えるようにしたいです。MaterialDesignのExsampleにMaskedTextBoxがあったので使えるかなと思ったのですが、これはXceed SoftwareのExtended.Wpf.Toolkitを利用していました。
Extended.Wpf.Toolkitはライセンスが以前はMS-PLライセンスだったみたいですが、ライセンスが変わって、非商用でも10人以上のユーザーがいれば商用ライセンスが必要となったようで、採用するのは難しいと思いました。そこで、いろいろと調べていたところ、Blindmeis's BlogにWPF – Masked Textbox Behaviorがとても参考になりました。
ブログの記事だと、汎用的だったので、参考にしながら、時刻用の設定を追加したりして完成できました。詳細は後で記事にするかもしれませんが、まずは参考にしていただければと思い、全コードを記載しておきます。
ちなみに、ビヘイビアとして作成しています。MaskedTextBoxBehavior : Behavior
using Microsoft.Xaml.Behaviors; using System; using System.ComponentModel; using System.Globalization; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace Sample.WPF.Behaviors { public class MaskedTextBoxBehavior : Behavior<TextBox> { #region DependencyProperties public string InputMask { get { return (string)GetValue(InputMaskProperty); } set { SetValue(InputMaskProperty, value); } } public static readonly DependencyProperty InputMaskProperty = DependencyProperty.Register("InputMask", typeof(string), typeof(MaskedTextBoxBehavior), null); public char PromptChar { get { return (char)GetValue(PromptCharProperty); } set { SetValue(PromptCharProperty, value); } } public static readonly DependencyProperty PromptCharProperty = DependencyProperty.Register("PromptChar", typeof(char), typeof(MaskedTextBoxBehavior), new PropertyMetadata('_')); public bool IsTime { get { return (bool)GetValue(IsTimeProperty); } set { SetValue(IsTimeProperty, value); } } public static readonly DependencyProperty IsTimeProperty = DependencyProperty.Register("MyProperty", typeof(bool), typeof(MaskedTextBoxBehavior), new PropertyMetadata(false)); #endregion public MaskedTextProvider Provider { get; private set; } protected override void OnAttached() { base.OnAttached(); AssociatedObject.Loaded += AssociatedObjectLoaded; AssociatedObject.PreviewTextInput += AssociatedObjectPreviewTextInput; AssociatedObject.PreviewKeyDown += AssociatedObjectPreviewKeyDown; AssociatedObject.LostFocus += AccociateObjectLostFocus; AssociatedObject.GotFocus += AssociatedObjectGotFocus; DataObject.AddPastingHandler(AssociatedObject, Pasting); } protected override void OnDetaching() { base.OnDetaching(); AssociatedObject.Loaded -= AssociatedObjectLoaded; AssociatedObject.PreviewTextInput -= AssociatedObjectPreviewTextInput; AssociatedObject.PreviewKeyDown -= AssociatedObjectPreviewKeyDown; AssociatedObject.LostFocus -= AccociateObjectLostFocus; AssociatedObject.GotFocus -= AssociatedObjectGotFocus; DataObject.RemovePastingHandler(AssociatedObject, Pasting); } /// <summary> /// カーソルを最初の位置にする /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void AssociatedObjectGotFocus(object sender, RoutedEventArgs e) { AssociatedObject.Select(0, 0); //選択時にSelectAllにする場合はこちら //AssociatedObject.Select(0, AssociatedObject.Text.Length); } void AssociatedObjectLoaded(object sender, System.Windows.RoutedEventArgs e) { Provider = new MaskedTextProvider(InputMask, CultureInfo.CurrentCulture); Provider.PromptChar = PromptChar; Provider.Set(AssociatedObject.Text); //ToDisplayString:表示できる形式で書式設定された文字列 AssociatedObject.Text = Provider.ToDisplayString(); var textProp = DependencyPropertyDescriptor.FromProperty(TextBox.TextProperty, typeof(TextBox)); if (textProp != null) { textProp.AddValueChanged(AssociatedObject, (s, args) => UpdateText()); } } void AssociatedObjectPreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e) { TreatSelectedText(); var position = GetNextCharacterPosition(AssociatedObject.SelectionStart); if (Keyboard.IsKeyToggled(Key.Insert)) { //上書きモード if (Provider.Replace(e.Text, position)) position++; } else { //挿入モード if (Provider.InsertAt(e.Text, position)) position++; } position = GetNextCharacterPosition(position); RefreshText(position); e.Handled = true; } void AssociatedObjectPreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Space) { TreatSelectedText(); var position = GetNextCharacterPosition(AssociatedObject.SelectionStart); if (Provider.InsertAt(" ", position)) RefreshText(position); e.Handled = true; } if (e.Key == Key.Back) { if (TreatSelectedText()) { RefreshText(AssociatedObject.SelectionStart); } else { if (AssociatedObject.SelectionStart != 0) { if (Provider.RemoveAt(AssociatedObject.SelectionStart - 1)) RefreshText(AssociatedObject.SelectionStart - 1); } } e.Handled = true; } if (e.Key == Key.Delete) { if (TreatSelectedText()) { RefreshText(AssociatedObject.SelectionStart); } else { if (Provider.RemoveAt(AssociatedObject.SelectionStart)) RefreshText(AssociatedObject.SelectionStart); } e.Handled = true; } } private void AccociateObjectLostFocus(object sender, RoutedEventArgs e) { if (IsTime) { if(CheckTime(AssociatedObject.Text) != null) { // Time is correct! } else { AssociatedObject.Text = null; } } } /// <summary> /// 00:00形式のテキスト入力が正しくできているかどうか、違う場合はnullにする /// </summary> /// <param name="time"></param> /// <returns></returns> private string CheckTime(string time) { if (time == null) return null; if (string.IsNullOrWhiteSpace(time)) return null; string[] HHmm = time.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (HHmm.Length != 2) return null; int hour; int minute; if (!int.TryParse(HHmm[0], out hour)) return null; if (!int.TryParse(HHmm[1], out minute)) return null; if (hour < 0 || hour > 24) return null; if (minute < 0 || minute > 59) return null; return time; } /// <summary> /// ペースト対応 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Pasting(object sender, DataObjectPastingEventArgs e) { if (e.DataObject.GetDataPresent(typeof(string))) { var pastedText = (string)e.DataObject.GetData(typeof(string)); TreatSelectedText(); var position = GetNextCharacterPosition(AssociatedObject.SelectionStart); if (Provider.InsertAt(pastedText, position)) { RefreshText(position); } } e.CancelCommand(); } /// <summary> /// Textの更新 /// </summary> private void UpdateText() { //同じときは更新なし if (Provider.ToDisplayString().Equals(AssociatedObject.Text)) return; var isSet = Provider.Set(AssociatedObject.Text); SetText(isSet ? Provider.ToDisplayString() : AssociatedObject.Text); } /// <summary> /// Provider.Textの整理 /// </summary> /// <returns></returns> private bool TreatSelectedText() { if (AssociatedObject.SelectionLength > 0) { return Provider.RemoveAt(AssociatedObject.SelectionStart, AssociatedObject.SelectionStart + AssociatedObject.SelectionLength - 1); } return false; } private void RefreshText(int position) { SetText(Provider.ToDisplayString()); AssociatedObject.SelectionStart = position; } /// <summary> /// Textをセットします /// </summary> /// <param name="text"></param> private void SetText(string text) { AssociatedObject.Text = string.IsNullOrWhiteSpace(text) ? string.Empty : text; } private int GetNextCharacterPosition(int startPosition) { var position = Provider.FindEditPositionFrom(startPosition, true); if (position == -1) return startPosition; else return position; } } }参考)
Blindmeis's Blog WPF – Masked Textbox Behavior (ドイツ語のブログでした?)
Microsoft Document MaskedTextProvider クラス