Eto.Formsでメモ帳のようなもの
GUIプログラミングといえばテキストエディタ(と個人的には思っているのです)。ということで、Eto.Formsでも簡単なサンプルを作ってみます。
できあがりは次のような感じです。
作成
今回はアプリケーションプロパティでPortable Class Library
ではなくFull .NET
を選ぶ点に注意してください。これはファイル操作コードが入っているからです。
using System; using System.IO; using System.Text; using Eto.Forms; using Eto.Drawing; namespace EtoSample2 { public class MainForm : Form { TextArea myText = new TextArea(); public MainForm() { Title = "Eto notepad"; ClientSize = new Size(400, 350); Content = myText; #region Commands var openCommand = new Command { MenuText = "&Open...", ToolBarText = "Open", Shortcut = Application.Instance.CommonModifier | Keys.O, }; openCommand.Executed += (s, e) => { var dialog = new OpenFileDialog(); dialog.Filters.Add("text file|.txt"); dialog.Filters.Add("any file|.*"); if (dialog.ShowDialog(this) != DialogResult.Ok) return; try { var text = File.ReadAllText( dialog.FileName, Encoding.UTF8); if (text != null) myText.Text = text; } catch (Exception ex) { MessageBox.Show("Failed. Detail:" + ex.Message); } }; var saveAsCommand = new Command { MenuText = "Save &As...", ToolBarText = "Save", Shortcut = Application.Instance.CommonModifier | Keys.S, }; saveAsCommand.Executed += (s, e) => { var dialog = new SaveFileDialog(); dialog.Filters.Add("text file|.txt"); dialog.Filters.Add("any file|.*"); if (dialog.ShowDialog(this) != DialogResult.Ok) return; try { File.WriteAllText( dialog.FileName, myText.Text, Encoding.UTF8); } catch(Exception ex) { MessageBox.Show("Failed. Detail:" + ex.Message); } }; var fontCommand = new Command { MenuText = "&Font...", }; fontCommand.Executed += (s, e) => { var dialog = new FontDialog { Font = myText.Font }; dialog.FontChanged += (s_, e_) => myText.Font = dialog.Font; dialog.ShowDialog(this); }; var backgroundColorCommand = new Command { MenuText = "&Background Color..." }; backgroundColorCommand.Executed += (s, e) => { var dialog = new ColorDialog { Color = myText.BackgroundColor }; dialog.ColorChanged += (s_, e_) => myText.BackgroundColor = dialog.Color; dialog.ShowDialog(this); }; var wrapCommand = new CheckCommand { MenuText = "Wrap Line", Checked = myText.Wrap }; wrapCommand.CheckedChanged += (s, e) => { myText.Wrap = wrapCommand.Checked; }; var quitCommand = new Command { MenuText = "Quit", Shortcut = Application.Instance.CommonModifier | Keys.Q }; quitCommand.Executed += (sender, e) => Application.Instance.Quit(); var aboutCommand = new Command { MenuText = "About..." }; aboutCommand.Executed += (sender, e) => MessageBox.Show(this, "About my app..."); #endregion #region Menus Menu = new MenuBar { Items = { new ButtonMenuItem { Text = "&File", Items = { openCommand, saveAsCommand } }, new ButtonMenuItem { Text = "&View", Items = { fontCommand, backgroundColorCommand, wrapCommand } }, }, ApplicationItems = { new ButtonMenuItem { Text = "&Preferences..." }, }, QuitItem = quitCommand, AboutItem = aboutCommand }; ToolBar = new ToolBar { Items = { openCommand, saveAsCommand } }; #endregion } } }
行数はやや長いものの、特に難しいことはないので読めば分かることと思います。
実行
実行します。
フォントおよび色選択ダイアログ
フォント選択ダイアログ(FontDialog)、色選択ダイアログ(ColorDialog)は、WPFだと独自実装になります。 WinFormsの名前空間引っ張った方がWindows標準になっていい(WPFが使える環境でWinFormsが使えないケースは事実上存在しない)と思うので、ここは残念。
折り返し設定
さらに折り返し設定も無効にしてみます。
Linux環境で実行
TextArea
複数行を扱えるテキストボックス(1行のみならTextBox)。
TextAreaは、プラットフォームによって結構異なるようです。
- WPFやWinFormsだと、多段階のUndoが可能。WPFのTextBoxは元々可能だが、WinFormsは本来は1段階なので、追加実装している模様。
- GTK+2やGTK+3だと、Undoはデフォルトでは不可能。確かにJava/SWTでテキストボックスを作ってGTK環境で動かしてもUndoできないので、デフォルト仕様なのでしょう。
なお、GTK+Fcitxだと、IMEで変換する際、たまに入力部分の文字表示が一瞬だけ乱れます。Java/SWTや、普通にGTK+を使った他のプログラムでも同様なので、おそらくこれも仕様なのだと思います。一瞬だけのことなので、実害はほとんどないと思いますが。
Command
XAMLでも利用できるCommandクラスですが、ここではメニューバーやツールバーで実行する内容を設定しています。ShortcutでCommonModifierを使っているのは主にMac対策です。
MenuTextやToolBarTextで半角「&」を使うと、対応プラットフォームならアクセスキーが定義できます(Windowsなら多くのアプリケーションでキーの[ALT+F]を押下すると「ファイル」メニューが開くなど)。
コモン・ダイアログ
今回使ったのは次の4つです。
- FontDialog
- ColorDialog
- OpenFileDialog
- SaveFileDialog
FontとColorについては、上でも書いたように、WPFを適用していると独自実装のダイアログになります。
また、API文書にある通り、macOSでは非同期動作となるため、Windows風に if (dialog.ShowDialog(this)==DialogResult.Ok)
と書くのは避けておいた方が無難です。
なお、上記コードで使っているFontChanged
やColorChanged
イベントは、WindowsやLinuxではOKボタンでダイアログを閉じた直後に発生するので、「選んだ瞬間に変わっちゃう?」などの疑念なく安心して設定処理を書くことができます。
ファイルダイアログは、WPFでも使える関係で、Windows標準のものとなります。 ファイルフィルタは、あいにく読み込み専用プロパティなので、構築後にAddメソッドで追加しなければなりません。 また、フィルタは1回につき1個しか追加できません。