質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
MFC

MFC (Microsoft Fouondation Class)とは、MicrosoftがVC++用に開発したWindows用アプリケーションのフレームワークです。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

3122閲覧

mfcを用いて、マウスの移動量を読み取るアプリケーションの開発

naushi

総合スコア11

MFC

MFC (Microsoft Fouondation Class)とは、MicrosoftがVC++用に開発したWindows用アプリケーションのフレームワークです。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2018/11/13 11:04

前提・実現したいこと

mfcを用いて、マウスの移動量を読み取るアプリケーションの開発をしているのですが
マウスの移動量を検出することができていません。
デバイス登録はできていることを確認しています。

発生している問題・エラーメッセージ

rawinputでマウスのデータを読み取れない ソースコードにおけるOnRawInputが実行されない

該当のソースコード

C++ MFC #include "stdafx.h" #include "MFCApplication3.h" #include "MFCApplication3Dlg.h" #include "afxdialogex.h" #include <afxwin.h > RAWINPUTHEADER g_header[12]; RAWMOUSE g_mouseInfo[12]; UINT nInputcode = 0; HRAWINPUT hRawInput = 0; LONG mouse_x_move[5]; LONG mouse_y_move[5]; LONG mouse_x_spd[5]; LONG mouse_y_spd[5]; RAWINPUT pRAWINPUT; HANDLE deviceID[10]; CMFCApplication3Dlg::CMFCApplication3Dlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_MFCAPPLICATION3_DIALOG, pParent){ for (int i = 0; i < 10; i++) { m_mouseData[i] = 0; } flg_run = 0; m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMFCApplication3Dlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); for (int i = 0; i < 5; i++) { DDX_Text(pDX, IDC_STATIC_1 + i, m_mouseData[i]); } } BEGIN_MESSAGE_MAP(CMFCApplication3Dlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDOK, &CMFCApplication3Dlg::OnBnClickedOk) ON_BN_CLICKED(IDCANCEL, &CMFCApplication3Dlg::OnBnClickedCancel) ON_BN_CLICKED(IDC_start, &CMFCApplication3Dlg::OnBnClickedstart) ON_BN_CLICKED(IDC_reset, &CMFCApplication3Dlg::OnBnClickedreset) ON_WM_TIMER() ON_WM_INPUT() ON_BN_CLICKED(IDC_BUTTON1, &CMFCApplication3Dlg::OnBnClickedButton1) END_MESSAGE_MAP() CDialogEx::OnInitDialog(); // "バージョン情報..." メニューをシステム メニューに追加します。 // IDM_ABOUTBOX は、システム コマンドの範囲内になければなりません。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != nullptr) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、 // Framework は、この設定を自動的に行います。 SetIcon(m_hIcon, TRUE); // 大きいアイコンの設定 SetIcon(m_hIcon, FALSE); // 小さいアイコンの設定 // TODO: 初期化をここに追加します。 // 現在接続されている入力デバイスの数を取得 UINT deviceNum = 0; UINT i = 0; HWND hwnd=NULL; GetRawInputDeviceList(NULL, &deviceNum, sizeof(RAWINPUTDEVICELIST)); // デバイス情報用構造体 RAWINPUTDEVICELIST* deviceList = new RAWINPUTDEVICELIST[deviceNum]; // デバイス情報の取得 if (GetRawInputDeviceList(deviceList, &deviceNum, sizeof(RAWINPUTDEVICELIST)) != deviceNum) { } else { } for (i = 0; i < 10; i++) { deviceID[i] = deviceList[i].hDevice; } // WM_INPUTで受け取れるように登録 RAWINPUTDEVICE device[1]; device[0].usUsagePage = 0x01; // マウス用の定数 device[0].usUsage = 0x02; // マウス用の定数 device[0].dwFlags = 0x00; device[0].hwndTarget = *this; //device[0].hwndTarget = hwnd; if (RegisterRawInputDevices(device, 1, sizeof(device[0])) == false) { } void CMFCApplication3Dlg::OnRawInput(UINT nInputcode, HRAWINPUT hRawInput) { LPARAM lp=NULL; UINT dwSize; GetRawInputData((HRAWINPUT)lp, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); unsigned char* lpb = new unsigned char[dwSize]; if (lpb == NULL) { // エラー return ; } if (GetRawInputData((HRAWINPUT)lp, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) { // エラー } RAWINPUT* raw = (RAWINPUT*)lpb; if (raw->header.dwType == RIM_TYPEMOUSE) { for (int i = 0; i < 10; i++) { if (raw->header.hDevice == deviceID[i]) { g_mouseInfo[i] = raw->data.mouse; g_header[i] = raw->header; m_mouseData[i] += g_mouseInfo[i].lLastX; } } delete[] lpb; } CDialogEx::OnRawInput(nInputcode, hRawInput); }

試したこと

Microsoftのusing raw inputを閲覧しサンプルプログラムを参考にコードを書き直したりしましたが、マウスの生データを得ることができませんでした。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t_obara

2018/11/13 23:09

開発したアプリが有効な状態で測定できれば良いのでしょうか。それともアプリ起動にかかわらず常時読み取りたいのでしょうか。
naushi

2018/11/14 07:33

有効な状態(起動状態)でマウスの移動量を読み取り、画面に数値を表示するようにしたいです
guest

回答1

0

ベストアンサー

手元では正しくOnInputRawが呼ばれました。

cpp

1 2// MFCApplication21Dlg.cpp : 実装ファイル 3// 4 5#include "stdafx.h" 6#include "MFCApplication21.h" 7#include "MFCApplication21Dlg.h" 8#include "afxdialogex.h" 9 10#ifdef _DEBUG 11#define new DEBUG_NEW 12#endif 13 14 15// アプリケーションのバージョン情報に使われる CAboutDlg ダイアログ 16 17class CAboutDlg : public CDialogEx 18{ 19public: 20 CAboutDlg(); 21 22// ダイアログ データ 23#ifdef AFX_DESIGN_TIME 24 enum { IDD = IDD_ABOUTBOX }; 25#endif 26 27 protected: 28 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート 29 30// 実装 31protected: 32 DECLARE_MESSAGE_MAP() 33}; 34 35CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX) 36{ 37} 38 39void CAboutDlg::DoDataExchange(CDataExchange* pDX) 40{ 41 CDialogEx::DoDataExchange(pDX); 42} 43 44BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) 45END_MESSAGE_MAP() 46 47 48// CMFCApplication21Dlg ダイアログ 49 50 51 52CMFCApplication21Dlg::CMFCApplication21Dlg(CWnd* pParent /*=NULL*/) 53 : CDialogEx(IDD_MFCAPPLICATION21_DIALOG, pParent) 54{ 55 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 56} 57 58void CMFCApplication21Dlg::DoDataExchange(CDataExchange* pDX) 59{ 60 CDialogEx::DoDataExchange(pDX); 61} 62 63BEGIN_MESSAGE_MAP(CMFCApplication21Dlg, CDialogEx) 64 ON_WM_SYSCOMMAND() 65 ON_WM_PAINT() 66 ON_WM_QUERYDRAGICON() 67 ON_WM_INPUT() 68END_MESSAGE_MAP() 69 70 71// CMFCApplication21Dlg メッセージ ハンドラー 72 73BOOL CMFCApplication21Dlg::OnInitDialog() 74{ 75 CDialogEx::OnInitDialog(); 76 77 // "バージョン情報..." メニューをシステム メニューに追加します。 78 79 // IDM_ABOUTBOX は、システム コマンドの範囲内になければなりません。 80 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 81 ASSERT(IDM_ABOUTBOX < 0xF000); 82 83 CMenu* pSysMenu = GetSystemMenu(FALSE); 84 if (pSysMenu != NULL) 85 { 86 BOOL bNameValid; 87 CString strAboutMenu; 88 bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); 89 ASSERT(bNameValid); 90 if (!strAboutMenu.IsEmpty()) 91 { 92 pSysMenu->AppendMenu(MF_SEPARATOR); 93 pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 94 } 95 } 96 97 // このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、 98 // Framework は、この設定を自動的に行います。 99 SetIcon(m_hIcon, TRUE); // 大きいアイコンの設定 100 SetIcon(m_hIcon, FALSE); // 小さいアイコンの設定 101 102 // TODO: 初期化をここに追加します。 103 104 RAWINPUTDEVICE device[1]; 105 device[0].usUsagePage = 0x01; // マウス用の定数 106 device[0].usUsage = 0x02; // マウス用の定数 107 device[0].dwFlags = 0x00; 108 device[0].hwndTarget = *this; 109 if (RegisterRawInputDevices(device, 1, sizeof(device[0])) == false) 110 { 111 112 } 113 114 return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を返します。 115} 116 117void CMFCApplication21Dlg::OnSysCommand(UINT nID, LPARAM lParam) 118{ 119 if ((nID & 0xFFF0) == IDM_ABOUTBOX) 120 { 121 CAboutDlg dlgAbout; 122 dlgAbout.DoModal(); 123 } 124 else 125 { 126 CDialogEx::OnSysCommand(nID, lParam); 127 } 128} 129 130// ダイアログに最小化ボタンを追加する場合、アイコンを描画するための 131// 下のコードが必要です。ドキュメント/ビュー モデルを使う MFC アプリケーションの場合、 132// これは、Framework によって自動的に設定されます。 133 134void CMFCApplication21Dlg::OnPaint() 135{ 136 if (IsIconic()) 137 { 138 CPaintDC dc(this); // 描画のデバイス コンテキスト 139 140 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); 141 142 // クライアントの四角形領域内の中央 143 int cxIcon = GetSystemMetrics(SM_CXICON); 144 int cyIcon = GetSystemMetrics(SM_CYICON); 145 CRect rect; 146 GetClientRect(&rect); 147 int x = (rect.Width() - cxIcon + 1) / 2; 148 int y = (rect.Height() - cyIcon + 1) / 2; 149 150 // アイコンの描画 151 dc.DrawIcon(x, y, m_hIcon); 152 } 153 else 154 { 155 CDialogEx::OnPaint(); 156 } 157} 158 159// ユーザーが最小化したウィンドウをドラッグしているときに表示するカーソルを取得するために、 160// システムがこの関数を呼び出します。 161HCURSOR CMFCApplication21Dlg::OnQueryDragIcon() 162{ 163 return static_cast<HCURSOR>(m_hIcon); 164} 165 166 167 168void CMFCApplication21Dlg::OnRawInput(UINT nInputcode, HRAWINPUT hRawInput) 169{ 170 171 TRACE(_T("OnRawInput called\n")); 172 CDialogEx::OnRawInput(nInputcode, hRawInput); 173} 174

実行結果

text

1c:****\mfcapplication21\mfcapplication21\mfcapplication21dlg.cpp(171) : atlTraceGeneral - OnRawInput called 2...

追記:2018/11/14 17:17

第一引数に勝手にでっちあげたlp(NULL)を渡しているので、関数が失敗しており、必要なサイズがdwSizeに書き込まれていません。

LPARAM lp=NULL;
GetRawInputData((HRAWINPUT)lp, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));

以下のようにすれば、より良くなるでしょう。

cpp

1void CMFCApplication21Dlg::OnRawInput(UINT nInputcode, HRAWINPUT hRawInput) 2{ 3 UINT dwSize = 0; 4 GetRawInputData(hRawInput, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); 5 unsigned char* lpb = new unsigned char[dwSize]; 6 if (lpb == NULL) 7 { 8 // エラー 9 return ; 10 } 11 if (GetRawInputData(hRawInput, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) 12 { 13 14 // エラー 15 } 16 RAWINPUT* raw = (RAWINPUT*)lpb; 17 18 if (raw->header.dwType == RIM_TYPEMOUSE) { 19 for (int i = 0; i < 10; i++) { 20 if (raw->header.hDevice == deviceID[i]) { 21 g_mouseInfo[i] = raw->data.mouse; 22 g_header[i] = raw->header; 23 m_mouseData[i] += g_mouseInfo[i].lLastX; 24 } 25 } 26 27 } 28 29 delete[] lpb; 30 CDialogEx::OnRawInput(nInputcode, hRawInput); 31}

本題とはそれますが、気になった点も挙げておきます。

  • APIはエラー処理を正しくやりましょう。
  • グローバル変数を使うのは極力やめましょう。
  • '10'といったマジックナンバーを使うのはやめましょう(#defineかenumかvectorのような可変長配列を使いましょう)

投稿2018/11/14 07:20

編集2018/11/14 08:20
takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

naushi

2018/11/14 07:59

ソースコードを載せていただきありがとうございます。 私の手元でもOnRawInputが呼ばれていることを確認しました。 しかし、OnRawInputの中でマウスの移動量(lLastX)を受け取り画面に表示しようとする処理を加えるとメモリ不足であるとの警告のメッセージが出てきます。 移動量を読み取り画面に表示させたいのですが、どのような処理を行えばよいのでしょうか?
takabosoft

2018/11/14 08:22 編集

回答を追記しました。「ソースコードにおけるOnRawInputが実行されない」というような誤った情報は載せないでくださいね。
naushi

2018/11/14 09:19

ありがとうございます。参考にさせていただいてエラーも出なくなりました。また、デバックしてマウスのデータが読み取れていることを確認しました。 まだ勉強中のために分かっていないことが多いですが、アドバイスを参考にして開発を続けていきたいと思います。
naushi

2018/11/14 09:32

最後に質問なのですが、OnRawInputで得たデータ(lLastX,lLastY)を別の関数で処理したい場合はどのようにデータの受け渡しすればよいのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問