Ello All,
I'm pretty new to c++ and I've been trying to get this to work for longer than I care to admit. So I've gone off of the following refs and gotten the controller to work in a console app.
xbox360 controller input with c using x input
Code proj article
MSDN
Here is the result
xbox360Controller.h
xbox360Controller.cpp
From there I'm trying to get it to work with cocos2d-x using steve tranby's post at the bottom of this thread (he adds to the )and adapting that to the 360 gamepad.
While I've gotten the keypad events to work
(it was standard windows input so not too bad)
LRESULT CCEGLView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
BOOL bProcessed = FALSE;
CCLog("Message sent = %d",message);
//note* only showing relavant sections of code for brevity
switch (message)
{
case WM_KEYDOWN:
if (wParam == VK_F1 || wParam == VK_F2)
{
CCDirector* pDirector = CCDirector::sharedDirector();
if (GetKeyState(VK_LSHIFT) getKeypadDispatcher()->dispatchKeypadMSG(wParam == VK_F1 ? kTypeBackClicked : kTypeMenuClicked);
}
}
else if (wParam == VK_ESCAPE)
{
CCDirector::sharedDirector()->getKeypadDispatcher()->dispatchKeypadMSG(kTypeBackClicked);
}
else
{
CCDirector::sharedDirector()->getKeypadDispatcher()->dispatchKeypadDown(wParam);
}
if ( m_lpfnAccelerometerKeyHook!=NULL )
{
(*m_lpfnAccelerometerKeyHook)( message,wParam,lParam );
}
break;
default:
if (m_wndproc)
{
m_wndproc(message, wParam, lParam, &bProcessed);
if (bProcessed) break;
}
return DefWindowProc(m_hWnd, message, wParam, lParam);
}
if (m_wndproc && !bProcessed)
{
m_wndproc(message, wParam, lParam, &bProcessed);
}
return 0;
}
I can't figure out where to put the controller logic. I've tried
in the WindowProc method and realized that didnt work as it only
fires as a callback to WindowProc events(I probably don't have the correct lingo for it, sorry)
The closest I've gotten it to something that fires often enough to check is at the point
static LRESULT CALLBACK _WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CCDirector* pDirector = CCDirector::sharedDirector();
XboxController* player1 = new XboxController(GamePadIndex_One);
if(player1->IsConnected())
{
player1->Update();
for(int i =0;iState._buttons[i]==true)
{
//CCApplication::sharedApplication()->getKe
pDirector->getKeypadDispatcher()->dispatchKeypadDown(i);
}
}
}
delete player1;
if (s_pMainWindow && s_pMainWindow->getHWnd() == hWnd)
{
return s_pMainWindow->WindowProc(uMsg, wParam, lParam);
}
else
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
The full code is here
and the source is at github Here.
Anyone know the right place to put the XboxController instance in order for it to respond to KeypadDown properly?
First of, WindowProc is a callback function that is called after there's an message sent to the window from Windows.
So, if there's no message, this function would not get called.
XInput api is not message-based api, it does not generate messages. It requires the app to read its state as frequent as possible. Usually it's read in every game loop, just before the game logic is processed. Alternatively, you could have a separated thread to poll the state every 33ms or so.
I'd to recommend you to take a look at how XInput work, the concept of Windows programming, and the basic concept of game engine architecture.
Related
I want to learn something about Windows Hooks. Right now, I'm only interested in "catching" messages.
So I did the following, but it doesn't work.
I want to catch the message in the same thread I'm using. I don't want to catch another thread's messages.
Can somebody explain to me what I'm doing wrong?
I install the hook as follows:
myhookdata.nType = WH_GETMESSAGE;
myhookdata.hkprc = GetMsgProc;
myhookdata.hhook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId());
Then in the hook procedure I do this, just for testing. But the "WM_LBUTTONDOWN" never get catched!!
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
LPCWPSTRUCT message = (LPCWPSTRUCT)lParam;
if (nCode < 0)
return CallNextHookEx(myhookdata.hhook, nCode,
wParam, lParam);
switch (nCode)
{
case HC_ACTION:
if (wParam)
if (message->message == WM_LBUTTONDOWN)
Sleep(0);
break;
default:
break;
}
return CallNextHookEx(myhookdata.hhook, nCode, wParam, lParam);
}
According to the documentation:
lParam [in]
Type: LPARAM
A pointer to an MSG structure that contains details about the message.
So you only need to change the code:
PMSG message = (PMSG)lParam;
Then it works for me.
I've got C++ application (used for share application's window via network). I need to update application's area on client side when it's size was changed on server side. For this purpose once in a period of time I call GetWindowPos to check if the window was resized. But I don't want to send the info when the window is in resizing state and send the info only when resizing is completed. I noticed that on Windows 8.1 and Windows 10 GetWindowPos returns same values when the window is in resizing state, however on Windows 7 it returns different values when the window is in resizing state. So the question is how to understand if window is in resizing state?
UPD: Implementation of WM_ENTERSIZEMOVE - WM_EXITSIZEMOVE variant
void WindowsDisplayHelperMasterWindow::SetMsgHook()
{
m_pThis = this;
m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, 0);
}
Static function that call non-static method of the class:
LRESULT CALLBACK WindowsDisplayHelperMasterWindow::MsgPoc(int code, WPARAM wParam, LPARAM lParam)
{
if (m_pThis != nullptr)
{
return m_pThis->GetMsgProcHook(code, wParam, lParam);
}
return CallNextHookEx(0, code, wParam, lParam);
}
Hook function:
LRESULT CALLBACK WindowsDisplayHelperMasterWindow::GetMsgProcHook(int code, WPARAM wParam, LPARAM lParam)
{
if (code < 0)
{
return CallNextHookEx(0, code, wParam, lParam);
}
MSG* lpmsg = (MSG*)lParam;
if (lpmsg->hwnd != m_windowHandle)
{
return CallNextHookEx(0, code, wParam, lParam);
}
if (lpmsg->message == WM_ENTERSIZEMOVE && !m_isWindowResizing)
{
m_isWindowResizing = true;
}
else if (lpmsg->message == WM_EXITSIZEMOVE && m_isWindowResizing)
{
m_isWindowResizing = false;
}
return CallNextHookEx(0, code, wParam, lParam);
}
m_pThis and m_msgHook are static class members:
WindowsDisplayHelperMasterWindow* WindowsDisplayHelperMasterWindow::m_pThis = nullptr;
HHOOK WindowsDisplayHelperMasterWindow::m_msgHook = NULL;
And here is the check itself:
if (!m_displayMode.IsEqualGeometry(displayMode) && !m_isWindowResizing)
{
DUMPER_DEBUG("DS_ERROR_MODE_CHANGED");
return DS_ERROR_MODE_CHANGED; // depending on this value server asks client to update application's window area
}
Thanks.
A window receives a WM_ENTERSIZEMOVE message, after it has entered the moving and sizing modal loop. A window receives a WM_EXITSIZEMOVE message, after it has exited the moving or sizing modal loop.
If you monitor those two messages, you know when a window is in moving and sizing state.
I have written an application to hook some procedure onto a new process to monitor mouse down events and to disable mouse down events on the new process. As of now, I am able to capture to mouse down events coming to this process and I am trying to disable all mouse down events as a POC. This is what I am doing currently in the hook procedure.
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
return false;
}
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
When I perform mouse down event, I am getting the log message that I have written. But I also expect that click event to be blocked since I am returning false. but it does not happen so and click event proceed as a normal click. How could I disable mouse down event. Thanks in advance for any help on this
This is how I call setWindowsHookEx
HHOOK handle = SetWindowsHookEx(WH_GETMESSAGE, addr, dll, threadID);
The reason you are supposed to call CallNextHookEx during your hook routine is so that the message can be passed on to any other hooks that might be installed. Failing to do so does not prevent the message from being seen by the application that received it.
The documentation for WM_NULL explains how to block the message:
For example, if an application has installed a WH_GETMESSAGE hook and wants to prevent a message from being processed, the GetMsgProc callback function can change the message number to WM_NULL so the recipient will ignore it.
The corrected code should therefore look something like this:
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
msg->message = WM_NULL;
return false;
}
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
However, this may cause inconsistent behaviour if other hooks are present, because whether another hook sees WM_LBUTTONDOWN or WM_NULL will depend on the order of the hook chain, which is unpredictable. It might be preferable to try something like this:
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
int result = CallNextHookEx(NULL, code, wParam, lParam);
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
msg->message = WM_NULL;
}
return result;
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
I am trying to add the possibility to use the RETURN key in an already made Login/Password form.
The thing is, I didn't make the form, and it is the first time I've used the Window API for Windows. So there is a lot I don't know...
So basically, a window is created, and inside of it, three child "windows" are created.
One editable: Login
A second one editable: Password
And a button: OK
Basically, I added a handle for the WM_CHAR in the message callback method:
else if (msg == WM_CHAR)
{
if (wParam == VK_RETURN)
{
char BufLogin[128];
char BufPasswd[128];
GetWindowText(hwndEditLogin, BufLogin, sizeof(BufLogin));
GetWindowText(hwndEditPasswd, BufPasswd, sizeof(BufPasswd));
print_msg(BufLogin);
print_msg(BufPasswd);
return (0);
}
else
return (DefWindowProcW(hwnd, msg, wParam, lParam));
}
(I also tried by replacing WM_CHAR with WM_KEYDOWN to no success.)
I checked on stack overflow, and the only solutions I've found so far talk of things I don't understand, or simply don't work...
I added a check in the message loog like so:
while(GetMessage(&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hWnd, &msg) || msg.wParam == VK_RETURN)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
And it did work, unless the user had clicked on any child window... Basically, it worked if the user hadn't clicked on anything or modified anything, which makes the Login/password part of the window pretty useless! ^^'
So what I'm guessing is that the (!IsDialogMessage) check rules out the WM_CHAR and the WM_KEYDOWN messages (still allowing the user to type for some reason), and if I add the check for the wParam, it works but only for the parent window.
If you guys had any idea on how to work aroun this conundrum of mine, I would be so grateful! Thanks in advance! :)
(P.S.: I edited this question, before I asked on how to make the TAB key work, because the IsDialogMessage check would make each character appear four times. I simply forgot to put the ! before the IsDialogMessage! ^^'
I make this note in case anyone found my question and had the same problem I had before editing! ;) )
Ok, so I've finally figured it out! Here's my solution for it if anyone needs to do the same! ;)
I made two global variables, one for each window that needs to handle the ENTER key:
WNDPROC wpOldEditProcPass;
WNDPROC wpOldEditProcLogin;
Then I created two CALLBACK methods, again, one for each window:
(Placed them before my main CALLBACK)
LRESULT CALLBACK CustomEditProcLogin(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CHAR:
{
if (wParam == VK_RETURN)
{
SendMessage(GetParent(hWnd), WM_COMMAND, MAKEWPARAM(ID_BUTTON, BN_CLICKED), 0);
return(0);
}
}
}
CallWindowProc(wpOldEditProcLogin, hWnd, msg, wParam, lParam);
}
LRESULT CALLBACK CustomEditProcPass(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CHAR:
{
if (wParam == VK_RETURN)
{
SendMessage(GetParent(hWnd), WM_COMMAND, MAKEWPARAM(ID_BUTTON, BN_CLICKED), 0);
return(0);
}
}
}
CallWindowProc(wpOldEditProcPass, hWnd, msg, wParam, lParam);
}
In the main CALLBACK, in the WM_CREATE handle, after I created the child windows, I subclassed them:
wpOldEditProcPass = (WNDPROC)SetWindowLongPtr(hwndEditPasswd, GWLP_WNDPROC, (LONG_PTR)CustomEditProcPass);
wpOldEditProcLogin = (WNDPROC)SetWindowLongPtr(hwndEditLogin, GWLP_WNDPROC, (LONG_PTR)CustomEditProcLogin);
And then in WM_DESTROY, I gave them back their original process:
(Before PostQuitMessage(0); )
SetWindowLongPtr(hwndEditPasswd, GWLP_WNDPROC, (LONG_PTR)wpOldEditProcPass);
SetWindowLongPtr(hwndEditLogin, GWLP_WNDPROC, (LONG_PTR)wpOldEditProcLogin);
And then I replaced the:
if (!IsDialogMessage(hWnd, &msg))
With:
if (!IsDialogMessage(hWnd, &msg) ||(msg.message == WM_KEYDOWN && msg.wParam == VK_RETURN))
And it works like a charm! :D
(I still can't figure out why I have to allow a WM_KEYDOWN message, but handle a WM_CHAR message... If I allow a WM_CHAR message, it doesn't work, and if I handle a WM_KEYDOWN message, I get the obnoxious "Ding" sound when I press enter! ^^' )
I'm using Windows 7 and VC++. The business is to know how many seconds my system has been set into screen saver mode or monitor screen off. To achieve this, I'm trying to catch the events WM_SYSCOMMAND and SC_SCREENSAVE, SC_MONITORPOWER. So I have created a Win32 project in Visual Studio 2008 and I'm receiving the events in WndProc function:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_SYSCOMMAND:
{
switch (LOWORD(wParam))
{
case SC_SCREENSAVE:
{
FILE *fl = fopen("this_is_a_event_test.txt","a");
fputs("SC_SCREENSAVE\n",fl);
fclose(fl);
}
break;
case SC_MONITORPOWER:
{
FILE *fl = fopen("this_is_a_event_test.txt","a");
fputs("SC_MONITORPOWER\n",fl);
fclose(fl);
}
break;
default:
{
}
}
}
break;
}
}
It works fine when dialog is in foreground, but in background (or if I comment ShowWindow function) it only works if I manually send the events:
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_SCREENSAVE, (LPARAM)2);
or
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);
So, it is not working when system power configuration sets the screen saver after 2 minutes of inactivity, and the same thing with automatic monitor screen off. Thats the real thing I want, know when the system is turning off the screen or setting the screen saver, with a background monitoring program.
I have also tried to use hook events with extern dll. I have followed this example http://www.codeproject.com/Articles/1037/Hooks-and-DLLs adding in the CALLBACK msghook() function the same switch code above in WndProc. It doesn't work even using the SendMessage.
After several days stuck with this issue, searching in the Internet, forums... I don't know what else I can do. Can anyone help me?
I were not using hooks properly, but it has been rare. Firstly, about setWindowsHookEx function, I have read WH_CALLWNDPROC or WH_SYSMSGFILTER must be used to get WM_SYSCOMMAND sent messages, and then get SC_SCREENSAVE wParam. In this case, I don't know why and maybe I'm wrong, but thats seems not to be true.
After use every possible message to SetWindowsHookEx, I realised WH_GETMESSAGE is the only one who sends SC_SCREENSAVE wParam, at least in this hook example in Windows 7.
HHOOK hook;
HHOOK hook = SetWindowsHookEx(WH_GETMESSAGE,
(HOOKPROC)msghook,
hInst,
0);
Secondly, listening for every message catched in hook function, WM_SYSCOMMAND were appeared with LPMSG. I have read also that wParam must to be combined to 0xFFF0 to be compared. But wParam & 0xFFF0 == SC_SCREENSAVE didn't work and wParam == SC_SCREENSAVE neither. In this case the only way is using LPMSG for both WM_SYSCOMMAND and SC_SCREENSAVE.
static LRESULT CALLBACK msghook(UINT code, WPARAM wParam, LPARAM lParam)
{
if(code > 0)
{
CallNextHookEx(hook, code, wParam, lParam);
return 0;
}
LPMSG msg = (LPMSG)lParam;
if(msg->message == WM_SYSCOMMAND)
{
if (msg->wParam == SC_SCREENSAVE)
{
MessageBoxA(NULL,L"SC_SCREENSAVE",L"SC_SCREENSAVE",MB_OK);
}
if (msg->wParam == SC_MONITORPOWER)
{
MessageBoxA(NULL,L"SC_MONITORPOWER",L"SC_MONITORPOWER",MB_OK);
}
}
return CallNextHookEx(hook, nCode, wParam, lParam);
}
And using FILE to test the events was a very bad idea, I think using MessageBox is not much better but I don't know how to test ir correctly.