BinaryViewer製作
Chapter9. ファイルデータの描画(1)
アプリケーション起動時に空ドキュメントを開かないようにする
ファイルデータ表示処理の前に、「MFCの森」のTipsで紹介している方法 を使って、
アプリケーション起動時に空のドキュメントを開かないようにしておきましょう。
BOOL CBinaryViewerApp::InitInstance()
{
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if(cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew){
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
}
if (!ProcessShellCommand(cmdInfo))
return FALSE;
}
|
コマンドライン引数の解析処理(ParseCommandLine関数)の結果、CCommandLineInfo::FileNew である場合に何もしないように書き換えてやります。
アドレス部の描画
材料が整ったので、データの表示処理に入ります。まずは、一番左のアドレス番号を表示するところです。
基本的には上の方から画面に表示できるだけ16ずつ値を追加して表示してやればよいのですが、実際のデータが少ない場合は
データが存在する行まで表示することにします。また、常にデータの先頭から表示するのではなく、画面スクロールを考慮すると
開始アドレスの計算も行う必要も出てきます。ただし、これはスクロール処理の中で対応していきます。
それからもうひとつ。先頭の行はガイダンス表示を行っていますので、表示開始位置は1行目(0行目から数えて)からとなります。
void CBinaryViewerView::OnDraw(CDC* pDC)
{
DWORD dwViewLine = 1;
DWORD dwBufferLine = 0;
DWORD dwShowMaxLine;
dwShowMaxLine = (clientRect.Height() / tm.tmHeight);
CHAR strOutput[256];
ZeroMemory(strOutput, sizeof(CHAR)*256);
while(dwViewLine <= dwShowMaxLine && (pDoc->GetLength()/16) >= dwBufferLine){
sprintf(strOutput, " %08X ", dwBufferLine*16);
pDC->SetTextColor(RGB(0xFF, 0xFF, 0));
pDC->TextOut(0, tm.tmHeight*dwViewLine, strOutput, (int)strlen(strOutput));
ZeroMemory(strOutput, sizeof(CHAR)*256);
dwViewLine++;
dwBufferLine++;
}
}
|
それほど難しいことは行っていません。行単位での繰り返しループの中で、ガイダンス部の描画で行ったように
アドレス番号を表示しています。
また、CBinaryViewerDocクラス に読み込んだデータのサイズを取得するための関数 GetLength() を追加しています。m_dwBufSize をそのまま返す関数です。(私はインライン関数としてヘッダファイル
BinaryViewerDoc.h に記述しました)
また、ここでは2つのカウンタ(dwViewLine, dwBufferLine)を用意しています。
前者はView画面内の現在の表示位置(行)を表し、後者は実際のバイナリデータの行番号を示しています。
これは、前述のとおりスクロール処理などにより、現在の画面が常にDocumentデータの先頭から表示するとは限らないためです。
バイナリ部の描画
バイナリ部の描画はViewとDocumentの連携により実現します。表示したい部分をViewがDocumentへ要求し、Documentはそれに応えて情報を提供します。
CBinaryViewerDocクラス に以下の関数を追加します。
これは、取得したい場所と長さを受け取り、同じく引数として受け取った格納用のバッファへバイナリデータをコピーしてあげる関数です。
DWORD CBinaryViewerDoc::GetBuffer(DWORD dwStart, DWORD dwLength, LPBYTE pOutBuf)
{
if(dwStart > m_dwBufSize || pOutBuf == NULL){
return 0;
}
DWORD dwRetSize;
DWORD dwEnd = dwStart + (dwLength-1);
if(dwEnd > (m_dwBufSize-1)){
dwRetSize = dwStart + dwLength - m_dwBufSize;
}else{
dwRetSize = dwLength;
}
memcpy(pOutBuf, m_pBuffer+dwStart, dwRetSize);
return dwRetSize;
}
|
View側では、上記の関数を使用してデータを行単位で取得し、適当な形に加工した
上で描画します。
CBinaryViewerDoc::GetBuffer関数 から取得したデータはバイナリ値(数値)です。
TextOut関数 で描画するためには、この数値を文字列へ変換する処理が必要となります。
void CBinaryViewerView::OnDraw(CDC* pDC)
{
DWORD dwViewLine = 1;
DWORD dwBufferLine = 0;
DWORD dwShowMaxLine;
dwShowMaxLine = (clientRect.Height() / tm.tmHeight);
CHAR strOutput[256];
ZeroMemory(strOutput, sizeof(CHAR)*256);
BYTE byBinBuf[16];
DWORD byBinCount;
LPBYTE pBinBufPos;
CHAR* pStrOutputPos;
while(dwViewLine <= dwShowMaxLine && (pDoc->GetLength()/16) >= dwBufferLine){
byBinCount = pDoc->GetBuffer(dwBufferLine*16, 16, byBinBuf);
if(byBinCount == 0){
break;
}
pStrOutputPos = strOutput;
pBinBufPos = byBinBuf;
*pStrOutputPos = 0x20;
pStrOutputPos++;
for(DWORD i = 0; i < byBinCount; i++){
sprintf(pStrOutputPos, "%02X ", *pBinBufPos);
pStrOutputPos += 3;
pBinBufPos++;
}
pDC->SetTextColor(RGB(0x00, 0x00, 0x00));
pDC->TextOut(tm.tmAveCharWidth*BV_LINENUMBER_NUM,
tm.tmHeight*dwViewLine, strOutput, (int)strlen(strOutput));
dwViewLine++;
dwBufferLine++;
}
}
|
ここまでの実行結果は以下のようになります。

上記は、アプリケーション起動後に BinaryViewerDoc.h を読み込んだ場合の処理結果です。サイズの小さいファイルを開いたり、
Viewのサイズを変更しても問題なく表示できていると思います。
これで残すは キャラクタ部 のみとなりました。
キャラクタ部はバイナリデータを文字として表したものを表示するのですが、日本語などのマルチバイト文字の処理という
やっかいな問題が存在します。テキストエディタでは各行の先頭から文章・文字が始まるためそれほど苦労はないのですが、バイナリビューワでは
強引に16バイトを1行として分断しているため、行の先頭が2バイト文字の後半を指している 場合があります。その辺りも含めて次回対応します。
トップへ
Programトップへ
←前へ
→次へ