CEditView 雑記

Last Updated: Apr.4,2003
使用しているコンパイラは、Microsoft Visual C++ 6.0 です。これ以外のバージョンでは記述と食い違うことがあるかも知れません。

6. ワードラップの切り替え

CEditView でワードラップするかしないかを切り替えるのは、最初は簡単に出来るだろうと思っていました。しかし、実際はビューを作成するときにウィンドウスタイルとして指定するものであり、途中でスタイルを変更しても反映されないということが分かってきました。結局、MFC のサンプル(灯台下暗し)を探したところ、ぴったりのコードがあるのを見つけました。その手順は、

  1. 現在のエディットコントロールの状態を保存する
  2. 新しいワードラップモードのエディットコントロールを作成
  3. 保存した前の状態を新しいエディットコントロールに適用
  4. 新しいエディットコントロールをビューと結びつける
  5. 古いエディットコントロールを破棄

とちょっと複雑です。

// サンプルのコードを修正したもの
BOOL CMyView::SetWordWrap(BOOL bWordWrap)
{
    bWordWrap = !!bWordWrap; // make sure ==TRUE || ==FALSE
    if (IsWordWrap() == bWordWrap)
        return FALSE;

    // preserve original control's state.
    CFont* pFont = GetFont();
    int nLen = GetBufferLength();
    TCHAR* pSaveText = new TCHAR[GetBufferLength()+1];
    GetWindowText(pSaveText, nLen+1);

    // create new edit control with appropriate style and size.
    DWORD dwStyle = dwStyleDefault & ~(ES_AUTOHSCROLL|WS_HSCROLL|WS_VISIBLE);
    if (!bWordWrap)
        dwStyle |= ES_AUTOHSCROLL|WS_HSCROLL;

    CWnd* pParent = GetParent();
    CRect rect;
    GetWindowRect(rect);
    pParent->ScreenToClient(rect);
    CWnd* pFocus = GetFocus();

    UINT nID = GetDlgCtrlID();

    HWND hWnd = ::CreateWindowEx(WS_EX_CLIENTEDGE, _T("edit"), NULL, dwStyle,
        rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
        pParent->m_hWnd, (HMENU)nID, AfxGetInstanceHandle(), NULL);

    if (hWnd == NULL)
    {
        delete[] pSaveText;
        return FALSE;
    }

    // set the window text to nothing to make sure following set doesn't fail
    SetWindowText(NULL);

    // restore visual state
    ::SetWindowText(hWnd, pSaveText);
    delete[] pSaveText;
    if (pFont != NULL)
    {
        ASSERT(pFont->m_hObject != NULL);
        ::SendMessage(hWnd, WM_SETFONT, (WPARAM)pFont->m_hObject, 0);
    }

    /* 一旦、OLE からはずす */
    m_dropTarget.Revoke();

    // detach old window, attach new
    SetDlgCtrlID(nID+1);
    HWND hWndOld = Detach();
    ::SetWindowLong(hWndOld, GWL_WNDPROC, (LONG)*GetSuperWndProcAddr());
    ASSERT(m_hWnd == NULL);
    SubclassWindow(hWnd);
    ASSERT(m_hWnd == hWnd);

    /* OLE に再登録 */
    if (!m_dropTarget.Register(this))
    {
        TRACE(_T("Fail in registing drop target\n"));
        return FALSE;
    }

    UINT nTabStops = m_nTabStops;
    GetEditCtrl().SetTabStops(nTabStops);

    GetClientRect(&rect);
    SetWindowPos(NULL, 0, 0, 0, 0,
        SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_SHOWWINDOW);
    SetWindowPos(NULL, 0, 0, 0, 0,
        SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_DRAWFRAME);
    SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
    UpdateWindow();

    // destroy old
    ::SetWindowPos(hWndOld, NULL, 0, 0, 0, 0,
        SWP_HIDEWINDOW|SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|
        SWP_NOZORDER);
    ::DestroyWindow(hWndOld);

    // restore rest of state...
    GetEditCtrl().LimitText(nMaxSize);
    if (pFocus == this)
        SetFocus();

    ASSERT_VALID(this);
    return TRUE;
}

/* ワードラップモードかどうか */
BOOL CMyView::IsWordWrap() const
{
    return (GetStyle() & ES_AUTOHSCROLL) == 0;
}

前述の OLE ドラッグ&ドロップ関係のコードを、ほんの少し書き足してあります。

←前ページ

Back Copyright (c) 2003 AOK. All Rights Reserved.