-1

I am trying to make a program that when you type "Alt+A" it will write type out a line like "Hello" for example. This is the closest I've gotten:

if (GetAsyncKeyState(65))
{

    cout << "worked" << std::endl;  
    string bind = "Hello";

    INPUT Input = { 0 };
    Input.type = INPUT_KEYBOARD;

    for (int i = 0; i < bind.length(); i++)
    {

        Input.ki.wVk = VkKeyScanA(bind[i]);
        SendInput(1, &Input, sizeof(Input));
    }
    Sleep(500);
}

It works similar to how I want, but there are some problems that I encountered:

  • I can't get the Alt key to work. When I use GetAsyncKeyState(18), it runs the "worked" output but it doesn't type out any of the word.
  • Whenever I press the key bind (for example "A"), it will type that letter as well. Is there any way I can cancel out that key press? I was thinking that I could just make it so that it types the backspace button before the word, but I'm assuming there is a better to go about this.
  • I also have a problem that the program doesn't type exactly what is put in. It doesn't type capital letters, and it only types one letter if there are two in a row. In the code that I put, it will say "helo" instead of "Hello."
Dharman
  • 30,962
  • 25
  • 85
  • 135
script
  • 55
  • 4
  • 4
    Just a quick terminology issue, the word "[macro](https://gcc.gnu.org/onlinedocs/cpp/Macros.html)" in the title threw me off. It means something very different to some C++ developers :) – chessofnerd Dec 23 '19 at 01:20
  • I saw that when I was looking up how to make this. Should I switch up the wording? Typing Bot or Script instead? – script Dec 23 '19 at 01:26
  • Also, you appear to be using the `std` namespace, this can [lead to problems](https://stackoverflow.com/a/1265092/1357841). Apologies that I'm answering all the issues you aren't asking and not the one you are ;) – chessofnerd Dec 23 '19 at 01:26
  • I wouldn't change the wording, just something to be aware of! – chessofnerd Dec 23 '19 at 01:27
  • The tutorial I used for SendInput used it. I usually go without it. – script Dec 23 '19 at 01:36
  • Your question should mention (and possibly tag) the library that you are using. Without a system-specific library, C++ has no concept of "keyboard" or "key press". – JaMiT Dec 23 '19 at 03:03
  • [RegisterHotkey](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey) is one way, but you need a window handle to receive messages. – Jonathan Potter Dec 23 '19 at 03:52
  • *"it only types one letter if there are two in a row"*, Because you only send keydown (0) and no keyup (`KEYEVENTF_KEYUP`) for each character. – Drake Wu Dec 23 '19 at 10:04
  • You'll need to unlearn everything you learned from the tutorial, that taught you how to use `SendInput`. `SendInput` allows you to inject a series of input *atomically* into the system. It was introduced to solve the issue with `keybd_event`, that cannot do this. Plus, the return value of [GetAsyncKeyState](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate) encodes several pieces of information. The implicit conversion to `bool` drops all of it. Time to read the documentation. – IInspectable Dec 23 '19 at 10:37
  • What would you recommend using instead of SendInput? Also before I tested if GetAsyncKeyState was equal to -32767, but I saw people use it as a bool. – script Dec 23 '19 at 17:48
  • [`GetAsyncKeyState`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate): *If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState.* -32767(0x8001): the key is down, and the key was pressed after the previous call to `GetAsyncKeyState`. 0x8000 and 0x8001 are both equal to true. – Drake Wu Dec 24 '19 at 06:44
  • The high-order byte of [`VkKeyScanA`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-vkkeyscana#return-value) return value contains the shift state. If it is a capital letter, the shift bit will be set to 1. – Drake Wu Dec 24 '19 at 06:58

1 Answers1

1

I have made some simple changes to your code, which can basically meet your needs. But if you need higher functionality, you may need to use RegisterHotKey, and create your window to handle the WM_HOTKEY message.

#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
    HWND hwnd = (HWND)0x001E0BF2; //notepad window
    SetForegroundWindow(hwnd);
    while (1)
    {
        if (GetAsyncKeyState(18)&0x8000)
        {
            if (GetAsyncKeyState(65)&0x8000)
            {
                INPUT keyup_ALT = { 0 };
                keyup_ALT.type = INPUT_KEYBOARD;
                keyup_ALT.ki.wVk = 18;
                keyup_ALT.ki.dwFlags = KEYEVENTF_KEYUP;
                SendInput(1, &keyup_ALT, sizeof(INPUT));

                cout << "worked" << std::endl;
                string bind = "Hello";

                INPUT Input[2] = { 0 };
                Input[0].type = Input[1].type = INPUT_KEYBOARD;
                Input[1].ki.dwFlags = KEYEVENTF_KEYUP;
                for (int i = 0; i < bind.length(); i++)
                {
                    short ch = VkKeyScanA(bind[i]);
                    Input[0].ki.wVk = Input[1].ki.wVk = ch;
                    if (((ch & 0xff00) >> 8) & 0x1)
                    {
                        INPUT shift = { 0 };
                        shift.type = INPUT_KEYBOARD;
                        shift.ki.wVk = VK_SHIFT;
                        SendInput(1, &shift, sizeof(INPUT));
                    }
                    SendInput(2, Input, sizeof(INPUT));
                    if (((ch & 0xff00) >> 8) & 0x1)
                    {
                        INPUT shift = { 0 };
                        shift.type = INPUT_KEYBOARD;
                        shift.ki.wVk = VK_SHIFT;
                        shift.ki.dwFlags = KEYEVENTF_KEYUP;
                        SendInput(1, &shift, sizeof(INPUT));
                    }
                }
                Sleep(500);
            }

        }
    }
}

CHANGES:

  1. Add status check of ALT key;
  2. Make the return value of the GetAsyncKeyState and (&) 0x8000;
  3. Make the ALT key up, to resolve "it runs the "worked" output but it doesn't type out any of the word."
  4. Check the return value of VkKeyScanA, the high-order byte contains the shift state, which control the capital letters, then determine whether to send shift key.
Drake Wu
  • 6,927
  • 1
  • 7
  • 30