A程序中通过调用ShellExecute调用程序B,B程序是一个街机模拟器mame,这时mame弹出一个子窗口,运行游戏,游戏窗口是激活的,可以接受键盘的输入,
我的问题是如何在A中向模拟器mame发送指定的键盘消息,比如现在由于游戏窗口是激活的我直接在键盘上按Esc,就可以推出游戏,我能不能在A中发送一个Esc的键盘消息给mame,从而让游戏退出?应该如何实现这个功能,能给出详细的代码吗?

解决方案 »

  1.   

    可以的。首先你要获取B程序的句柄,用hwnd = ::FindWindow();
    然后使用 ::PostMessage(hwnd,Key_Event,VK_ESC,0); 发送按键消息
      

  2.   

    ::SendMessage(hWnd,WM_CHAR,VK_ESC,0);
      

  3.   

    找到对方窗口的Handle,然后使用sendmessage或postmessage发送消息
      

  4.   

    关键是如何用FindWindow()找到B的窗口,我用“mame”,作为FindWindow()的第二个参数,可以找到mame主程序的窗口,但是mame运行游戏会弹出一个子窗口,我应该如何找到这个子窗口哦?
    如果有两个运行的word程序,一个文件名为1,另一个为2,如果要向其中一个发送消息,FindWindow()的两个参数应该怎样传?我在msdn中看到的B程序一般都是一个自己可以编程的程序,当然可以知道他的窗口类名和窗口名字,如果像word这样,我们怎么得到他的类名或者某个特定的窗口名?
      

  5.   

    你可以枚举窗口,然后取窗口的标题,看是否为“XXXX”(mame新开的一个子窗口的标题),如果是,就是这个HWND了,枚举窗口可以用://建立--------------------------------------------
    BOOL CALLBACK CHideWinDlg::EnumWindowsProc(HWND hwnd,LPARAM lparam)

    m_lCount=0;
    char lpWinTitle[256];  
             ::GetWindowText(hwnd,lpWinTitle,256-1);  
             CString m_strTitle; 
             m_strTitle.Format("%s",lpWinTitle); 
    m_strTitle.MakeUpper();
             if(m_strTitle.Find("你要的标题")!=-1) 或  //if (m_strTitle.CompareNoCase(_T("你要的标题"))==0)
    {
    //AfxMessageBox("找到了这个窗口!") ; 
                      //在这里操作吧。
      } 
           return TRUE ;
    }//在要枚举窗口的地方写下面这行
    ::EnumWindows(EnumWindowsProc,NULL);
      

  6.   

    你可以枚举窗口,然后取窗口的标题,看是否为“XXXX”(mame新开的一个子窗口的标题),如果是,就是这个HWND了,枚举窗口可以用://建立--------------------------------------------
    BOOL CALLBACK CHideWinDlg::EnumWindowsProc(HWND hwnd,LPARAM lparam)

    m_lCount=0;
    char lpWinTitle[256];  
             ::GetWindowText(hwnd,lpWinTitle,256-1);  
             CString m_strTitle; 
             m_strTitle.Format("%s",lpWinTitle); 
    m_strTitle.MakeUpper();
             if(m_strTitle.Find("你要的标题")!=-1) 或  //if (m_strTitle.CompareNoCase(_T("你要的标题"))==0)
    {
    //AfxMessageBox("找到了这个窗口!") ; 
                      //在这里操作吧。
                      ::SendMessage(hwnd,WM_CHAR,VK_ESC,0);  } 
           return TRUE ;
    }//在要枚举窗口的地方写下面这行
    ::EnumWindows(EnumWindowsProc,NULL);
      

  7.   

    非常感谢 TianChong ,枚举窗口很好用,可是PostMessage还是不行,sendMessage也不行
    代码如下:void CMainFrame::OnMenu() 
    {
    // TODO: Add your command handler code here
           ShellExecute(this->m_hWnd, "open",
    "K:\\Program Files\\MAME32K\\mame32k.exe",  "dino", NULL, SW_SHOWNA);    Sleep(3000);
           
    HWND   hwnd1=::FindWindow(NULL,"MAME: Cadillacs and Dinosaurs (World 930201) [dino]");
    char str[100];

    if (hwnd1)
    {
    ::GetWindowText(hwnd1,str,100);
    MessageBox(str);
    }
    else
    MessageBox("F");

    ::PostMessage(hwnd1,WM_KEYDOWN,VK_RETURN,NULL);
    ::PostMessage(hwnd1,WM_KEYDOWN,VK_ESCAPE,NULL);
      FILE   *hFile   =   fopen("K:\\Program Files\\MAME32K\\1.txt",   "w");     
      EnumWindows(   (   WNDENUMPROC   )   EnumWindowsProc,   (   LPARAM   )   hFile   );   
      fclose(hFile); 
    }
    这段程序,MessageBox(str);结果可以打出str的值,也符合,1.txt里面也有窗口的标题,
    就是发送消息::PostMessage(hwnd1,WM_KEYDOWN,VK_RETURN,NULL);
    ::PostMessage(hwnd1,WM_KEYDOWN,VK_ESCAPE,NULL);不能像想象中那样,那游戏退出,游戏一点反应都没有,是不是什么地方些的不对?
    大年三十,我在线上等,希望大家可以帮帮我
      

  8.   

    将:
    ::PostMessage(hwnd1,WM_KEYDOWN,VK_RETURN,NULL);
    ::PostMessage(hwnd1,WM_KEYDOWN,VK_ESCAPE,NULL);
    改为:
    ::PostMessage(hwnd1,WM_KEYDOWN,VK_RETURN,NULL);
    ::PostMessage(hwnd1,WM_KEYUP,VK_RETURN,NULL);
    ::PostMessage(hwnd1,WM_KEYDOWN,VK_ESCAPE,NULL);
    ::PostMessage(hwnd1,WM_KEYUP,VK_ESCAPE,NULL);
    因为你发送了“WM_KEYDOWN”后,还要发送“WM_KEYUP”消息,否则按下的键并没有弹起,当然不会产生效果,就算这样还是不行,你还可以发送销毁窗口的消息,让此窗口关闭。
      

  9.   

    得到那个程序的句柄,再发消息
    FindWindow
    PostMessage
      

  10.   

    ::SetForegroundWindow(m_hNeedPasteDataWnd);
    ::SetActiveWindow(m_hNeedPasteDataWnd);
    ::SetFocus(m_hNeedPasteDataWnd);keybd_event(VK_CONTROL, (BYTE)0, 0 ,0);
    keybd_event('V', (BYTE)0, 0 ,0);
    keybd_event('V', (BYTE)0, KEYEVENTF_KEYUP, 0);
    keybd_event(VK_CONTROL, (BYTE)0, KEYEVENTF_KEYUP,0);上面代码是是像另一进程窗口m_hNeedPasteDataWnd产生一个Ctrl + V击键消息.
      

  11.   

    再去翻一下<WINDOWS核心编程>中第六部分"窗口"
    第27章"硬件输入框和局部输入法状态"一章应该能找到答案.祝你好运.
      

  12.   

    感谢 Juchiyufei 问题解决了,mame不接受消息,用模拟按键keybd_event解决了keybd_event('5', MapVirtualKey('5',0), NULL ,NULL);
    Sleep(100);
    keybd_event('5', MapVirtualKey('5',0), KEYEVENTF_KEYUP ,NULL);第二个参数不能设为null,必须传递扫描码,Sleep(100);也是必须的,否则两个事件太靠近,游戏无法识别