Edit Control响应全选(Ctrl+A)
MFC中的Edit控件用于输入数据,当输入的数据为大段数字的时候,全选功能就显得非常重要了,可偏偏在MFC中Edit控件就不 支持全选。Ctrl+A不行,双击也不行。
Ctrl+C和Ctrl+V都是默认支持的。因此为了使用方便,我们仅仅能自己让Edit去支持Ctrl+A全选 功能了。
实现的方式也比較简单,自己处理消息就是!
Ctrl+A是一个组合消息,在检測到A或者a按键按下的时候。推断Ctrl键的状态,假设Ctrl键有效则说明用户按下了Ctrl+A按键,这时候我们将Edit中内容设置为全选就可以。
在类定义中加入:
BOOL PreTranslateMessage(MSG* pMsg);
实现例如以下:
<span style="color:#444444;">BOOL C***Dlg::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN) { BOOL bCtrl = ::GetKeyState(VK_CONTROL) & 0x80; //BOOL bShift = ::GetKeyState(VK_SHIFT) & 0x80; //BOOL bAlt = ::GetKeyState(VK_MENU) & 0x80; switch (pMsg->wParam) { case 'a': case 'A': if (bCtrl) { </span><span style="color:#ff0000;">m_ctrLog.SetSel(0, -1); //或 SendDlgItemMessage(IDC_Log, EM_SETSEL, 0, -1);</span><span style="color:#444444;"> } break; } } return CWnd::PreTranslateMessage(pMsg); }</span>
或:
BOOL C***Dlg::PreTranslateMessage(MSG* pMsg) { if(pMsg->message == WM_KEYDOWN) { BOOL b = GetKeyState(VK_CONTROL) & 0×80; if(b && (pMsg->wParam==’a'||pMsg->wParam==’A')) { <span style="color:#ff0000;">SetSel(0,-1); //或 SendDlgItemMessage(IDC_Log, EM_SETSEL, 0, -1);</span> return TRUE; } } return CWnd::PreTranslateMessage(pMsg); }
备注:
为了避免对使用的Edit一个个的进行处理,能够通过从CEdit类派生一个新类CEditEx类让Edit支持Ctrl+A全选功能。
另外:
Ctrl + A 实现循环 全选/取消全选。尽管取消全选非常easy,一句话SetSel(-1),但难点在于怎样推断取消全选的条件。代码例如以下:
对于一个编辑框。实现它的全选和取消全选(前提:该编辑框获得焦点)
新建一个dialog based MFC application, 命名为“d1”。界面例如以下:
为对话框类加入一个成员变量:bool m_bSelectAll;用于控制全选状态。
另外重载对话框类的PreTranslateMessage事件,加入例如以下代码:
BOOL CD1Dlg::PreTranslateMessage(MSG*
pMsg) { if ((GetAsyncKeyState(VK_CONTROL)
& 0x8000) && (GetAsyncKeyState( 'A' )
& 0x8000) && pMsg->hwnd == m_pEdit->m_hWnd) { if (m_bSelectAll) { m_pEdit->SetSel(-1);
//
取消全选 } else { m_pEdit->SetSel(0,
-1); //
全选 } m_bSelectAll
= !m_bSelectAll; return TRUE; } return CDialog::PreTranslateMessage(pMsg); } |
这样。当编辑框获得焦点时,假设再按下Ctrl+A,编辑框的内容就会被“全选”或“取消全选”。
可是上面以m_bSelectAll来作为推断是否“已经处于全选”状态有个问题,那就是当全选时,用户点击编辑框而取消了全选,但这时,m_bSelectAll却还处于全选状态,也就是说这个标志(m_bSelectAll)与实际的全选状态不一致。
所以採用了另外的方法来验证是否处于全选状态(就是选中内容的长度与编辑框内容长度是否一致)。代码例如以下:
BOOL CD1Dlg::PreTranslateMessage(MSG*
pMsg) { if (pMsg->hwnd
== m_pEdit->m_hWnd && (GetAsyncKeyState(VK_CONTROL) & 0x8000) && (GetAsyncKeyState(_T( 'A' ))
& 0x8000)) { CString
txt; int start,
end; m_pEdit->GetWindowText(txt); m_pEdit->GetSel(start,
end); if (txt.GetLength()
== end - start) //
处于全选状态 { m_pEdit->SetSel(-1);
//
取消全选 } else { m_pEdit->SetSel(0,
-1); //
全选 } return TRUE; } return CDialog::PreTranslateMessage(pMsg); } |
说明:GetAsyncKeyState()仅仅检查一个键是否被按下,而不区分大写和小写!