Binary Editor を作成する

Text Editor で表示できない Binary 形式のファイルを編集する Binary Editor を作成します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. ハンドルと Global Area の定義です。
    *App は BEdit Object Class の定義で、基本的な操作は Object Class で行います。
        #include    "BEdit.h"
        #include    "resource.h"
    
        // Defines, constants, and global variables
        BEdit       *App = NULL;        //Binary Edit Class
        HINSTANCE   g_hInst;            //Instance Handle
        HWND        g_hListL;           //List Handle
        HWND        g_hListR;           //List Handle
        HWND        g_hEditL;           //Edit Handle
        HWND        g_hEditR;           //Edit Handle
        HWND        g_hButtomL1,g_hButtomL2,g_hButtomL3,g_hButtomL4,g_hButtomL5;
        HWND        g_hButtomR1,g_hButtomR2,g_hButtomR3,g_hButtomR4,g_hButtomR5;
        
  2. WinMain() と InitAll() はフレームワークの作成と同じです。
    詳細は フレームワークの作成 を参照して下さい。
  3. CALLBACK 関数です。
    WM_CREATE: から呼び出す InitAll() 関数で、ウインドウの初期化と設定を行います。
    ボタンがクリックされたときや、メニュー選択されたときは WM_COMMAND: にメッセージがポストされます。
    COMMAND は ListBox に合わせて、左右が対称に処理されています。
    基本的な操作は Object Class で行っています。
        LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
        {   HDC     hDC;
            HWND    hCtrl;
    
            switch (msg)
            {   case WM_CREATE:
                    InitAll(hWnd);
                    break;
                case WM_COMMAND:
                    switch(LOWORD(wp))
                    {   case ID_OPENL:          //ファイルのオープン
                            App->OpenReadDataL();
                            App->SetBoxL();
                            break;
                        case ID_OPENR:
                            App->OpenReadDataR();
                            App->SetBoxR();
                            break;
                        case ID_NEXTL:          //次のブロック
                            App->SetNextL();
                            break;
                        case ID_NEXTR:
                            App->SetNextR();
                            break;
                        case ID_BACKL:          //前のブロック
                            App->SetBackL();
                            break;
                        case ID_BACKR:
                            App->SetBackR();
                            break;
                        case ID_EDITL:          //ITEM の編集
                            App->SelectL();
                            break;
                        case ID_EDITR:
                            App->SelectR();
                            break;
                        case ID_UPDATEL:        //編集バファの更新
                            App->UpdateL();
                            break;
                        case ID_UPDATER:
                            App->UpdateR();
                            break;
                        case ID_PUTL:           //File の上書き
                            App->PutDataL();
                            break;
                        case ID_PUTR:
                            App->PutDataR();
                            break;
                        case IDCLOSE:
                            PostMessage(hWnd,WM_CLOSE,0,0);
                            return TRUE;
                        case ID_VER:
                            MessageBox(NULL,"Binary Edit Ver 1.0  By Maeda Minoru","Binary Editor",MB_OK);
                            return TRUE;
                    }
                    break;
                case WM_CTLCOLOREDIT:
                {   hDC = (HDC)wp;
                    hCtrl = (HWND)lp;
                    if (hCtrl==g_hEditL || hCtrl==g_hEditR)
                    {   SetBkMode(hDC, OPAQUE);             // 背景を塗りつぶし
                        SetTextColor(hDC, RGB(255,0,0));    // テキストの色
                        SetBkColor(hDC,RGB(150,170,192));   // テキストが書かれている部分のテキストの背景の色
                        return (LRESULT)App->hBrush_BkColor;// テキストが書かれていない部分の背景の色
                    }
                    break;
                }
                case WM_DESTROY:
                    SAFE_DELETE(App);
                    PostQuitMessage(0);
                    break;
                default:
                    return (DefWindowProc(hWnd,msg,wp,lp));
            }
            return 0L;
        }
        
  4. Binary Editor の操作概要です。

BEdit Object Class Header

FileL,FileR が左右に表示されるファイルの名前です。
PosL,PosR はファイルの先頭からのオフセットです。
BufL,BufR は入出力のバッファ領域で、LenL,LenR がそのバイト長です。
SelNoL,SelNoR が編集中の ListBox の行で、UpL,UpR が更新フラグです。
//★ Binary Editor Object Class Header  Ver 1.0  前田 稔

class BEdit
{ //★非公開部分
  protected:
    HWND        ListL;              //List Handle
    HWND        ListR;              //List Handle
    HWND        EditL;              //Edit Handle
    HWND        EditR;              //Edit Handle

    char        szDir[MAX_PATH];
    int         PosL;               //Rocord Pointer Left
    int         PosR;               //Rocord Pointer Right
    BYTE        BufL[520];          //Binary Data Buffer Left
    BYTE        BufR[520];          //Binary Data Buffer Right
    int         LenL;               //BufL Length
    int         LenR;               //BufR Length
    int         SelNoL;             //ITEM Select NumberL
    int         SelNoR;             //ITEM Select NumberR
    int         UpL;                //Buf[] 更新フラグ
    int         UpR;                //Buf[] 更新フラグ
    char        work[80];           //ListBox Edit Work
    char        wk[80];             //ListBox ITEM Work
    char        b16[16];            //Hex 2 Bin Work
    int         blen;               //Hex 2 Bin Leng
    HFONT       hFont;              //ListBox Font
    int         rc;

    int         Hex2Bin(char *hex, char buf[16]);
    int         SetBox(HWND hList, BYTE buf[], int len, int loc);
    HFONT       SetMyFont(LPCTSTR face,int h,int angle);

  //★公開部分
  public:
    char        FileL[MAX_PATH];    //File Name Left
    char        FileR[MAX_PATH];    //File Name Right
    HBRUSH      hBrush_BkColor;     //背景の色

    BEdit(HWND, HWND, HWND, HWND);  //Constructor
    ~BEdit();                       //Destructor
    void        DMsg(char *chr, int n);
    DWORD       ReadData(LPSTR fname, DWORD pos, void *buf, DWORD len);
    DWORD       WriteData(LPSTR fname, DWORD pos, void *buf, DWORD len);
    HRESULT     OpenFileName(LPSTR szDir, char *file);

    HRESULT     OpenReadDataL();
    HRESULT     OpenReadDataR();
    DWORD       ReadDataL(DWORD pos);
    DWORD       ReadDataR(DWORD pos);
    DWORD       PutDataL();
    DWORD       PutDataR();
    int         SetBoxL();
    int         SetBoxR();
    HRESULT     SetNextL();
    HRESULT     SetBackL();
    HRESULT     SetNextR();
    HRESULT     SetBackR();
    HRESULT     SelectL();
    HRESULT     SelectR();
    HRESULT     UpdateL();
    HRESULT     UpdateR();
};

BEdit Object Class

  1. BEdit Object Class の Constructor です。
        //★ Constructor
        BEdit::BEdit(HWND listl, HWND listr, HWND editl, HWND editr)
        {
            ListL= listl;
            ListR= listr;
            EditL= editl;
            EditR= editr;
            PosL=PosR=LenL=LenR= 0;
            UpL=UpR= 0;
    
            hBrush_BkColor= CreateSolidBrush(RGB(150,170,192));
            hFont= SetMyFont((LPCTSTR)"MS ゴシック",12,0);
            SendMessage(ListL,WM_SETFONT,(WPARAM)hFont,MAKELPARAM(TRUE,0));
            SendMessage(ListR,WM_SETFONT,(WPARAM)hFont,MAKELPARAM(TRUE,0));
            GetPrivateProfileString("BinEdit","DIR","c:\\",szDir,MAX_PATH,"Maeda.ini");
        }
        
  2. BEdit Object Class の Destructor です。
        //★ Destructor
        BEdit::~BEdit()
        {
            DeleteObject(hBrush_BkColor);
            DeleteObject(hFont);
            WritePrivateProfileString("BinEdit","DIR",FileL,"Maeda.ini");
        }
        
  3. fname のファイルをオープンして pos の位置から len バイトのデータを入力して buf に格納します。
        //★ Data Record(pos) を buf[512] に入力する
        DWORD  BEdit::ReadData(LPSTR fname, DWORD pos, void *buf, DWORD len)
        {   HANDLE      hFile;
            DWORD       dwBytes;
    
            hFile = CreateFile(fname,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
            if (hFile==INVALID_HANDLE_VALUE)
            {   MessageBox(NULL,fname,"ReadData Open Error",MB_OK);
                return 0;
            }
            if (SetFilePointer(hFile,pos,0,FILE_BEGIN)==0xFFFFFFFF) return 0;
            ReadFile(hFile,buf,len,&dwBytes,NULL);
            *((u_char*)buf+dwBytes)= 0;
            CloseHandle(hFile);
            return dwBytes;
        }
        
  4. fname のファイルの pos の位置から len バイトのデータを書き換えます。
        //★ buf[512] を pos の位置から上書きする
        DWORD  BEdit::WriteData(LPSTR fname, DWORD pos, void *buf, DWORD len)
        {   HANDLE      hFile;
            DWORD       dwBytes;
    
            hFile = CreateFile(fname,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,
                               FILE_ATTRIBUTE_NORMAL,NULL);
            if (hFile==INVALID_HANDLE_VALUE)
            {   MessageBox(NULL,fname,"UPDATE Open Error",MB_OK);
                return 0;
            }
            if (SetFilePointer(hFile,pos,0,FILE_BEGIN)==0xFFFFFFFF) return 0;
            WriteFile(hFile,buf,len,&dwBytes,NULL);
            CloseHandle(hFile);
            return dwBytes;
        }
        
  5. 16進数[] を Binary に編集して buf に格納します。
        //★ 16進数[] を Binary に編集して格納する
        int  BEdit::Hex2Bin(char *hex, char buf[16])
        {   int     j;
            char    *p;
            BYTE    w;
    
            p= hex;
            for(j=0; j<16 && *p!='\0'; j++)
            {   for(; *p==' '; p++);
                w= *p;
                if (w>'9')  w-= 7;
                w&= 0x0F;
                buf[j]= w<<4;
                for(p++; *p==' '; p++);
                w= *p;
                if (w>'9')  w-= 7;
                w&= 0x0F;
                buf[j]|= w;
                p++;
            }
            return j;
        }
        
  6. Buf[512] のデータを16進数と文字に編集して ListBox に表示します。
        //★ Buf[512] のデータを ListBox に編集する
        int  BEdit::SetBox(HWND hList, BYTE buf[], int len, int loc)
        {   int     cnt,i,j,pos;
    
            SendMessage(hList,LB_RESETCONTENT,0L,0L);
            cnt= (len+15)/16;
            for(i=0; i<cnt; i++)
            {   wsprintf(work,"%4X  ",i+(loc>>4));
                for(j=0; j<16 && i*16+j<len; j++)
                {   pos= j*2+j/8+j/4+6;
                    wsprintf(work+pos,"%02X  ",buf[i*16+j]);
                }
                for(pos+=2; pos<44; pos++)  work[pos]= ' ';
                for(j=0; j<16 && i*16+j<len; j++)
                {   if ((buf[i*16+j]<0x20) || (buf[i*16+j]>=0xFE) || (buf[i*16+j]>=0x80 && j>14))
                    work[j+44]= '.';
                    else    work[j+44]= buf[i*16+j];
                }
                work[j+44]= '\0';
                SendMessage(hList,LB_INSERTSTRING,(WPARAM)i,(LPARAM)work);
            }
            SendMessage(hList,LB_SETCURSEL,0L,0L);
            return cnt;
        }
        
  7. 後は基本関数を呼び出すための補助関数です。
    Unicode に対応した Binary Editor は ベータ版の完成です を参照して下さい。
    リンクがエラーになるときは「前田稔の超初心者のプログラム入門/C# Frame Work」から辿って下さい。

[Previous Chapter ↑] フレームワークの作成

超初心者のプログラム入門(Win32API C++)