F#とXAMLでブツをナニすることを考える

2017/04/04

前回の投稿が5月29日なので、およそ10ヶ月ぶりの更新なのだが、この間いろいろあって、ついに仕事を辞めてしまった。これ以上はもう耐えられそうにない。生活には困るが、後悔はない。

というメモ書きと、もう1つ。いまさらながら、F#とXAMLでソフトを作る手順を調べたから、その結果だけ残しておく。

まず、F#でWPFとかXAMLで作る方法を検索すると、FsXamlという追加のパッケージみたいなやつを入れて作れ、といっているサイトがいくつかヒットする。

まぁ、個人でやっているだけだし、著作権て何ですか? おいしいんですか? という程度の認識しかないのだから、別にドコにナニをツッっこんでアッーなことをしてもいいのだが、やっぱり、得体の知れないものを無暗やたらに使うのは気分がよくない。

というか、最近?では、業務システムの開発でそれをやる奴が多くて困る。「このライブラリがないと動きません(キリッ ライセンス?サポート? 知りませんね。それは僕の仕事ではありません。気になるのなら、あなたが何とかすればいいんじゃないですかw?」とのたまい、GPL汚染がっつりなコードを製品に混入しようとする馬鹿が本気でいるから困る。もう、そういう尻拭いをするのに疲れた。

と、余談はいいとして、そもそも、Visual Studio 2017になってからなのかどうかは知らないが、なんか、プロジェクトの作成時にオンラインでテンプレートを検索してもFsXamlなるものが出てこないし、2015で登録してやってみても、なんかちゃんとコンパイルできないし。

ということで、すべて自前で対応する方法を模索してみた。

(1)まずは、新規にF#のプロジェクトを作成する。



コンソールアプリケーションを指定しているが、気にしない。後で変更する。

(2)参照設定を変更する
いきなりだが、必要なライブラリを追加する。少なくとも以下のものが必要。
・FSharp.Core
・mscorlib
・PresentationCore
・PresentationFramework
・System
・System.Core
・WindowsBase

このうち、PresentationCore・PresentationFramework・WindowsBaseの3つはデフォルトでは登録されていないから、明示的に指定してやる必要がある。





(3)アプリケーションのプロパティを変更する
出力の種類として「コンソール アプリケーション」という指定になっているものを、「Windows アプリケーション」に変更する。






ターゲット F# ランタイムとか、対象のフレームワークとか、気になる項目が多数あるが、たぶん、なんでもいい。

(4)XAMLのコードを追加する
ファイルは適当にプロジェクトに追加すればいい。

内容はこんな感じにしておく。



コードを示すとこんな感じ。

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="aaaa" Height="262" Width="500" >
<Canvas HorizontalAlignment="Left" Height="131" Margin="21,19,0,0" VerticalAlignment="Top" Width="237" >
<Button x:Name="button1" Content="Button1" Height="32" Canvas.Left="6" Canvas.Top="21" Width="97" />
<Button x:Name="button2" Content="Button2" Height="35" Canvas.Left="118" Canvas.Top="21" Width="119" />
<TextBox x:Name="TextBox1" Height="74" Canvas.Left="72" Canvas.Top="96" Width="103" />
</Canvas>
</Window>

あとここで、追加したXAMLのファイル(ここではMainWindow.xamlとする)のプロパティで、ビルドアクションという項目で「Resource」、出力ディレクトリにコピーという項目で「常にコピーする」を選択しておく。これを忘れると動かない。

(5)F#のコードを追加する。



コードを示すとこんな感じ

module MainApp
open System
open System.Windows
open System.Windows.Controls


//////////////////////////////////
// ウインドウ全体を示すクラス

type CMainWindow() =
   
    // XAMLのコードをリソースからロードする
    let m_Window =
        Application.LoadComponent(
            new System.Uri( "/FsTest3;component/mainwindow.xaml", UriKind.Relative )
        ) :?> Window    // System.Windows.Windowクラスに動的ダウンキャスト


    // コントールのオブジェクトを取得する
    let Button1 = m_Window.FindName( "button1" ) :?> Button
    let Button2 = m_Window.FindName( "button2" ) :?> Button
    let TextBox = m_Window.FindName( "TextBox1" ) :?> TextBox


    // main関数でRunしてやるために、Windowオブジェクトを公開している
    // このクラスのメンバでRunするようにすれば、公開する必要はない気がする

    member this.TheWindow with get() = m_Window


    // ウインドウ全体の初期化
    member this.Initialize =
        // ボタンのイベントハンドラを追加している
        // 単にCMainWindowのメンバを呼び出すようにしているだけ

        Button1.Click.AddHandler ( fun sender e -> this.OnButton1_Click sender e )
        Button2.Click.AddHandler ( fun sender e -> this.OnButton2_Click sender e )


    // ボタン1の押下時に呼び出される
    member this.OnButton1_Click sender e =
        TextBox.Text <- "OnButton1_Click"


    // ボタン2の押下時に呼び出される
    member this.OnButton2_Click sender e =
        TextBox.Text <- "OnButton2_Click"


//////////////////////////////////
// エントリポイント

[<STAThread>]
[<EntryPoint>]

let main(_) =
    // ウインドウのクラスを作って・・・
    let WinObj = new CMainWindow()

    // 初期化して・・・
    WinObj.Initialize

    // 実行してやる
    ( new Application() ).Run( WinObj.TheWindow )


ダサい。

コードとデザインの分離性とかなんとか考えると、Bindingとかいう方法を使った方がいいらしいのだが、それだとどうにもうまく実装することができなかった、というか、よくわからなくて面倒になった。

F#のコードとXAMLのデザインが分離されてないとか、いちいちイベントのハンドラを登録しないといけないとか、いろいろな面倒はあるが、それは結局、今までWin32APIやMFCでも泥臭くやってきたことだと思えば、まぁいいかという気がする。

1ミリも進歩がないけどな!


(6)実行する



こんなんでも、一応ボタンを押すとテキストボックスに文字列が設定されて、想定通りに動作していることが伺える。

あと、上のプログラムだと、CMainWindowの定義とmainの定義をひとまとめに書いてしまったが、俺の趣味からすればファイルを分けて作りたくなる。

つまり、XAML+C#の場合と同じように、XAMLのファイル1つに対してF#のソースが1本あって、かつ、その中にウインドウを管理するクラスが1つ定義されていれば、雰囲気だけでもMFCで作ってきたのと同じ枠組みで考えられるのではないかという気がする。

まぁ、1ミリも進歩がないけどな!



0 Comments:

コメントを投稿

Links to this post:

リンクを作成

<< Home