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();
}
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;
}
“编辑”和“丰富编辑”控件的默认行为是在控件没有输入焦点时使选择不可见,并且只有在控件具有焦点时才使其可见。 然而,选择并没有改变。 ES_NOHIDESEL
样式将覆盖此默认行为,并使选择始终显示在控件中,而不管它是否具有焦点。 您之前已经看到过这种行为:Microsoft Word和Visual Studio都是这样做的。
因此,您对SDK文档的理解是完全正确的。 不幸的是,Rich Edit控件行为的另一个方面正在阻碍。 无论何时托管在对话框中的编辑或Rich Edit控件接收到焦点,它都会自动选择其所有文本,从而消除流程中当前的脱字符号位置。 ES_NOHIDESEL
对此行为没有任何影响; 它只会改变当控件未聚焦时选择是否可见。 您可以通过按照建议的IInspectable进行操作来覆盖此全选焦点行为,并对控件进行子类化以自定义其对WM_GETDLGCODE
消息的处理。
但是有一个更简单的解决方案。 与ES_NOHIDESEL
, 您希望在创建时为控件设置ES_SAVESEL
样式 。 尽管可以在资源编辑器中设置ES_NOHIDESEL
(“无隐藏选择”),但ES_SAVESEL
没有等效属性。 您可以手动将其添加到RC文件,但不保证在Visual Studio重新生成该文件时它不会被删除。
或者,您可以发送Rich Edit控件一个EM_SETOPTIONS
消息,指定ECO_SAVESEL
选项。 在MFC中, SetOptions
成员函数包装发送此消息。 例如,在您的OnInitDialog
函数中,您可能会有以下内容:
m_myRichEditCtrl.SetOptions(ECOOP_OR, ECO_SAVESEL); // maintain selection across focus events
链接地址: http://www.djcxy.com/p/39261.html
上一篇: CRichEditCtrl selects all text when it gets focus
下一篇: WPF TextBox stealing focus after neighboring CheckBox is clicked