Как разрешить меню для Edit Control

В CDialog или другом окне, которое не имеет меню edit для вырезания (cutting), копирования (copying), и вставки (pasting), контролы CEdit обрабатывают эти функции через обычные Windows акселераторы (CTRL+X,V,C, или SHIFT-DELETE, SHIFT-INSERT, CTRL-INSERT, CTRL-DELETE, и т.д.).Однако в стандартном приложении MDI или SDI эти опции запрещены.

Это происходит из-за того, что AppWizard присваивает обработчики меню и клавиши акселераторов стандартному меню. Поэтому окошко редактирования никак не реагирует на клавиши акселераторов. Данная статья показывает, как добавить в элементы управления edit на форме, наследованной от CFormView, функции буфера обмена (clipboard).

Если полностью удалить опции меню (не просто разрешить или запретить) и различные объявления акселераторов, то никаких конфликтов в Вашем CEdit не будет и он будет как обычно работать с функциями буфера обмена. Однако, если Вы захотите включить функции буфера обмена в стандартном меню Edit (и соответствующие им  кнопки на тулбаре), то Вам понадобится добавить некоторые дополнительные обработчики в программу.

  • Ваши UPDATE_COMMAND_UI должны будут определять, действительно элемент управления, который имеет фокус в данный момент, является CEdit и есть ли в нём какой-нибудь текст, для которого можно применить данную операцию.

  • Так как Вы имеете пункты меню для Cut, Copy, или Paste которые привязаны к стандартным акселераторам, то Вам понадобится написать обработчики для действий.

Пример по шагам


Этот пример содержит код, который можно добавить, чтобы позволить вырезать, копировать и вставлять текст в элемент управления CEdit в CFormView.

  1. Сперва определяем, действительно элемент имеющий фокус является CEdit:
       // IsEdit: вспомогательная функция для определения, указывает ли
    // данный указатель CWnd на элемент управления CEDit.
    // Используйте функцию SDK ::GetClassName() так как MFC-шный IsKindOf
    // выдаст ошибку, если это не CEdit

    BOOL CMyFormView::IsEdit( CWnd* pWnd )
    {
    ASSERT( pWnd != NULL );
    HWND hWnd = pWnd->GetSafeHwnd();
    if (hWnd == NULL)
    return FALSE;

    TCHAR szClassName[6];
    return ::GetClassName(hWnd, szClassName, 6) &&
    _tcsicmp(szClassName, _T("Edit")) == 0;
    }
  2. Добавляем обработчики UPDATE_COMMAND_UI для ID_EDIT_COPY & ID_EDIT_CUT:
       // UPDATE_COMMAND_UI обработчик для Edit Copy и Edit Cut, которые оба
    // требуют, чтобы текущий фокус находился в окошке редактирования,
    // которое содержит выделенный текст.

    void CMyFormView::OnUpdateNeedSel(CCmdUI* pCmdUI)
    {
    // получаем текущий фокус и определяем, находится ли он на CEdit
    CWnd* pWnd = GetFocus();
    if (NULL == pWnd || !IsEdit( pWnd ))
    {
    pCmdUI->Enable( FALSE );
    }
    else
    {
    CEdit* pEdit = (CEdit*)pWnd;
    int nBeg, nEnd;

    pEdit->GetSel( nBeg, nEnd );
    pCmdUI->Enable( nBeg != nEnd );
    }
    }
  3. Добавляем обработчики UPDATE_COMMAND_UI для ID_EDIT_PASTE:
       // UPDATE_COMMAND_UI обработчики для Edit Paste, требующие, чтобы
    // фокус был на окне редактирования и чтобы буфер обмена содержал
    // текст, который будет вставлен в контрол.

    void CMyFormView::OnUpdateNeedClip(CCmdUI* pCmdUI)
    {
    // получаем текущий фокус и определяем, находится ли он на CEdit
    // а так же проверяем, чтобы элемент управления не был read-only.
    CWnd* pWnd = GetFocus();
    if ( NULL == pWnd ||
    !IsEdit( pWnd ) ||
    (pWnd->GetStyle() & ES_READONLY) != 0 )
    {
    pCmdUI->Enable( FALSE );
    }
    else
    pCmdUI->Enable(::IsClipboardFormatAvailable(CF_TEXT));
    }
  4. Добавляем стандартные обработчики для ID_EDIT_COPY, ID_EDIT_CUT, и ID_EDIT_PASTE:
       void CMyFormView::OnEditCopy()
    {
    CEdit* pEdit = (CEdit*)GetFocus();
    ASSERT( IsEdit( pEdit) );
    pEdit->Copy();
    }

    void CMyFormView::OnEditCut()
    {
    CEdit* pEdit = (CEdit*)GetFocus();
    ASSERT( IsEdit( pEdit) );
    pEdit->Cut();
    }

    void CMyFormView::OnEditPaste()
    {
    CEdit* pEdit = (CEdit*)GetFocus();
    ASSERT( IsEdit( pEdit) );
    ASSERT(::IsClipboardFormatAvailable(CF_TEXT));
    pEdit->Paste();