Re: WM_Input runtime crash
I changed RegisterRawInputDevices(Rid, 2, sizeof(Rid[0])) == FALSE)
to RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE)
Now I don't get the 1004 error, hopefully that's because the mouse initializes and not because it just skips the failure loop for some reason.
Still get the run time error of course. I assume it is one of these early return 0's? Sigh.
Re: WM_Input runtime crash
Are you trying to write a console program that processes mouse input or a windows program that displays a window and processes mouse input? You have mixed up elements of programming from each.
DefWindowProc and WM_INPUT message belong to windows programs and not console programs. However, you don't write windows programs using the standard API functions like this.
If you want a console program that processes mouse input then you don't use DefWindowsProc and WM_INPUT message.
Which are you trying to write - console or windows program? Once we know, we can better advise.
For console progams, there are a specific set of console API functions. See
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
Mouse input is dealt with using ReadConsoleInput
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
with an INPUT_RECORD of MOUSE_EVENT.
For an introduction to windows programming, see
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
For both Windows and console programming, but especially windows, you have to know what you are doing and how it all is expected to work. You can't just 'try a few things' and hope they'll do what you want. They probably won't.
For an into to windows programming I suggest
Programming Windows by Charles Petzold
http://www.amazon.co.uk/Programming-...etzold+charles
Re: WM_Input runtime crash
Quote:
Originally Posted by
2kaud
Are you trying to write a console program that processes mouse input or a windows program that displays a window and processes mouse input? You have mixed up elements of programming from each.
DefWindowProc and WM_INPUT message belong to windows programs and not console programs. However, you don't write windows programs using the standard API functions like this.
Yikes. If it's easier I could just have a program that displays a window with text and have it update with the mouse movement ala direct x mouserate checker.
I'm not sure I trust anything other than WM_INPUT to be 'raw' enough so I may have to go the windows program route.
What elements do I have that belong to console programming here though? The vast majority of it is from the ms site on wm_input.
Quote:
If you want a console program that processes mouse input then you don't use DefWindowsProc and WM_INPUT message.
Which are you trying to write - console or windows program? Once we know, we can better advise.
Ok I will restructure it as a windows program and see how far I get.
Quote:
For both Windows and console programming, but especially windows, you have to know what you are doing and how it all is expected to work. You can't just 'try a few things' and hope they'll do what you want. They probably won't.
I'm definitely getting that impression. :-)
Re: WM_Input runtime crash
Quote:
Originally Posted by
Labyrinth
Yikes. If it's easier I could just have a program that displays a window with text and have it update with the mouse movement ala
direct x mouserate checker.
Windows programs are not written in the same way as a "normal" program. Windows programs are event driven. You must write an event loop and wait for the messages to be processed.
Quote:
What elements do I have that belong to console programming here though?
The issue is not console or not console -- it is event driven and non-event driven. You can write a console program that displays "Hello World" on the console and exits -- that is not an event driven program. You can write a console program that calls GetMessage() in a loop, and does something with those messages -- that now becomes an event driven program.
One thing with your code:
Code:
LPBYTE lpb = new BYTE[dwSize];
if (lpb == NULL)
What version of Visual C++ are you using? If it is anything above 6.0, then this condition can never occur. The call to "new[]" throws an exception if it cannot fulfill the request for the memory -- it does not return NULL. There are ways to make it return NULL, but without doing that, that body of the if () condition will never be executed -- either it will be skipped over due to an exception being thrown, or lpb will always have a good value.
Regards,
Paul McKenzie
Re: WM_Input runtime crash
Ok, bit of a rewrite :-)
Code:
#include "stdafx.h"
#include "inter2.h"
#include <Strsafe.h>
#include <iostream>
//#include <sstream>
//#include <string>
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
static bool Mouse_Initialized = 0;
TCHAR szTempOutput[3000];
HRESULT hResult;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_INTER2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_INTER2));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
void mouse_init() {
if (!Mouse_Initialized) {
RAWINPUTDEVICE Rid[2];
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = 0x02;
Rid[0].dwFlags = RIDEV_NOLEGACY;
Rid[0].hwndTarget = 0;
if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) {
std::cout << "init failed " << "\n";
std::cout << GetLastError() << "\n";
}
}
Mouse_Initialized = 1;
return;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INTER2));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_INTER2);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC;
int a = 10;
char buf[64];memset(buf, 0, sizeof(char)*64);
sprintf(buf, "%d", a);
std::string mystring = buf;
char szBuffer[]="Mouse Output";
hDC = BeginPaint(hWnd, &ps);
TextOut(hDC,10,10,szBuffer,strlen(szBuffer));
TextOut(hDC,10,40,buf,strlen(buf));
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
}
case WM_INPUT:
{
mouse_init();
UINT dwSize;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize,
sizeof(RAWINPUTHEADER));
LPBYTE lpb = new BYTE[dwSize];
if (lpb == NULL)
{
return 0;
}
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize,
sizeof(RAWINPUTHEADER)) != dwSize )
OutputDebugString (TEXT("GetRawInputData does not return correct size !\n"));
RAWINPUT* raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
hResult = StringCchPrintf(szTempOutput, STRSAFE_MAX_CCH, TEXT("Mouse: usFlags=%04x ulButtons=%04x usButtonFlags=%04x usButtonData=%04x ulRawButtons=%04x lLastX=%04x lLastY=%04x ulExtraInformation=%04x\r\n"),
raw->data.mouse.usFlags,
raw->data.mouse.ulButtons,
raw->data.mouse.usButtonFlags,
raw->data.mouse.usButtonData,
raw->data.mouse.ulRawButtons,
raw->data.mouse.lLastX,
raw->data.mouse.lLastY,
raw->data.mouse.ulExtraInformation);
if (FAILED(hResult))
{
// TODO: write error handler
}
OutputDebugString(szTempOutput);
}
delete[] lpb;
//return 0;
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
This compiles but with some random warnings.
What I need now is how to get the wm_input messages into a variable/string that I can write in the window and have updated as the mouse moves. No clue how to do that.
Re: WM_Input runtime crash
Any ideas?
What needs to be done to get data.mouse.lLastX updated live on the screen?
Here's the code now after I've been poking at it.
Code:
#include "stdafx.h"
#include "inter2.h"
#include <iostream>
#include <Strsafe.h>
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
static bool Mouse_Initialized = 0;
TCHAR szTempOutput[3000];
HRESULT hResult;
int mouse_x = 0;
int mouse_y = 0;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_INTER2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_INTER2));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
void mouse_init() {
if (!Mouse_Initialized) {
RAWINPUTDEVICE Rid[2];
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = 0x02;
Rid[0].dwFlags = RIDEV_NOLEGACY;
Rid[0].hwndTarget = 0;
if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) {
std::cout << "init failed " << "\n";
std::cout << GetLastError() << "\n";
}
}
Mouse_Initialized = 1;
return;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INTER2));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_INTER2);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC;
char buf[64];memset(buf, 0, sizeof(char)*64);
sprintf_s(buf, "%d", mouse_x);
std::string mystring = buf;
char cuf[64];memset(cuf, 0, sizeof(char)*64);
sprintf_s(cuf, "%d", mouse_y);
std::string mystring2 = cuf;
char szBuffer[]="Mouse Output";
hDC = BeginPaint(hWnd, &ps);
TextOut(hDC,10,10,szBuffer,strlen(szBuffer));
TextOut(hDC,10,40,buf,strlen(buf));
TextOut(hDC,10,60,cuf,strlen(cuf));
TextOut(hDC,10,80,szTempOutput,strlen(cuf));
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
}
case WM_INPUT:
{
mouse_init();
UINT dwSize;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize,
sizeof(RAWINPUTHEADER));
LPBYTE lpb = new BYTE[dwSize];
if (lpb == NULL)
{
return 0;
}
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize,
sizeof(RAWINPUTHEADER)) != dwSize )
OutputDebugString (TEXT("GetRawInputData does not return correct size !\n"));
RAWINPUT* raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
hResult = StringCchPrintf(szTempOutput, STRSAFE_MAX_CCH, TEXT("Mouse: usFlags=%04x ulButtons=%04x usButtonFlags=%04x usButtonData=%04x ulRawButtons=%04x lLastX=%04x lLastY=%04x ulExtraInformation=%04x\r\n"),
raw->data.mouse.usFlags,
raw->data.mouse.ulButtons,
raw->data.mouse.usButtonFlags,
raw->data.mouse.usButtonData,
raw->data.mouse.ulRawButtons,
raw->data.mouse.lLastX,
raw->data.mouse.lLastY,
raw->data.mouse.ulExtraInformation);
mouse_x = raw->data.mouse.lLastX;
mouse_y = raw->data.mouse.lLastY;
if (FAILED(hResult))
{
// TODO: write error handler
}
OutputDebugString(szTempOutput);
}
delete[] lpb;
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
Re: WM_Input runtime crash
When devloping windows programs, you don't have available the console by standard so cout etc don't have any effect. With windows program you have to specially allocate a console before you can output to it. See http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
WM_INPUT message is only generated after the program has registered the input device correctly (http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx). So mouse_int() needs to be done outside of the WM_INPUT message. Initialisation like this is often done by processing the WM_CREATE message which is generated when the window is created (http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx). So I would suggest you extend the switch statement in wndproc to include WM_CREATE and put the call to mouse_int() in that case.
Re: WM_Input runtime crash
Code:
#include "stdafx.h"
#include "inter2.h"
#include <iostream>
#include <Strsafe.h>
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst;
TCHAR szTitle[MAX_LOADSTRING];
TCHAR szWindowClass[MAX_LOADSTRING];
TCHAR szTempOutput[3000];
HRESULT hResult;
char mousemsg[256];
char rawinputdevices[256];
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
void mouse_init() {
RAWINPUTDEVICE Rid[49];
UINT nDevices;
PRAWINPUTDEVICELIST pRawInputDeviceList;
if (GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)) != 0) {
return ; }
pRawInputDeviceList = (RAWINPUTDEVICELIST *)malloc(sizeof(RAWINPUTDEVICELIST) * nDevices);
GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST));
wsprintf(rawinputdevices,"Number of raw input devices: %i\n\n", nDevices);
free(pRawInputDeviceList);
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = 0x02;
Rid[0].dwFlags = RIDEV_NOLEGACY;
Rid[0].hwndTarget = 0;
if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) {
wsprintf(mousemsg,"RawInput init failed:\n");
wsprintf((LPSTR)GetLastError(), "rabbit\n" );
}
return;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INTER2));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_INTER2);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
RAWINPUT *raw;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC;
RECT rc;
hDC = BeginPaint(hWnd, &ps);
char szBuffer[]="Mouse Output";
TextOut(hDC,10,10,szBuffer,strlen(szBuffer));
GetClientRect(hWnd, &rc);
DrawText(hDC, mousemsg, strlen(mousemsg), &rc, DT_CENTER);
OffsetRect(&rc,0,200);
DrawText(hDC, rawinputdevices, strlen(rawinputdevices), &rc, DT_CENTER);
EndPaint(hWnd, &ps);
break;
}
case WM_INPUT:
{
UINT dwSize = 40;
static BYTE lpb[40];
static long maxx = 0;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT,
lpb, &dwSize, sizeof(RAWINPUTHEADER));
//RAWINPUT* raw = (RAWINPUT*)lpb;
//lpb = malloc(sizeof(LPBYTE) * dwSize);
// if (lpb == NULL)
// {
// return 0;
// }
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize,
sizeof(RAWINPUTHEADER)) != dwSize )
OutputDebugString (TEXT("GetRawInputData doesn't return correct size !\n"));
raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
long msx, msy;
msx = raw->data.mouse.lLastX;
msy = raw->data.mouse.lLastY;
//maxx = msx;
wsprintf(mousemsg,"Mouse:hDevice %d \n \nlLastX=%ld \nlLastY=%ld\r",
raw->header.hDevice,
msx,
msy);
}
InvalidateRect(hWnd,0,TRUE);
SendMessage(hWnd,WM_PAINT,0,0);
free(lpb);
return 0;
}
default:
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
int APIENTRY
WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
{
HWND hwndMain;
MSG msg;
WNDCLASSEX wndclass;
char* szMainWndClass = "WinTestWin";
memset (&wndclass, 0, sizeof(WNDCLASSEX));
wndclass.lpszClassName = szMainWndClass;
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.hInstance = hInst;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
RegisterClassEx (&wndclass);
hwndMain = CreateWindow (
szMainWndClass,
"Horsebother",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInst,
NULL
);
ShowWindow (hwndMain, nShow);
UpdateWindow (hwndMain);
mouse_init();
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
Ok should be a bit better now, and should at least get the last x and y into the window.
Not sure how to fix this lpb null business, so I just commented it out for now.
Compiles but when I run it I get a heap corruption error? Any ideas?
Re: WM_Input runtime crash
Code:
wsprintf(mousemsg,"RawInput init failed:\n");
wsprintf((LPSTR)GetLastError(), "rabbit\n" );
Shouldn't this be
Code:
wsprintf(mousemsg, "RawInput init failed: %i\n", GetLastError());
GetLastError() returns the error code which can't be cast to a char pointer!
You don't send a WM_PAINT message. InvalidateRect will cause a WM_PAINT message to be generated. See
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
lpb is now defined as a static BYTE array so the memory cannot be freed!
Re: WM_Input runtime crash
Quote:
Originally Posted by
2kaud
Shouldn't this be
Yes it should! I put rabbit there to remind me to go back and fix it at some point lol. Thanks.
Quote:
GetLastError() returns the error code which can't be cast to a char pointer!
Right ok. Fixed.
Are you saying that I shouldn't send a WM_PAINT message, or that I'm not and I should be?
Quote:
lpb is now defined as a static BYTE array so the memory cannot be freed!
Code:
case WM_INPUT:
{
UINT dwSize = 40;
//static BYTE lpb[40];
LPBYTE lpb = {0};
GetRawInputData((HRAWINPUT)lParam, RID_INPUT,
lpb, &dwSize, sizeof(RAWINPUTHEADER));
RAWINPUT* raw = (RAWINPUT*)lpb;
lpb = malloc(sizeof(LPBYTE) * dwSize);
if (lpb == NULL)
{
return 0;
}
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize,
sizeof(RAWINPUTHEADER)) != dwSize )
OutputDebugString (TEXT("GetRawInputData doesn't return correct size !\n"));
raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
long msx, msy;
msx = raw->data.mouse.lLastX;
msy = raw->data.mouse.lLastY;
wsprintf(mousemsg,"Mouse:hDevice %d \n \nlLastX=%ld \nlLastY=%ld\r",
raw->header.hDevice,
msx,
msy);
}
InvalidateRect(hWnd,0,TRUE);
SendMessage(hWnd,WM_PAINT,0,0);
free(lpb);
return 0;
}
If I just do LPBYTE lpb I get: error C2440: '=' : cannot convert from 'void *' to 'LPBYTE'
1> Conversion from 'void*' to pointer to non-'void' requires an explicit cast
That's why I had that section commented out, but I guess it's important because my program crashes on mouse over. When I ran the debugger it stops at if (raw->header.dwType == RIM_TYPEMOUSE), so it must have something to do with this.
Re: WM_Input runtime crash
Quote:
Are you saying that I shouldn't send a WM_PAINT message, or that I'm not and I should be?
You shouldn't send WM_PAINT as InvalidateRect() will do this.
If you look at the Microsoft example, they have the first part of WM_INPUT coded as
Code:
UINT dwSize;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize,
sizeof(RAWINPUTHEADER));
LPBYTE lpb = new BYTE[dwSize];
ie the first call to GetRawInputData passes NULL as the third param, not lpb as you are doing. See
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
Re: WM_Input runtime crash
Ok cool. It works without crashing now. Thanks for your help I really appreciate it. The LPBYTE thing is fixed.
One issue I am having is that it won't let me click the 'x' to close it though. It is like in frozen thinking mode, even though the numbers appear to update correctly and I can still move the mouse.
I can alt-tab to another window, then come back and get the pointer again, but I still can't close it by hitting the close button. Otherwise it remains the "hour glass".
Of course I can just close it with ALT+F4, but there's something alarming about not being able to hit the x.
Any ideas on this? The code is mostly unchanged.
Re: WM_Input runtime crash
Quote:
it won't let me click the 'x' to close it though
As you are getting mouse data as raw input via WM_INPUT, don't you need to process mouse input there if you want to do something like close the window?