if (pMsg->message == WM_KEYDOWN) { switch (pMsg->wParam) { case VK_UP: //My code//====================第句记得return true;!!! break; case VK_DOWN: //My code break; case VK_SPACE: case VK_RETURN: //My code break; ...................
BOOL CModelView::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN) { switch (pMsg->wParam) { case VK_UP: case VK_DOWN: case VK_LEFT: case VK_RIGHT: afxDump << pMsg->wParam << "=WM_KEYDOWN"; return TRUE;// These VK's will be captured !!! use tab to another control. }
step1:
BOOL CKeyTestDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message==WM_KEYDOWN)//检测按钮按下
{
OnKeyDown(pMsg->wParam, LOWORD(pMsg->lParam),HIWORD(pMsg->lParam)); //调用消息响应函数
}
return CDialog::PreTranslateMessage(pMsg);
}
step2:void CKeyTestDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch (nChar)
{
case VK_UP: //My code
break;
case VK_DOWN: //My code
break;
case VK_SPACE:
case VK_RETURN: //My code
break;
................... CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
}
我的CModelView是继承自CWnd的一个窗口类, 用于在对话框界面上开辟一个窗口进行显示.BOOL CModelView::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类 //有按键按下
if (pMsg->message == WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case VK_UP: m_Size += 0.1f*m_scaleModel;
break;
case VK_DOWN: m_Size -= 0.1f*m_scaleModel;
break;
case VK_SPACE:
case VK_RETURN:
if (!m_IsDataDisplay) {
break;
}
if (m_ModelPickState == STATE_DISPLAY) {
switch(m_DataDisState)
{
case WAITING: case PAUSE:
// MessageBox(L"进来!");
m_DataDisState = RUNNING;
SetTimer(TIME_DISPLAY, 1000, NULL);
break;
case RUNNING:
m_DataDisState = PAUSE;
KillTimer(TIME_DISPLAY);
break;
case END:
m_CurrentDisTime = 340;
m_DataDisState = RUNNING;
SetTimer(TIME_DISPLAY, 1000, NULL);
break;
default:
break;
}
}
break;
default: // MessageBox(L"Press the arrow keys only");.
break;
}
} InvalidateRect(NULL,FALSE); return CWnd::PreTranslateMessage(pMsg);
}
2. PreTranslateMessage这个函数我以前也用过, 我看网上大部分人都这么用的, 也没啥问题. 但我以前也是用的对话框类里面的PreTranslateMessage, 现在我这个窗口类是继承自Cwnd的, 可以看上一楼的详细代码....
3. 目前我找到一个妥协的办法, 就是我上面提到的, 在窗口弹出之前人为添加一条模拟方向键按下的消息. 我选择在OnSize函数的最后加上了一句
::PostMessage(m_hWnd, WM_KEYDOWN, VK_LEFT, 0);
然后再运行的时候就没有任何问题了...
4. 我感觉就是最初PreTranslateMessage被阻塞掉了, 而只有四个方向键能解除阻塞. 但实在不理解为什么...
有没有 加速键 ?
View? 我就是对话框窗口哈, 然后在界面上新建一个基于CWnd的窗口类进行显示的, 跟文档视图里面的View应该没关系吧?
加速键是什么?
看看这部分代码加速键 就是 资源里的 accelerator
GetClientRect(&ClientRect); CRect SubRect;
SubRect.left = 10;
SubRect.top = 10;
SubRect.right = ClientRect.right-10;
SubRect.bottom = ClientRect.bottom-10; m_MyModel->Create(NULL,NULL,WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_VISIBLE,SubRect,this,0);
上面的代码是在对话框主程序里面调用的.我没用过加速键, 您的意思是我这种在主窗口里面开辟的子窗口应该使用加速键吗?
按下按键之前可以接受鼠标操作的(可以用鼠标来控制模型旋转位置什么的), 应该已经focus了吧?..对话框界面上面就只有初始的确定和取消两个按钮, 没有其他的控件了
代码给全点不行吗 ?
:OnInitDialog()
里有没有设置焦点?
没有类名?
我不是在OnInitDialog里面创建的..是在加载了模型文件后显示的...完整代码如下
//打开模型网格文件
void CMy3DDisplayDlg::OnFileOpenmesh()
{
// TODO: 在此添加命令处理程序代码
//先选择模型
CFileDialog objDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
L"Wavefront OBJ (*.obj)||", NULL); //打开文件对话框,选择obj文件
if (objDlg.DoModal() == IDOK)
{
strPath = objDlg.GetPathName(); if (m_MyModel != NULL) {
delete m_MyModel;
m_MyModel = NULL;
}
m_MyModel = new CModelView;
BOOL ifRead = m_MyModel->_LoadOBJFile(strPath); //读取obj文件 //显示模型
CRect ClientRect;
GetClientRect(&ClientRect); CRect SubRect;
SubRect.left = 10;
SubRect.top = 10;
SubRect.right = ClientRect.right-10;
SubRect.bottom = ClientRect.bottom-10; m_MyModel->Create(NULL,NULL,
WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_VISIBLE,SubRect,this,0);
}
}
加上了这么两句:
TCHAR szBuff[256]={0};
GetClassName(m_MyModel->GetSafeHwnd(),szBuff,sizeof(szBuff)/sizeof(TCHAR));
m_MyModel->Create(szBuff,NULL,WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_VISIBLE,SubRect,this,0);但是GetClassName函数执行过后szBuff还是空的啊...
m_MyModel->Create(NULL,NULL,
WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_VISIBLE,SubRect,this,0);
时 加 WS_TABSTOP 看看。
另外:
GetClassName(m_MyModel->GetSafeHwnd(),szBuff,sizeof(szBuff)/sizeof(TCHAR));
放Create 后, 可以 看到 类名为 “Afx 40000 0”
按下按键之前可以接受鼠标操作的(可以用鼠标来控制模型旋转位置什么的), 应该已经focus了吧?..对话框界面上面就只有初始的确定和取消两个按钮, 没有其他的控件了BOOL CXXXDialog::OnInitDialog()
{
CDialog::OnInitDialog(); // TODO: 在此添加额外的初始化
..............................
return TRUE; // return TRUE unless you set the focus to a control//注意这一行代码的意思,你要初始化对话框以后想把焦点放到控件上,需要return FALSE!!!!!!
// 异常: OCX 属性页应返回 FALSE
}
创建:
m_MyModel->Create(NULL,NULL,
WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_VISIBLE,SubRect,this,0); 后:
在m_MyModel 的Create中, 再创建一个 IDOK 的按钮,把 焦点设置到 这个按钮上。
在 m_MyModel 的 PreTranslateMessage里:
if(pMsg->message==WM_KEYDOWN) afxDump << "WM_KEYDOWN";再 按 方向键 时:
如果 m_MyModel 有焦点则会进入 m_MyModel 的 PreTranslateMessage 里 输出 "WM_KEYDOWN";还按方向键 就没有了 因为 焦点到 其它东西了 (主对话框上 OK CANCEL)按TAB 再看看。
在 m_MyModel 没有焦点时 方向键是 TAB 键的 替代。
在 m_MyModel 有焦点时 方向键 可以 在 PreTranslateMessage 检测到。
我试了下, Create窗口时添加WS_TABSTOP没有什么效果...但是使用Tab键(解除阻塞or获取焦点?) 跟使用方向键的效果是一样的...
只有 m_MyModel 有焦点才能 接受到方向键.
我该怎么判断最初时他有没有焦点呢? 是这样的, 窗口最初创建的时候接受不了方向键(现在再加一个Tab键)之外的输入. 创建以后比如我点击一下m_MyModel之外的区域应该会导致他失去焦点吧? 但这时候也不需要通过再重按方向键来获取焦点啊...
所以叫你创建一个 Button , 创建后SetFocus, 不就可以看到焦点了.
我觉得用对话框方便 用 CWnd 里面什么都没有.
如果 m_MyModel 上 有 combo list ... 等控件,方向键会被 这些控件 捕获..
这时只能用tab 才能 到下个 控件.
if (pMsg->message == WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case VK_UP: //My code//====================第句记得return true;!!!
break;
case VK_DOWN: //My code
break;
case VK_SPACE:
case VK_RETURN: //My code
break;
...................
{
if (pMsg->message == WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case VK_UP:
case VK_DOWN:
case VK_LEFT:
case VK_RIGHT:
afxDump << pMsg->wParam << "=WM_KEYDOWN";
return TRUE;// These VK's will be captured !!! use tab to another control.
}