CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    Join Date
    Nov 2013
    Posts
    11

    WM_Input runtime crash

    I am a novice programmer trying to create the following application:

    1. Can just be a simple CLI program.

    2. Gets mouse input from WM_Input, not for buttons just whatever the mouse sends for left/right/up/down.

    3. When a mouse event is received a timer starts.

    4. If there has not been a mouse event for x amount of milliseconds, stop the timer, report the time elapsed with the idle time subtracted along with the counts that were received during the time interval.

    5. Program then idles and waits for another mouse event. Perhaps it can wait on some key to quit (although I could just ctrl+c).

    I think I can figure out the timer part (#include <ctime>?). I should be able to figure out the printing of the x and y variables provided I can get it to 'live update'.

    The WM_INPUT stuff is over my head though. I tried using the MS example, but it says "case WM_INPUT" which would need a switch would it not? I just did if WM_INPUT whatever it equals so that control could look through the rest of the code.

    It compiles but doesn't run without crashing. Running it I get a runtime error "application has requested the Runtime to terminate it in an unusual way".

    If I put init() in main I get an init failed with invalid flag (getlasterror 1004). RIDEV_NOLEGACY is a valid flag though. Maybe when I removed the keyboard stuff from the MS example it's no longer asking for the right variable or somet. I'm so confused.

    Any help is greatly appreciated. Thank you for your time.

    Code:
    #include <Windows.h>
    #include <iostream>
    #include <Strsafe.h>
    
    static bool Mouse_Initialized = 0;
    HRESULT hResult;
    TCHAR szTempOutput[3000];
    
    void 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, 2, sizeof(Rid[0])) == FALSE) {
    			
    				std::cout << "init failed " << "\n"; 
    				std::cout << GetLastError() << "\n";
    				}
    
    			}
    
    	Mouse_Initialized = 1;
    
    	return;
    }
    
    
    
    int main() {
    
            init();
    
    	MSG msg = {0};
    
    	DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
    
    	if (WM_INPUT == 0x00FF) { 
    
        UINT dwSize;
    
        GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, NULL, &dwSize, 
                        sizeof(RAWINPUTHEADER));
        LPBYTE lpb = new BYTE[dwSize];
    
        if (lpb == NULL) 
        {
    		std::cout << "lpb == NULL" << "\n"; 
            return 0;
        } 
    
        if (GetRawInputData((HRAWINPUT)msg.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: lLastX=%04x lLastY=%04x \r\n"), 
               
                raw->data.mouse.lLastX, 
                raw->data.mouse.lLastY); 
                
    
    		if (FAILED(hResult))
    		{
    		// TODO: write error handler
    			std::cout << "FAILED(hResult)" << "\n";
    		}
            OutputDebugString(szTempOutput);
        } 
    
        delete[] lpb; 
        return 0;
    }
    	
    return 0;
    
    }

  2. #2
    Join Date
    Nov 2013
    Posts
    11

    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.

  3. #3
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    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
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  4. #4
    Join Date
    Nov 2013
    Posts
    11

    Re: WM_Input runtime crash

    Quote Originally Posted by 2kaud View Post
    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.

    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.

    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. :-)

  5. #5
    Join Date
    Apr 1999
    Posts
    27,449

    Re: WM_Input runtime crash

    Quote Originally Posted by Labyrinth View Post
    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.
    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
    Last edited by Paul McKenzie; November 16th, 2013 at 10:14 PM.

  6. #6
    Join Date
    Nov 2013
    Posts
    11

    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.

  7. #7
    Join Date
    Nov 2013
    Posts
    11

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

  8. #8
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    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.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  9. #9
    Join Date
    Nov 2013
    Posts
    11

    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?

  10. #10
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    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!
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  11. #11
    Join Date
    Nov 2013
    Posts
    11

    Re: WM_Input runtime crash

    Quote Originally Posted by 2kaud View Post
    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.

    GetLastError() returns the error code which can't be cast to a char pointer!
    Right ok. Fixed.

    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
    Are you saying that I shouldn't send a WM_PAINT message, or that I'm not and I should be?

    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.

  12. #12
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: WM_Input runtime crash

    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
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  13. #13
    Join Date
    Nov 2013
    Posts
    11

    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.
    Last edited by Labyrinth; November 17th, 2013 at 07:35 PM.

  14. #14
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: WM_Input runtime crash

    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?
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured