CRichEditCtrl выделяет весь текст, когда получает фокус

У меня был диалог с меню и CTabCtrl. CTabCtrl имел одну вкладку, которая содержала CDialog. В свою очередь, это содержало несколько статических текстов и CRichEditCtrl. Не было особой проблемы с окном, получающим и теряющим фокус.

С тех пор я добавил вторую идентичную вкладку, и теперь каждый раз, когда вкладка меняется, весь текст в CRichEditCtrl, по-видимому, выделяется. Это показано в перевернутой цветовой схеме, и весь текст заменяется, если вы нажмете клавишу.

Описание флага ECO_NOHIDESEL, говорит (выделено мое):

Отрицает поведение по умолчанию для элемента управления редактирования. Поведение по умолчанию
скрывает выбор, когда элемент управления теряет фокус ввода и шоу
выбор, когда элемент управления получает фокус ввода.
если ты
укажите ECO_NOHIDESEL, выделенный текст инвертируется, даже если
контроль не имеет фокуса.

«показывает выбор» для меня звучит как «показать, какой выбор был в прошлый раз, когда этот элемент управления был в фокусе», а это не то, что происходит. Обычно ничего не выделяется до потери фокуса, но если я попытаюсь оставить выделение, вернусь на другую вкладку и вернусь, весь текст, как обычно, выделяется.

Можно ли предотвратить этот выбор?

void EditorDialog :: OnTabSelChange (NMHDR * phdr, LRESULT * pResult) {

  CTabCtrl* ptab = (CTabCtrl*) GetDlgItem( IDC_TAB );

int iPageActive = ptab->GetCurSel();

if ( iPageActive >= appage.N() ) {
AKS( AKSWarn, "got tab change to tab %d when I only have %d ppages", iPageActive, appage.N() );
return;
}

ppageActive = appage[ iPageActive ];

SetActivePagePos();

SCWinUtilSetWindowTextVA( this, "Editor: %s", ppageActive->pszFileName );
}void EditorDialog::SetActivePagePos() {

// STEP 1: Make the proper tab page visible.

for ( int i = 0; i < appage.N(); i++ )
appage[i]->ShowWindow( SW_HIDE );
ppageActive->ShowWindow( SW_SHOW );

// STEP 2: Make the new tab page the right size and position.

CTabCtrl* ptab = (CTabCtrl*) GetDlgItem( IDC_TAB );

CRect rectTab, rectItem;

ptab->GetClientRect( &rectTab );
ptab->GetItemRect( 0, &rectItem );

int iPageX = rectItem.left   + 2;
int iPageY = rectItem.bottom + 4;
int iPageW = rectTab.right   - 2 - iPageX;
int iPageH = rectTab.bottom  - 2 - iPageY;

ppageActive->SetWindowPos( &wndTop, iPageX, iPageY, iPageW, iPageH, SWP_SHOWWINDOW | SWP_NOZORDER );

// STEP 3: Give the window focus and let it know to redraw.

ppageActive->SetFocus();

// When the tab changes the entire content of the RichEdit is selected for some reason.
// As a workaround I manually clear the selection.
CRichEditCtrl* prich = (CRichEditCtrl*) ppageActive->GetDlgItem( IDC_PATCH );
prich->SetSel(-1,-1);

// Redrawing just the prich, or the ppageActive, or the ptab, doesn't
// cause the RichEdit to redraw correctly, but Redrawing the entire dialog does.
RedrawWindow();
}

3

Решение

Поведение по умолчанию для элементов управления Edit и RichEdit — выделять все содержимое, когда они получают фокус. ES_NOHIDESEL не изменяет это поведение, а просто указывает элементу управления всегда показывать свой выбор, даже если у него нет фокуса ввода.

Чтобы изменить поведение по умолчанию элемента управления RichEdit на сохранить его выбор вы должны извлечь из него и предоставить свой обычай OnGetDlgCode реализация:

UINT RichEditSelectionPreserving::OnGetDlgCode() {
// Call the base class implementation
UINT code = CRichEditCtrl::OnGetDlgCode();
// And mask out the undesired feature
code = code & ~DLGC_HASSETSEL;
return code;
}
4

Другие решения

Поведение по умолчанию для элементов управления Edit и Rich Edit — сделать выбор невидимый когда элемент управления не имеет фокус ввода и делает его видимым только тогда, когда элемент управления имеет фокус. Выбор не, однако, изменено. ES_NOHIDESEL стиль переопределяет это поведение по умолчанию и вызывает выбор всегда появляются в элементе управления, независимо от того, имеет ли он фокус. Вы наверняка видели такое поведение раньше: это то, что делают и Microsoft Word, и Visual Studio.

Таким образом, ваше понимание документации SDK совершенно правильно. К сожалению, есть другой аспект поведения элемента управления Rich Edit, который мешает. Всякий раз, когда элемент управления Edit или Rich Edit размещены в диалоговом окне получает фокус, автоматически выбирает весь текст, стирая текущую позицию каретки в процессе. ES_NOHIDESEL не влияет на это поведение; это просто изменяет, является ли выбор видимый когда контроль не сфокусирован. Вы, конечно, можете переопределить это поведение «все на фокусе», выполнив Рекомендуется а также наследование элемента управления, чтобы настроить его обработку WM_GETDLGCODE сообщение.

Но есть много более простое решение. В том же духе, что и ES_NOHIDESEL, Вы хотите установить ES_SAVESEL стиль для контроля при создании. Хотя вы можете установить ES_NOHIDESEL в редакторе ресурсов («Без скрытого выделения») нет эквивалентного свойства для ES_SAVESEL, Вы можете вручную добавить его в файл RC, но нет гарантии, что он не будет удален, когда Visual Studio сгенерирует этот файл.

Кроме того, вы можете отправить элемент управления Rich Edit a EM_SETOPTIONS сообщение с указанием ECO_SAVESEL вариант. В МФЦ SetOptions функция-член оборачивает отправку этого сообщения. Например, в вашем OnInitDialog функция, у вас может быть следующее:

m_myRichEditCtrl.SetOptions(ECOOP_OR, ECO_SAVESEL);  // maintain selection across focus events
2

По вопросам рекламы [email protected]