DIRECTX1 DirectPlay 6 文字列の送信&受信(チャット)

文字列の送信もデータの通信と同じですが、長さが違うところが問題です。送信するたびに長さを調べてその長さ分、送信しなければいけません。受け取る方もその名がさぶんのデータを読み込んでそれを文字列としてキャストして受け取ることになります。

実質的にはチャットになるので、送信する文章を入力出来るようにしましょう。フォームにエディットボックスを貼り付けてその下にテキスト送信用のボタンをつけてください。受信した文章は、リストボックスに表示するようにします。

送信ボタンのコードは以下の通り。
 

//----- Editボックス内のテキストを送信する
void CDxptestView::OnButton5()
{
 // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
 
 SendDataString msggen;
 
 msggen.dwType = -1; // システムメッセージではない
 msggen.myType = 1; // 自分のアプリの中で使うフラグ、位置データか、シュートデータ、など
 
 m_Edit1.GetWindowText((char*)&msggen.str, 1024);
 
 HRESULT ret = dxp.DxSendString(&msggen, sizeof(msggen));
 if(ret == DPERR_ALREADYINITIALIZED){
  AfxMessageBox("?????");
 }
}
 

CDxPlayの文字列送信用のメンバ関数は以下の通り。
 

//==================================================
// データ送信(データバイトを送る)
HRESULT CDxPlay::DxSendString(SendDataString* mdb, DWORD size)
{
 
 HRESULT ret = lpDP4A->Send( playerDPID, // 送信者ID
 DPID_ALLPLAYERS, // 受信者IDあるいはフラグ
 //0, // DPSEND_ 型の値。
 //メッセージの送信方法を示します。
 //このパラメータに 0 を指定すると、
 //メッセージは保証されず、
 //標準的な優先順位で送信されます。
 DPSEND_GUARANTEED, // メッセージが保証されるフラグ
 mdb,
 size);
 
 return DP_OK;
}
 

CDxPLay.cppのグローバルエリアの変数に
 

 //----- チャット用データ
 CString chatData;
 int DrawFlag = 0;
 

を追加します。

受信スレッドのテキスト受信部分は下の赤い部分です。
 

//===== ユーザメッセージの処理(idFrom == -1)

SendDataByte * sd;
sd = (SendDataByte*)lpvMsgBuffer;
switch(sd->myType)
{
case 0:{ // 位置データ
 sdb.mPosiX = sd->mPosiX; // データを取り出す
 sdb.mPosiY = sd->mPosiY; // データを取り出す
 sdb.mPosiH = sd->mPosiH; // データを取り出す
 sdb.mDirect = sd->mDirect; // データを取り出す
 break;
}
case 1:{ // ストリングデータ
 SendDataString *sds;
 sds = (SendDataString*)lpvMsgBuffer;
 chatData = sds->str;
 DrawFlag = 1;
 break;

}
 
}
 

ここではグローバルメモリに文字列データをコピーしています。コピーした文字列データは、OnDrawで、リストボックスに追加しますが、そのままではOnDrawにくるたびに追加されるので、一度だけ追加するためにDrawFlagを追加しています。これが1のときだけリストボックスに追加します。

リストボックスに追加する部分はOnDrawの以下の部分です。
 

void CDxptestView::OnDraw(CDC* pDC)
{
 // TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください

 // char * is;
 // _itoa(dxp.GetReceiveData()->mPosiX, is, 10); // 削除

 
 char is[20];
 itoa(dxp.GetReceiveData()->mPosiX, is, 10); // 修正

 
 pDC->TextOut(0,0,is);
 
 if(dxp.getDrawflag() == 1){
  m_List1.AddString(dxp.GetReceiveString());
  dxp.setDrawflag(0);
 }


}
 

上で使用している  GetReceiveString() 関数はCDxPlay.cppの中にあるグローバル変数に直接アクセスできないので作った関数です。ただ、文字列を返す関数です。あと、dxp.setDrawflag(0)はフラグをリセットする関数です。それぞれ以下の通り。
 

char * CDxPlay::GetReceiveString()
{
return chatData.GetBuffer(1025);//ReceiveData;
}
 
int CDxPlay::getDrawflag()
{
 return DrawFlag;
}
 
int CDxPlay::setDrawflag(int flag)
{
 DrawFlag = flag;
 return 0;
}
 

ビルドして実行しましょう。テキストボックスにテキストを入力して送信ボタンを押してください。相手側のリストボックスに入力した文字列が表示されればOKです。

簡単なチャットプログラムですが、これを改良すれば実用に耐えるチャットプログラムが出来るでしょう。

次は、実際に使うためのCDxPlayクラスの作成です。完成したCDxPlayクラスを改良して使いやすいようにします。

追加  2000-3-6

現在の段階でリリースバージョンを実行すると、受信データの初期値に変な数字が出てしまうのでこれを初期化することにしました。CDxPLayクラスのコンストラクタに以下のコードを追加してください。
 

sdb.dwType = -1;
sdb.mDirect= 0;
sdb.mPosiH = 0;
sdb.mPosiX = 0;
sdb.mPosiY = 0;
sdb.myType = 0;