【求助】关于combobox控件中enter键消息的处理

不减丨狂骄 2013-11-11 04:46:45
我用win32api,写了一个简单的窗口程序,一个主窗口,一个WS_CHILD|WS_VISIBLE|CBS_DROPDOWN样式的combobox控件。然后,发现在主窗口的窗口过程函数中无法处理当combobox控件获取焦点时,按下enter键的消息。查询得知WM_COMMAND消息中并未有关于enter的通知码。
首先,我尝试用SetWindowLong函数改变combobox控件的窗口过程函数,在改变的窗口过程函数中处理WM_CHAR和WM_KEYDOWN消息。但是运行时,仍然无法捕获enter按键消息。
之后,我又在GetMessage循环中尝试通过GetFocus和判断msg->wParam来截获combobx的enter按键消息,但是还是失败了。
在百度的时候,发现都是说在MFC中的重载PreTranslateMessage函数,难道我要重写TranslateMessage函数????想想也不太可能啊
所以,究竟用什么方法才能实现捕获和处理combobox或者edit控件的enter按键消息呢???我说的是纯API的编程,不是在MFC中。希望大神不吝赐教啊。
...全文
403 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
向立天 2013-12-20
  • 打赏
  • 举报
回复
您好 我是本版版主 此帖已多日无人关注 请您及时结帖 如您认为问题没有解决可按无满意结帖处理 另外本版设置了疑难问题汇总帖 并已在版面置顶 相关规定其帖子中有说明 您可以根据规定提交您帖子的链接 如您目前不想结帖只需回帖说明 我们会删除此结帖通知 见此回复三日内无回应 我们将强制结帖 相关规定详见界面界面版关于版主结帖工作的具体办法
bsnry 2013-11-20
  • 打赏
  • 举报
回复
引用 28 楼 schlafenhamster 的回复:
"是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,如果该函数返回TRUE,则不会把该消息分发给窗口函数处理。" 为什么 你的 返回 FALSE ???
schlafenhamster 2013-11-19
  • 打赏
  • 举报
回复
"是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,如果该函数返回TRUE,则不会把该消息分发给窗口函数处理。" 为什么 你的 返回 FALSE ???
bsnry 2013-11-19
  • 打赏
  • 举报
回复
引用 26 楼 bsnry 的回复:
[quote=引用 25 楼 schlafenhamster 的回复:] 至于MFC 的 对话框中,要 这样: BOOL CMyComboDlg::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class if(pMsg->message == WM_KEYDOWN) { if(pMsg->wParam == VK_RETURN) { if(GetFocus()->m_hWnd==m_ctrlMyCombo.m_hCbEdit) { m_ctrlMyCombo.SendMessage(WM_CHAR,VK_RETURN); return TRUE;// 不让 默认 按钮 OK 得到 return } } } return CDialog::PreTranslateMessage(pMsg); }
你好,我对这个问题做了一个简单的扩展, mfc方式拦截combobox的wm_char BOOL Ctest5Dlg::PreTranslateMessage(MSG* pMsg) { // TODO: 在此添加专用代码和/或调用基类 if(pMsg->message == WM_KEYDOWN) { if(pMsg->wParam == VK_RETURN) { if(m_combobox.m_hwndEdit == GetFocus()->m_hWnd) { m_combobox.SendMessage(WM_KEYDOWN,pMsg->wParam,pMsg->lParam); return FALSE; } } } if(pMsg->message == WM_CHAR) //考虑wm_char { if(m_combobox.m_hwndEdit == GetFocus()->m_hWnd) { m_combobox.SendMessage(WM_CHAR,pMsg->wParam,pMsg->lParam); return FALSE; } } return CDialog::PreTranslateMessage(pMsg); } void CMyComboBox::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //if(nChar == VK_RETURN) { AfxMessageBox(_T("OnChar")); } CComboBox::OnChar(nChar, nRepCnt, nFlags); } 结果: 我输入字符p后,弹出OnChar后, 编辑框里出现2个p,即:pp 这种怪异现象。 我开始以为我眼花了,数次验证后,依然如此。 我于是思考 wm_keydown, wm_char的顺序。 似乎从顺序里难以寻出真实的答案,来解释以上的怪异现象。 [/quote] 有没有帮忙解答这个诡异现象,查询资料无果
bsnry 2013-11-18
  • 打赏
  • 举报
回复
引用 25 楼 schlafenhamster 的回复:
至于MFC 的 对话框中,要 这样: BOOL CMyComboDlg::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class if(pMsg->message == WM_KEYDOWN) { if(pMsg->wParam == VK_RETURN) { if(GetFocus()->m_hWnd==m_ctrlMyCombo.m_hCbEdit) { m_ctrlMyCombo.SendMessage(WM_CHAR,VK_RETURN); return TRUE;// 不让 默认 按钮 OK 得到 return } } } return CDialog::PreTranslateMessage(pMsg); }
你好,我对这个问题做了一个简单的扩展, mfc方式拦截combobox的wm_char BOOL Ctest5Dlg::PreTranslateMessage(MSG* pMsg) { // TODO: 在此添加专用代码和/或调用基类 if(pMsg->message == WM_KEYDOWN) { if(pMsg->wParam == VK_RETURN) { if(m_combobox.m_hwndEdit == GetFocus()->m_hWnd) { m_combobox.SendMessage(WM_KEYDOWN,pMsg->wParam,pMsg->lParam); return FALSE; } } } if(pMsg->message == WM_CHAR) //考虑wm_char { if(m_combobox.m_hwndEdit == GetFocus()->m_hWnd) { m_combobox.SendMessage(WM_CHAR,pMsg->wParam,pMsg->lParam); return FALSE; } } return CDialog::PreTranslateMessage(pMsg); } void CMyComboBox::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //if(nChar == VK_RETURN) { AfxMessageBox(_T("OnChar")); } CComboBox::OnChar(nChar, nRepCnt, nFlags); } 结果: 我输入字符p后,弹出OnChar后, 编辑框里出现2个p,即:pp 这种怪异现象。 我开始以为我眼花了,数次验证后,依然如此。 我于是思考 wm_keydown, wm_char的顺序。 似乎从顺序里难以寻出真实的答案,来解释以上的怪异现象。
schlafenhamster 2013-11-14
  • 打赏
  • 举报
回复
create 时, style 有没有问题 ?
bsnry 2013-11-14
  • 打赏
  • 举报
回复
引用 17 楼 schlafenhamster 的回复:
我是 vc6 上试过的代码,运行无误的。 看看你是怎么 子类化的。
我用win7 vs2008 mfc 试了一下, 依然如此。 是否是因为 gdi库升级了。 wm_char, wm_keydown 均失效,似乎只有cbn_editchange这个消息码可以使用,这个消息是wm_command
schlafenhamster 2013-11-14
  • 打赏
  • 举报
回复
至于MFC 的 对话框中,要 这样: BOOL CMyComboDlg::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class if(pMsg->message == WM_KEYDOWN) { if(pMsg->wParam == VK_RETURN) { if(GetFocus()->m_hWnd==m_ctrlMyCombo.m_hCbEdit) { m_ctrlMyCombo.SendMessage(WM_CHAR,VK_RETURN); return TRUE;// 不让 默认 按钮 OK 得到 return } } } return CDialog::PreTranslateMessage(pMsg); }
schlafenhamster 2013-11-14
  • 打赏
  • 举报
回复
combo 有2种 风格, 上部分别对应 CStatic 和 CEdit,我给你的 是 CBS_DROPDOWNLIST (static),对于 CBS_DROPDOWN (edit),还要多一层 处理 , 需要 进一步 子类化 cb 中的 edit : // 子类化 ComboBox 中的 edit 过程, CBS_DROPDOWN HWND m_hCbEdit=0; WNDPROC CBoldEditProc; LRESULT CALLBACK CbEditProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch(Msg) { case WM_KEYDOWN: if(wParam==VK_RETURN) OutputDebugString("VK_RETURN\r\n"); break; } return CallWindowProc(CBoldEditProc, hWnd, Msg, wParam, lParam); } 子类化 edit 在 : //子类化 ComboBox 过程 WNDPROC CBoldProc; LRESULT CALLBACK CBProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { char promp[40]; // switch(Msg) { case WM_CTLCOLOREDIT: if(m_hCbEdit==0) { m_hCbEdit=(HWND) lParam; CBoldEditProc = (WNDPROC)SetWindowLong(m_hCbEdit, GWL_WNDPROC, (LONG)CbEditProc); } break; case WM_CHAR:// only CBS_DROPDOWNLIST if(wParam==VK_RETURN) { OutputDebugString("VK_RETURN\n"); } break; 。。。。 } 处理。
bsnry 2013-11-14
  • 打赏
  • 举报
回复
引用 22 楼 schlafenhamster 的回复:
你那个 combo 不能 放在 对话框 中,例子中的 主窗口 是 win32 窗口,不是 对话框。 因为 对话框 中 有个 default button 问题 ,需要 在 PreTranslateMessage() 处理。
可否提供权威资料验证一下。 个人感觉与默认按钮无关。原因如下: 对话框上的combobox子类化wm_char没有响应, 我是用
schlafenhamster 2013-11-14
  • 打赏
  • 举报
回复
你那个 combo 不能 放在 对话框 中,例子中的 主窗口 是 win32 窗口,不是 对话框。 因为 对话框 中 有个 default button 问题 ,需要 在 PreTranslateMessage() 处理。
许文君 2013-11-14
  • 打赏
  • 举报
回复
重载虚函数PreTranslateMessage();自己处理所有的键盘消息。
bsnry 2013-11-14
  • 打赏
  • 举报
回复
引用 19 楼 schlafenhamster 的回复:
create 时, style 有没有问题 ?
cbs_dropdown ,cbs_hasstrings
schlafenhamster 2013-11-13
  • 打赏
  • 举报
回复
我是 vc6 上试过的代码,运行无误的。 看看你是怎么 子类化的。
不减丨狂骄 2013-11-13
  • 打赏
  • 举报
回复
引用 12 楼 schlafenhamster 的回复:
例子:主窗口调用: HWND CreateCB(HWND parentWnd) { HWND hComboBox=0; hComboBox = CreateWindow("COMBOBOX", NULL, WS_CHILD|WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST |CBS_SORT, 330, 40, 90, 140, parentWnd, (HMENU)IDC_COMBOBOX, (HINSTANCE) GetWindowLong(parentWnd, GWL_HINSTANCE), NULL); // ShowWindow(hComboBox,SW_SHOW); SendMessage(hComboBox,CB_ADDSTRING ,0,(LPARAM)"你好"); SendMessage(hComboBox,CB_ADDSTRING ,0,(LPARAM)"我好"); SendMessage(hComboBox,CB_ADDSTRING ,0,(LPARAM)"他好"); return hComboBox; } //子类化 ComboBox 过程,Create CB 后 WNDPROC CBoldProc; LRESULT CALLBACK CBProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { HWND hwndCB = GetDlgItem(hWnd, IDC_COMBOBOX); char promp[40]; // switch(Msg) { case WM_CHAR: if(wParam==VK_RETURN) { OutputDebugString("VK_RETURN\n"); } break; default : sprintf(promp,"Msg %04X\n",Msg); OutputDebugString(promp); break; } return CallWindowProc(CBoldProc, hWnd, Msg, wParam, lParam); } // 主窗口 Create 时: m_hComboBox=CreateCB(hwnd); // 子类化: CBoldProc = (WNDPROC)SetWindowLong(m_hComboBox, GWL_WNDPROC, (LONG)CBProc);
兄台用的这个方法,我测试下还是无法捕捉enter键消息。这个方法好像和我开题说的第一个方法是一个意思,旨在更改控件的窗口过程函数,但是还是无法捕捉
不减丨狂骄 2013-11-13
  • 打赏
  • 举报
回复
引用 14 楼 qq762532765 的回复:
[quote=引用 11 楼 schlafenhamster 的回复:] "无法处理当combobox控件获取焦点时" 指的是 combo 中 的 edit 获取焦点时 ???
感觉第一种方法和我用的是一样的,
引用 11 楼 schlafenhamster 的回复:
"无法处理当combobox控件获取焦点时" 指的是 combo 中 的 edit 获取焦点时 ???
恩 是的 因为我想在edit获得焦点并有输入时处理enter键的消息 到目前为止还是没有解决啊。[/quote] 第一个引用发错人了 应该是发给bsnry兄台的
不减丨狂骄 2013-11-13
  • 打赏
  • 举报
回复
引用 11 楼 schlafenhamster 的回复:
"无法处理当combobox控件获取焦点时" 指的是 combo 中 的 edit 获取焦点时 ???
感觉第一种方法和我用的是一样的,
引用 11 楼 schlafenhamster 的回复:
"无法处理当combobox控件获取焦点时" 指的是 combo 中 的 edit 获取焦点时 ???
恩 是的 因为我想在edit获得焦点并有输入时处理enter键的消息 到目前为止还是没有解决啊。
schlafenhamster 2013-11-13
  • 打赏
  • 举报
回复
响应是: case WM_CHAR: if(wParam==VK_RETURN) { OutputDebugString("VK_RETURN\n"); } break;
schlafenhamster 2013-11-13
  • 打赏
  • 举报
回复
例子:主窗口调用: HWND CreateCB(HWND parentWnd) { HWND hComboBox=0; hComboBox = CreateWindow("COMBOBOX", NULL, WS_CHILD|WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST |CBS_SORT, 330, 40, 90, 140, parentWnd, (HMENU)IDC_COMBOBOX, (HINSTANCE) GetWindowLong(parentWnd, GWL_HINSTANCE), NULL); // ShowWindow(hComboBox,SW_SHOW); SendMessage(hComboBox,CB_ADDSTRING ,0,(LPARAM)"你好"); SendMessage(hComboBox,CB_ADDSTRING ,0,(LPARAM)"我好"); SendMessage(hComboBox,CB_ADDSTRING ,0,(LPARAM)"他好"); return hComboBox; } //子类化 ComboBox 过程,Create CB 后 WNDPROC CBoldProc; LRESULT CALLBACK CBProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { HWND hwndCB = GetDlgItem(hWnd, IDC_COMBOBOX); char promp[40]; // switch(Msg) { case WM_CHAR: if(wParam==VK_RETURN) { OutputDebugString("VK_RETURN\n"); } break; default : sprintf(promp,"Msg %04X\n",Msg); OutputDebugString(promp); break; } return CallWindowProc(CBoldProc, hWnd, Msg, wParam, lParam); } // 主窗口 Create 时: m_hComboBox=CreateCB(hwnd); // 子类化: CBoldProc = (WNDPROC)SetWindowLong(m_hComboBox, GWL_WNDPROC, (LONG)CBProc);
schlafenhamster 2013-11-13
  • 打赏
  • 举报
回复
"无法处理当combobox控件获取焦点时" 指的是 combo 中 的 edit 获取焦点时 ???
加载更多回复(10)

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧