- 投稿日:2020-08-04T20:08:57+09:00
Prism小さなサンプル
■環境
- Windows 10
- Visual Studio Community 2019 (Version 16.6.5)
- Prism Template Pack 2.2.1
- .NET Core 3.x
■STEP0. インストール、プロジェクト作成
◇0-1. 最初の作業
メニューの
拡張機能
-拡張機能の管理
でPrism Template Pack
をインストール。
Visual Studio再起動。◇0-2. STEPごとにやる作業
新しいプロジェクトで
Prism Blank App (.NET Core)
を選択。
プロジェクト名を付ける(プログラム例では PrismStep● という名前でSTEPごとにプロジェクトを作成している)。
PRISM PROJECT WIZARDでコンテナにUnity
を選択。ソリューションエクスプローラーでプロジェクトを右クリック、プロパティを選択。
対象のフレームワークが.NET Core 3.0
になっていたら.NET Core 3.1
に変更。◇0-3. 目次
- STEP1. バインディング
- STEP2. 別画面ポップアップ表示
- STEP3. 呼び出す画面にパラメータを渡す
- STEP4. 呼び出し元画面にパラメータを渡す
- STEP5. メッセージボックスを表示
- STEP6. ページ切り替え
■STEP1. バインディング
◇1-1. ViewModelの記述
バインド用の変数はコードスニペット
propp
、コマンドはcmd
を使うと楽。MainWindowViewModel.csusing Prism.Commands; using Prism.Mvvm; using System; using System.Collections.ObjectModel; namespace PrismStep1.ViewModels { public class MainWindowViewModel : BindableBase { private string _title = "バインディングの確認"; /// <summary> /// タイトル /// </summary> public string Title { get { return _title; } set { SetProperty(ref _title, value); } } private string _systemDateText = "---"; /// <summary> /// システム日付テキスト /// </summary> public string SystemDateText { get { return _systemDateText; } set { SetProperty(ref _systemDateText, value); } } private ObservableCollection<string> _fruits = new ObservableCollection<string>(); /// <summary> /// 果物リスト /// </summary> public ObservableCollection<string> Fruits { get { return _fruits; } set { SetProperty(ref _fruits, value); } } private DelegateCommand _setSystemDateCommand; /// <summary> /// システム日付設定コマンド /// </summary> public DelegateCommand SetSystemDateCommand => _setSystemDateCommand ?? (_setSystemDateCommand = new DelegateCommand(ExecuteSetSystemDateCommand)); /// <summary> /// システム日付設定処理 /// </summary> void ExecuteSetSystemDateCommand() { SystemDateText = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); } /// <summary> /// コンストラクタ /// </summary> public MainWindowViewModel() { _fruits.Add("りんご"); _fruits.Add("梨"); _fruits.Add("ブドウ"); _fruits.Add("桃"); _fruits.Add("ブルーベリー"); } } }◇1-2. Viewの記述
MainWindow.xaml<Window x:Class="PrismStep1.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Title="{Binding Title}" Width="350" Height="200" prism:ViewModelLocator.AutoWireViewModel="True"> <StackPanel> <Button Margin="5" Command="{Binding SetSystemDateCommand}" Content="システム日時" /> <!-- システム日時表示エリア --> <TextBlock Margin="5" Text="{Binding SystemDateText}" /> <!-- 果物リスト --> <ListBox Height="80" Margin="5" ItemsSource="{Binding Fruits}" /> <ContentControl prism:RegionManager.RegionName="ContentRegion" /> </StackPanel> </Window>■STEP2. 別画面ポップアップ表示
◇2-1. 別画面の追加
ソリューションエクスプローラーで
Views
フォルダを右クリック、追加
-新しい項目
を選択。
Prism UserControl (WPF)
を選択し、名前にSubWindow.xaml
と入力し追加
ボタン選択。
自動的にViewModelのファイルも生成される。◇2-2. メイン画面
◎2-2-1. ViewModelの記述
MainWindowViewModel.csusing Prism.Commands; using Prism.Mvvm; using Prism.Services.Dialogs; namespace PrismStep2.ViewModels { public class MainWindowViewModel : BindableBase { private readonly IDialogService _dialogService; private string _title = "別画面の表示"; /// <summary> /// タイトル /// </summary> public string Title { get { return _title; } set { SetProperty(ref _title, value); } } private DelegateCommand _showCommand; /// <summary> /// 画面表示コマンド /// </summary> public DelegateCommand ShowCommand => _showCommand ?? (_showCommand = new DelegateCommand(ExecuteShowCommand)); /// <summary> /// 画面表示処理 /// </summary> void ExecuteShowCommand() { _dialogService.Show( nameof(Views.SubWindow), // 表示するビュー名 null, // 渡すパラメータ null); // 閉じた後の処理 } private DelegateCommand _showDialogCommand; /// <summary> /// 画面モーダル表示コマンド /// </summary> public DelegateCommand ShowDialogCommand => _showDialogCommand ?? (_showDialogCommand = new DelegateCommand(ExecuteShowDialogCommand)); /// <summary> /// 画面モーダル表示処理 /// </summary> void ExecuteShowDialogCommand() { _dialogService.ShowDialog( nameof(Views.SubWindow), // 表示するビュー名 null, // 渡すパラメータ null); // 閉じた後の処理 } /// <summary> /// コンストラクタ /// </summary> /// <param name="dialogService"></param> public MainWindowViewModel(IDialogService dialogService) { _dialogService = dialogService; } } }◎2-2-2. Viewの記述
MainWindow.xaml<Window x:Class="PrismStep2.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Title="{Binding Title}" Width="350" Height="150" prism:ViewModelLocator.AutoWireViewModel="True"> <Window.Resources> <Style TargetType="Button"> <Setter Property="Margin" Value="5" /> </Style> </Window.Resources> <StackPanel> <Button Command="{Binding ShowCommand}" Content="画面表示" /> <Button Command="{Binding ShowDialogCommand}" Content="画面モーダル表示" /> <ContentControl prism:RegionManager.RegionName="ContentRegion" /> </StackPanel> </Window>◇2-3. 子画面
◎2-3-1. ViewModelの記述
IDialogAware
を実装する。SubWindowViewModel.csusing Prism.Mvvm; using Prism.Services.Dialogs; using System; namespace PrismStep2.ViewModels { public class SubWindowViewModel : BindableBase, IDialogAware { public SubWindowViewModel() { } #region IDialogAwareの実装 public string Title => "子画面"; public event Action<IDialogResult> RequestClose; public bool CanCloseDialog() { return true; } public void OnDialogClosed() { } public void OnDialogOpened(IDialogParameters parameters) { } #endregion } }◎2-3-2. Viewの記述
SubWindow.xaml<UserControl x:Class="PrismStep2.Views.SubWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True"> <Grid> <TextBlock FontSize="70" Text="*** 子画面 ***" /> </Grid> </UserControl>◇2-4. Appクラス
App.xaml.csusing Prism.Ioc; using PrismStep2.ViewModels; using PrismStep2.Views; using System.Windows; namespace PrismStep2 { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App { protected override Window CreateShell() { return Container.Resolve<MainWindow>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { // 子画面をコンテナに登録 containerRegistry.RegisterDialog<SubWindow, SubWindowViewModel>(); } } }■STEP3. 呼び出す画面にパラメータを渡す
◇3-1. 別画面の追加
STEP2と同様、
Views
フォルダにPrism UserControl (WPF)
を名前SubWindow.xaml
で追加。◇3-2. メイン画面
◎3-2-1. ViewModelの記述
DialogParametersのインスタンスにパラメータを追加し、ダイアログ表示時に渡す。
MainWindowViewModel.csusing Prism.Commands; using Prism.Mvvm; using Prism.Services.Dialogs; using System; namespace PrismStep3.ViewModels { public class MainWindowViewModel : BindableBase { private readonly IDialogService _dialogService; private string _title = "別画面にパラメータを渡す"; public string Title { get { return _title; } set { SetProperty(ref _title, value); } } private string _input1 = "abcde"; /// <summary> /// 入力パラメータ /// </summary> public string Input1 { get { return _input1; } set { SetProperty(ref _input1, value); } } private DelegateCommand _showCommand; /// <summary> /// 別画面表示コマンド /// </summary> public DelegateCommand ShowCommand => _showCommand ?? (_showCommand = new DelegateCommand(ExecuteShowCommand)); /// <summary> /// 別画面表示処理 /// </summary> void ExecuteShowCommand() { var param = new DialogParameters(); param.Add("Param1", Input1); param.Add("Param2", 456); param.Add("Param3", DateTime.Now); _dialogService.ShowDialog( nameof(Views.SubWindow), // 表示するビュー名 param, // 渡すパラメータ null); // 閉じた後の処理 } /// <summary> /// コンストラクタ /// </summary> /// <param name="dialogService"></param> public MainWindowViewModel(IDialogService dialogService) { _dialogService = dialogService; } } }◎3-2-2. Viewの記述
MainWindow.xaml<Window x:Class="PrismStep3.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Title="{Binding Title}" Width="350" Height="150" prism:ViewModelLocator.AutoWireViewModel="True"> <StackPanel> <TextBox Width="100" Margin="5" Text="{Binding Input1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> <Button Margin="5" Command="{Binding ShowCommand}" Content="別画面表示" /> <ContentControl prism:RegionManager.RegionName="ContentRegion" /> </StackPanel> </Window>◇3-3. 子画面
◎3-3-1. ViewModelの記述
SubWindowViewModel.csusing Prism.Mvvm; using Prism.Services.Dialogs; using System; namespace PrismStep3.ViewModels { public class SubWindowViewModel : BindableBase, IDialogAware { private string _showText; /// <summary> /// 表示するテキスト(呼び出し元から受け取ったパラメータを加工して表示) /// </summary> public string ShowText { get { return _showText; } set { SetProperty(ref _showText, value); } } public SubWindowViewModel() { } #region IDialogAwareの実装 public string Title => "子画面"; public event Action<IDialogResult> RequestClose; public bool CanCloseDialog() { return true; } public void OnDialogClosed() { } /// <summary> /// 画面オープン時 /// </summary> /// <param name="parameters"></param> public void OnDialogOpened(IDialogParameters parameters) { // パラメータを取り出す var p1 = parameters.GetValue<string>("Param1"); var p2 = parameters.GetValue<int>("Param2"); var p3 = parameters.GetValue<DateTime>("Param3"); ShowText = $"{p1}★{p2}★{p3:yyyy/MM/dd HH:mm:ss}"; } #endregion } }◎3-3-2. Viewの記述
SubWindow.xaml<UserControl x:Class="PrismStep3.Views.SubWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Width="500" Height="150" prism:ViewModelLocator.AutoWireViewModel="True"> <StackPanel> <TextBlock Margin="5" FontSize="20" Text="{Binding ShowText}" /> </StackPanel> </UserControl>◇3-4. Appクラス
STEP2と同様
■STEP4. 呼び出し元画面にパラメータを渡す
◇4-1. 別画面の追加
Views
フォルダにPrism UserControl (WPF)
を名前SubWindow.xaml
で追加。◇4-2. メイン画面
◎4-2-1. ViewModelの記述
MainWindowViewModel.csusing Prism.Commands; using Prism.Mvvm; using Prism.Services.Dialogs; namespace PrismStep4.ViewModels { public class MainWindowViewModel : BindableBase { private readonly IDialogService _dialogService; private string _title = "別画面からパラメータを受け取る"; /// <summary> /// タイトル /// </summary> public string Title { get { return _title; } set { SetProperty(ref _title, value); } } private string _resultText; /// <summary> /// 結果テキスト /// </summary> public string ResultText { get { return _resultText; } set { SetProperty(ref _resultText, value); } } private DelegateCommand _showCommand; /// <summary> /// 別画面表示コマンド /// </summary> public DelegateCommand ShowCommand => _showCommand ?? (_showCommand = new DelegateCommand(ExecuteShowCommand)); /// <summary> /// 別画面表示処理 /// </summary> void ExecuteShowCommand() { _dialogService.Show( nameof(Views.SubWindow), // 表示するビュー名 null, // 渡すパラメータ Dialog_Close); // 閉じた後の処理 } /// <summary> /// 画面を閉じたときの処理 /// </summary> /// <param name="dr"></param> private void Dialog_Close(IDialogResult dr) { if (dr.Result == ButtonResult.OK) { ResultText = dr.Parameters.GetValue<string>("Param1"); } } /// <summary> /// コンストラクタ /// </summary> /// <param name="dialogService"></param> public MainWindowViewModel(IDialogService dialogService) { _dialogService = dialogService; } } }◎4-2-2. Viewの記述
MainWindow.xaml<Window x:Class="PrismStep4.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Title="{Binding Title}" Width="350" Height="150" prism:ViewModelLocator.AutoWireViewModel="True"> <StackPanel> <Button Margin="5" Command="{Binding ShowCommand}" Content="別画面表示" /> <!-- 別画面呼び出し結果を表示 --> <TextBlock Margin="5" Text="{Binding ResultText}" /> <ContentControl prism:RegionManager.RegionName="ContentRegion" /> </StackPanel> </Window>◇4-3. 子画面
◎4-3-1. ViewModelの記述
SubWindowViewModel.csusing Prism.Commands; using Prism.Mvvm; using Prism.Services.Dialogs; using System; namespace PrismStep4.ViewModels { public class SubWindowViewModel : BindableBase, IDialogAware { private string inputParam; /// <summary> /// 入力パラメータ(呼び出し元に渡す) /// </summary> public string InputParam { get { return inputParam; } set { SetProperty(ref inputParam, value); } } private DelegateCommand _okCommand; /// <summary> /// OKコマンド /// </summary> public DelegateCommand OkCommand => _okCommand ?? (_okCommand = new DelegateCommand(ExecuteOkCommand)); /// <summary> /// OK時の処理 /// </summary> void ExecuteOkCommand() { var param = new DialogParameters(); // 呼び出し元に渡すパラメータを設定 param.Add("Param1", InputParam); // 画面を閉じる RequestClose?.Invoke(new DialogResult(ButtonResult.OK, param)); } private DelegateCommand _cancelCommand; /// <summary> /// キャンセルコマンド /// </summary> public DelegateCommand CancelCommand => _cancelCommand ?? (_cancelCommand = new DelegateCommand(ExecuteCancelCommand)); /// <summary> /// キャンセル時の処理 /// </summary> void ExecuteCancelCommand() { // 画面を閉じる RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel)); } public SubWindowViewModel() { } #region IDialogAwareの実装 public string Title => "子画面"; public event Action<IDialogResult> RequestClose; /// <summary> /// 画面を閉じられるかどうか /// </summary> /// <returns></returns> public bool CanCloseDialog() { // 入力があればtrue(true:画面を閉じられる、false:画面を閉じられない) return string.IsNullOrEmpty(InputParam) == false; } public void OnDialogClosed() { } public void OnDialogOpened(IDialogParameters parameters) { } #endregion } }◎4-3-2. Viewの記述
SubWindow.xaml<UserControl x:Class="PrismStep4.Views.SubWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Width="350" Height="150" prism:ViewModelLocator.AutoWireViewModel="True"> <UserControl.Resources> <Style TargetType="Button"> <Setter Property="Margin" Value="5" /> <Setter Property="Width" Value="100" /> </Style> </UserControl.Resources> <StackPanel> <TextBlock Margin="5" Text="子画面" /> <!-- 呼び出し元に渡す内容 --> <TextBox Margin="5" Text="{Binding InputParam}" /> <StackPanel Orientation="Horizontal"> <Button Command="{Binding OkCommand}" Content="OK" /> <Button Command="{Binding CancelCommand}" Content="キャンセル" /> </StackPanel> </StackPanel> </UserControl>◇4-4. Appクラス
STEP2と同様
■STEP5. メッセージボックスを表示
◇5-1. メッセージボックス用画面の追加
Views
フォルダにPrism UserControl (WPF)
を名前MessageWindow.xaml
で追加。◇5-2. メイン画面
◎5-2-1. ViewModelの記述
MainWindowViewModel.csusing Prism.Commands; using Prism.Mvvm; using Prism.Services.Dialogs; using PrismStep5.Views; namespace PrismStep5.ViewModels { public class MainWindowViewModel : BindableBase { IDialogService _dialogService; private string _title = "メッセージボックス表示"; public string Title { get { return _title; } set { SetProperty(ref _title, value); } } private DelegateCommand _showMessageCommand; /// <summary> /// メッセージ表示コマンド /// </summary> public DelegateCommand ShowMessageCommand => _showMessageCommand ?? (_showMessageCommand = new DelegateCommand(ExecuteShowCommand)); /// <summary> /// メッセージ表示処理 /// </summary> void ExecuteShowCommand() { var msg = new DialogParameters(); msg.Add(nameof(MessageWindowViewModel.Message), "こんにちは"); // メッセージ表示 _dialogService.ShowDialog(nameof(MessageWindow), msg, null); } /// <summary> /// コンストラクタ /// </summary> /// <param name="dialogService"></param> public MainWindowViewModel(IDialogService dialogService) { _dialogService = dialogService; } } }◎5-2-2. Viewの記述
MainWindow.xaml<Window x:Class="PrismStep5.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Title="{Binding Title}" Width="300" Height="250" prism:ViewModelLocator.AutoWireViewModel="True"> <StackPanel> <Button Margin="10" Command="{Binding ShowMessageCommand}" Content="メッセージ表示" /> <ContentControl prism:RegionManager.RegionName="ContentRegion" /> </StackPanel> </Window>◇5-3. メッセージボックス画面
◎5-3-1. ViewModelの記述
MessageWindowViewModel.csusing Prism.Commands; using Prism.Mvvm; using Prism.Services.Dialogs; using System; namespace PrismStep5.ViewModels { public class MessageWindowViewModel : BindableBase, IDialogAware { private string _message; /// <summary> /// 表示メッセージ /// </summary> public string Message { get { return _message; } set { SetProperty(ref _message, value); } } private DelegateCommand _okCommand; /// <summary> /// OKコマンド /// </summary> public DelegateCommand OkCommand => _okCommand ?? (_okCommand = new DelegateCommand(ExecuteOkCommand)); /// <summary> /// OK時の処理 /// </summary> void ExecuteOkCommand() { RequestClose?.Invoke(new DialogResult(ButtonResult.OK)); } public MessageWindowViewModel() { } #region IDialogAwareの実装 public string Title => "メッセージ"; public event Action<IDialogResult> RequestClose; public bool CanCloseDialog() { return true; } public void OnDialogClosed() { } public void OnDialogOpened(IDialogParameters parameters) { Message = parameters.GetValue<string>(nameof(Message)); } #endregion } }◎5-3-2. Viewの記述
MessageWindow.xaml<UserControl x:Class="PrismStep5.Views.MessageWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" MinWidth="300" prism:ViewModelLocator.AutoWireViewModel="True"> <prism:Dialog.WindowStyle> <Style TargetType="Window"> <Setter Property="ShowInTaskbar" Value="True" /> <Setter Property="ResizeMode" Value="NoResize" /> <Setter Property="SizeToContent" Value="WidthAndHeight" /> </Style> </prism:Dialog.WindowStyle> <StackPanel> <TextBlock Margin="10" Text="{Binding Message}" /> <Button Width="100" Margin="10" Command="{Binding OkCommand}" Content="OK" /> </StackPanel> </UserControl>◇5-4. Appクラス
App.xaml.csusing Prism.Ioc; using PrismStep5.ViewModels; using PrismStep5.Views; using System.Windows; namespace PrismStep5 { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App { protected override Window CreateShell() { return Container.Resolve<MainWindow>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterDialog<MessageWindow, MessageWindowViewModel>(); } } }■STEP6. ページ切り替え
◇6-1. 切り替え用ページ画面の追加
Views
フォルダにPrism UserControl (WPF)
を名前SubPage1.xaml
,SubPage2.xaml
で追加。◇6-2. メイン画面
◎6-2-1. ViewModelの記述
MainWindowViewModel.csusing Prism.Commands; using Prism.Mvvm; using Prism.Regions; using PrismStep6.Views; namespace PrismStep6.ViewModels { public class MainWindowViewModel : BindableBase { private readonly IRegionManager _regionManager; private string _title = "埋め込み画面サンプル"; /// <summary> /// タイトル /// </summary> public string Title { get { return _title; } set { SetProperty(ref _title, value); } } private DelegateCommand _showPage1Command; /// <summary> /// ページ1表示コマンド /// </summary> public DelegateCommand ShowPage1Command => _showPage1Command ?? (_showPage1Command = new DelegateCommand(ExecuteShowPage1Command)); /// <summary> /// ページ1表示処理 /// </summary> void ExecuteShowPage1Command() { _regionManager.RequestNavigate( "ContentRegion", // xamlのContentControlのRegionNameを指定 nameof(SubPage1)); // 表示するビュー名 } private DelegateCommand _showPage2Command; /// <summary> /// ページ2表示コマンド /// </summary> public DelegateCommand ShowPage2Command => _showPage2Command ?? (_showPage2Command = new DelegateCommand(ExecuteShowPage2Command)); /// <summary> /// ページ2表示処理 /// </summary> void ExecuteShowPage2Command() { _regionManager.RequestNavigate( "ContentRegion", // xamlのContentControlのRegionNameを指定 nameof(SubPage2)); // 表示するビュー名 } /// <summary> /// コンストラクタ /// </summary> /// <param name="regionManager"></param> public MainWindowViewModel(IRegionManager regionManager) { _regionManager = regionManager; } } }◎6-2-2. Viewの記述
MainWindow.xaml<Window x:Class="PrismStep6.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" Title="{Binding Title}" Width="350" Height="200" prism:ViewModelLocator.AutoWireViewModel="True" ResizeMode="CanResizeWithGrip"> <Window.Resources> <Style TargetType="Button"> <Setter Property="Margin" Value="5,5,0,0" /> <Setter Property="Padding" Value="15,0" /> </Style> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal"> <Button Command="{Binding ShowPage1Command}" Content="ページ1" /> <Button Command="{Binding ShowPage2Command}" Content="ページ2" /> </StackPanel> <!-- ページ表示エリア --> <ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" /> </Grid> </Window>◇6-3. ページ1
◎6-3-1. ViewModelの記述
SubPage1ViewModel.csusing Prism.Mvvm; namespace PrismStep6.ViewModels { public class SubPage1ViewModel : BindableBase { public SubPage1ViewModel() { } } }◎6-3-2. Viewの記述
SubPage1.xaml<UserControl x:Class="PrismStep6.Views.SubPage1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True"> <Grid Background="AliceBlue"> <Viewbox> <TextBlock Foreground="Blue" Text="ページ1" /> </Viewbox> </Grid> </UserControl>◇6-4. ページ2
◎6-4-1. ViewModelの記述
SubPage2ViewModel.csusing Prism.Mvvm; namespace PrismStep6.ViewModels { public class SubPage2ViewModel : BindableBase { public SubPage2ViewModel() { } } }◎6-4-2. Viewの記述
SubPage2.xaml<UserControl x:Class="PrismStep6.Views.SubPage2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True"> <Grid Background="LightYellow"> <Viewbox> <TextBlock Foreground="Orange" Text="ページ2" /> </Viewbox> </Grid> </UserControl>◇6-5. Appクラス
App.xaml.csusing Prism.Ioc; using PrismStep6.Views; using System.Windows; namespace PrismStep6 { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App { protected override Window CreateShell() { return Container.Resolve<MainWindow>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterForNavigation<SubPage1>(); containerRegistry.RegisterForNavigation<SubPage2>(); } } }
- 投稿日:2020-08-04T14:37:13+09:00
SNMPでWIFIルーターの電波OFFをする
やりたいこと
WIFIルーターの電波on/offをリモートで行う。
前提となる知識
SNMP(Simple Network Management Protocol)
- ネットワーク機器を管理するために用いられるプロトコル。今回でいうと、ルーターの設定値を読み出したり、電波をon/offしたり。
- ルーターの設定をSNMPプロトコルを通じて変更が可能 (変更が許可されているもののみ)。
- ルーターの設定値を読み出すことも可能。
MIBファイル形式
- MIBファイルにはルーターの各設定について、OID(Object ID)が何で、データ型が何なのか、設定許可されているかどうかなどが記載されている。
- ルーターの各設定項目について、それぞれObject ID(OID)が設定されている(メーカー独自)ため、ルーターのメーカーからMIBファイルを入手する必要がある。もしくはルーターの管理画面からダウンロードできるのかもしれない。
- MIBファイル形式について
- Q:SNMPv2形式の拡張MIBファイルの基本的な文法
OID(Object ID)について
設定値がツリー構造になっており、数字を順番に辿っていくと、ある設定値にたどり着く。たとえば、以下の例だとxxはベンダー名が割り当てられている。それ以降はモデル名だったり、設定値だったりと続いていく。これはベンダー毎に定義がされている。
1.3.6.1.4.1.xx実際のMIBファイルはテキストになっているが、解読するのは結構大変だった。以下は実際の例。
使用したツール
TWSNMP
http://www.twise.co.jp/twsnmp.html
MIBファイルを読み込ませる必要がある。GUIで、設定値が一覧で見えてくるので直感的でわかりやすい。現在設定値の確認、ObjectIDの確認などを行うときに使用した。
snmpwalk (windowns)
コマンドラインで設定の読み出しや変更を行う。実際にプログラム内でコマンドを投げるときに、正しくObjectIDや型などを送信しないといけないのだが、そのコマンドの確認のために使用。TWSNMPだと、実際にどういうコマンドが投げられているのかはわからない。Object IDはわかるのだが、型をどう指定するのかとか、Object IDの末尾の数字をどうするとか、そのあたりが確認できた。
例えば、1.3.6.1.4.1.xx.xx.xx.xxというObject IDの値を読み出したいというとき、SNMPv2-SMI::なんとかと返ってくる。ちなみに-vはSNMPのバージョン(今回はv2)。 -cはコミュニティ名。ここでは"public"という名前(ルーターの設定でsnmp communityという項目があるはず)。1.3.6.1.4.1.xx.xx.xx.xxのあとに、1とか0などがでてきて、データ型がなんなのかを教えてくれる。で、実際にコマンドを投げるときは、1.3.6.1.4.1.xx.xx.xx.xx.1をObjectIDとする必要があった。ここがわからず結構はまった。
設定値の読み出しc:\usr\bin>snmpwalk -v 2c -c public 192.168.1.10 1.3.6.1.4.1.xx.xx.xx.xx SNMPv2-SMI::enterprises.xx.xx.xx.xx.1 = INTEGER:0
- 設定の書き込みをする場合はルーターのsnmpの設定で、READ-WRITEの設定をしておく(書き込み可能にしておく)。
- enterprises.xx.xx.xx.xx.1の最後に1なのか0なのかはMIBファイルを見ただけではわからなかった。(何か規則性がある?)
- ここで得られたenterprises.xx.xx.xx.xx.1をOIDとして設定している。
SharpSnmp (.NET SNMP Library)
SNMPを行うためのライブラリ。いくつか似たようなのがある。
SNMP Library Documentation
インストール方法はここに書いてある。using Lextm.SharpSnmpLib; using Lextm.SharpSnmpLib.Messaging;
- SNMPv2を使用した。v2はわりとシンプル。v3は認証などもありで複雑、たぶん。今回はローカルの環境でしか使用しないので、v2を使用。
SetRequest 設定を送信する
設定値の送信private void SetRequest(string oid, int val) { // Snmp v2 VersionCode version = VersionCode.V2; var receiver = new IPEndPoint(IPAddress.Parse(ip), snmpProt); Discovery discovery = Messenger.GetNextDiscovery(SnmpType.GetRequestPdu); ReportMessage report = discovery.GetResponse(timeout, receiver); // int型のデータを送信する場合 ISnmpData data = new Integer32(val); // string型のデータを送信する場合 // ISnmpData data = new OctetString(val); var test = new Variable(new ObjectIdentifier(oid), data); var vList = new List<Variable>(); vList.Add(test); var request = new SetRequestMessage(Messenger.NextRequestId, version, new OctetString(community), vList); ISnmpMessage reply = request.GetResponse(timeout, receiver); if (reply.Pdu().ErrorStatus.ToInt32() != 0) { throw ErrorException.Create( "error in response", receiver.Address, reply); } // 結果を出力 foreach (Variable v in reply.Pdu().Variables) { Console.WriteLine(v); } }設定を取得する
ここではint型の設定を返している。
設定値の取得private int GetRequest(string oid) { VersionCode version = VersionCode.V2; var receiver = new IPEndPoint(IPAddress.Parse(ip), snmpProt); Discovery discovery = Messenger.GetNextDiscovery(SnmpType.GetRequestPdu); ReportMessage report = discovery.GetResponse(timeout, receiver); // 取得したいOID var test = new Variable(new ObjectIdentifier(oid)); var vList = new List<Variable>(); vList.Add(test); var request = new GetRequestMessage(Messenger.NextRequestId, version, new OctetString(community), vList); ISnmpMessage reply = request.GetResponse(timeout, receiver); if (reply.Pdu().ErrorStatus.ToInt32() != 0) { throw ErrorException.Create( "error in response", receiver.Address, reply); } // 結果を出力 foreach (Variable v in reply.Pdu().Variables) { Console.WriteLine(v); } return int.Parse(reply.Pdu().Variables[0].Data.ToString()); } }その他はまったポイント
ルーターの設定画面にラウザでアクセスしている状態(ログインしている)で、プログラムからコマンドを投げてもうまく反映がされなかった。コマンドを投げるときは、一旦ログアウトしてから、コマンドを投げる。その後、もう一度ルーターにログインして、値が変更されているかを確認する、といったことをやらなければならなかった。これも気づくまでに時間がかかった。
参考
- 投稿日:2020-08-04T13:51:09+09:00
ReactiveProperty v7.2.0 をリリースしました
ReactiveProperty v7.2.0 をリリースしました。
NuGet パッケージはこちら
ReactiveProperty v7.2.0 | NuGet Gallery
追加
DisposePreviousValue
拡張メソッドが追加されています。
IObservable
の最新より前の値に対してDispose
の呼び出しを行います。
ReadOnlyReactiveProperty<T>
に対してDispose
の呼び出しが必要な型などをSelect
で生成して使う場合に便利です。var source = new Subject<string>(); var rp = source.Select(x => new SomeDisposableObject(x)) .DisposePreviousValue() .ToReadOnlyReactivePropertySlim(); source.OnNext("aaa"); source.OnNext("bbb"); // aaa から作られたものは Dispose される source.OnComplete(); // ソースが終了したタイミングで現在の値も Dispose される
- 投稿日:2020-08-04T13:00:47+09:00
数独自動解法
導入
数独を自動で解くプログラムを作成した。
できるだけ早く、どんな問題も解くをコンセプトに設計開発をした。
自動生成部は説明割愛します。
肝となる Form1.cs について説明します。
複数関数で使う変数はグローバル変数で定義します。
関数呼び出しが長くなるし、ポインダーの定義が面倒だっだからです。
定数も、C#(VisualStado)ならではの定義方法となっています。
ファイル分けもしませんでした。グローバル変数を上手にとりまわせなかったのが原因です。
試行錯誤しながら作成したためソースが読みにくくなっています。準備
81個のマスの数字を青色にします。
public Form1() { InitializeComponent(); BGamen(); }初期動作時に青色にしています。
BGamen();
が数字を青くする関数です。
Set_ColorB(textBox11);
で1つの枠の色を青くしています。//青くするのサブルーチン private void Set_ColorB(TextBox textBox) { textBox.ForeColor = Color.Blue; }もう少しスマートな書き方もあっただろうがこれで目的を達成しています。
問題の数字を入力して、開始ボタンを押下すると0以外の数字を赤に変えて
計算処理開始です。
Gamen();
が数字を赤くする関数です。
Set_Color(textBox11);
で1つの枠の数字を赤くしています。//赤くするのサブルーチン private void Set_Color(TextBox textBox) { if( textBox.Text != "0") { textBox.ForeColor = Color.Red; } }数字が0以外だったら文字を赤くしています。
計算
1.各枠に入る数字を初期化します。
//各マスの設定できる数字の初期化 for (int jj = 1; jj <= 9; jj++) { for (int kk = 1; kk <= 9; kk++) { for (int ii = 0; ii <=9; ii++) { Num[ii, jj, kk] = 0; } } }iiが縦位置、jjが横位置、kkが数字0は画面(1-9)が入る1-9は数字(あれば1、なければ0)このポリシーはプログラム全体に同じ。
2.各枠に入らない数字の洗い出し。
横方向にすでに数字があれば、kkの数字に1を立てる。
縦方向にすでに数字があれば、kkの数字に1を立てる。
隣り合った9升にすでに数字があれば、kkの数字に1を立てる。3.kkが1-9の内1だけ0があればその数字をセットする。
4.3がなければ上の段の右から下の段の左に向かってkkの大きい数字の0をセット
5.矛盾が発生したら1個升を戻って1から実行
6.全升がうまったら終了
ちょっと長いけどソース。但しこれだけでは動きません。
/* =============================================================================== 数独ソリッドプログラム 解決力80%(予測) タイムアタック及び解法手順確認用 オープンソース 基礎コーディング by N.Tanaka 2020.04.19 =============================================================================== */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; using System.Threading; //プロジェクト 数独表示 namespace SuudokuHyouji { //メインフォームソース public partial class Form1 : Form { int[,,] No= new int[Con.CalcMax, 10, 10]; //メイン配列 int[,,] Num = new int[10, 10, 10]; //各位置に書ける数字用配列 Boolean FlgSet; //数字を新たにセット出来たか? Boolean Mujyun; //矛盾発生しているか? bool LoopFlg = true; //メインループ中? int Shin = 0; //手順位置 #if ERR101 int[,] Ren = new int[2,3]; //同一操作チェック用配列 #endif int[] Undo = new int[Con.CalcMax]; //操作を戻す用配列 int[,] UBack = new int[Con.CalcMax,2]; //操作を戻す位置用配列 int[,] NBack = new int[10, 2]; //太い線で囲まれた3×3の設定最初位置用配列 int SShin = 0; //メイン配列書き込み位置 int UShin; //借置き位置 int Back = 0; //現在の戻り位置 int XBack = 0; //現在の位置の戻り数字 int t = 0; //時間計算用 #if DEBUG string log; #endif public Form1() { InitializeComponent(); BGamen(); } //開始ボタン押下時の処理 private void button1_Click(object sender, EventArgs e) { DateTime dt = DateTime.Now; //開始時の現在時刻 string result = dt.ToString(); //時刻の文字列 int Rc; //関数の戻り値 //初期情報セット button1.Enabled = false; button2.Enabled = false; label1.Text += result; t = System.Environment.TickCount; get_No(); Gamen(); UBack[Shin, 0] = Back++; UBack[Shin, 1] = XBack++; //メインループ while (LoopFlg == true) { FlgSet = false; Mujyun = false; //各マスの設定できる数字の初期化 for (int jj = 1; jj <= 9; jj++) { for (int kk = 1; kk <= 9; kk++) { for (int ii = 0; ii <=9; ii++) { Num[ii, jj, kk] = 0; } } } //各マスの設定できる数字の算出 for (int jj = 1; jj <= 9; jj++) { for (int kk = 1; kk <= 9; kk++) { Tate_Set(No[Shin, jj, kk], kk); Yoko_Set(No[Shin, jj, kk], jj); A_Set(No[Shin, jj, kk], jj, kk); B_Set(No[Shin, jj, kk], jj, kk); C_Set(No[Shin, jj, kk], jj, kk); D_Set(No[Shin, jj, kk], jj, kk); E_Set(No[Shin, jj, kk], jj, kk); F_Set(No[Shin, jj, kk], jj, kk); G_Set(No[Shin, jj, kk], jj, kk); H_Set(No[Shin, jj, kk], jj, kk); I_Set(No[Shin, jj, kk], jj, kk); } } // メッセージ・キューにあるWindowsメッセージをすべて処理する Application.DoEvents(); //ただ1つの設定数字の確定 for (int jj = 1; jj <= 9; jj++) { for (int kk = 1; kk <= 9; kk++) { One_Kennsaku(jj, kk); if (FlgSet == true) break; } if (FlgSet == true) break; } label3.Text = "思考:" + SShin.ToString(); //解けた!!チェック if (Seikai() == 729) break; if (FlgSet == false) { #if DEBUG log = String.Concat("kuuhaku_Kennsaku\r\n"); LogSave(log); #endif //空白をチェックして埋める kuuhaku_Kennsaku(); { // メッセージ・キューにあるWindowsメッセージをすべて処理する Application.DoEvents(); } //解けた!!チェック if (Seikai() == 729) break; } if (FlgSet == false) { Undo[Shin] = 1; #if DEBUG log = String.Concat("Undo_kennsaku Shin =", Shin.ToString(), "\r\n"); LogSave(log); #endif //手順を戻す if (Undo_kennsaku() == 0) { break; } //矛盾チェック if (Mujyun == true) { Rc = Seikai(); if (Rc > 0) Rc = 0; Go_Start(Rc); if (FlgSet == false) break; Mujyun = false; } } Set_No(); if (checkBox1.Checked == true) Thread.Sleep(200); } //解けなかった場合の処理 if (Seikai() != 729) { label2.Text = "降参"; } Set_No(); t = System.Environment.TickCount - t; int tHour = t / 1000 / 60 / 60; int tMinu = (t - tHour * 1000 * 60 * 60) / 1000 / 60; int tSec = (t - tHour * 1000 * 60 * 60 - tMinu * 1000 * 60) / 1000; int tmSec = t - tHour * 1000 * 60 * 60 - tMinu * 1000 * 60 - tSec * 1000; label2.Text += tHour.ToString() + "時" + tMinu.ToString() + "分" + tSec.ToString() + "秒" + tmSec.ToString() + "ミリ秒"; button2.Enabled = true; } //画面データ→配列データ private void get_No() { No[Shin, 1, 1] = int.Parse(textBox11.Text); No[Shin, 1, 2] = int.Parse(textBox12.Text); No[Shin, 1, 3] = int.Parse(textBox13.Text); No[Shin, 1, 4] = int.Parse(textBox14.Text); No[Shin, 1, 5] = int.Parse(textBox15.Text); No[Shin, 1, 6] = int.Parse(textBox16.Text); No[Shin, 1, 7] = int.Parse(textBox17.Text); No[Shin, 1, 8] = int.Parse(textBox18.Text); No[Shin, 1, 9] = int.Parse(textBox19.Text); No[Shin, 2, 1] = int.Parse(textBox21.Text); No[Shin, 2, 2] = int.Parse(textBox22.Text); No[Shin, 2, 3] = int.Parse(textBox23.Text); No[Shin, 2, 4] = int.Parse(textBox24.Text); No[Shin, 2, 5] = int.Parse(textBox25.Text); No[Shin, 2, 6] = int.Parse(textBox26.Text); No[Shin, 2, 7] = int.Parse(textBox27.Text); No[Shin, 2, 8] = int.Parse(textBox28.Text); No[Shin, 2, 9] = int.Parse(textBox29.Text); No[Shin, 3, 1] = int.Parse(textBox31.Text); No[Shin, 3, 2] = int.Parse(textBox32.Text); No[Shin, 3, 3] = int.Parse(textBox33.Text); No[Shin, 3, 4] = int.Parse(textBox34.Text); No[Shin, 3, 5] = int.Parse(textBox35.Text); No[Shin, 3, 6] = int.Parse(textBox36.Text); No[Shin, 3, 7] = int.Parse(textBox37.Text); No[Shin, 3, 8] = int.Parse(textBox38.Text); No[Shin, 3, 9] = int.Parse(textBox39.Text); No[Shin, 4, 1] = int.Parse(textBox41.Text); No[Shin, 4, 2] = int.Parse(textBox42.Text); No[Shin, 4, 3] = int.Parse(textBox43.Text); No[Shin, 4, 4] = int.Parse(textBox44.Text); No[Shin, 4, 5] = int.Parse(textBox45.Text); No[Shin, 4, 6] = int.Parse(textBox46.Text); No[Shin, 4, 7] = int.Parse(textBox47.Text); No[Shin, 4, 8] = int.Parse(textBox48.Text); No[Shin, 4, 9] = int.Parse(textBox49.Text); No[Shin, 5, 1] = int.Parse(textBox51.Text); No[Shin, 5, 2] = int.Parse(textBox52.Text); No[Shin, 5, 3] = int.Parse(textBox53.Text); No[Shin, 5, 4] = int.Parse(textBox54.Text); No[Shin, 5, 5] = int.Parse(textBox55.Text); No[Shin, 5, 6] = int.Parse(textBox56.Text); No[Shin, 5, 7] = int.Parse(textBox57.Text); No[Shin, 5, 8] = int.Parse(textBox58.Text); No[Shin, 5, 9] = int.Parse(textBox59.Text); No[Shin, 6, 1] = int.Parse(textBox61.Text); No[Shin, 6, 2] = int.Parse(textBox62.Text); No[Shin, 6, 3] = int.Parse(textBox63.Text); No[Shin, 6, 4] = int.Parse(textBox64.Text); No[Shin, 6, 5] = int.Parse(textBox65.Text); No[Shin, 6, 6] = int.Parse(textBox66.Text); No[Shin, 6, 7] = int.Parse(textBox67.Text); No[Shin, 6, 8] = int.Parse(textBox68.Text); No[Shin, 6, 9] = int.Parse(textBox69.Text); No[Shin, 7, 1] = int.Parse(textBox71.Text); No[Shin, 7, 2] = int.Parse(textBox72.Text); No[Shin, 7, 3] = int.Parse(textBox73.Text); No[Shin, 7, 4] = int.Parse(textBox74.Text); No[Shin, 7, 5] = int.Parse(textBox75.Text); No[Shin, 7, 6] = int.Parse(textBox76.Text); No[Shin, 7, 7] = int.Parse(textBox77.Text); No[Shin, 7, 8] = int.Parse(textBox78.Text); No[Shin, 7, 9] = int.Parse(textBox79.Text); No[Shin, 8, 1] = int.Parse(textBox81.Text); No[Shin, 8, 2] = int.Parse(textBox82.Text); No[Shin, 8, 3] = int.Parse(textBox83.Text); No[Shin, 8, 4] = int.Parse(textBox84.Text); No[Shin, 8, 5] = int.Parse(textBox85.Text); No[Shin, 8, 6] = int.Parse(textBox86.Text); No[Shin, 8, 7] = int.Parse(textBox87.Text); No[Shin, 8, 8] = int.Parse(textBox88.Text); No[Shin, 8, 9] = int.Parse(textBox89.Text); No[Shin, 9, 1] = int.Parse(textBox91.Text); No[Shin, 9, 2] = int.Parse(textBox92.Text); No[Shin, 9, 3] = int.Parse(textBox93.Text); No[Shin, 9, 4] = int.Parse(textBox94.Text); No[Shin, 9, 5] = int.Parse(textBox95.Text); No[Shin, 9, 6] = int.Parse(textBox96.Text); No[Shin, 9, 7] = int.Parse(textBox97.Text); No[Shin, 9, 8] = int.Parse(textBox98.Text); No[Shin, 9, 9] = int.Parse(textBox99.Text); } //配列データ→画面データ private void Set_No() { textBox11.Text = No[Shin, 1, 1].ToString(); textBox12.Text = No[Shin, 1, 2].ToString(); textBox13.Text = No[Shin, 1, 3].ToString(); textBox14.Text = No[Shin, 1, 4].ToString(); textBox15.Text = No[Shin, 1, 5].ToString(); textBox16.Text = No[Shin, 1, 6].ToString(); textBox17.Text = No[Shin, 1, 7].ToString(); textBox18.Text = No[Shin, 1, 8].ToString(); textBox19.Text = No[Shin, 1, 9].ToString(); textBox21.Text = No[Shin, 2, 1].ToString(); textBox22.Text = No[Shin, 2, 2].ToString(); textBox23.Text = No[Shin, 2, 3].ToString(); textBox24.Text = No[Shin, 2, 4].ToString(); textBox25.Text = No[Shin, 2, 5].ToString(); textBox26.Text = No[Shin, 2, 6].ToString(); textBox27.Text = No[Shin, 2, 7].ToString(); textBox28.Text = No[Shin, 2, 8].ToString(); textBox29.Text = No[Shin, 2, 9].ToString(); textBox31.Text = No[Shin, 3, 1].ToString(); textBox32.Text = No[Shin, 3, 2].ToString(); textBox33.Text = No[Shin, 3, 3].ToString(); textBox34.Text = No[Shin, 3, 4].ToString(); textBox35.Text = No[Shin, 3, 5].ToString(); textBox36.Text = No[Shin, 3, 6].ToString(); textBox37.Text = No[Shin, 3, 7].ToString(); textBox38.Text = No[Shin, 3, 8].ToString(); textBox39.Text = No[Shin, 3, 9].ToString(); textBox41.Text = No[Shin, 4, 1].ToString(); textBox42.Text = No[Shin, 4, 2].ToString(); textBox43.Text = No[Shin, 4, 3].ToString(); textBox44.Text = No[Shin, 4, 4].ToString(); textBox45.Text = No[Shin, 4, 5].ToString(); textBox46.Text = No[Shin, 4, 6].ToString(); textBox47.Text = No[Shin, 4, 7].ToString(); textBox48.Text = No[Shin, 4, 8].ToString(); textBox49.Text = No[Shin, 4, 9].ToString(); textBox51.Text = No[Shin, 5, 1].ToString(); textBox52.Text = No[Shin, 5, 2].ToString(); textBox53.Text = No[Shin, 5, 3].ToString(); textBox54.Text = No[Shin, 5, 4].ToString(); textBox55.Text = No[Shin, 5, 5].ToString(); textBox56.Text = No[Shin, 5, 6].ToString(); textBox57.Text = No[Shin, 5, 7].ToString(); textBox58.Text = No[Shin, 5, 8].ToString(); textBox59.Text = No[Shin, 5, 9].ToString(); textBox61.Text = No[Shin, 6, 1].ToString(); textBox62.Text = No[Shin, 6, 2].ToString(); textBox63.Text = No[Shin, 6, 3].ToString(); textBox64.Text = No[Shin, 6, 4].ToString(); textBox65.Text = No[Shin, 6, 5].ToString(); textBox66.Text = No[Shin, 6, 6].ToString(); textBox67.Text = No[Shin, 6, 7].ToString(); textBox68.Text = No[Shin, 6, 8].ToString(); textBox69.Text = No[Shin, 6, 9].ToString(); textBox71.Text = No[Shin, 7, 1].ToString(); textBox72.Text = No[Shin, 7, 2].ToString(); textBox73.Text = No[Shin, 7, 3].ToString(); textBox74.Text = No[Shin, 7, 4].ToString(); textBox75.Text = No[Shin, 7, 5].ToString(); textBox76.Text = No[Shin, 7, 6].ToString(); textBox77.Text = No[Shin, 7, 7].ToString(); textBox78.Text = No[Shin, 7, 8].ToString(); textBox79.Text = No[Shin, 7, 9].ToString(); textBox81.Text = No[Shin, 8, 1].ToString(); textBox82.Text = No[Shin, 8, 2].ToString(); textBox83.Text = No[Shin, 8, 3].ToString(); textBox84.Text = No[Shin, 8, 4].ToString(); textBox85.Text = No[Shin, 8, 5].ToString(); textBox86.Text = No[Shin, 8, 6].ToString(); textBox87.Text = No[Shin, 8, 7].ToString(); textBox88.Text = No[Shin, 8, 8].ToString(); textBox89.Text = No[Shin, 8, 9].ToString(); textBox91.Text = No[Shin, 9, 1].ToString(); textBox92.Text = No[Shin, 9, 2].ToString(); textBox93.Text = No[Shin, 9, 3].ToString(); textBox94.Text = No[Shin, 9, 4].ToString(); textBox95.Text = No[Shin, 9, 5].ToString(); textBox96.Text = No[Shin, 9, 6].ToString(); textBox97.Text = No[Shin, 9, 7].ToString(); textBox98.Text = No[Shin, 9, 8].ToString(); textBox99.Text = No[Shin, 9, 9].ToString(); } //最初入力数字を赤くする private void Gamen() { Set_Color(textBox11); Set_Color(textBox12); Set_Color(textBox13); Set_Color(textBox14); Set_Color(textBox15); Set_Color(textBox16); Set_Color(textBox17); Set_Color(textBox18); Set_Color(textBox19); Set_Color(textBox21); Set_Color(textBox22); Set_Color(textBox23); Set_Color(textBox24); Set_Color(textBox25); Set_Color(textBox26); Set_Color(textBox27); Set_Color(textBox28); Set_Color(textBox29); Set_Color(textBox31); Set_Color(textBox32); Set_Color(textBox33); Set_Color(textBox34); Set_Color(textBox35); Set_Color(textBox36); Set_Color(textBox37); Set_Color(textBox38); Set_Color(textBox39); Set_Color(textBox41); Set_Color(textBox42); Set_Color(textBox43); Set_Color(textBox44); Set_Color(textBox45); Set_Color(textBox46); Set_Color(textBox47); Set_Color(textBox48); Set_Color(textBox49); Set_Color(textBox51); Set_Color(textBox52); Set_Color(textBox53); Set_Color(textBox54); Set_Color(textBox55); Set_Color(textBox56); Set_Color(textBox57); Set_Color(textBox58); Set_Color(textBox59); Set_Color(textBox61); Set_Color(textBox62); Set_Color(textBox63); Set_Color(textBox64); Set_Color(textBox65); Set_Color(textBox66); Set_Color(textBox67); Set_Color(textBox68); Set_Color(textBox69); Set_Color(textBox71); Set_Color(textBox72); Set_Color(textBox73); Set_Color(textBox74); Set_Color(textBox75); Set_Color(textBox76); Set_Color(textBox77); Set_Color(textBox78); Set_Color(textBox79); Set_Color(textBox81); Set_Color(textBox82); Set_Color(textBox83); Set_Color(textBox84); Set_Color(textBox85); Set_Color(textBox86); Set_Color(textBox87); Set_Color(textBox88); Set_Color(textBox89); Set_Color(textBox91); Set_Color(textBox92); Set_Color(textBox93); Set_Color(textBox94); Set_Color(textBox95); Set_Color(textBox96); Set_Color(textBox97); Set_Color(textBox98); Set_Color(textBox99); } //赤くするのサブルーチン private void Set_Color(TextBox textBox) { if( textBox.Text != "0") { textBox.ForeColor = Color.Red; } } //最初入力数字を青くする private void BGamen() { Set_ColorB(textBox11); Set_ColorB(textBox12); Set_ColorB(textBox13); Set_ColorB(textBox14); Set_ColorB(textBox15); Set_ColorB(textBox16); Set_ColorB(textBox17); Set_ColorB(textBox18); Set_ColorB(textBox19); Set_ColorB(textBox21); Set_ColorB(textBox22); Set_ColorB(textBox23); Set_ColorB(textBox24); Set_ColorB(textBox25); Set_ColorB(textBox26); Set_ColorB(textBox27); Set_ColorB(textBox28); Set_ColorB(textBox29); Set_ColorB(textBox31); Set_ColorB(textBox32); Set_ColorB(textBox33); Set_ColorB(textBox34); Set_ColorB(textBox35); Set_ColorB(textBox36); Set_ColorB(textBox37); Set_ColorB(textBox38); Set_ColorB(textBox39); Set_ColorB(textBox41); Set_ColorB(textBox42); Set_ColorB(textBox43); Set_ColorB(textBox44); Set_ColorB(textBox45); Set_ColorB(textBox46); Set_ColorB(textBox47); Set_ColorB(textBox48); Set_ColorB(textBox49); Set_ColorB(textBox51); Set_ColorB(textBox52); Set_ColorB(textBox53); Set_ColorB(textBox54); Set_ColorB(textBox55); Set_ColorB(textBox56); Set_ColorB(textBox57); Set_ColorB(textBox58); Set_ColorB(textBox59); Set_ColorB(textBox61); Set_ColorB(textBox62); Set_ColorB(textBox63); Set_ColorB(textBox64); Set_ColorB(textBox65); Set_ColorB(textBox66); Set_ColorB(textBox67); Set_ColorB(textBox68); Set_ColorB(textBox69); Set_ColorB(textBox71); Set_ColorB(textBox72); Set_ColorB(textBox73); Set_ColorB(textBox74); Set_ColorB(textBox75); Set_ColorB(textBox76); Set_ColorB(textBox77); Set_ColorB(textBox78); Set_ColorB(textBox79); Set_ColorB(textBox81); Set_ColorB(textBox82); Set_ColorB(textBox83); Set_ColorB(textBox84); Set_ColorB(textBox85); Set_ColorB(textBox86); Set_ColorB(textBox87); Set_ColorB(textBox88); Set_ColorB(textBox89); Set_ColorB(textBox91); Set_ColorB(textBox92); Set_ColorB(textBox93); Set_ColorB(textBox94); Set_ColorB(textBox95); Set_ColorB(textBox96); Set_ColorB(textBox97); Set_ColorB(textBox98); Set_ColorB(textBox99); } //青くするのサブルーチン private void Set_ColorB(TextBox textBox) { textBox.ForeColor = Color.Blue; } //縦使用数値設定 private void Tate_Set(int mm, int j) { if(mm == 0) { return; } for ( int i = 1; i <= 9; i++ ) { Num[mm, i, j] = 1; } return; } //横使用数値設定 private void Yoko_Set(int mm, int j) { if (mm == 0) { return; } for (int i = 1; i <= 9; i++) { Num[mm, j, i] = 1; } return; } private void A_Set(int mm, int kk, int jj) { int[,] gloup = new int[9, 2] { { 1, 1 }, { 1, 2 }, { 1, 3 }, { 2, 1 }, { 2, 2 }, { 2, 3 }, { 3, 1 }, { 3, 2 }, { 3, 3 } }; if (mm == 0) { return; } if(kk > 3 || jj > 3 ) { return; } for (int i = 0; i <= 8; i++) { Num[mm, gloup[i, 0], gloup[i, 1]] = 1; } return; } private void B_Set(int mm, int kk, int jj) { int[,] gloup = new int[9, 2] { { 1, 4 }, { 1, 5 }, { 1, 6 }, { 2, 4 }, { 2, 5 }, { 2, 6 }, { 3, 4 }, { 3, 5 }, { 3, 6 } }; if (mm == 0) { return; } if (kk > 3 || jj < 4 || jj > 6) { return; } for (int i = 0; i <= 8; i++) { Num[mm, gloup[i, 0], gloup[i, 1]] = 1; } return; } private void C_Set(int mm, int kk, int jj) { int[,] gloup = new int[9, 2] { { 1, 7 }, { 1, 8 }, { 1, 9 }, { 2, 7 }, { 2, 8 }, { 2, 9 }, { 3, 7 }, { 3, 8 }, { 3, 9 } }; if (mm == 0) { return; } if (kk > 3 || jj < 7) { return; } for (int i = 0; i <= 8; i++) { Num[mm, gloup[i, 0], gloup[i, 1]] = 1; } return; } private void D_Set(int mm, int kk, int jj) { int[,] gloup = new int[9, 2] { { 4, 1 }, { 4, 2 }, { 4, 3 }, { 5, 1 }, { 5, 2 }, { 5, 3 }, { 6, 1 }, { 6, 2 }, { 6, 3 } }; if (mm == 0) { return; } if (kk < 4 || kk > 6 || jj > 3) { return; } for (int i = 0; i <= 8; i++) { Num[mm, gloup[i, 0], gloup[i, 1]] = 1; } return; } private void E_Set(int mm, int kk, int jj) { int[,] gloup = new int[9, 2] { { 4, 4 }, { 4, 5 }, { 4, 6 }, { 5, 4 }, { 5, 5 }, { 5, 6 }, { 6, 4 }, { 6, 5 }, { 6, 6 } }; if (mm == 0) { return; } if (kk < 4 || kk > 6 || jj < 4 || jj > 6) { return; } for (int i = 0; i <= 8; i++) { Num[mm, gloup[i, 0], gloup[i, 1]] = 1; } return; } private void F_Set(int mm, int kk, int jj) { int[,] gloup = new int[9, 2] { { 4, 7 }, { 4, 8 }, { 4, 9 }, { 5, 7 }, { 5, 8 }, { 5, 9 }, { 6, 7 }, { 6, 8 }, { 6, 9 } }; if (mm == 0) { return; } if (kk < 4 || kk > 6 || jj < 7) { return; } for (int i = 0; i <= 8; i++) { Num[mm, gloup[i, 0], gloup[i, 1]] = 1; } return; } private void G_Set(int mm, int kk, int jj) { int[,] gloup = new int[9, 2] { { 7, 1 }, { 7, 2 }, { 7, 3 }, { 8, 1 }, { 8, 2 }, { 8, 3 }, { 9, 1 }, { 9, 2 }, { 9, 3 } }; if (mm == 0) { return; } if (kk < 7 || jj > 3) { return; } for (int i = 0; i <= 8; i++) { Num[mm, gloup[i, 0], gloup[i, 1]] = 1; } return; } private void H_Set(int mm, int kk, int jj) { int[,] gloup = new int[9, 2] { { 7, 4 }, { 7, 5 }, { 7, 6 }, { 8, 4 }, { 8, 5 }, { 8, 6 }, { 9, 4 }, { 9, 5 }, { 9, 6 } }; if (mm == 0) { return; } if (kk < 7 || jj < 4 || jj > 6) { return; } for (int i = 0; i <= 8; i++) { Num[mm, gloup[i, 0], gloup[i, 1]] = 1; } return; } private void I_Set(int mm, int kk, int jj) { int[,] gloup = new int[9, 2] { { 7, 7 }, { 7, 8 }, { 7, 9 }, { 8, 7 }, { 8, 8 }, { 8, 9 }, { 9, 7 }, { 9, 8 }, { 9, 9 } }; if (mm == 0) { return; } if (kk < 7 || jj < 7) { return; } for (int i = 0; i <= 8; i++) { Num[mm, gloup[i, 0], gloup[i, 1]] = 1; } return; } //確定数値1個の決定 private void One_Kennsaku(int jj, int kk) { int Cnt = 0; int work = 0; if ( No[Shin, jj, kk] != 0) { return; } for (int i = 1; i <= 9; i++) { if ( Num[i, jj, kk] == 0) { Cnt++; work = i; } } if (Cnt == 1) { No[Shin, jj, kk] = work; FlgSet = true; #if DEBUG log = String.Concat("One_Kennsaku jj = ", jj.ToString()); LogSave(log); log = String.Concat(" kk = ", kk.ToString()); LogSave(log); log = String.Concat(" work = ", work.ToString(), "\r\n"); LogSave(log); #endif } return; } //空白検索 private int kuuhaku_Kennsaku() { int rc = 0; int Cnt; int SetCnt = 0; Boolean UFlag = false; Boolean USet = false; int[] work = new int [10]; for (int jj = 1; jj <= 9; jj++) { for (int kk = 1; kk <= 9; kk++) { if (No[Shin, jj, kk] != 0) { SetCnt++; if (SetCnt >= 81) { FlgSet = true; return rc; } continue; } Cnt = 0; for (int i = 1; i <= 9; i++) { if (Num[i, jj, kk] == 0) { work[Cnt++] = i; } } if (Cnt == 0) { UFlag = true; break; } #if ERR101 if (Ren[0,0] == 0) { Ren[0, 0] = 1; Ren[0, 1] = jj; Ren[0, 2] = kk; } else { if (Ren[1,0] == 1) { Ren[0, 1] = Ren[1, 1]; Ren[0, 2] = Ren[1, 2]; } Ren[1, 0] = 1; Ren[1, 1] = jj; Ren[1, 2] = kk; if (Ren[0, 1] == Ren[1, 1] && Ren[0, 2] == Ren[1, 2]) { UFlag = true; break; } } #endif for (int rr = 0; rr < Cnt; rr++) { if (SShin + 1 >= Con.CalcMax) { FlgSet = false; return rc; } CopyMap(SShin + 1, Shin); No[SShin + 1, jj, kk] = work[rr]; UBack[SShin + 1, 0] = Back; UBack[SShin + 1, 1] = XBack; SShin++; #if DEBUG log = String.Concat("kuuhaku_Kennsaku loop SShin = ", SShin.ToString()); LogSave(log); log = String.Concat(" jj = ", jj.ToString()); LogSave(log); log = String.Concat(" kk = ", kk.ToString()); LogSave(log); log = String.Concat(" work[rr] = ", work[rr].ToString()); LogSave(log); log = String.Concat(" UBack[SShin+1, 0] Back= ", Back.ToString()); LogSave(log); log = String.Concat(" UBack[SShin+1, 1] XBack= ", XBack.ToString(), "\r\n"); LogSave(log); #endif USet = true; } if ( USet == true) { { int[,] gloup = new int[9, 2] { { 1, 1 }, { 1, 2 }, { 1, 3 }, { 2, 1 }, { 2, 2 }, { 2, 3 }, { 3, 1 }, { 3, 2 }, { 3, 3 } }; bool SSFlg = false; for (int i = 0; i <= 8; i++) { if (jj == gloup[i, 0] && kk == gloup[i, 1]) SSFlg = true; } if (Shin > 0 && SSFlg == true && NBack[1, 0] == 0) { NBack[1, 0] = 1; NBack[1, 1] = SShin; } } { int[,] gloup = new int[9, 2] { { 1, 4 }, { 1, 5 }, { 1, 6 }, { 2, 4 }, { 2, 5 }, { 2, 6 }, { 3, 4 }, { 3, 5 }, { 3, 6 } }; bool SSFlg = false; for (int i = 0; i <= 8; i++) { if (jj == gloup[i, 0] && kk == gloup[i, 1]) SSFlg = true; } if (Shin > 0 && SSFlg == true && NBack[2, 0] == 0) { NBack[2, 0] = 1; NBack[2, 1] = SShin; } } { int[,] gloup = new int[9, 2] { { 1, 7 }, { 1, 8 }, { 1, 9 }, { 2, 7 }, { 2, 8 }, { 2, 9 }, { 3, 7 }, { 3, 8 }, { 3, 9 } }; bool SSFlg = false; for (int i = 0; i <= 8; i++) { if (jj == gloup[i, 0] && kk == gloup[i, 1]) SSFlg = true; } if (Shin > 0 && SSFlg == true && NBack[3, 0] == 0) { NBack[3, 0] = 1; NBack[3, 1] = SShin; } } { int[,] gloup = new int[9, 2] { { 4, 1 }, { 4, 2 }, { 4, 3 }, { 5, 1 }, { 5, 2 }, { 5, 3 }, { 6, 1 }, { 6, 2 }, { 6, 3 } }; bool SSFlg = false; for (int i = 0; i <= 8; i++) { if (jj == gloup[i, 0] && kk == gloup[i, 1]) SSFlg = true; } if (Shin > 0 && SSFlg == true && NBack[4, 0] == 0) { NBack[4, 0] = 1; NBack[4, 1] = SShin; } } { int[,] gloup = new int[9, 2] { { 4, 4 }, { 4, 5 }, { 4, 6 }, { 5, 4 }, { 5, 5 }, { 5, 6 }, { 6, 4 }, { 6, 5 }, { 6, 6 } }; bool SSFlg = false; for (int i = 0; i <= 8; i++) { if (jj == gloup[i, 0] && kk == gloup[i, 1]) SSFlg = true; } if (Shin > 0 && SSFlg == true && NBack[5, 0] == 0) { NBack[5, 0] = 1; NBack[5, 1] = SShin; } } { int[,] gloup = new int[9, 2] { { 4, 7 }, { 4, 8 }, { 4, 9 }, { 5, 7 }, { 5, 8 }, { 5, 9 }, { 6, 7 }, { 6, 8 }, { 6, 9 } }; bool SSFlg = false; for (int i = 0; i <= 8; i++) { if (jj == gloup[i, 0] && kk == gloup[i, 1]) SSFlg = true; } if (Shin > 0 && SSFlg == true && NBack[6, 0] == 0) { NBack[6, 0] = 1; NBack[6, 1] = SShin; } } { int[,] gloup = new int[9, 2] { { 7, 1 }, { 7, 2 }, { 7, 3 }, { 8, 1 }, { 8, 2 }, { 8, 3 }, { 9, 1 }, { 9, 2 }, { 9, 3 } }; bool SSFlg = false; for (int i = 0; i <= 8; i++) { if (jj == gloup[i, 0] && kk == gloup[i, 1]) SSFlg = true; } if (Shin > 0 && SSFlg == true && NBack[7, 0] == 0) { NBack[7, 0] = 1; NBack[7, 1] = SShin; } } { int[,] gloup = new int[9, 2] { { 7, 4 }, { 7, 5 }, { 7, 6 }, { 8, 4 }, { 8, 5 }, { 8, 6 }, { 9, 4 }, { 9, 5 }, { 9, 6 } }; bool SSFlg = false; for (int i = 0; i <= 8; i++) { if (jj == gloup[i, 0] && kk == gloup[i, 1]) SSFlg = true; } if (Shin > 0 && SSFlg == true && NBack[8, 0] == 0) { NBack[8, 0] = 1; NBack[8, 1] = SShin; } } { int[,] gloup = new int[9, 2] { { 7, 7 }, { 7, 8 }, { 7, 9 }, { 8, 7 }, { 8, 8 }, { 8, 9 }, { 9, 7 }, { 9, 8 }, { 9, 9 } }; bool SSFlg = false; for (int i = 0; i <= 8; i++) { if (jj == gloup[i, 0] && kk == gloup[i, 1]) SSFlg = true; } if (Shin > 0 && SSFlg == true && NBack[9, 0] == 0) { NBack[9, 0] = 1; NBack[9, 1] = SShin; } } Back = SShin; XBack++; break; } } if (USet == true || UFlag == true) { break; } } if ( UFlag == true) { FlgSet = false; Undo[Shin] = 1; } else { FlgSet = true; } if (USet == false && UFlag == false) { Mujyun = true; } Shin = SShin; return rc; } //正解チェック private int Seikai() { int Rc = 0; UShin = Shin; for (int jj = 1; jj <= 9; jj++) { for (int kk = 1; kk <= 9; kk++) { for (int nn = 1; nn <=9; nn++) { int[] ss = new int[11] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; ss[0] = A_UNum(nn, jj, kk); ss[1] = B_UNum(nn, jj, kk); ss[2] = C_UNum(nn, jj, kk); ss[3] = D_UNum(nn, jj, kk); ss[4] = E_UNum(nn, jj, kk); ss[5] = F_UNum(nn, jj, kk); ss[6] = G_UNum(nn, jj, kk); ss[7] = H_UNum(nn, jj, kk); ss[8] = I_UNum(nn, jj, kk); for (int mm = 0; mm <= 8; mm++) { if (ss[mm] == 1) { Rc++; } else if (ss[mm] > 0) { Rc = (mm + 1) * -100; #if DEBUG log = String.Concat("Seikai loop mm = ", mm.ToString()); LogSave(log); log = String.Concat(" ss[mm] = ", ss[mm].ToString()); LogSave(log); log = String.Concat(" Shin = ", Shin.ToString()); LogSave(log); log = String.Concat(" UShin = ", UShin.ToString(), "\r\n"); LogSave(log); #endif Go_Start(Rc); return Rc; } } } } } return Rc; } private int Tate_UNum(int mm, int j) { int rc = 0; if (mm == 0) { return rc; } for (int i = 1; i <= 9; i++) { if (No[UShin, i, j] == mm) { rc++; } } return rc; } private int Yoko_UNum(int mm, int j) { int rc = 0; if (mm == 0) { return rc; } for (int i = 1; i <= 9; i++) { if (No[UShin, j, i] == mm) { rc++; } } return rc; } private int A_UNum(int mm, int kk, int jj) { int rc = 0; int[,] gloup = new int[9, 2] { { 1, 1 }, { 1, 2 }, { 1, 3 }, { 2, 1 }, { 2, 2 }, { 2, 3 }, { 3, 1 }, { 3, 2 }, { 3, 3 } }; if (mm == 0) { return rc; } if (kk > 3 || jj > 3) { return rc; } for (int i = 0; i <= 8; i++) { if (No[UShin, gloup[i, 0], gloup[i, 1]] == mm) { rc++; } } return rc; } private int B_UNum(int mm, int kk, int jj) { int rc = 0; int[,] gloup = new int[9, 2] { { 1, 4 }, { 1, 5 }, { 1, 6 }, { 2, 4 }, { 2, 5 }, { 2, 6 }, { 3, 4 }, { 3, 5 }, { 3, 6 } }; if (mm == 0) { return rc; } if (kk > 3 || jj < 4 || jj > 6) { return rc; } for (int i = 0; i <= 8; i++) { if (No[UShin, gloup[i, 0], gloup[i, 1]] == mm) { rc++; } } return rc; } private int C_UNum(int mm, int kk, int jj) { int rc = 0; int[,] gloup = new int[9, 2] { { 1, 7 }, { 1, 8 }, { 1, 9 }, { 2, 7 }, { 2, 8 }, { 2, 9 }, { 3, 7 }, { 3, 8 }, { 3, 9 } }; if (mm == 0) { return rc; } if (kk > 3 || jj < 7) { return rc; } for (int i = 0; i <= 8; i++) { if (No[UShin, gloup[i, 0], gloup[i, 1]] == mm) { rc++; } } return rc; } private int D_UNum(int mm, int kk, int jj) { int rc = 0; int[,] gloup = new int[9, 2] { { 4, 1 }, { 4, 2 }, { 4, 3 }, { 5, 1 }, { 5, 2 }, { 5, 3 }, { 6, 1 }, { 6, 2 }, { 6, 3 } }; if (mm == 0) { return rc; } if (kk < 4 || kk > 6 || jj > 3) { return rc; } for (int i = 0; i <= 8; i++) { if (No[UShin, gloup[i, 0], gloup[i, 1]] == mm) { rc++; } } return rc; } private int E_UNum(int mm, int kk, int jj) { int rc = 0; int[,] gloup = new int[9, 2] { { 4, 4 }, { 4, 5 }, { 4, 6 }, { 5, 4 }, { 5, 5 }, { 5, 6 }, { 6, 4 }, { 6, 5 }, { 6, 6 } }; if (mm == 0) { return rc; } if (kk < 4 || kk > 6 || jj < 4 || jj > 6) { return rc; } for (int i = 0; i <= 8; i++) { if (No[UShin, gloup[i, 0], gloup[i, 1]] == mm) { rc++; } } return rc; } private int F_UNum(int mm, int kk, int jj) { int rc = 0; int[,] gloup = new int[9, 2] { { 4, 7 }, { 4, 8 }, { 4, 9 }, { 5, 7 }, { 5, 8 }, { 5, 9 }, { 6, 7 }, { 6, 8 }, { 6, 9 } }; if (mm == 0) { return rc; } if (kk < 4 || kk > 6 || jj < 7) { return rc; } for (int i = 0; i <= 8; i++) { if (No[UShin, gloup[i, 0], gloup[i, 1]] == mm) { rc++; } } return rc; } private int G_UNum(int mm, int kk, int jj) { int rc = 0; int[,] gloup = new int[9, 2] { { 7, 1 }, { 7, 2 }, { 7, 3 }, { 8, 1 }, { 8, 2 }, { 8, 3 }, { 9, 1 }, { 9, 2 }, { 9, 3 } }; if (mm == 0) { return rc; } if (kk < 7 || jj > 3) { return rc; } for (int i = 0; i <= 8; i++) { if (No[UShin, gloup[i, 0], gloup[i, 1]] == mm) { rc++; } } return rc; } private int H_UNum(int mm, int kk, int jj) { int rc = 0; int[,] gloup = new int[9, 2] { { 7, 4 }, { 7, 5 }, { 7, 6 }, { 8, 4 }, { 8, 5 }, { 8, 6 }, { 9, 4 }, { 9, 5 }, { 9, 6 } }; if (mm == 0) { return rc; } if (kk < 7 || jj < 4 || jj > 6) { return rc; } for (int i = 0; i <= 8; i++) { if (No[UShin, gloup[i, 0], gloup[i, 1]] == mm) { rc++; } } return rc; } private int I_UNum(int mm, int kk, int jj) { int rc = 0; int[,] gloup = new int[9, 2] { { 7, 7 }, { 7, 8 }, { 7, 9 }, { 8, 7 }, { 8, 8 }, { 8, 9 }, { 9, 7 }, { 9, 8 }, { 9, 9 } }; if (mm == 0) { return rc; } if (kk < 7 || jj < 7) { return rc; } for (int i = 0; i <= 8; i++) { if (No[UShin, gloup[i, 0], gloup[i, 1]] == mm) { rc++; } } return rc; } //思考画面を戻す private int Undo_kennsaku() { int Rc = 0; for (int i = Shin; i >= 1; i--) { if (Undo[i] == 0) { Rc = i; break; } } if ( Rc != 0) { Undo[Rc] = 1; #if DEBUG log = String.Concat(" Rc =", Rc.ToString(), "\r\n"); LogSave(log); #endif Shin = Rc; } return Rc; } //画面コピー private void CopyMap(int t1, int t2) { for (int j2 = 1; j2 <= 9; j2++) { for (int j3 = 1; j3 <= 9; j3++) { No[t1, j2, j3] = No[t2, j2, j3]; } } } //最初の分岐まで戻す private void Go_Start(int TT) { int Rc = 0; int WW = 0; FlgSet = true; #if DEBUG log = String.Concat("Go_Start TT = ", TT.ToString(), "\r\n"); LogSave(log); #endif switch (TT) { case 0: for(int i = 1; i <= 9; i++) { if (NBack[i, 0] == 1) { WW = UBack[NBack[i, 1], 1]; #if DEBUG log = String.Concat("Go_Start i = ", i.ToString()); LogSave(log); log = String.Concat(" NBack[i, 1] = ", NBack[i, 1].ToString(), "\r\n"); LogSave(log); #endif break; } } break; case -100: WW = UBack[NBack[1, 1], 1]; break; case -200: WW = UBack[NBack[2, 1], 1]; break; case -300: WW = UBack[NBack[3, 1], 1]; break; case -400: WW = UBack[NBack[4, 1], 1]; break; case -500: WW = UBack[NBack[5, 1], 1]; break; case -600: WW = UBack[NBack[6, 1], 1]; break; case -700: WW = UBack[NBack[7, 1], 1]; break; case -800: WW = UBack[NBack[8, 1], 1]; break; case -900: WW = UBack[NBack[9, 1], 1]; break; default: FlgSet = false; return; } #if DEBUG log = String.Concat("Go_Start Shin = ", Shin.ToString()); LogSave(log); log = String.Concat(" WW = ", WW.ToString(), "\r\n"); LogSave(log); #endif if (WW == 0) { LoopFlg = false; return; } for (int i = Shin; i >= 1; i--) { if (Undo[i] == 0 && UBack[i,1] == WW) { Shin = UBack[i, 0]; Undo[Shin] = 1; Rc = i; break; } } if ( Rc != 0) { for (int i = Shin; i >= 1; i--) { if (Undo[i] == 0 && UBack[i, 1] == WW) { Shin = i; Back = i; Rc = i; Undo[Rc] = 1; if (SShin + 1 >= Con.CalcMax) { FlgSet = false; return; } if (UBack[NBack[1, 1], 0] == 1 && UBack[i, 1] == UBack[NBack[1, 1], 1]) { for (int k = 0; k <= 9; k++) { NBack[k, 0] = 0; NBack[k, 1] = 0; } } CopyMap(SShin + 1, Rc); Shin = SShin + 1; SShin++; UBack[Shin, 0] = Shin; UBack[Shin, 1] = XBack++; break; } else { if (UBack[i, 1] != WW) { FlgSet = false; for (int j = 1; j <= 9; j++) { if (Undo[i] == 0 && NBack[j, 0] == 1) { Undo[i] = 1; WW = UBack[NBack[j, 1], 1]; FlgSet = true; if (SShin + 1 >= Con.CalcMax) { FlgSet = false; return; } CopyMap(SShin + 1, i); Shin = SShin + 1; SShin++; UBack[Shin, 0] = Shin; UBack[Shin, 1] = XBack++; #if DEBUG log = String.Concat("Go_Start Shin = ", Shin.ToString()); LogSave(log); log = String.Concat(" j = ", j.ToString()); LogSave(log); log = String.Concat(" NBack[j, 1] = ", NBack[j, 1].ToString(), "\r\n"); LogSave(log); #endif return; } } } else { Rc = 0; LoopFlg = false; return; } } } } if (Rc == 0) { FlgSet = false; return; } } private void LogSave(string text) { string filePath = @"Debag.log"; StreamWriter sw = new StreamWriter(filePath, true, Encoding.GetEncoding("shift_jis")); sw.Write(text); sw.Close(); } private void Form1_Load(object sender, EventArgs e) { Set_No(); } private void button2_Click(object sender, EventArgs e) { Shin = 0; //手順位置 SShin = 0; //メイン配列書き込み位置 Back = 0; //現在の戻り位置 XBack = 0; //現在の位置の戻り数字 t = 0; //時間計算用 LoopFlg = true; for(int i = 0; i < 10; i++) { NBack[i, 0] = 0; NBack[i, 1] = 0; } for (int i = 0; i < Con.CalcMax; i++) Undo[i] = 0; for (int i = 0; i <=9; i++) { for(int j = 0; j <= 9; j++) { No[0, i, j] = 0; } } label1.Text = "開始"; label2.Text = "終了"; Set_No(); BGamen(); button1.Enabled = true; } } static class Con { public const int CalcMax = 999990; // 配列上限 } }
- 投稿日:2020-08-04T10:12:03+09:00
.NET Coreの画像処理ライブラリはどれが良い?
概要
- 本記事はMicrosoft 開発者ブログの引用で、ConclusionをDeeplで和訳、整理したものになります。
- 詳細はリンク先を参照ください。パフォーマンスや品質についても述べられています。
- 2017年1月時点の情報なので、今は状況が変わっているかもしれません。
結論
.NET Core上での画像処理のためのライブラリは、さまざまな要件に対応できるように、今日では多くの選択肢がありますが、近い将来さらに多くの選択肢が出てくるでしょう。
- パフォーマンスを優先するならば、CoreCompat.System.Drawingが良い
- ただし、Windowsサーバーのシナリオでのロック問題がアプリケーションを停止させてしまわない場合に限る
- SkiaSharpは、Linuxのセットアップ問題が解決されれば、品質を損なうことなくパフォーマンスを提供する素晴らしい選択肢となる
- 品質を最優先に考え、Windowsのみで動作する場合、MagicScalerはパフォーマンスを犠牲にすることなく、素晴らしい選択肢となる
- ファイルタイプのサポートを優先するのであれば、Magick.NETが良い
- ただし、クロスプラットフォームのサポートはまだ不十分
- 現時点で利用可能な唯一の純粋なマネージドコードライブラリであるImageSharp
- その性能はMagick.NETに近い
- ネイティブに依存せず、.NET Coreのどこでも動作することを保証している
- このライブラリはまだアルファ版であり、特に将来のSpanとrefリターンの使用により、大幅なパフォーマンスの向上が見込まれる。
私見
.NET Coreはどのプラットフォームでも動作するという点が強みであると考えています。したがって、上記の記事を読む限りでは、ImageSharpが最も有力であるかなと思いました。
ただ、2年前の記事であるので、ちゃんと選定したい場合には各ライブラリの対応状況を確認したほうが良いと思われます。.NET Coreの画像処理ライブラリに知見を持つ人がいらっしゃれば是非コメントをお願いします!
- 投稿日:2020-08-04T10:02:40+09:00
WPFアプリにおいてタイマ処理でUIを更新できない場合の対処法
はじめに
本記事は、開発で得た小さなTipsを備忘録として残すことを目的としています。
遭遇した問題
WPFアプリにおいてこちらのタイマクラスを使っている。タイマ時間経過時に実行されるハンドル処理内で、Dispathcerクラスを使ってUI更新をするとUIスレッドにアクセスできず、例外が出てしまう。
対処法
こちらのSystem.Windows.Threading.DispatcherTimerクラスを使えば、タイマ時間経過後の処理は必ずUIスレッドで実施されるため、Dispathcerクラスを使わずとも例外発生せずUI更新できる。
使い方はこちらの記事を参照のこと。まとめ
遭遇した問題は自分のDispathcerクラスの使い方が不適切で発生している可能性もあるが、タイマ処理内でUI更新処理をすることが初めからわかっている場合は、System.Windows.Threading.DispatcherTimerクラスを使うのが良いと個人的に感じた。
- 投稿日:2020-08-04T03:33:54+09:00
『眠気吹っ飛ばす作業用アプリ』【暖かい目で見てね】
なぜつくったの?
寝落ちでぴえんしそうになったから
作ったもの
- 常駐するWPFアプリケーション
GitHub リリースページ
Github初心者感すごいですが、気にしないでください
概要gif
解決したい課題
寝落ちせずに作業がしたい
私の趣味は、『締め切りギリギリに徹夜で作業や課題をすること』
この趣味は、寝落ちする可能性をぬぐい切れません。
そこで、寝落ちしないようなアプリケーションを作成した。こうなってほしい
1.作業中に常駐する
2.マウスとキーボードの入力が一定時間止まる
3.設定したアラーム音を鳴らす
4.びっくりして起きる
問題点
気持ちよく寝ているところを起こされると不機嫌になってしまう
実装した処理(折り畳み:ソースコード)
入力が一定時間ないことを判別する
public static class User32Interop{ /// 最終操作からの経過時間 /// </summary> ミリ秒で表示される Ex. 1sec -> 1000, 5sec -> 5000 public static TimeSpan GetLastInput(){ var plii = new LASTINPUTINFO(); plii.cbSize = (uint)Marshal.SizeOf(plii); if (GetLastInputInfo(ref plii)) return TimeSpan.FromMilliseconds(Environment.TickCount - plii.dwTime); else throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); } [DllImport("user32.dll", SetLastError = true)] static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); struct LASTINPUTINFO{ public uint cbSize; public uint dwTime; } }
アラーム音を鳴らす
SoundFilePlay.csstring SoundFilePath = SleepDown.Properties.Settings.Default.FilePath; string FileExtension = System.IO.Path.GetExtension(SoundFilePath); switch (FileExtension){ case ".mp3"://This is fall through so it's not that i forget break; case ".wav": case ".flac": Microsoft.SmallBasic.Library.Sound.PlayAndWait(SoundFilePath); break; default: MessageBox.Show("音声ファイルは\n対応した拡張子を設定してください"); break; }
再生する音源をローカルファイルから選択可能にする
GetFilePath.cs//設定に音源ファイルのパスを保存しているため //パスを取得 var FileDialog = new Microsoft.Win32.OpenFileDialog(); FileDialog.Title = "開くファイルを選択してください"; FileDialog.Filter = "mp3ファイル|*.mp3|wavファイル|*.wav|flacファイル|*.flac"; if (FileDialog.ShowDialog() == true){ SoundFilePath = FileDialog.FileName; }実装したい処理
- 再生音源の音量調整
- アラーム音を再生途中で入力があった場合の途中停止
最後に
もし読んでくれた人がいたならありがとうございます。
深夜テンションでヒャッハー!して書いたのでわけわからないところはご愛嬌で頼んます。ps.
初めて書いたのでC#もQiitaもぐちゃぐちゃです。