ソフトウェア実現 課題 ~手描きチャットプログラム~
シラバスへ TOPへ

1.レポート課題

授業で配布したチャットプログラムをもとに[手書き文字]機能への拡張をします。 手書き文字機能とは、

  1. ウィンドウ上の任意の位置にマウスを移動し、
  2. マウスの左ボタンを押すと[仮想ペン]が[仮想キャンバス]のうえに下りる。
  3. 左ボタンを押しながらマウスを動かすと、そのまま[仮想キャンバス]上にペンを滑らせる、つまり手書きの絵や文字が書ける。

という機能です。 手書きチャットとはこの手書き文字機能をネットワークの上に乗せたものです。 すなわちネットワーク上の複数(課題では2名)の利用者が同じキャンバスを共有しあい、お互い好きなように手書き文字を書きあえるという仮想の伝言板です(下図)。

手描きチャットプログラムの実行例
そこで、このような機能の詳細すなわち仕様と、これを実装するための通信規約(アプリケーション層プロトコル)について説明します。 まず、仕様について述べます。

2.手描きチャットプログラムの機能

  1. このプログラムを起動すると画面上に[接続]、[接続待ち]、[切断要請]および[切断]の4つのボタンと、ホスト名を入力するエディットボックス、ならびに仮想伝言板として横800ドット、縦600ドットのキャンバスを表示する(上図のキャンバスは小さめになっています, レポート用の実装でも800×600が辛かったら小さめにしてもOKです. そのときにはレポートの外部仕様のところで変更したことを明記してください.)。
  2. 起動時には[接続]ボタンと[接続待ち]ボタンのみがアクティブ(入力可能な状態)になっており、他の2つのボタンは非アクティブ(入力不可能な状態)になっている。 ここで、サーバとして稼動する場合は[接続待ち]ボタンを、クライアントとして稼動する場合はエディットボックスに相手側(つまりサーバ側)のホスト名を入力して[接続]ボタンを押す。
  3. サーバ側、クライアント側のそれぞれで上記2.の操作が終了するとクライアントからサーバに接続され、両サイドでキャンバスがアクティブになる。
  4. サーバ側、クライアント側のどちらからでも、マウスドラッグにより仮想キャンバス上で仮想ペンによるペン書きをすることができる。
  5. 自分のペンは黒(太さ3)で、相手のペンは赤(太さ3)で互いのキャンバス上に手書きの文字筆記が実時間表示される。
  6. 終了する場合は、
    1. 「パニック」終了(何らかの突発的なできごとが起きて、強制終了すること)の場合は[切断]ボタンを押す → これによりソケット通信路が切断される。
    2. 正常終了したい場合は、[切断要請]ボタンを押す → これにより相手に切断の予告通知をする → 予告通知を貰った側から切断してもらう。
  7. ソケット通信路を互いに切断した後、プログラムを終了する。

以上が機能仕様です。 次にアプリケーションプロトコルについて述べます。

3.手書きチャットプログラムのアプリケーションプロトコル

アプリケーション層のプロトコルについて説明します。まず、トランスポート層のプロトコルとしてTCP/IP:ストリームソケットを用います。 利用するポート番号は十進の10000とします。 アプリケーション層のメッセージは以下に述べる2種類のみから構成されます。

マウス移動通知コマンド:FXY
自分のマウスダウン時、及びドラッグ時に絶えず相手に送信されるコマンドで、ペンフラグF1バイト)、X座(3バイト)、Y座標(3バイト)の7バイトから構成される。 ここでペンダウンフラグが以下を意味します。
ペンフラグ
ペンフラグ:0
ペンを下ろし始めたことを意味する(マウスボタン押下開始)
ペンフラグ:1
ペンが下りている状態であることを意味する(マウスボタン押下中)
X座標、Y座標
3桁の数字を半角文字3個で表す。
例)[1022345]
ペンフラグが1、X座標が22(百の位は0になる事に注意)、Y座標が345となる。
切断要請コマンド:REJECT
切断要請をする側から送信される。これを受信した側では、ユーザに対し速やかに切断すべき旨を通知し、[切断]ボタンを押すことを促す。

4.手書き文字チャットの基本設計例(プログラム設計のヒント)

描画方法

マウスを使って自由線を描く時、まずマウスのボタンを押した時に座標を取得します。 次にボタンを押したままマウスを動かした時に座標を取得します。 (その検出方法はあとで述べます)そして、これらの座標間を線でつなぎます。 ここで、これらの座標データは保持しておく必要があります。 なぜなら、再描画するために必要となるからです。 そこで、これらの座標を格納しておくテーブルの例を表1に示します。 今回の、サンプルプログラムでは次のようなテーブルを自分用と相手用の2つを定義しています。

表1:座標格納テーブルの例

点番号 1 2 3 4 5 6 ・・・
ペンダウンフラグ 0 1 1 1 0 1 ・・・
X座標 109 120 135 140 350 298 ・・・
Y座標 9 25 50 120 238 240 ・・・

ペンダウンフラグが1の時は、マウスの左ボタンを押して動かすことを意味しており、1つ前の座標とその座標を線で結ぶというフラグです。 表1で説明すると、点番号2は1つ前の点番号1と線で結びなさいということになります。 また、ペンダウンフラグ0は線の始点であることを表しています。 つまり、表1の点番号1~4までが1つの線分で点番号5~が別の線分である事を示しています。

マウスボタンの状態検出方法

今回必要とするマウスボタンの状態は、マウスボタンを押した時とマウスボタンを押したまま動かした時の2つです。 このうち前者のメッセージは授業中で参照したホームページに掲載されています。 後者についてあまり詳しく説明されていないので補足します。

WM_MOUSEMOVEメッセージを検出した後に“ボタンが押されているかどうか”を検出しなくてはなりません。 ウィンドウ関数の引数(WPARAM型)には、押されたキーのASCIIコードが入ってきます。 この引数がMK_LBUTTONであるかどうかでマウスの左ボタンが押されているか調べる事ができます。 表2にWPARAM型引数の種類を示します。

表2:MOUSEMOVE時のWPARAM型引数の種類

引数(WPARAM型) 状態
MK_CONTROL Ctrlキーが押されている
MK_LBUTTON マウスの左ボタンが押されている
MK_RBUTTON マウスの右ボタンが押されている
MK_SHIFT Shiftキーが押されている

文字列の送受信について

実際に送受信されるものは簡略化のため文字列で行います。 そのため、取得した整数の座標を文字列に変換しなければなりません。 その時、注意しなければならないのは整数→文字列の変換です。 チャットプログラムのプロトコルでは文字列でペンダウンフラグ1バイト、X座標3バイト、Y座標3バイトです。 これを守らないととんでもない座標が相手に送られてします。 たとえ座標が2桁であっても1桁であっても3バイトで送らなければなりません。

例:[0002034] ―――― ペンダウンフラグ0、X座標2、Y座標34

RECT構造体について

意図的に再描画命令を発行する方法にInvalidateRect()がある事は「再描画」のところで説明しました。 この命令の第2引数をNULLにした場合、画面全体に再描画が行われます。 この手書きチャットプログラムにおいて、この引数をNULLにしてしまうと再描画命令が頻繁に発行されるため、画面のちらつきが激しくなってしまいます。 これを抑えるために第2引数を長方形の領域(クリッピング領域)を指定するRECT構造体へのポインタにします。 つまり、このクリッピング領域を指定する事で実際に再描画が行われる範囲を限定する事ができます。 この領域を指定するRECT構造体には以下のような4つのメンバがあります。

left
長方形の左側のX座標
top
長方形の上側のY座標
right
長方形の右側のX座標
bottom
長方形の下側のY座標

5.レポートの提出について

manabaで提出する。


シラバスへ TOPへ