众所周知,Win SDK的标准Edit控件要接收Enter键只能在样式里增加一个“多行”,如果保持单行还想接收Enter键呢?
MSDN指出了3个方法:
1是在父窗口的WM_COMMAND中处理。2是通过为控件注册回调函数实现。3是通过MFC类重载函数实现。
第1个方法我试了不知道为什么拦截不到Enter按键。
第2个方法在StackoverFlow上有解决方案:
WNDPROC oldEditProc;
LRESULT CALLBACK subEditProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_KEYDOWN:
switch (wParam)
{
case VK_RETURN:
//Do your stuff
break; //or return 0; if you don't want to pass it further to def proc
//If not your key, skip to default:
}
default:
return CallWindowProc(oldEditProc, wnd, msg, wParam, lParam);
}
return 0;
}
void somecreateeditproc()
{
HWND hInput = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL,
0, 0, 100, 100, hwnd, (HMENU)IDC_MAIN_INPUT, GetModuleHandle(NULL), NULL);
oldEditProc = (WNDPROC)SetWindowLongPtr(hInput, GWLP_WNDPROC, (LONG_PTR)subEditProc);
}
这个是可以达到效果的。
之后我尝试了控件子类化:
TEdit.h:
#pragma once
#include
#include
#include
class TEdit
{
protected:
static WNDPROC oldEditProc;
static LRESULT CALLBACK subEditProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam);
void TEdit::CreateEx(DWORD dwExStyle, LPCTSTR lpszClass, LPCTSTR lpszName, DWORD dwStyle,int x, int y, int nWidth, int nHeight, HWND hParent,HMENU hMenu, HINSTANCE hInst);
virtual LRESULT TEdit::WndProc(WNDPROC wndproc, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//接收VK_RETURN,VK_ESCAPE,返回值决定是否调用默认消息处理
virtual bool TEdit::OnKeyDown(WPARAM wParam, LPARAM lParam);
//接收字符按键,返回值决定是否调用默认消息处理
virtual bool TEdit::OnChar(WPARAM wParam, LPARAM lParam);
public:
HWND m_hWnd;
HINSTANCE m_hInst;
TEdit();
~TEdit();
void TEdit::CreateEditEx(HWND hParent, UINT id, HINSTANCE hInst);//创建Edit
void TEdit::SetPos(int x, int y, int width, int height);//设置大小及位置
void TEdit::ShowWindow(bool bShow);//设置可见性
void CDECL TEdit::SetText(TCHAR szFormat[], ...);//设置内容
int TEdit::GetLength();//获取字符串长度
void TEdit::SetSelect(int iStart, int iEnd);//选择
void TEdit::SetSelectAll();//全选
};
TEdit.cpp:
#include "TEdit.h"
TEdit::TEdit()
{
m_hWnd = NULL;
m_hInst = NULL;
}
TEdit::~TEdit()
{
}
WNDPROC TEdit::oldEditProc;
LRESULT CALLBACK TEdit::subEditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
TEdit * pEdit;
pEdit=(TEdit *)GetWindowLong(hWnd, GWL_USERDATA);
if (pEdit)
return pEdit->WndProc(oldEditProc,hWnd, uMsg, wParam, lParam);
else
return CallWindowProc(oldEditProc, hWnd, uMsg, wParam, lParam);
}
LRESULT TEdit::WndProc(WNDPROC wndproc,HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CHAR:
if (OnChar(wParam, lParam))
return CallWindowProc(wndproc, hWnd, uMsg, wParam, lParam);
else
return 0;
case WM_KEYDOWN:
if (OnKeyDown(wParam, lParam))
return CallWindowProc(wndproc, hWnd, uMsg, wParam, lParam);
else
return 0;
}
return CallWindowProc(wndproc, hWnd, uMsg, wParam, lParam);
}
void TEdit::CreateEx(DWORD dwExStyle, LPCTSTR lpszClass, LPCTSTR lpszName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight, HWND hParent,
HMENU hMenu, HINSTANCE hInst)
{
m_hInst = hInst;
m_hWnd = CreateWindowEx(dwExStyle, lpszClass,
lpszName, dwStyle, x, y, nWidth, nHeight,
hParent, hMenu, hInst, 0);
}
void TEdit::CreateEditEx(HWND hParent,UINT id,HINSTANCE hInst)
{
m_hInst = hInst;
TEdit::CreateEx(WS_EX_CLIENTEDGE,
TEXT("Edit"), 0,
WS_CHILD,// | ES_AUTOHSCROLL | WS_VISIBLE
0, 0, 0, 0, hParent,(HMENU)id, hInst);
SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this);
oldEditProc = (WNDPROC)::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)subEditProc);
}
void TEdit::SetPos(int x, int y, int width, int height)
{
::SetWindowPos(m_hWnd, HWND_TOP, x,y,width,height,0);//SWP_SHOWWINDOW
}
void TEdit::ShowWindow(bool bShow)
{
::ShowWindow(m_hWnd, bShow ? SW_SHOWNORMAL : SW_HIDE);
}
bool TEdit::OnKeyDown(WPARAM wParam, LPARAM lParam)
{
switch (wParam)
{
case VK_ESCAPE:
case VK_SPACE:
case VK_RETURN:
SetWindowText(this->m_hWnd, TEXT("no"));
return false;//若是这3个键按下则修改TEXT为“no”,并且吞掉空格键
}
return true;
}
bool TEdit::OnChar(WPARAM wParam, LPARAM lParam)
{
return false;//截掉所有输入
}
int TEdit::GetLength()
{
return ::GetWindowTextLength(m_hWnd);
}
void TEdit::SetSelect(int iStart, int iEnd)
{
SendMessage(m_hWnd, EM_SETSEL, iStart, iEnd);
}
void TEdit::SetSelectAll()
{
SetSelect(0, GetLength());
}
void CDECL TEdit::SetText(TCHAR szFormat[], ...)
{
TCHAR szBuffer[1024];
va_list pArgList;
va_start(pArgList, szFormat);
_vsntprintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), szFormat, pArgList);
va_end(pArgList);
SetWindowText(m_hWnd, szBuffer);
}
使用示例:
TEdit edit;
edit.CreateEditEx(hWnd, IDR_LINEEDIT, m_hInst);
edit.SetPos(0, 0, 40, 20);
edit.ShowWindow(true);
edit.UpdateWindow();
hWnd为edit的父窗口句柄。修改TEdit.cpp中的OnChar和OnKeyDown函数即可拦截Edit Control的所有按键。也可创建一个TEdit的子类,重载OnChar和OnKeyDown函数。
在两个函数中根据输入情况得出不同的返回值,可以决定Edit是否调用默认消息处理。
参考文献
How To Use the ENTER Key from Edit Controls in a Dialog Box
https://support.microsoft.com/en-us/kb/102589
Edit control capture enter key
http://stackoverflow.com/questions/15711311/edit-control-capture-enter-key
WM_CHAR、WM_KEYDOWN和WM_SYSKEYDOWN消息
http://blog.csdn.net/xiexievv/article/details/6313911