C++ Registering A Single Mouse Click - c++

I have a question about registering a single mouse click on a hotspot - it's been giving me all sorts of problems, and I cannot seem to find the answer here, in any of my books, or on Google. I've only been at programming for a couple months, so bear with me.
I have managed to create an (albeit primitive and not very elegant) hotbox where someone rolls over a button and their icon changes. If they click on the button, it populates a vector on another screen and plays a sound. That's all fine. However, the code I'm using counts the MouseLButton down action - which means, because of the loop, the MouseLButton down keeps being registered. How would I make this code count the action as a single click and do nothing afterward until a user clicks again:
OfficeManager.cpp:
void Hire::hireScreenNavigation()
{
if ((input->getMouseLButton()) && (input->getMouseX() > 900 && input->getMouseX() < 940) && (input->getMouseY() > 154 && input->getMouseY() < 174))
{
audio->playCue (CLICK_EXPAND);
hire = true;
Office.push_back (HireRecruitmentPool[0]);
--officeCapacity;
}
if ((hireScreenSwitch==true) && (input->getMouseX() > 900 && input->getMouseX() < 940) && (input->getMouseY() > 154 && input->getMouseY() < 174))
{
SetCursor(LoadCursor(NULL,IDC_HAND));
}
}
This is the code in the Game class above (Game.cpp):
if(initialized)
{
switch( msg )
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN: case WM_SYSKEYDOWN:
input->keyDown(wParam);
return 0;
case WM_KEYUP: case WM_SYSKEYUP:
input->keyUp(wParam);
return 0;
case WM_CHAR:
input->keyIn(wParam);
return 0;
case WM_MOUSEMOVE:
input->mouseIn(lParam);
return 0;
case WM_INPUT:
input->mouseRawIn(lParam);
return 0;
case WM_LBUTTONDOWN:
input->setMouseLButton(true);
input->mouseIn(lParam);
clicked = true;
return 0;
case WM_LBUTTONUP:
input->setMouseLButton(false);
input->mouseIn(lParam);
return 0;
case WM_MBUTTONDOWN:
input->setMouseMButton(true);
input->mouseIn(lParam);
return 0;
case WM_MBUTTONUP:
input->setMouseMButton(false);
input->mouseIn(lParam);
return 0;
case WM_RBUTTONDOWN:
input->setMouseRButton(true);
input->mouseIn(lParam);
return 0;
case WM_RBUTTONUP:
input->setMouseRButton(false);
input->mouseIn(lParam);
return 0;
}
}
return DefWindowProc( hwnd, msg, wParam, lParam );
If anyone has any examples on how to code it so that the hire functionality above counts a single click within those coordinates (instead of mouse down), I would be extremely appreciative. Keep in mind the coordinates for the hotspots will be different for each button in the game.
Thanks!

Generally a "click" involves both a down action and an up action, and in fact some people only consider the up event when determining a click. What you might try:
1. On button down, record the position so you know where on the screen the user pressed down. More specifically, record the item that was "hit".
2. Do nothing until the up event. At that time, check that the mouse position is still over the item that was originally hit. If so, consider that a successful click on the item and do whatever processing you need.

Related

How to add mouse double click to ListBox

To this code: https://www.dreamincode.net/forums/topic/163804-microsoft-working-with-listboxes-part-i/
It is displaying list and looping nicely.
Sadly my guru never finished his code.
So plan would be adding double click detection on a name. How?
case WM_COMMAND:
{
return 0;
}
Something like this? 11 is this child window where names are.
case WM_COMMAND:
{
if (LOWORD(wparam) == 11) {
if ((message) == LBN_DBLCLK) {
cout << "double click" << endl;
}
}
return 0;
}
Doesn't work
First, according to the documentation:
Parameters
wParam
The LOWORD contains the identifier of the list box. The HIWORD specifies the notification code.
lParam
Handle to the list box.
Remarks
This notification code is sent only by a list box that has the LBS_NOTIFY style.
So in the first step you need to add this style and use HIWORD (wParam) to determine whether to double-click the list.
Then if you need to get the elements of the list, you should not send LB_GETCURSEL to window_handle, but should send it to This->listbox_handle, which is the window handle of the listbox. Then you can get it by sending LB_GETTEXT Text content.
Here is the code:
case WM_COMMAND:
{
if (HIWORD(wparam) == LBN_DBLCLK) {
TCHAR temp[100]{};
int index = SendMessageW(This->listbox_handle, LB_GETCURSEL, 0, 0L);
SendMessageW(This->listbox_handle, LB_GETTEXT, index, (LPARAM)temp);
MessageBox(window_handle, temp, L"test", 0);
}
return 0;
}
And it works for me:
Try replacing:
if ((message) == LBN_DBLCLK)
with:
if (HIWORD (wParam) == LBN_DBLCLK)
Documentation here.

MessageBox() returning 0 when called from Win32 button press

I'm barely a week into Win32 GUI programming, so I'm confident/hopeful this is something simple. For your consideration, I've provided a sample of my code below.
As a quick brief, my application watches for another application to be open so that I can modify that application's memory. I've placed this initial check at the top of my UI looper as follows such that it will only run once (in which case the user can only cancel and the app closes, or execution resumes past the if statement with hWndApp having a value assigned):
if (!hWndApp) {
appCheck();
}
If I start my application and the other application isn't running, appCheck(); fires and the waterfall of execution therefrom acts accordingly: a message box appears (and will keep appearing if the user clicks "Retry") until the other application's window is found. If the user clicks "Cancel," the application exits and all is well. If they click "Retry" once the other application is running, then my application will finish painting to the screen and execution is normal.
The funny business starts the next time I call appCheck(); (which happens when one of either two buttons is clicked) if the other application has been opened, then closed.
While debugging (via Visual Studio 2017), the variable I assign the MessageBox() call to equals 0 when the other application has been opened, then closed, then the following:
Push button to call appCheck();
getProcessHandleAndPID(); is then called within the if statement because the window can't be found
AppCheckMessageBox(); is then called within the while loop because the window can't be found
The debugger then points to the first line inside of AppCheckMessageBox();, which is the entire int msgboxID = MessageBox(); bit
Pressing F11 (Step Into), no window shows and the application exists after the default choice in the switch statement is triggered since the value of msgboxID is 0 (indicating the MessageBox() call failed, so I tried calling GetLastError() before exit(EXIT_FAILURE), but to no avail).
I'm not sure where my error lies, but I've sought many solutions--none of which have panned out. Finally, if you see any variables below that look misnamed or undeclared, it's solely due to my modification of the code for this post to try to generalize/ shorten it. I may have left out some global variable declarations, etc.
Thank you for any help/guidance you can provide! I'm at my wit's end with this right now...lol.
//--------------------------------------------------
// Function to get process handle and PID of app /
//------------------------------------------------
void getProcessHandleAndPID()
{
hWndApp = FindWindow(NULL, _T("NameOfApplication"));
while (!hWndApp) {
AppCheckMessageBox();
}
//Much more code here
}
//---------------------------------
// Function to show message box /
//-------------------------------
int AppCheckMessageBox()
{
int msgboxID = MessageBox(
NULL, //I tried making this hWndApp as well, but no difference
(LPCWSTR)L"Cancel to exit or start the app and click Retry.",
(LPCWSTR)L"Application Not Found!",
MB_ICONSTOP | MB_RETRYCANCEL | MB_SYSTEMMODAL | MB_SETFOREGROUND
);
switch (msgboxID)
{
case IDCANCEL:
exit(EXIT_FAILURE);
case IDRETRY:
getProcessHandleAndPID();
break;
default:
//GetLastError();
exit(EXIT_FAILURE);
}
return msgboxID;
}
//------------------------------------------------
// Function to check if application is running /
//----------------------------------------------
void appCheck() {
if (!FindWindow(NULL, _T("NameOfApplication"))) {
getProcessHandleAndPID();
}
}
//--------------------------------------------------
// Function to get process handle and PID of app /
//------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (!hWndApp) {
appCheck();
}
switch (message)
{
case WM_PAINT:
//Code here
break;
case WM_CREATE:
//Code here
break;
case WM_COMMAND:
switch (HIWORD(wParam))
{
case BN_CLICKED:
if (LOWORD(wParam) == BTN_ENABLE) {
appCheck();
//Do stuff with button press
}
if (LOWORD(wParam) == BTN_DISABLE) {
appCheck();
//Do stuff with button press
}
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
Not really an answer, but too long for comments:
This isn't your real code. Many things are missing, there are mismatched braces which would prevent compilation, etc. Always show your real code if you want help.
As David says, calling appCheck() every time you receive a message is the wrong approach. If you want to call it once after your window opens, do that before entering your message loop.
Your code is needlessly recursive (getProcessHandleAndPID() calls AppCheckMessageBox() which calls getProcessHandleAndPID() which calls...) and will potentially lead to a stack overflow.

Open GL SDL Keypresses and behaviours mismatched on program start

I'm developing a simple game in OpenGL and using the SDL library to handle my input.
The game uses several keyboard buttons for input. Two arrow keys, the space bar, the 'r' button to reset the game and escape to close it.
What's currently happening is that the output or the methods being called when these buttons are pressed when I first launch the game are mismatched. (i.e left arrow performs the right arrow's method). This random behaviour ends once I press each of the buttons the game uses apart from the escape button once.
I'm wondering if there is something I'm missing as it feels like I have to 'assign' each button on each launch of the game. I've provided my input handling code below.
if (e.type == SDL_KEYDOWN) {
switch (e.key.keysym.sym) {
case SDLK_ESCAPE:
m_isClosed = true;
break;
case SDLK_SPACE:
m_selection = true;
break;
case SDLK_LEFT:
m_leftPressed = true;
break;
case SDLK_RIGHT:
m_rightPressed = true;
break;
case SDLK_r:
m_reset = true;
break;
}
}
if(e.type == SDL_KEYUP)
switch (e.key.keysym.sym)
{
case SDLK_LEFT:
m_leftPressed = false;
m_keydown = false;
break;
case SDLK_RIGHT:
m_rightPressed = false;
m_keydown = false;
break;
case SDLK_SPACE:
m_selection = false;
m_keydown = false;
break;
case SDLK_r:
m_reset = false;
m_keydown = false;
break;
}
}
Each event handler simply sets a boolean used for the game logic in another class. If you think you need to see anymore code in order to help me let me know.
It turns out that I had not initialised the booleans corresponding to the button listeners to false. A silly mistake but I thought I should provide the solution nonetheless.

Hook Keyboard to change the key code

I have buy this keyboard http://www.mobilitylab.eu/mini-design-touch-silver.html of 107 touch,
and I want a keypad to put it on my left hand.
but when we activate the numlock of the keypad, it activates the numlock on the keyboard.
So we have 456- instead of uiop.
I have found this program but it don't work on a 64 bits OS. http://www.bellamyjc.org/fr/systeme.html#knumlock.
So i want to do my own program with C++, but it don't work fine, the hook is allright (WH_GETMESSAGE) but i don't understand how we can change the keycode and how we can find if it's a key of the keypad or the keybord ?
Here this is my code where i try to change the message :
//-----------------Keyboard Hook Callback---------------//
Hookmsg_API LRESULT CALLBACK Hookmsg(int ncode,WPARAM wparam,LPARAM lparam){
//if(ncode>=0) //
if(ncode<0)
return CallNextHookEx(hook,ncode,wparam,lparam);
MSG *msg;
msg=(MSG *)lparam;
WORD newVK,oldVK;
WORD newSC,oldSC;
if(ncode==HC_ACTION)
{
if((msg->message == WM_KEYUP))//Check whether key was pressed(not released).)
{
oldVK=msg->wParam;
oldSC=SCANCODE(msg->lParam);
bool extendkey=false;
if(((HIWORD(msg->wParam) & 0x0100) == 0x0100))
{
extendkey=true;
}
if(!extendkey)
{
bool modif=true;
switch(oldVK)//wparam
{
case VK_INSERT: newVK=VK_NUMPAD0; break;
case VK_END: newVK=VK_NUMPAD1; break;
case VK_DOWN: newVK=VK_NUMPAD2; break;
case VK_NEXT: newVK=VK_NUMPAD3; break;
case VK_LEFT: newVK=VK_NUMPAD4; break;
case VK_CLEAR: newVK=VK_NUMPAD5; break;
case VK_RIGHT: newVK=VK_NUMPAD6; break;
case VK_HOME: newVK=VK_NUMPAD7; break;
case VK_UP: newVK=VK_NUMPAD8; break;
case VK_PRIOR: newVK=VK_NUMPAD9; break;
case VK_DELETE: newVK=VK_DECIMAL; break;
default: modif=false;
}
if(modif==true)
{
msg->wParam = VK_NUMPAD0;
UINT newSC=MapVirtualKey(VK_NUMPAD0,MAPVK_VK_TO_VSC);
msg->lParam &= 0xFF00;
msg->lParam += (newSC << 16 );
//MessageBox( NULL, TEXT("OK"), TEXT("Error!"), MB_OK);
}
}
}
}
return ( CallNextHookEx(hook,ncode,wparam,lparam) );//pass control to next hook in the hook chain.
}
cant understand u...
u have 2 keyboards? if yes, try to use Raw Input (raw data from USB HID device)
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645543(v=vs.85).aspx
Lparam and wparam are not visible for other applications.
Keyboard input is much more than just windows messages. Modifying the messages will work in some cases, but is a vastly incomplete solution. You also need to consider driver state, GetKeyboardState, and others.
If you want to remap keys on your keyboard, you can create a new keyboard layout and assign it to a locale.
If keyboard layouts don't satisfy your needs, you will need to write a keyboard device driver.
If you only need this functionality in a specific application (not system globally), then you might be able to get lucky and only modify windows messages.

dialog box controls - detect changes

I want to detect when any control on a dialog box is changed by user action. For example, when data is entered in a text box, a date is entered in a date-time picker, a check box is checked or unchecked, etc. Up to now I have ignored such notifications and simply retrieved the state of the controls when the user pushes some button but now I want to know a change has taken place (I want to enable the Apply button on a property sheet). I don't really care what change has taken place, all I want to know is that something has changed. By change I do NOT mean a change in focus but some actual action by the user to change a control.
I use plain old c++, no MFC or anything fancy.
How do I go about this?
You can test whether a checkbox has been checked with the BN_CLICKED notification code which you'd get through WM_COMMAND.
switch( uMsg ) {
...
case WM_COMMAND: {
switch( HIWORD( wParam ) ) {
case BN_CLICKED: {
if( Button_GetCheck( lParam ) == BST_CHECKED ) {
...
}
break;
}
default:
return false;
}
break;
}
default:
return false;
}
return true;
That is an example of how your DialogProc might be set up. You can switch on lParam or LOWORD( wParam ) to identify which button.