15年前のMFCあるいはMVC

15年前のMFC

View more presentations from moonmile.
2012年6月の.NETラボ勉強会のライトニングトークスで発表した資料です。

歴史をさかのぼれば、コンソールアプリケーションまでさかのぼって解説をしないと駄目なのですが、それだと時間が無くなるので、時間をさかのぼるスタイルで解説していきます。
このスライドでは、いきなりMFCのところからスタートしていますが、実はMVC(MVVMなどが生まれる前の「MVC」という用語の)やXAMLあたりからさかのぼっていきます。XAMLはSVGの派生であって、かつDHTMLの後継(とも言える)スタイルなのです。一見、動的な操作が加えられているように見えますが、本質的なところは、Viewです。Viewというのは人にとってはDisplayです。時にはInterfaceであったり、Presentationであったり(Persentする側があるという意味で)だったりします。
そこで、Viewの部分をXAMLという「言語」で書きました。現実的にはXMLの派生ということなのですが、タグフォーマットという「言語」で書きます。で、実際の内部動作はどうなっているかというと、C#やVBなどの「言語」で書きます。この2つの「言語」を使い分けるのが、XAMLというViewを使う特徴です。
(実は、内部的にXAMLにResourceなどの記述が入っているので、完全にXMLに準拠=XMLの文法だけで解析できる訳ではないので、微妙にことなるのですが)。
さて、XAML+C#あるいはXAML+VB、Windows 8 MetroStyle、あるいは、WPF、Windows Phone, Silverlight などのアプリケーションは、皆 XAML を View として扱います。
さて、View 以外の部分、MVC で言うところの、Model と Controller はどうなるかというとここではさておき(MVVMや様々なMVC実装などでimpliment自体が異なるので)、「View を異なる言語で書いたのは、WPF などが最初であったか?」という話なのですが、実は、VC++6(あたり、正確には何時だったけ?)から View の実装があります。

これが「*.rc」です。CDialog や CView という形で View を分離しておいて、その中でリソースを参照させます。このリソースの中身は、

IDD_HC_WAVE_VRETICAL_PAGE DIALOGEX 0, 0, 279, 193
STYLE DS_SETFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
CAPTION "Vertical"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
    LTEXT           "Group name:",IDC_STATIC,5,10,77,8
    LTEXT           "Hatch cover no:",IDC_STATIC,5,26,77,8
    LTEXT           "Length of hatch opening (m):",IDC_STATIC,5,42,101,8
    LTEXT           "Breadth of hatch opening (m):",IDC_STATIC,5,57,101,8
    LTEXT           "Hatch center location FP (m):",IDC_STATIC,5,74,101,8
    LTEXT           "Pressure P (kN/m2):",IDC_STATIC,5,91,101,8
    EDITTEXT        IDC_E_HC_WAVE_LOADS_GROUP_NAME,114,10,92,12,ES_AUTOHSCROLL
    EDITTEXT        IDC_E_HC_WAVE_LOADS_BREADTH,114,57,92,12,ES_AUTOHSCROLL
    EDITTEXT        IDC_E_HC_WAVE_LOADS_HATCH_COVER_NO,114,26,92,12,ES_AUTOHSCROLL
    EDITTEXT        IDC_E_HC_WAVE_LOADS_LENGTH,114,42,92,12,ES_AUTOHSCROLL
    EDITTEXT        IDC_E_HC_WAVE_LOADS_CENTER,114,73,92,12,ES_AUTOHSCROLL
    EDITTEXT        IDC_E_HC_WAVE_LOADS_PRESSURE,114,89,92,12,ES_AUTOHSCROLL
END

な感じなのです。これを見てみるとわかりますね。
実は、XAML のように構造化されているところが同じなのです。

LTEXT は静的なラベルを貼っているところ、EDITTEXT はテキストボックスです。IDC_E_HC_WAVE_LOADS_GROUP_NAME は名前です。内部的にはint形として処理されています。これを XAML 風に書くならば、

<grid font="MS Sans Serif" fontsize="8pt">
	<LTEXT content="Group name:" type="IDC_STATIC" position="5,10,77,8"/>
	<LTEXT content="Hatch cover no:" type="IDC_STATIC" position="5,26,77,8"/>
	<LTEXT content="Length of hatch opening (m):" type="IDC_STATIC" position="5,42,101,8"/>
	...
	<EDITTEXT name="IDC_E_HC_WAVE_LOADS_GROUP_NAME" position="114,10,92,12" ES_AUTOHSCROLL="true" />
    <EDITTEXT name="IDC_E_HC_WAVE_LOADS_BREADTH" position="114,57,92,12" ES_AUTOHSCROLL="true" />
	...
</grid>

のように対応付けられます。

ただし、ボタンクリックのイベントは、XAML の場合 Click 属性に設定できるのですが、*.rc の場合はできなくて ON_COMMAND などを駆使しています。このあたりは、実装の違い、かつ Click 属性などのような動的なイベント/データの扱いが、実は View とは異なる領域にあることを示しています(このあたりの話は後日)。

この *.rc の書き方ですが、その昔はどうしていたかというと、CreateWindow 関数を駆使しながら「C++」言語で書いていました。多少は、CButton, CEdit というコントロールができたものの、position を指定する(静的に設定できる値)場合には、違った書き方をしていたわけです。C++ だけで書くというやり方と、*.rc と C++ で書くというやり方ですね。
実際のところ、*.rc は Visual Studio のデザイナを使うために直接扱うことはありません。デザイナ自体がちょっと重たいので、大量に画面を作りたい場合は、直接テキストエディタで *.rc を開いて編集してます。
実は、このあたりの編集スタイルも XAML と似たようなものなのです。

となると、MVC における VC++ の *.rc は元祖なのか?というと実は違います。まだ先祖がいるのですよ。VB1.0 なんですね。かのアラン・クーパーが開発した Visual Basic は、この View と動作コードを分離させていました。

Visual Basic 6.0 のサンプルコードをダウンロードしてテキストエディタを開くと、先頭の部分はこんな風になっています。

VERSION 5.00
Object = "{648A5603-2C6E-101B-82B6-000000000014}#1.1#0"; "MSCOMM32.OCX"
Begin VB.Form Form2
   Caption         =   "Terminal"
   ClientHeight    =   3450
   ClientLeft      =   60
   ClientTop       =   345
   ClientWidth     =   3600
   LinkTopic       =   "Form2"
   ScaleHeight     =   3450
   ScaleWidth      =   3600
   StartUpPosition =   3  'Windows の既定値
   Begin VB.PictureBox Pic_Info
      Height          =   255
      Left            =   3120
      ScaleHeight     =   195
      ScaleWidth      =   315
      TabIndex        =   9
      Top             =   3120
      Width           =   375
   End
   Begin VB.CommandButton IDB_DISCONNECT
      Caption         =   "Disconnect"
      Height          =   255
      Left            =   120
      TabIndex        =   8
      Top             =   2760
      Width           =   975
   End
...
End

見ると、*.rc と同じように「構造化」がされていますね。それもそのはずで、VC++ の *.rc は VB のフォームリソースを真似して(憧れて)作られているので当然似ていて当然なのです。
普段、Visual Basic 6.0 をデザイナで編集している場合は気が付かないのですが、これも大量のフォームを作るときには直接エディタで編集していたのです。

と、いうところで 30 分経ったのでおしまい。この先は、XLib や Motif, toolkit が続くわけですが、またの機会に。
あと、イベントに関しては、VB6、VC++, C# と発想がかなり違っているのがミソです。このあたりも別の機会に。

カテゴリー: 開発, C++ パーマリンク