Introduction
I wanted to add multiple mouse inputs to my applications. I've written several multi-player games which use Nintendo's Wiimote, and have found that it is easiest to develop the apps using mice first, then add Wiimote support later. Microsoft just released a new MultiPoint SDK, but it doesn't support C++, and I wanted to add this support to some older apps I wrote in VC++ 6.0. So maybe, this will help someone else.
There are several apps I've released on my blog (nwpodcast.blogspot.com) that use or will use this with mice or Wiimotes, and I've always enjoyed CodeProject, so I thought I'd contribute.
Background
There are several options out there of drivers people have written - a Google search for "MouseParty", "raw_mouse", and "ManyMouse" will help you learn more about what is available. I chose to use Ryan Gordon's "ManyMouse" code. You can find it here: http://icculus.org/manymouse/. It provides the raw button, mouse-wheel, and movement data to use.
You must use XP or greater to have the OS actually see multiple mouse devices, though I haven't actually confirmed this.
Using the code
For my MFC-based Dialog project, I simply created a new ManyMouse object, and then monitored and maintained the individual cursors for each mouse manually. I tried to document the demo code because that is the best way to see how it works.
First, we init the ManyMouse object like this:
int m_mice = ManyMouse_Init();
The next thing is to override the mouse related messages from Windows - like WM_LBUTTONDOWN
and WM_MOUSEMOVE
. In these functions we just detect which mouse moved, and adjust the tracking cursor data for each:
void CManyMouseDlgDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
CString junk;
if(m_2cursors){
ManyMouseEvent event;
while (ManyMouse_PollEvent(&event)) {
if (event.type == MANYMOUSE_EVENT_BUTTON){
if(event.device == 1){ m_m0=TRUE;
m_hit = m_cursor1point;
Invalidate(FALSE); return;
}
if(event.device == 0){ m_m1=TRUE;
m_hit = m_cursor2point;
Invalidate(FALSE); return; }
}
} }
}
void CManyMouseDlgDlg::OnMouseMove(UINT nFlags, CPoint point)
{
if(m_2cursors){
ManyMouseEvent event;
while (ManyMouse_PollEvent(&event)) {
if (event.type == MANYMOUSE_EVENT_RELMOTION) {
if(event.device == 1){ if(event.item == 0) { m_cursor1point.x = m_cursor1point.x + event.value; }
else { m_cursor1point.y = m_cursor1point.y + event.value; }
m_cursor1moved = TRUE;
}
if(event.device == 0){
if(event.item == 0) { m_cursor2point.x = m_cursor2point.x + event.value; }
else { m_cursor2point.y = m_cursor2point.y + event.value; }
m_cursor2moved = TRUE;
} } } Invalidate(FALSE); } else { CDialog::OnMouseMove(nFlags, point); }
}
Note that I keep it pretty simple and exposed - it can be cleaned up quite a bit, but this is to explain it, right? The other thing to note is that I invalidate the window to force it to redraw and allow me to manually draw in the multiple cursors or indicate if we had a button press:
if(m_m0){
junk.Format("Button 0 FIRED!");
m_m0 = FALSE;
dc.TextOut(m_hit.x,m_hit.y,junk);
}
if(m_2cursors){ if(m_cursor2moved){ dc.MoveTo(((int)m_cursor2point.x-20), (int)m_cursor2point.y);
dc.LineTo(((int)m_cursor2point.x+20),(int)m_cursor2point.y); dc.MoveTo((int)m_cursor2point.x, (int)m_cursor2point.y-20);
dc.LineTo((int)m_cursor2point.x, (int)m_cursor2point.y+20); m_cursor2moved = FALSE;
}
}
That is basically it. Yeah, it is crude, and yeah, managed C++, C#, or the SDK are better ways to go, but I wanted to figure out how to make it work.
Points of interest
Couple of things to look out for:
First, the VC++ 6.0 compiler has bugs, and they show up in the form of Link and Build Errors. "fatal error LNK2005:" shows up so you have to tell the compiler to use the "Force file output" option in the Customization feature for the Project settings.
The next joy of the 6.0 compiler is a debug bug causing a "fatal error LNK1103:" error. This only happens for the debug version build, and not for the release, so to overcome it, the MS recommendation is 'don't do a debug build'.
Finally, after you have added Ryan Gordon's ManyMouse .c and .h files to your MFC project, you have to tell the compiler to not use pre-compiler processing for each of those files.
You should be able to build and test the application now. Plug in a second USB mouse and have fun testing it.
History
- Rev. 1.0 - First release. No future releases planned ;-)
Always trying something new. blog tries to keep up (nwpodcast.blogspot.com)