解决方案 »

  1.   

    用法不对。PreTranslateMessage(MSG* pMsg)函数仅用于完成函数注册。具体操作响应代码写到要写到OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)函数里面。如下所示:
    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);
    }
      

  2.   


    我的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);
    }
      

  3.   

    1. 你是在PreTranslateMessage里面再调用OnKeyDown的, 但我调试的时候发现第一次按下方向键以及其他按键的时候跟本就进不到PreTranslateMessage函数里面, 只有在按下一次方向键之后, 再按其他按键才能进入PreTranslateMessage里面, 此后就一切正常了...
    2. PreTranslateMessage这个函数我以前也用过, 我看网上大部分人都这么用的, 也没啥问题. 但我以前也是用的对话框类里面的PreTranslateMessage, 现在我这个窗口类是继承自Cwnd的, 可以看上一楼的详细代码....
    3. 目前我找到一个妥协的办法, 就是我上面提到的, 在窗口弹出之前人为添加一条模拟方向键按下的消息. 我选择在OnSize函数的最后加上了一句
    ::PostMessage(m_hWnd, WM_KEYDOWN, VK_LEFT, 0);
    然后再运行的时候就没有任何问题了...
    4. 我感觉就是最初PreTranslateMessage被阻塞掉了, 而只有四个方向键能解除阻塞. 但实在不理解为什么...
      

  4.   

    View 不在 激活 状态 ?
    有没有 加速键 ?
      

  5.   


    View? 我就是对话框窗口哈, 然后在界面上新建一个基于CWnd的窗口类进行显示的, 跟文档视图里面的View应该没关系吧?
    加速键是什么?
      

  6.   

    “新建一个基于CWnd的窗口类进行显示的”
    看看这部分代码加速键  就是 资源里的 accelerator
      

  7.   

    你输入的时候CModelView 是否focus?窗体上边是否还有其他控件存在?
      

  8.   

    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); 
    上面的代码是在对话框主程序里面调用的.我没用过加速键, 您的意思是我这种在主窗口里面开辟的子窗口应该使用加速键吗?
      

  9.   


    按下按键之前可以接受鼠标操作的(可以用鼠标来控制模型旋转位置什么的), 应该已经focus了吧?..对话框界面上面就只有初始的确定和取消两个按钮, 没有其他的控件了
      

  10.   

    对话框主程序  :OnInitDialog() ?
    代码给全点不行吗 ?
    :OnInitDialog() 
    里有没有设置焦点?
      

  11.   

    "m_MyModel->Create(NULL,NULL,"
    没有类名?
      

  12.   


    我不是在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); 
    }
    }
      

  13.   

    "m_MyModel->Create(NULL,NULL,"查查类名  GetClassName()没有焦点 ?
      

  14.   


    加上了这么两句:
    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还是空的啊...
      

  15.   

    “按一下四个方向键其中之一后”有时 与 TAB 有 相同 功能, 创建
     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”
      

  16.   


    按下按键之前可以接受鼠标操作的(可以用鼠标来控制模型旋转位置什么的), 应该已经focus了吧?..对话框界面上面就只有初始的确定和取消两个按钮, 没有其他的控件了BOOL CXXXDialog::OnInitDialog()
    {
    CDialog::OnInitDialog(); // TODO:  在此添加额外的初始化
            ..............................
    return TRUE;  // return TRUE unless you set the focus to a control//注意这一行代码的意思,你要初始化对话框以后想把焦点放到控件上,需要return FALSE!!!!!!
    // 异常: OCX 属性页应返回 FALSE
    }
      

  17.   

    可以这样搞:
    创建:
    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 再看看。
      

  18.   

    结论:
    在  m_MyModel  没有焦点时 方向键是  TAB 键的 替代。
    在  m_MyModel  有焦点时 方向键 可以 在 PreTranslateMessage 检测到。
      

  19.   


    我试了下, Create窗口时添加WS_TABSTOP没有什么效果...但是使用Tab键(解除阻塞or获取焦点?) 跟使用方向键的效果是一样的...
      

  20.   

    create里面可以创建IDOK按钮? 感觉比我在代码里面人工发送一条方向键消息差不多...都不是从本质上解决问题...
      

  21.   

    ".都不是从本质上解决问题" 创建Button 不是要.解决问题, 而是要 验证问题.
    只有 m_MyModel  有焦点才能 接受到方向键.
      

  22.   


    我该怎么判断最初时他有没有焦点呢? 是这样的, 窗口最初创建的时候接受不了方向键(现在再加一个Tab键)之外的输入. 创建以后比如我点击一下m_MyModel之外的区域应该会导致他失去焦点吧? 但这时候也不需要通过再重按方向键来获取焦点啊...
      

  23.   

    "该怎么判断最初时他有没有焦点"
    所以叫你创建一个 Button , 创建后SetFocus, 不就可以看到焦点了.
    我觉得用对话框方便 用 CWnd 里面什么都没有.
      

  24.   

    另外
    如果 m_MyModel  上 有 combo    list ... 等控件,方向键会被 这些控件 捕获..
    这时只能用tab 才能 到下个 控件.
      

  25.   


    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;
                 ...................

      

  26.   

    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.
           }
      

  27.   

    结贴: 最终还是没有解决..不过还是感谢@schlafenhamster哈,很有耐心~