前回はRCファイルの記述を行ったが、実はあれだけだとまだプログラムではロードできない。たとえば"Transfer"→"Start"を選択するとIDM_XFER_STARTというMessageが飛ぶことになるわけだが、まだIDM_XFER_STARTという値そのものを定義していないから、このままビルドするとUndefined Symbolということでエラーになる。

この値の定義を行っているのは、resource.hというinclude fileである。Visual Studio.NET 2010 Professionalだとこのinclude fileも勝手に作ってくれるが、Expressではこれもユーザーが作らなければならない。

といっても、こちらはほかと重ならない様に適当に値を割り振るだけである。List1に、実際に今回使ったresource.hの関係部分を示すが、IDC_MYICON~IDR_MAINFRAMEまでの値は、一番最初のWizardを掛けた時に自動的に生成される分、続くID_SETTINGS_PORT~IDM_PORT_COM7までが、後から(Resource Editorを使って)生成した分である。この結果、たとえば最初に設定したけど後で「要らない」と削除した項目(32778が振られているID_PORT_COM)も残っていたりするのはご愛嬌である。手作業で入力の場合は、こういう無駄なIDは削除してかまわない。自分でカスタマイズする場合に備えて説明すれば、IDの数字は16bitで、前半(0~32768)+2つ(32769/32770)はリザーブとされているので、32771から順に振ってゆけばよい(ここは自分の好みでカスタマイズできるので、たとえば2番飛ばしとかでも可能)。

さて、今回は全ソースを用意した(80LED.zip)。流石にソースを全部掲載すると長すぎる(80LED.cppは545行)ので、こちらをダウンロードして、適当なエディタなどで開きながら記事を読んでいただければと思う。同時に80LED.rcやresource.h、(全く変更はしていないが)80LED.hも添付したので、前回の手順で作成したプロジェクトのファイルと置き換えてビルドすれば、プログラムも完成する筈である。またZIPファイルの中には80LED.exeと、ランタイムのmsvcr100.dllも添付している。80LED.exeは、Arduinoを接続しなくても一応単体で動作して、CPUの負荷率をリアルタイム表示してくれるから、理解の参考になればということで添付した。msvcr100.dllはVisual Studio.NET 2010をインストールしている環境では不要だが、もしまだインストールしていない場合は、80LED.exeと同じディレクトリにおいてほしい。

さて、では実際のプログラムである。includeに関しては、379回で説明したとおりいくつか必要なものを追加する事になる。#defineに関しても、いくつか追加しているのが判る筈だ。全く新しいのはTIMER_IDで、これは前回説明したとおり定期的にCPU負荷を取得するための割り込みを掛けるために使うタイマー用のもの。FONTHEIGHTとかWINDOWWIDTH/WINDOWHEIGHTは画面サイズやフォントの大きさの指定を行っているものだ。

続く_tWinMain()とMyRegisterClass()は一切無変更であるが、InitInstance()だけはちょっと手を入れている。このInitInstance()の中でCreateWindow()を呼び出して、80LEDのウィンドウの実体を生成しているが、ここのオプションをいじって、最大化ボタンを無効にし、かつウィンドウのリサイズを不可能にしている。また、先に#defineで定義した画面の縦と横の幅を指定している。画面一杯にこれを表示しても仕方ないし、ということでの対処である。

次のSetTitle()とOpenRS232C()は、今回新規に作成した関数である。前者は? というと、ウィンドウのタイトルバーに現在の設定を表示するというものである。プログラムを立ち上げてもらうと判るが、タイトルバーに通信ポートと通信速度、それとCPU負荷取得のインターバルが表示されるようになっている。これは設定を変更するたびに呼び出される関数で、やることは簡単(wsprintf()を呼んで、プログラムタイトル/通信ポート/通信速度/更新インターバルを順に並べた文字列をまず作り、ついでそれをSetWindwoText()で反映するだけ)なのだが、これをいちいち全部のcallbackに記述するのも馬鹿なのでまとめたものだ。OpenRS232C()の方は、というとこれはもう名前のままで、COMポートをオープンし、かつパラメータを設定するだけである。なんでこれを別関数としたかというと、たとえば一時的に転送を中止し、再度復活させるなんてケースでは、一度COMポートをCloseする仕組みにしているので、

  • プログラムの起動時にCOMポートをOpen
  • プログラム実行中に一度COMポートをCloseし、再度Open

の2つのケースが考えられる。だからといって、二箇所で同じコードを書くのも馬鹿なので、ひとつにまとめたという次第だ。COMポートのCloseは、CloseHandle()一発で済むし、エラー処理の必要もない(エラー処理をしようにも、せいぜいがプログラムを終了させる以外の案がない)から、こちらは特にまとめる必要もないと判断した。

(続く)

List 1:

#define IDC_MYICON                      2
#define IDD_MY80LED_DIALOG              102
#define IDS_APP_TITLE                   103
#define IDD_ABOUTBOX                    103
#define IDM_ABOUT                       104
#define IDM_EXIT                        105
#define IDI_MY80LED                     107
#define IDI_SMALL                       108
#define IDC_MY80LED                     109
#define IDR_MAINFRAME                   128
#define ID_SETTINGS_PORT                32771
#define ID_PORT_COM1                    32772
#define ID_PORT_COM2                    32773
#define ID_PORT_COM3                    32774
#define ID_PORT_COM4                    32775
#define ID_PORT_COM5                    32776
#define ID_PORT_COM6                    32777
#define ID_PORT_COM                     32778
#define ID_PORT_COM8                    32779
#define IDM_PORT_COM1                   32780
#define IDM_PORT_COM2                   32781
#define IDM_PORT_COM3                   32782
#define IDM_PORT_COM4                   32783
#define IDM_PORT_COM5                   32784
#define IDM_PORT_COM6                   32785
#define IDM_PORT_COM                    32786
#define IDM_PORT_COM8                   32787
#define ID_SETTINGS_SPEED               32788
#define IDM_SPEED_300                   32789
#define ID_SPEED_600BPS                 32790
#define ID_SPEED_1200BPS                32791
#define ID_SPEED_2400BPS                32792
#define ID_SPEED_4800BPS                32793
#define ID_SPEED_9600BPS                32794
#define ID_SPEED_19200BPS               32795
#define ID_SPEED_38400BPS               32796
#define IDM_SPEED_600                   32797
#define IDM_SPEED_1200                  32798
#define IDM_SPEED_2400                  32799
#define IDM_SPEED_4800                  32800
#define IDM_SPEED_9600                  32801
#define IDM_SPEED_19200                 32802
#define IDM_SPEED_38400                 32803
#define ID_SETTINGS_REFRESH             32804
#define ID_REFRESH_0                    32805
#define ID_REFRESH_1                    32806
#define ID_REFRESH_2                    32807
#define ID_REFRESH_1SEC                 32808
#define IDM_Refresh_100                 32809
#define IDM_Refresh_200                 32810
#define IDM_Refresh_500                 32811
#define IDM_Refresh_1000                32812
#define ID_TRANSFER_START               32813
#define ID_TRANSFER_STOP                32814
#define IDM_XFER_START                  32815
#define IDM_XFER_STOP                   32816
#define IDM_PORT_COM7                   32817
#define IDC_STATIC                      -1