点击这里下载源代码
2011年8月4日 17:11:29
准备工作:4.当关闭程序时,读取手柄控制bool型变量为false,使得读取手柄数据线程终止,等待读取手柄数据线程终止后程序退出.
// Joystick_Test1Dlg.h : 头文件 // #pragma once // ############################################################################# // ############################################################################# #include <XInput.h> #include "afxwin.h" #pragma comment(lib, "XInput.lib") // ############################################################################# // ############################################################################# // CJoystick_Test1Dlg 对话框 class CJoystick_Test1Dlg : public CDialog { // 构造 public: CJoystick_Test1Dlg(CWnd* pParent = NULL); // 标准构造函数 // 对话框数据 enum { IDD = IDD_JOYSTICK_TEST1_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: HICON m_hIcon; // 生成的消息映射函数 virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: afx_msg void OnBnClickedButton1(); public: afx_msg void OnBnClickedButtonInitialize(); public: afx_msg void OnBnClickedButtonVibrate(); public: // 手柄状态变量 XINPUT_STATE m_ControlerState; public: CButton m_buttonVibrate; public: // true时读取数据,false停止读取 bool m_bRead; public: afx_msg void OnClose(); public: // 线程句柄 CWinThread* m_threadHandle; public: CButton m_buttonDpadUp; public: CButton m_buttonDpadLeft; public: CButton m_buttonDpadDown; public: CButton m_buttonDpadRight; public: CButton m_buttonLeftShoulder; public: CButton m_buttonBack; public: CButton m_buttonStart; public: CButton m_buttonY; public: CButton m_buttonX; public: CButton m_buttonA; public: CButton m_buttonB; public: CButton m_buttonRightShoulder; public: CButton m_buttonInitialize; public: XINPUT_VIBRATION m_vibration; public: CButton m_buttonStopVibrate; public: afx_msg void OnBnClickedButtonStopVibrate(); };
// Joystick_Test1Dlg.cpp : 实现文件 // #include "stdafx.h" #include "Joystick_Test1.h" #include "Joystick_Test1Dlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialog { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // CJoystick_Test1Dlg 对话框 CJoystick_Test1Dlg::CJoystick_Test1Dlg(CWnd* pParent /*=NULL*/) : CDialog(CJoystick_Test1Dlg::IDD, pParent) , m_bRead(false) , m_threadHandle(NULL) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CJoystick_Test1Dlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_BUTTON_VIBRATE, m_buttonVibrate); DDX_Control(pDX, IDC_BUTTON_DPAD_UP, m_buttonDpadUp); DDX_Control(pDX, IDC_BUTTON_DPAD_LEFT, m_buttonDpadLeft); DDX_Control(pDX, IDC_BUTTON_DPAD_DOWN, m_buttonDpadDown); DDX_Control(pDX, IDC_BUTTON_DPAD_RIGHT, m_buttonDpadRight); DDX_Control(pDX, IDC_BUTTON_LEFT_SHOULDER, m_buttonLeftShoulder); DDX_Control(pDX, IDC_BUTTON_BACK, m_buttonBack); DDX_Control(pDX, IDC_BUTTON_START, m_buttonStart); DDX_Control(pDX, IDC_BUTTON_Y, m_buttonY); DDX_Control(pDX, IDC_BUTTON_X, m_buttonX); DDX_Control(pDX, IDC_BUTTON_A, m_buttonA); DDX_Control(pDX, IDC_BUTTON_B, m_buttonB); DDX_Control(pDX, IDC_BUTTON_RIGHT_SHOULDER, m_buttonRightShoulder); DDX_Control(pDX, IDC_BUTTON_INITIALIZE, m_buttonInitialize); DDX_Control(pDX, IDC_BUTTON_STOP_VIBRATE, m_buttonStopVibrate); } BEGIN_MESSAGE_MAP(CJoystick_Test1Dlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_BUTTON_INITIALIZE, &CJoystick_Test1Dlg::OnBnClickedButtonInitialize) ON_BN_CLICKED(IDC_BUTTON_VIBRATE, &CJoystick_Test1Dlg::OnBnClickedButtonVibrate) ON_WM_CLOSE() ON_BN_CLICKED(IDC_BUTTON_STOP_VIBRATE, &CJoystick_Test1Dlg::OnBnClickedButtonStopVibrate) END_MESSAGE_MAP() // CJoystick_Test1Dlg 消息处理程序 BOOL CJoystick_Test1Dlg::OnInitDialog() { CDialog::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CJoystick_Test1Dlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CJoystick_Test1Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标显示。 // HCURSOR CJoystick_Test1Dlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } UINT ReadJoystickThread(LPVOID lpParm) { CJoystick_Test1Dlg *dlg = (CJoystick_Test1Dlg*)lpParm; XINPUT_GAMEPAD gamepad; CString temp; while(XInputGetState(0, &(dlg->m_ControlerState)) == ERROR_SUCCESS && dlg->m_bRead) { gamepad = dlg->m_ControlerState.Gamepad; temp.Format(L"%hd/%hd", gamepad.sThumbLX, gamepad.sThumbLY); dlg->SetDlgItemText(IDC_EDIT_LEFT_THUMBSTICK, temp); temp.Format(L"%hd/%hd", gamepad.sThumbRX, gamepad.sThumbRY); dlg->SetDlgItemText(IDC_EDIT_RIGHT_THUMBSTICK, temp); temp.Format(L"%u", gamepad.bLeftTrigger); dlg->SetDlgItemText(IDC_EDIT_LEFT_TRIGGER,temp); temp.Format(L"%u", gamepad.bRightTrigger); dlg->SetDlgItemText(IDC_EDIT_RIGHT_TRIGGER, temp); (gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) ? (dlg->m_buttonDpadUp.EnableWindow(TRUE)): (dlg->m_buttonDpadUp.EnableWindow(FALSE)); (gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) ? (dlg->m_buttonDpadDown.EnableWindow(TRUE)) : (dlg->m_buttonDpadDown.EnableWindow(FALSE)); (gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)?(dlg->m_buttonDpadLeft.EnableWindow(TRUE)):(dlg->m_buttonDpadLeft.EnableWindow(FALSE)); (gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)?(dlg->m_buttonDpadRight.EnableWindow(TRUE)):(dlg->m_buttonDpadRight.EnableWindow(FALSE)); (gamepad.wButtons & XINPUT_GAMEPAD_START)?(dlg->m_buttonStart.EnableWindow(TRUE)):(dlg->m_buttonStart.EnableWindow(FALSE)); (gamepad.wButtons & XINPUT_GAMEPAD_BACK)?(dlg->m_buttonBack.EnableWindow(TRUE)):(dlg->m_buttonBack.EnableWindow(FALSE)); (gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER)?(dlg->m_buttonLeftShoulder.EnableWindow(TRUE)):(dlg->m_buttonLeftShoulder.EnableWindow(FALSE)); (gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER)?(dlg->m_buttonRightShoulder.EnableWindow(TRUE)):(dlg->m_buttonRightShoulder.EnableWindow(FALSE)); (gamepad.wButtons & XINPUT_GAMEPAD_A)?(dlg->m_buttonA.EnableWindow(TRUE)):(dlg->m_buttonA.EnableWindow(FALSE)); (gamepad.wButtons & XINPUT_GAMEPAD_B)?(dlg->m_buttonB.EnableWindow(TRUE)):(dlg->m_buttonB.EnableWindow(FALSE)); (gamepad.wButtons & XINPUT_GAMEPAD_X)?(dlg->m_buttonX.EnableWindow(TRUE)):(dlg->m_buttonX.EnableWindow(FALSE)); (gamepad.wButtons & XINPUT_GAMEPAD_Y)?(dlg->m_buttonY.EnableWindow(TRUE)):(dlg->m_buttonY.EnableWindow(FALSE)); } return 0; } void CJoystick_Test1Dlg::OnBnClickedButtonInitialize() { // TODO: 在此添加控件通知处理程序代码 //初始化游戏手柄 ZeroMemory(&m_ControlerState, sizeof(XINPUT_STATE)); if (XInputGetState(0, &m_ControlerState) != ERROR_SUCCESS) { MessageBox(_T("No Controller Connected!")); return; } else { m_buttonVibrate.EnableWindow(TRUE); m_bRead = true; m_threadHandle = AfxBeginThread(ReadJoystickThread, this, THREAD_PRIORITY_NORMAL, 0, 0, NULL); m_buttonInitialize.EnableWindow(FALSE); } } void CJoystick_Test1Dlg::OnBnClickedButtonVibrate() { // TODO: 在此添加控件通知处理程序代码 //震动游戏手柄 ZeroMemory(&m_vibration, sizeof(XINPUT_VIBRATION)); m_vibration.wLeftMotorSpeed = 60000; m_vibration.wRightMotorSpeed = 60000; XInputSetState(0, &m_vibration); m_buttonVibrate.EnableWindow(FALSE); m_buttonStopVibrate.EnableWindow(TRUE); } void CJoystick_Test1Dlg::OnClose() { // TODO: 在此添加消息处理程序代码和/或调用默认值 WaitForSingleObject(m_threadHandle, INFINITE); m_bRead = false; CDialog::OnClose(); } void CJoystick_Test1Dlg::OnBnClickedButtonStopVibrate() { // TODO: 在此添加控件通知处理程序代码 ZeroMemory(&m_vibration, sizeof(XINPUT_VIBRATION)); XInputSetState(0, &m_vibration); m_buttonVibrate.EnableWindow(TRUE); m_buttonStopVibrate.EnableWindow(FALSE); }