MDIを使ったエディターの作成 ステップ2


■ ツールバー上に検索用コンボボックスを追加
 ステップ1では、MFCのCEditViewに検索・置換処理を追加しましたが、今回はVisualStudioのように検索文字列を表示・入力可能なコンボボックスをツールバーに追加してみます。
その前に、デフォルトのツールバーに検索用のボタンを幾つか追加してみましょう。
今回の例では、[検索]、[上方検索]、[下方検索]をそれぞれ、4、6、7番目になります。
この順番は、左端から0から数えたもので、途中のスペーサーも含めたものです。
 次に、コンボボックスですが5番目のスペーサーの位置に作成することにします。
コンボボックスの追加は、CMainFrame内で行います。

@ メンバ変数の登録
 CMainFrameに以下の2つの変数を登録します。これは、作成するコンボボックスのポインターと、コンボボックスで使用するフォントです。
    CComboBox*      m_pFindComboBox;        // 検索用コンボボックス
    CFont           m_FindFont;             // 検索用コンボボックスのフォント
A コンボボックス用コントロールIDの作成
 作成するコンボボックスのためのID(IDW_COMBO)を、ストリング・テーブルに以下のように追加します。

B 変数の初期化と破棄
 次に、コンボボックスの変数の初期化と終了時の破棄を、それぞれコンストラクタ、デストラクタに追加します。
CMainFrame::CMainFrame()
{
    // TODO: この位置にメンバの初期化処理コードを追加してください。
    m_pFindComboBox = NULL;
}

CMainFrame::~CMainFrame()
{
    if ( m_pFindComboBox)
        delete m_pFindComboBox;
}

C コンボボックスの作成

 CMainFrameのOnCreate内に以下のようにコンボボックスの作成処理を追加します。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
        デフォルト処理のコードは省きます。

        // エディター用のフォント作成. (ステップ1で作成)
        LOGFONT         lf;

        memset( &lf, 0, sizeof(lf));
        lf.lfHeight = -14;
        lf.lfWidth = 0;
        lf.lfCharSet = SHIFTJIS_CHARSET;
        strcpy( lf.lfFaceName, "MS ゴシック");              // 固定フォント.
        if ( !m_EditorFont.CreateFontIndirect( &lf))
        {
            TRACE0("Could Not create font for editor\n");
            return -1;
        }

        /////////////////////////////////////////////////////////////////////////
        //      ツールバーに検索用コンボボックスを追加.
        const int               nComboWidth             = 120;          // コンボボックスの幅
        const int               nDropHeight             = 100;          // ドロップダウンリストのサイズ
        CRect                   rect;

        m_wndToolBar.SetButtonInfo( 5, IDW_COMBO, TBBS_SEPARATOR, nComboWidth); // コンボ ボックス
        m_wndToolBar.GetItemRect( 5, &rect);
        rect.bottom = rect.top + nDropHeight;
        m_pFindComboBox = new CComboBox;
        if ( !m_pFindComboBox->Create(
                        CBS_AUTOHSCROLL | CBS_DROPDOWN | WS_VISIBLE | WS_TABSTOP,
                        rect, &m_wndToolBar, IDW_COMBO))
        {
            TRACE0( "Failed to create combo-box\n");
            return -1;
        }
        //  コンボ ボックス用のフォントを作成します。
        memset( &lf, 0, sizeof(lf));
        lf.lfHeight = -12;                              // サイズ
        lf.lfWidth = 0;
        lf.lfWeight = FW_BOLD;                          // 太字
        lf.lfCharSet = SHIFTJIS_CHARSET;                // シフトJIS

        strcpy( lf.lfFaceName, "MSP ゴシック");
        if ( !m_FindFont.CreateFontIndirect( &lf))
            TRACE0("Could Not create font for combo\n");
        else
            m_pFindComboBox->SetFont( &m_FindFont);

        return 0;
}
D コンボボックスへの検索文字列の追加処理
 次に、コンボボックスと検索処理を結びつけるわけですが、ここではまず検索処理を実行するときに、検索文字列をコンボボックスに登録する関数を作成します。
void CMainFrame::AddEditString( CString cs)
{
    int             n;

    n = m_pFindComboBox->FindStringExact( 0, cs);   // 既に登録されているか調べる
    if ( n == CB_ERR)               // 新規登録.
    {
        m_pFindComboBox->InsertString( 0, cs);
    }
    m_pFindComboBox->SetWindowText( cs);
}
この関数では、引数の文字列csをコンボボックスに登録するわけですが、このときコンボボックスが既に同じ文字列を格納しているかどうかを調べて、無い場合のみ登録をするようにしてあります。

E コンボボックスから文字列を取得処理
 これは、前述のコンボボックスへの入力に対し、コンボボックスからの出力処理になります。
これにより、コンボボックスに直接入力した文字列に対し検索を行えるようにします。
void CMainFrame::GetEditString( CString& cs)
{
    m_pFindComboBox->GetWindowText( cs);
}

F ビューへの処理の追加
 最後に、CMDIEditorView内にコンボボックスに対する処理を追加します。
追加する処理は、
・検索実行前にコンボボックスの現在のテキストを取得する。
・検索実行後にコンボボックスのバッファに検索文字列を登録する。
以下に、前方検索の処理を例として示します。
void CMDIEditorView::OnFindNext() 
{
    CMainFrame*        pMainFrame      = (CMainFrame*)theApp.m_pMainWnd;

    pMainFrame->GetEditString( m_FindStr);
    if ( m_FindStr.GetLength())
    {
        FindText( m_FindStr, TRUE, m_bMachCase);
        pMainFrame->AddEditString( m_FindStr);          // コンボボックスに登録.
    }
}
検索・置換ダイアログのための処理ルーチン内でも、追加内容は同じです。
またここで、CMainFrameのアドレスの取得方法は、ステップ1と同じなのでそちらを参照してください。

■ 実行してみましょう
 ここまでをビルドして実行してみましょう。

上図では、子ウィンドウを最大化してあります。

 これだけでは、使いにくい点も残っていると思います。皆さんで更に改良してみてください。

 次回は、当ホームページのサンプルにもある「エディタに行番号を追加」を利用して、ここまでのものに行番号を付けてみることにしましょう。
■ サンプルプロジェクトファイルのダウンロード
(VC++6.0プロジェクトファイル25KB)