I've started using SFML as my base graphics framework for a code editor I'm working on, the only thing I can't seem get completely right is keyboard input.
What I'm used to in QB64 (a language similar to Visual Basic), is to get keypresses using either the _keyhit command (which returns a virtual keycode), or the inkey$ command (which directly returns the current keypress's character). I'm looking for a similar solution in C++ (not necessarily cross-platform, possibly easily implementable along with SFML)
What I've tried as of now is to use _getch, which doesn't seem to work with the Windows framework, nor SFML, perhaps I should use some of the Windows.h routines for this purpose, but judging from what I've seen, those check for specific keypresses, not exactly what I need. The SFML framework provides "sf::Keyboard::isKeyPressed", but that one also checks for a specific keypress, but not for the whole keyboard, I also tried creating an array that serves as a map from the "sf::Keyboard::Key" enum to ASCII characters, but its not convincing, furthermore, the keys seem to "stick" and the pressed key's character keeps getting read even after it has been released.
If you are using SFML, it is actually quite simple. You need to use the sf::Event::KeyEvent class (or in this case, the struct).
https://www.sfml-dev.org/documentation/2.5.0/structsf_1_1Event_1_1KeyEvent.php
Though the catch is you have to get the event from something. Generally this is used from an SFML window.
//assuming your code is already set up for these items...
sf::Event Event;
while (window.GetEvent(Event))
{
if (Event.Type == sf::Event::KeyPressed)
{
//to get the key code, use Event.Key.Code
//your code
//for example
switch(Event.KeyEvent.Code)
{
case(sf::Keyboard::Key::Y):
//do stuff
break;
}
}
}
Heads up, it has been a while since I have worked with SFML so I am not 100% sure if the it will work with switch statements. Comparing with == will work too, in an if-else if-else statement.
There may also be other ways to get the sf::Event defined without a window.
Otherwise, it is fairly simple.
If you are looking just to detect a keypress kbhit() is the fuction.(Borland family of compilers , conio.h , but not a part of C++ standards when I googled it ).
https://www.cprogramming.com/fod/kbhit.html
Alternative : Under Unix-like operating system you can use ncurses to emulate most conio behavior( see if it works for you)
https://www.quora.com/With-which-function-can-I-replace-kbhit-in-C++-because-the-header-conio-h-doesnt-exist-in-linux
If you are looking for a code that can detect which key was pressed (ie Numpad 1 and 1 above the alphabets or Something like Esc or arrow keys).This code worked for me on a borland compiler. When you fetch the scan code ( not ascii ) it is different for every key in keyboard ( even the non ascii ones have a value)
void getkey()
{
union REGS ii,oo;
while(!kbhit());
ii.h.ah=0;//service no for ascii and scan code
int86(22,&ii,&oo);
ascii=oo.h.al;
scan=oo.h.ah;
}
I used the above code in my school project, so I don't remember the exact source where I found it .But I think it was Let us C by Yashwant Kanetkar under the GUI part ( It was removed later so you are looking for a publication pre 2008).
Hope it helps.
Related
I'm making a hobby project that is basically a bot for a very old flash game, the mouse move and click works fine, but all key presses make the operating system lag/stutter and sometimes stop listening to all keyboard inputs, real or fake.
I started using just XLib with XTests but didn't work, so I tried XSendEvent instead of XTests, but all symptoms stayed the same, so the last attempt was with XDO, which gave better results, but still freezes the OS.
this is the current snippet that I'm trying to use to simulate a keypress:
//Constructor
CheatCore::CheatCore() {
xdo_t x = xdo_new(NULL);
Window *list;
xdo_search_t search;
unsigned int nwindows;
memset(&search, 0, sizeof(xdo_search_t));
search.max_depth = -1;
search.require = xdo_search::SEARCH_ANY;
search.searchmask = SEARCH_CLASS | SEARCH_ONLYVISIBLE;
search.winclass = "Chrome";
int id = xdo_search_windows(x, &search, &list, &nwindows);
qDebug() << nwindows;
if(!nwindows){
qDebug() << "Chrome not found";
return;
}
w = list[0];
//I have to call activate twice to really bring it forward, I suspect that its
//because I use a transparent "overlay" that show stats for the cheat and it is set as Aways on top
//(i used Qt to set it to not get any Events)
xdo_activate_window(x,w);
xdo_activate_window(x,w);
}
//there is a function that executes every second to check if a pixel color has changed,
//if so, then the SendKey is called to Reload weapon magazine pressing the "space" key
void CheatCore::SendKey(){
xdo_activate_window(x,w);
xdo_activate_window(x,w);
xdo_send_keysequence_window(x, w, "space", 500);
}
I'm using a transparent overlay to show the bot status, with just some numbers appearing, it is a widget created using Qt that is AlwaysOnTop and the paint event draws the desired information's, it is another object and don't have direct impact in the CheatCore, but this is the window flags used to draw over a transparent window and ignore events.
setWindowFlags(Qt::WindowTransparentForInput | Qt::FramelessWindowHint |
Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
I didn't manage to understand what could be provoking this weird behavior, could it be the windowing system?
Also, I tried to find a Qt way of simulating mouse/keyboard inputs, but i didn't manage to find any solution to send events to other windows if there is a way possible of achieving this would be great!
The game i'm trying to automate is called "Storm the House"
If interested this is the link to the online repo : link
Can you help me make this work? Thank you!
Context about the setup:
Ubuntu 18.10 using VGA and Nvidia drivers (if it may influence the xserver)
Did you ever try to use xdotool from command line. To use xdotool you need to install package first.
To simualte a key press, you can use.
xdotool key <key>
For example if you want to simulate key press for X you can use this code
xdotool key x
Or any other combination like
xdotool key ctrl+f
Also you can replace key press with another one, for example if you want to replace pressing D with Backspace you can try this one
xdotool key D BackSpace
You can read complete guid online, also you can write script with this tool and use it in many different situations.
Also you can use it for remote connection too.
I hope this helps you with your little problem.
Using evdev is a linux specific option.
It's a simpler solution as you just need to open the correct file and write to it.
Take a look at this similar question to see how to get started.
I would like to take over how keys repeat in my program, which means disabling how SDL2 does it automatically.
It's possible to ignore SDL_KEYDOWN repeat events since the Event union member key has a repeat boolean you can filter with (this question explores that solution: How to disable key repeat in SDL2?). But SDL_TEXTINPUT events do not have the same info available in them, and so it's impossible to filter out characters that have repeated.
Is there any way to outright disable key repeating?
It seems there is currently no simple way to do this, and because I need this as well I made a ticket: https://bugzilla.libsdl.org/show_bug.cgi?id=4598
If you have another additional use case why you want this, feel free to add a comment on the bug ticket so the developers get an idea what sort of uses this is important for. (Mine is providing an emergency disable option for people with keys-getting-stuck bluetooth keyboards on android who want to still be able to type texts without major accidents)
Well in SDL lib might be a solution, but you can also add some simple c++ code to resolve your problem. For example if you don't want to play with SDL_KEYUP you can just do something like this:
//before loop
int keypress_control = 0;
//much Code, loop etc.
//
swich(event.type)
case SDL_KEYDOWN :
/*if or switch again as you want */if (keypress_control ==
2)
{
/*Code here*/
keypress_control = 0;
}
else
{
keypress_control = 0;
}
}
//after switch but Still in program loop
Keypress_control++;
//
//
I created a dialog MainDialog.cpp with 2 edit controls whose IDs are IDC_EDITCONTROL_A and IDC_EDITCONTROL_B, and have variables defined as m_editControlA and m_editControlB, respectively.
Also, I have 2 buttons whose IDs are IDC_MFCBUTTON_KEY_X and IDC_MFCBUTTON_KEY_Y, and variables are m_buttonKeyX and m_buttonKeyY, respectively.
Below is the code in the source file
#include "afxdialogex.h"
IMPLEMENT_DYNAMIC(CMainDialog, CDialogEx)
CMainDialog::CMainDialog(CWnd* pParent): CDialogEx(IDD_MAIN_DIALOG, pParent)
{
}
CMainDialog::~CMainDialog()
{
}
void CMainDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDITCONTROL_A, m_editControlA);
DDX_Control(pDX, IDC_EDITCONTROL_B, m_editControlB);
DDX(Control(pDX, IDC_MFCBUTTON_KEY_X, m_buttonKeyX);
DDX(Control(pDX, IDC_MFCBUTTON_KEY_Y, m_buttonKeyY);
}
BEGIN_MESSAGE_MAP(CMainDialog, CDialogEx)
ON_EN_CHANGE(IDC_EDITCONTROL, &CMainDialog::OnEnChangeEditA)
ON_BN_CLICKED(IDC_MFCBUTTON_KEY_X, &CMainDialog::OnBnClickedButtonX)
ON_BN_CLICKED(IDC_MFCBUTTON_KEY_Y, &CMainDialog::OnBnClickedButtonY)
END_MESSAGE_MAP()
void CMainDialog::OnBnClickedButtonX()
{
m_editControlA.SetWindowTextW(_T("X")); // test
}
void CMainDialog::OnBnClickedButtonX()
{
m_editControlA.SetWindowTextW(_T("Y")); // test
}
I am trying to understand how I can have each button send their respective character (i.e. X or Y in this example) to the selected edit control if one is selected. Essentially, I would like to simulate keyboard input.
I have read the docs about how to simulate keyboard events and also the sendMessage but I could not understand how to implement it since my C++ knowledge is very basic. Also, following my previous question I have found that the GetFocus would be useful but still my main issue currently is sending the input.
Any example code or useful link could be very useful for me to learn how I can simulate a keyboard input inside an app.
The characters are sent from the OS to the edit controls using the WM_CHAR message.
In reality it is a bit more complex than that, but you do not need to emulate the entire WM_KEYUP WM_KEYDOWN message sequence, since its end result is to generate a WM_CHAR message.
You can use CWnd::PostMessage to send characters directly to your edit controls, even when they do not have the focus.
You have probably already found the documentation for WM_CHAR here: https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms646276(v=vs.85).aspx
oops.. excuse my french, ths english doc is here
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646276(v=vs.85).aspx
(just changing the fr-fr to en-us does the trick, it probably works for all other languages, neat!
wParam holds the character you want to send. Either an plain ASCII character, or one of the VK_ constants... I suggest you use the unicode version WM_CHARW, as most windows software uses unicode nowadays. The notation for wide chars is either L'X' or _T('X'), the unicode (UTF-16) character type is wchar_t.
lParam contains other keystroke details, 0 should be fine for what you want to do.
to send X, simply call
m_editControlA.PostMessage(WM_CHAR, _T('X'));
When using the _T() notation, the character (or string) literal between the parenthesis will be automatically converted to the right character width for your app's unicode setting (you should set that to UNICODE, since that's what the OS is using, and is also the only valid encoding for Windows CE, for example, and you should get used to manipulating this type.
the _T() macros and _t* overrides for almost all C library functions operating on strings are defined in tchar.h, which is included by Visual Studio in stdafx.h. Under MFC, you'll mostly use CString, but it's good to know where these things are.
[EDIT] When you get that running, you should start playing with WM_KEYDOWN. You will discover that PostMessage(WM_CHAR, VK_ESCAPE) directly to your dialog does not close it, while a PostMessage(WM_KEYDOWN, VK_ESCAPE) does. And that m_editBox.PostMessage(WM_KEYDOWN, _T('X')) will send a lower key 'x' to your edit box. But that's another topic to ivestigate.
Have fun with MFC!
For your last question:
Sure, but it gets a bit more complicated, as your button will gain focus, as soon as you click on it. You'd have to create handlers for EN_SETFOCUS for eeach of your edit boxes, and add a CWnd* data member to keep track of the last edit box that had focus.
Your EN_SETFOCUS handlers should look something like this
void CdlgDlg::OnEnSetfocusEdit1()
{
m_pWndLastFocus = &m_edit1;
}
Don't forget to set the pointer to NULL in your constructor and to chjeck it's valid before calling m_pWndLastFocus->PostMessage() though.
The way to synthesize input in MFC is by using the SendInput method.
How to read key from keyboard in c++ ?
i used _getch() but this is not working always.
i heard about win32 keyboard api. i am targeting to windows so window specific technique is fine. can anyone give me simple example how to read key and check for arrow and function key.
i read article
How to simultaneous read keys on keyboard?
but this is not working in may case. here is my attempt inspired from above linked reference
char temp;
BYTE keys[256];
while(true)
{
temp = _getch();
if(GetKeyboardState(keys))
{
if(keys[VK_UP]&0xF0)
{
// Move Up : Case failing when i pressed up key
}
else if(keys[VK_DOWN]&0xF0 || keys[VK_RETURN]&0xF0)
{
// Move Down : Case failing when i pressed down or enter
}
else if(keys[VK_TAB]&0xF0)
{
// Move Next : Case failing when i pressed tab
}
else
{
// Print charecter which read using _getch()
cout<<temp;
}
}
}
i read MSDN article but do not understand what they are doing. i am doing such program first time so please make your example clear and illustrative so i can easly get it. thanks
I don't have a Windows machine at hand to test this out, but I am thinking that the fact that you are using temp = _getch(); before GetKeyboardState(keys) is eating your characters.
there are many library in C++ which handle this type of problem, if you are the choice, I advise you to use QKeySequence and other classes to let useful keyboard management.
If you want to see example, refer you to chromium project, here is an example used to test code of "keyboard driver".
you can either search many example with "filetype" syntax in google search engine (example : filetype:cc GetKeyboardState)...
you need to set correctly the layout before use GetKeyboardState...
Hope this help you.
Regards,
/Mohamed
I want to show a message to user when the user changes the language keyboard layout of Windows for example from EN to FR. But I don't know how can I be informed when the user changes it using either the taskbar or ALT+SHIFT. Which win32api function should I use?
I need something like this pseudocode :
void inputLanguageChanged(char *ln)
{
message("You selected " + ln + " language");
}
The traditional way of doing this was to handle the WM_INPUTLANGCHANGE message. But there are a couple of problems with this method:
it is only sent to the active (focused) window, and
it doesn't catch all possible cases, and may not be reliable on modern versions of Windows.
The better solution, then, is to implement the ITfLanguageProfileNotifySink interface, whose OnLanguageChanged method is called whenever the input language changes, regardless of the way that it was changed.
However, I see that your question is tagged with both the C and C++ tags. You can use COM from C, but it's a real pain in the neck. Far simpler if you're using C++. If I needed to do this work in a C program, I'd probably just find a way to make WM_INPUTLANGCHANGE work for me. Maybe I'm just lazy.
You can use WM_INPUTLANGCHANGE message:
case WM_INPUTLANGCHANGE:
{
HKL hkl = (HKL)lParam;
WCHAR localeName[LOCALE_NAME_MAX_LENGTH];
LCIDToLocaleName(MAKELCID(LOWORD(hkl), SORT_DEFAULT), localeName, LOCALE_NAME_MAX_LENGTH, 0);
WCHAR lang[9];
GetLocaleInfoEx(localeName, LOCALE_SISO639LANGNAME2, lang, 9);
}
https://learn.microsoft.com/windows/win32/intl/locale-names
https://learn.microsoft.com/windows/win32/intl/nls--name-based-apis-sample