つづき。
BOOL SetCommState( HANDLE hFile, //ポートのハンドル LPDCB lpDCB //DCB構造体 );
前回の CreateFile でポートは開くことができた。これであとは読み書きするだけだ。と思ったら大間違いである。シリアルポートで通信を行うということは、通信相手とのしかるべき取り決めに従ってデータを送りあわねばならない。つまり、通信速度やフロー制御などの設定を行わなければならない。これらは、 SetCommState API を用いて設定する。 SetCommState 関数のプロトタイプは code.2 のようになっている。この第二引数の DCB 構造体に様々なパラメータを設定する。DCB とは device-control block のことである。細かいパラメータは後述する。
BOOL GetCommState( HANDLE hFile, //ポートのハンドル LPDCB lpDCB //DCB構造体を受け取るアドレス );
逆に現在のポートの設定を得るには、 GetCommState 関数を使う。code.3 がプロトタイプである。SetCommState 及び GetCommState は、成功すればゼロ以外を返す。ゼロが返ったらエラーである。詳細なエラー情報は、 GetLastError を用いて取得できる。最初にシリアルポートを開いた後に設定をする場合は、まず GetCommState で現在の状態を取得した後、取得した DCB 構造体を必要な部分のみ変更した後 SetCommState を用いるのがよい。
さて、問題の DCB 構造体であるが、宣言は code.4 のようになっている。
typedef struct _DCB { // dcb
DWORD DCBlength; // sizeof(DCB)
DWORD BaudRate; // current baud rate
DWORD fBinary: 1; // binary mode, no EOF check
DWORD fParity: 1; // enable parity checking
DWORD fOutxCtsFlow:1; // CTS output flow control
DWORD fOutxDsrFlow:1; // DSR output flow control
DWORD fDtrControl:2; // DTR flow control type
DWORD fDsrSensitivity:1; // DSR sensitivity
DWORD fTXContinueOnXoff:1; // XOFF continues Tx
DWORD fOutX: 1; // XON/XOFF out flow control
DWORD fInX: 1; // XON/XOFF in flow control
DWORD fErrorChar: 1; // enable error replacement
DWORD fNull: 1; // enable null stripping
DWORD fRtsControl:2; // RTS flow control
DWORD fAbortOnError:1; // abort reads/writes on error
DWORD fDummy2:17; // reserved
WORD wReserved; // not currently used
WORD XonLim; // transmit XON threshold
WORD XoffLim; // transmit XOFF threshold
BYTE ByteSize; // number of bits/byte, 4-8
BYTE Parity; // 0-4=no,odd,even,mark,space
BYTE StopBits; // 0,1,2 = 1, 1.5, 2
char XonChar; // Tx and Rx XON character
char XoffChar; // Tx and Rx XOFF character
char ErrorChar; // error replacement character
char EofChar; // end of input character
char EvtChar; // received event character
WORD wReserved1; // reserved; do not use
} DCB;
MSDN からのコピペなので英語だが、だいたい意味は分かるであろう。設定すべき重要なパラメータは、通信速度(ボーレート)、ストップビット、フロー制御、データビットである。 BaudRate には通信速度を設定する。今回の仕様ではボーレートは9600となっていたので、 BaudRate は CBR_9600 とする。 Flow とついている値がフロー制御の設定である。今回は、このようなフロー制御は用いなかったので、すべて FALSE とする。ストップビットは1ビットとするので、 StopBits は1とする。データビットサイズは8bitとするので、 ByteSize は8とする。このように細かく設定して、データを送受信する相手との設定を合わせなければならない。ハードウェアとの通信を行うアプリケーションを作る場合は、まず通信の仕様をよく読むことが大事である。この設定さえしっかりできれば、ほぼ完成したも同然である。
参考までに今回作成したシリアルポート送受信用クラスを掲載しよう。GComm.lzh
掲載したソース中には、いままでに説明しなかった部分がかなりある。ポートのオープン及び設定はここまでで説明したので、次回はイベント駆動 I/O について解説したい。
先日、CSSのサポートは IE が最も進んでいると書いたが、よく考えたら Mozilla の方が CSS をちゃんと解釈する。Netscape6 は Mozilla 0.6 がベースなのでどうかと思うが、最新の Mozilla 0.9.2 だったら CSS1 に関してはかなり精度は高いのではないだろうか。たとえば、IE5 にはマージンのパーセント指定やauto指定を正しく解釈しない。このページの背景が黒い部分は、本来ならば左と右に等量のグレイの部分があり、真ん中に表示されるはずである。Mozillaはこれを正しく解釈する。Netscape6 を導入した方は、あれが重すぎて使い物にならない事は知っていると思うが、 Mozilla はもっと軽いので導入してみてはいかがだろうか。しかし、まだ正式リリースではないので、自己責任と言うことになるので注意して貰いたい。
はっきり言ってやる気が無いのである。やる気が無い事が最も大きな問題である事は、火を見るより明らかである。以前にこの雑記を書いてから既に九ヶ月。これだけ時間が経てば、ここを見ている方もいないだろう。好き勝手なことを書いても罰は当たるまい。また気が向いたら何か書いていくことにしよう。
休んでいた間、何をしていたかと思い返してみると、結構いろいろなことがあったような気がする。研究やら就職やらでドタバタしていたが、よくよく考えるとあまり細かいことは覚えていない。いつの間にか住んでいるところも変わっているが、いつ引っ越したのだろうか。世の中不思議なことが多いものである。
ごく最近の事なら、少しは覚えているかもしれない。そういえば、 XHTML の本を買ったのだ。ソースを見れば分かると思うが、このページも XHTML1.0 Strict と CSS1 で書かれている。そんな規格に真正直に従ったところで、どうせ意図した通りには表示されないのであろうが、標準に従っておくことは悪いことではない。世のWebページのソースを見ると、殆どのページがHTMLの文法を守っていない。しかし、そのような文法に従わないページの表示は、いつまでもブラウザにサポートされるとは限らないのではないだろうか。データの保存と保守を考えた場合、標準に従っておくのが賢いやり方であると考える。
大義名分を振りかざしてはみたが、このページが本当に標準に準拠しているかといえば怪しいものである。 IE でしか表示の確認はしていない。所詮は自己満足だ。 IE でしか確認しないのは、 CSS のサポートが最も進んでいるのが IE だからであって、別に Netscape が嫌いなわけではない。ちなみに Netscape Navigator4.x で表示すると、上の方は全く何が書いてあるのか分からない状態になる。私は NN4 は使わないので気にしないことにしよう。
XHMTL については多少勉強したので、このページを見ている方で XHTML や CSS について知りたいという方がいたら、答えられる範囲で質問にはお答えするつもりである。XHTML はともかく、 CSS を使えばページの見た目をかなり思い通りに制御できる。もしあなたが HTML によるページの表現能力に限界を感じているならば、導入を検討すべきである。だが、巷に出回っている書籍はいい加減な事を書いてある事が多い。もし書籍を購入するのであれば、慎重に吟味して選択して欲しい。書籍に頼るよりもWeb上の情報を見た方が確実な場合もある。言うまでもなく CSS は W3C に仕様が公開されている。これを見るのが最も確実だ。
他に最近やっていた事といえば、プログラミングである。あるシステムの試作品を作っていたのだが、その製品では、ハードウェアと PC との間は RS-232C によるシリアル通信を用いる。いままで面倒なことは極力避けてきたので、ハードとの通信などという事はやったことがなかった。しかし今回は仕様が確定している以上避けようがない。仕方なく Web や書籍を漁ってなんとか納期には間に合った。以下はシリアル通信の覚え書きである。
HANDLE hComm; hComm = ::CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
Windows の API には、別にシリアルポートを開く専用の関数があるわけではない。通常のファイル操作と同様の方法を用いればよいのである。code1 は、 COM1 ポートを開いたところである。このように、 CreateFile API を用いてポートをオープンする。 CreateFile の一番目の引数は、オープンするポートの名前をそのまま指定する。二番目の引数は、アクセスモードの指定である。三番目は共有モードの指定だ。ここは必ず 0 (共有不可)とする。三番目はファイルが存在しない場合の扱いを指定する。COMポートの場合は必ず OPEN_EXISTING とする。四番目はファイルの属性である。これは FILE_ATTRIBUTE_NORMAL (属性なし)とすればよい。非同期 I/O を用いる場合は、ここに FILE_FLAG_OVERLAPPED を指定する必要がある。最後の引数は、必ず NULL とする。
あとは細かい設定をした後、ファイルを扱うのと同様に、 hCommに対して ReadFile 、 WriteFile API を使って読み書きが出来る。問題は、 どうやってその細かい設定を行うか、ということだ。それについては次回紹介したい。
先ほどと違い、こちらは趣味のプログラム。
タスクトレイのアイコンは普通マウスでしか操作できない。これはキーボード派にとっては致命的である。なんとかキーボードから操作する事はできないものだろうか。
実は別に自分で作らなくても、キーボードでタスクトレイを操作するツールはフリーで公開されている。Googleかなにかで、「タスクトレイ キーボード」で検索すれば一発で出てくる。これは素晴らしいツールであるのだが、やはり昔から気になっている以上、なんとか自分で作りたい。というわけで、いろいろと試行錯誤をしているところである。
とりあえず何とかなりそうな気がしたのでテストプログラムを作成してみた。MFC を使っているため MFC42 の共有ライブラリが無いところでは実行できないので、落とす場合は注意してもらいたい。 Cap ボタンはタスクトレイの絵をキャプチャする。 LBTN ボタンは、トレイにある一番左のアイコンをマウスで左クリックしたときの動作を行う。同様に、 RBTN ボタンは右クリックで、 DBL ボタンはダブルクリックである。 Focus ボタンは、トレイにフォーカスを移動する。これは、Windows2000以上でないと動作しない。知っている方もいると思うがWindwos2000では、タスクトレイにフォーカスを移動することができる。これをボタン一発で行うというだけである。Windows XPでも同様にタスクトレイにはフォーカスを移動できるようである。
ともかくテストプログラムの機能は以上である。このテストプログラムは、一番左のアイコンしか操作できないが、メッセージを投げるところを少し変えれば、他のアイコンも操作できると思われる。今のところ成功はしていないが。
まひるはいいヤツである。偏見は良くない。