WM_MOUSEMOVE

Any programming topics about device input and output here

Re: WM_MOUSEMOVE

Postby sinyester » Fri Oct 09, 2009 9:01 am

Thanks for the huge efford for making that demo Hieran_Del8! :D

The input works now! 8-)
I don't really know what I changed but I think I moved the definitions for the Rawinput mouse device!

I will put up the client version of the *game* when i've gotten a little further with it in the showcase section here. So you can take a look of what you helped me accomplish :lol:

The things that are working atm is:

Character moving
Simple character frameanimation
Collision layer (player vs tiles, not player vs objects yet)
Camera collision (so it doesn't go outside the map)
Texture loading
Tilemap (saving/loading to / from textfiles)
Simple textdisplay
Simple Mapeditor (in game)
Sprites (for HUD)

And there's a clientserver running in the background of the game: which can receive data and print it out on the screen.
( :!: thanks lonewolf for superb tutorials :!: )
User avatar
sinyester
Regular
 
Posts: 45
Joined: Sun Aug 23, 2009 3:38 am
Location: Sweden

Re: WM_MOUSEMOVE

Postby Hieran_Del8 » Sat Oct 10, 2009 1:30 am

No problem. Glad to help! :)

I look forward to the game you're developing--lots of heavy work accomplished in the running list. Good job!
Image
User avatar
Hieran_Del8
Most Valuble Contributor
 
Posts: 349
Joined: Thu Nov 06, 2008 4:59 am
Location: Marengo, IL

Re: WM_MOUSEMOVE

Postby Hieran_Del8 » Sun Oct 11, 2009 7:15 am

I seem to have made an error. For some reason, RIDEV_CAPTUREMOUSE as an optional flag will not function correctly. Also, its usage is slightly different then I previously stated. To clarify, according to windows docs, this flag:
Windows SDK Nov 2008 wrote:If set, the mouse button click does not activate the other window[s].
If and when I figure out why it isn't working in my app, I'll post. (You don't need that flag. I actually prefer not using it, but now this bug bothers me. I'll be on it.)

EDIT:
To clarify again, the example app I posted works fine. Still haven't researched how to get that RIDEV_CAPTUREMOUSE option working yet.
Image
User avatar
Hieran_Del8
Most Valuble Contributor
 
Posts: 349
Joined: Thu Nov 06, 2008 4:59 am
Location: Marengo, IL

Re: WM_MOUSEMOVE

Postby sinyester » Sun Oct 11, 2009 7:43 pm

hmm okey.

While i'm still here, is there a function/prop that bounds the mouse so it can't go outside the boundary of the *game* window?
Atm i'm using a object ingame and translates it by mouse, but I may switch to windowsmouse for menus and such!

:roll:
Quote of the day: The real number of the beast is int* int* int*!
User avatar
sinyester
Regular
 
Posts: 45
Joined: Sun Aug 23, 2009 3:38 am
Location: Sweden

Re: WM_MOUSEMOVE

Postby Hieran_Del8 » Mon Oct 12, 2009 8:25 am

Well, kind of. I have to go right now, but I'll get back to you. :)
Image
User avatar
Hieran_Del8
Most Valuble Contributor
 
Posts: 349
Joined: Thu Nov 06, 2008 4:59 am
Location: Marengo, IL

Re: WM_MOUSEMOVE

Postby Hieran_Del8 » Tue Oct 13, 2009 2:40 pm

Ok. This function is dangerous, as the cursor is a shared resource. Remember that whatever you allocate, you must release in the end. This definitely applies here. Enter ClipCursor().

ClipCursor() is a nifty way to confine the cursor to a specific screen rectangle. It only has one parameter, a RECT to restrict movement to. If the parameter is NULL, the cursor is released to the whole screen space. Following is an example app that uses GetClipCursor(), ClipCursor(), and GetWindowRect() to restrict the mouse cursor to a rectangular screen space:
Code: Select all
//ClipCursor demo.cpp
//by Jay Tennant 10/12/09
//demonstrates ClipCursor() and GetClipCursor() to restrict mouse cursor movement

#include <windows.h>

RECT g_rcOriginal; //original area mouse is restricted to
RECT g_rcClientArea; //client area created by window that mouse will be restricted to

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
{
   HWND hWnd = NULL;
   WNDCLASSEX wc = {0};
   MSG msg;

   wc.cbSize = sizeof(wc);
   wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
   wc.hCursor = LoadCursor(0, IDC_ARROW);
   wc.hIcon = LoadIcon(0, IDI_APPLICATION);
   wc.hIconSm = LoadIcon(0, IDI_APPLICATION);
   wc.hInstance = hInst;
   wc.lpfnWndProc = (WNDPROC)WndProc;
   wc.lpszClassName = TEXT("ClipCursorDemo_WindowClass");
   wc.style = CS_HREDRAW | CS_VREDRAW;

   RegisterClassEx(&wc);

   hWnd = CreateWindowEx(0,
                    TEXT("ClipCursorDemo_WindowClass"),
                    TEXT("ClipCursor() Demo"),
                    WS_OVERLAPPEDWINDOW,
                    0,
                    0,
                    800,
                    600,
                    0,
                    0,
                    hInst,
                    0);
   ShowWindow(hWnd, nShowCmd);
   UpdateWindow(hWnd);

   GetClipCursor(&g_rcOriginal); //get original clip area, will be restored at end
   GetWindowRect(hWnd, &g_rcClientArea); //get screen area covered by client
   ClipCursor(&g_rcClientArea); //restrict mouse cursor to client's clip area

   while(GetMessage(&msg, 0, 0, 0))
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }

   //restore original clip area (may be whole screen space)
   ClipCursor(&g_rcOriginal); //specifying NULL releases to the whole screen

   return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
   switch(msg)
   {
   case WM_DESTROY:
      {
         PostQuitMessage(0);
      } break;
   default:
      return DefWindowProc(hWnd, msg, wParam, lParam);
   }
   return 0;
}


EDIT: To clarify, confining the mouse pointer does not affect raw input received from the mouse. ;)
Image
User avatar
Hieran_Del8
Most Valuble Contributor
 
Posts: 349
Joined: Thu Nov 06, 2008 4:59 am
Location: Marengo, IL

Re: WM_MOUSEMOVE

Postby Hieran_Del8 » Thu Oct 29, 2009 1:25 pm

Hieran_Del8 wrote:Ok, the vsync issue. When using mouse as input and having multiple backbuffers in video sync, it is possible to have mouse lag--that is, the mouse movement has a delayed affect on the frames displayed. One remedy is disabling vsync. In the d3d presentation parameters, set the presentation interval to D3DPRESENT_INTERVAL_IMMEDIATE. That's it.

I don't disable vsync, because I don't like graphical tears, and I rarely notice mouse lag. Others may be more affected by it, though.

Just following up on this earlier post. There is another remedy to this situation that preserves video sync and keeps the window's messages flowing: run the message pump in the extra time in between the frame presentations. For instance:
Code: Select all
MSG msg;
bool bAppRunning = true;
while(bAppRunning)
{
   if(PeekMessage(g_hWnd, 0, 0, PM_REMOVE))
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
      if(msg.message == WM_QUIT)
      {
         bAppRunning = false;
         break;
      }
   }

   static DWORD dwFrameControl = GetTickCount();

   d3ddev->BeginScene();
   //... drawing frame ...
   d3ddev->EndScene();
   d3ddev->Present(0,0,0,0);

   while(GetTickCount() - dwFrameControl < 17)
   {
      if(PeekMessage(g_hWnd, 0, 0, PM_REMOVE))
      {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
         if(msg.message == WM_QUIT)
         {
            bAppRunning = false;
            break;
         }
      }
   }
   dwFrameControl = GetTickCount();
}

Notice how the message pump runs twice: once at the beginning (to determine upon entry into the function whether to quit the app), and once continuously at the end until 17 milliseconds have passed (1/60th of a second, a standard monitor framerate). Because dwFrameControl is declared static, its value persists between function calls, causing the last continuous message pump to run during the time the rest of the program does not need extra cycles.

By implementing this, you can have raw input, vsync, and no mouse lag! You can adjust the 17 milliseconds to whatever value fits your needs. Just make sure it's at least as long as the presentation interval (usually is 60hz = 1 frame per 1/60th second = 1 frame per 17 milliseconds).
Image
User avatar
Hieran_Del8
Most Valuble Contributor
 
Posts: 349
Joined: Thu Nov 06, 2008 4:59 am
Location: Marengo, IL

Re: WM_MOUSEMOVE

Postby Hieran_Del8 » Thu Jul 01, 2010 6:49 pm

Hieran_Del8 wrote:I seem to have made an error. For some reason, RIDEV_CAPTUREMOUSE as an optional flag will not function correctly. Also, its usage is slightly different then I previously stated. To clarify, according to windows docs, this flag:
Windows SDK Nov 2008 wrote:If set, the mouse button click does not activate the other window[s].
If and when I figure out why it isn't working in my app, I'll post. (You don't need that flag. I actually prefer not using it, but now this bug bothers me. I'll be on it.)

Well, I finally have an answer for this. According to Ondrej Spanel in the msdn community docs:
Ondrej Spanel wrote:RIDEV_CAPTUREMOUSE requires RIDEV_NOLEGACY

As seen in the header file, if you want to set RIDEV_CAPTUREMOUSE, you need to set RIDEV_NOLEGACY as well:

#define RIDEV_CAPTUREMOUSE 0x00000200 // effective when mouse nolegacy is specified, otherwise it would be an error


Also, as follow up to the previous post on preserving vsync and raw input, the easiest method is:
Code: Select all
while(!bQuitting)
{
   if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
   {
      if(msg.message == WM_QUIT)
         bQuitting = true;
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }
   else
   {
      ...do stuff...
   }
}
Image
User avatar
Hieran_Del8
Most Valuble Contributor
 
Posts: 349
Joined: Thu Nov 06, 2008 4:59 am
Location: Marengo, IL

Re: WM_MOUSEMOVE

Postby Lonewolff » Fri Sep 03, 2010 5:00 pm

Moved topic to I/O as I have found this to be extremely useful.

Thanks Heiran_Del8 8-)
Image
User avatar
Lonewolff
Site Admin
 
Posts: 268
Joined: Thu Oct 30, 2008 3:40 pm

Re: WM_MOUSEMOVE

Postby Lonewolff » Fri Sep 03, 2010 6:16 pm

I have been trying to implement this into my own code but dont seem to be getting any response whatsoever from WM_INPUT. Arrgh!

This is my Callback procedure, incase I am doing something stupid after hours of programming (you know how it gets :oops: )

Code: Select all
LRESULT CALLBACK Engine::WindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
   switch(message)
   {
      case WM_DESTROY:
      {
         PostQuitMessage(0);
      }
      break;
      case WM_INPUT:
      {
         MessageBox(NULL,"","",NULL);
         RAWINPUT input;
         UINT nSize=sizeof(input);
         GetRawInputData((HRAWINPUT)lParam,RID_INPUT,&input,&nSize,sizeof(input.header));
         if(processMouseX(&input))
            processMouseY(&input);
      }
      break;
   }
   return DefWindowProc(hWnd,message,wParam,lParam);
}

I would expect to see a blank message box when I move the mouse. But nothing yet.

WM_DESTROY works ok though :roll:
Image
User avatar
Lonewolff
Site Admin
 
Posts: 268
Joined: Thu Oct 30, 2008 3:40 pm

PreviousNext

Return to Input / Output

Who is online

Users browsing this forum: No registered users and 0 guests