#pragma twice

KAB-studio > プログラミング > #pragma twice > 198 Version 10.20 SDK だけで作るテキストエディタもどき

#pragma twice 198 Version 10.20 SDK だけで作るテキストエディタもどき

前のページへ 表紙・目次へ 次のページへ

 Version 10.20
SDK だけで作るテキストエディタもどき

「さて、 SDK 編最後はテキストエディタもどきです」
『 Version 9.15 ( No.176 ) で MFC 使ってやった部分ね』
「そう、あれを SDK だけで作ってみます。 SDK だけで作る分、簡単なとこ
ろもあるし、難しい所もあるから」
『ツールバーやステータスバーもそうだったものね』
「では、まずキー入力を受け取るようにします」
『 Version 10.06 ( No.184 ) でやったのだね』
「具体的にはこうします」

// ウィンドウプロシージャ。
LRESULT CALLBACK WndProc
    ( HWND p_hWnd
    , UINT p_uiMessage
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    if( p_uiMessage == WM_CREATE )
    {
        return OnCreate( p_hWnd, p_wParam, p_lParam );
    }
    else if( p_uiMessage == WM_DESTROY )
    {
        return OnDestroy();
    }
    else if( p_uiMessage == WM_RBUTTONUP )
    {
        return OnRButtonUp( p_hWnd, p_wParam, p_lParam );
    }
    else if( p_uiMessage == WM_COMMAND )
    {
        if( LOWORD( p_wParam ) == ID_MENU_TEST )
        {
            return OnMenuTest( p_hWnd, p_wParam, p_lParam );
        }
    }
    else if( p_uiMessage == WM_CHAR )
    {
        return OnChar( p_hWnd, p_wParam, p_lParam );
    }

    // 標準的な処理をします。
    return DefWindowProc( p_hWnd, p_uiMessage, p_wParam, p_lParam );
}

『おなじみ WM_CHAR だね』
「もちろん、本格的なテキストエディタにするなら WM_KEYDOWN とかにも対
応しないといけないけどね」
『カーソルキーとか使えないもんね。……そういえば』
「そういえば?」
『この WM_CHAR が使えるのって TranslateMessage() 使ってるからだよね』
「そう、この API が WM_KEYDOWN とかを WM_CHAR に変換してるから」
『……その時点で SDK の方が面倒じゃん』
「でも、メッセージループなんて一度作っちゃったら他のプログラムでも使
い回せるよ?」
『あ、そういえば』
「で、それの大がかりなのが MFC ってこと」
『ぇ?』
「 MFC のメッセージループだって、他の誰かが作ったメッセージループ
ってだけで、それを使い回してるのは同じってこと」
『あ……そういう意味じゃ、あたしが作ったメッセージループをあたしが使
い回しても、 MFC のメッセージループを使っても同じなんだ』
「そういうこと。 MFC みたいな大きなライブラリを使ってると構えちゃう
かもしれないけど、そんなに難しく考える必要はないから」
『でもやっぱレベル違うし……』
「まあね……で。この WM_CHAR が送られてきた時に呼ばれる関数 OnChar() 
は、次のような感じ」

// キー入力がありました。
LRESULT OnChar
    ( HWND p_hWnd
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    char pch[256];
    sprintf( pch, "%c", (char)p_wParam );
    OutputDebugString( pch );

    return 0;
}

『 MFC の時は TRACE() だけだったのに……』
「 Version 5.07 ( No.072 ) でやったでしょ、 TRACE() と同じに使える
って」
『あー』
「 TRACE() の変わりに、文字を文字列に変換するのに sprintf() を、アウ
トプットウィンドウに出力するのに OutputDebugString() を使ってます」
『ってことは、キーは p_wParam に入ってるんだ』
「そういうこと。とりあえずここで試してみて」
『ほい。おー、アウトプットウィンドウにキーが出る! あの時と同じ〜』
「では次に、再描画の部分を作ります。二度手間になっちゃうけど、ウィン
ドウプロシージャをもう一度修正して」

// ウィンドウプロシージャ。
LRESULT CALLBACK WndProc
    ( HWND p_hWnd
    , UINT p_uiMessage
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    if( p_uiMessage == WM_CREATE )
    {
        return OnCreate( p_hWnd, p_wParam, p_lParam );
    }
    else if( p_uiMessage == WM_DESTROY )
    {
        return OnDestroy();
    }
    else if( p_uiMessage == WM_RBUTTONUP )
    {
        return OnRButtonUp( p_hWnd, p_wParam, p_lParam );
    }
    else if( p_uiMessage == WM_COMMAND )
    {
        if( LOWORD( p_wParam ) == ID_MENU_TEST )
        {
            return OnMenuTest( p_hWnd, p_wParam, p_lParam );
        }
    }
    else if( p_uiMessage == WM_CHAR )
    {
        return OnChar( p_hWnd, p_wParam, p_lParam );
    }
    else if( p_uiMessage == WM_PAINT )
    {
        return OnPaint( p_hWnd, p_wParam, p_lParam );
    }

    // 標準的な処理をします。
    return DefWindowProc( p_hWnd, p_uiMessage, p_wParam, p_lParam );
}

「 WM_PAINT の部分を追加しました」
『あ、そっか、 MFC で使った OnDraw() ってないんだよね』
「そう、本当は再描画するときは WM_PAINT が送られてきて、 MFC はその
時に OnDraw() を呼んでました。で、 SDK の方は代わりに OnPaint() 
って関数を作って呼ぶようにします。それがこれ」

// 再描画します。
LRESULT OnPaint
    ( HWND p_hWnd
    , WPARAM p_wParam
    , LPARAM p_lParam
    )
{
    PAINTSTRUCT stPaintStruct;
    HDC hDC
         = ::BeginPaint
                ( p_hWnd
                , &stPaintStruct 
                );

    const char pchText[] = "あいうえお";
    TextOut
        ( hDC
        , 0
        , 28
        , pchText
        , strlen( pchText ) 
        );

    ::EndPaint
        ( p_hWnd
        , &stPaintStruct 
        );

    return 0;
}

『あれ、これってどっかでみたよーな』
「 Version 7.15 ( No.135 ) と同じだよ」
『あ! そっか、ダイアログでデバイスコンテキスト使ったときのと同じな
んだ』
「ダイアログだと MFC のシステムが備わってなかったから、 SDK と同じ方
法で描画したんです。だからあの時と同じ」
『でもちょっと違うよね』
「あの時はスタティックコントロールのウィンドウハンドルを使ったけど、
今回はウィンドウプロシージャのをそのまま使ってるから」
『 p_hWnd ね。それより……』

    TextOut
        ( hDC
        , 0
        , 28
        , pchText
        , strlen( pchText ) 
        );

「の 28 っていうのが気になるんだけど」
『それは次回に続く!』
「ええっ!?」

/*
    Preview Next Story!
*/
『 28 って謎な数字』
「こういうのって難しいんだよね」
『何が?』
「本当はこういうふうに直に書くのはいけないんだけど」
『だよね。前にそんなのきいたよーな』
「でも、最初に教える時はこういう具体的な数字の方が解りやすいから」
『ならそっちの方がいいじゃん』
「というわけで次回」
< Version 10.21 ツールバーとクライアントエリア >
『につづく!』
「でもさ、これで次回見なかったりされると困る……」
『いるの?』
「毎週しっかり読むのは大変じゃないかな」
『確かに……』
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。