U
						
					
					
						
					
				
				
					compilierbares "minimal"bsp.:
(sendet "Hey" and nen fenster, dessen Name mit " - Editor" endet. das sollte bei nem deutschen windows notepad sein)
->
notepad öffnen
compilieren/ausführen
<-
#include <windows.h>
#include <stdexcept>
namespace keys
{
	enum type : int
	{
		A = 'A', B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
		NUM_0 = '0', NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9,
		SPACE = VK_SPACE,
		SHIFT = VK_SHIFT,
		/*...*/
		CTRL_L = VK_LCONTROL,
		nothing = 0
	};
}
struct key_send
{
	key_send(keys::type key, bool manual_ctrl = false)
	{
		input.type = INPUT_KEYBOARD;
		input.ki.time = 0;
		input.ki.dwExtraInfo = 0;
		input.ki.wVk = WORD(key);
		if (key >= keys::A && key <= keys::Z || key == keys::SPACE || key >= keys::NUM_0 && key <= keys::NUM_9)
			input.ki.dwFlags = KEYEVENTF_SCANCODE;
		else
			input.ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
		input.ki.wScan = WORD(MapVirtualKey(UINT(key), MAPVK_VK_TO_VSC));
		if (!manual_ctrl)
			press();
	}
	void press()
	{
		if (down)
			return;
		send();
	}
	void release()
	{
		if (!down)
			return;
		input.ki.dwFlags |= KEYEVENTF_KEYUP;
		send();
	}
	~key_send()
	{
		try
		{
			release();
		}
		catch (...)
		{
			;
		}
	}
private:
	void send()
	{
		auto events = SendInput(1, &input, sizeof(input));
		if (events != 1)
			throw std::runtime_error("SendInput");
		down = !down;
	}
	bool down = false;
	INPUT input;
};
#include <vector>
#include <cassert>
#include <cstring>
namespace window
{
	using handle_t = HWND;
	const handle_t no_handle = handle_t(0);
	class thread_attacher
	{
	public:
		thread_attacher(handle_t hwnd_from, handle_t hwnd_to)
		{
			from = ::GetWindowThreadProcessId(hwnd_from, 0);
			to = ::GetWindowThreadProcessId(hwnd_to, 0);
			::AttachThreadInput(from, to, true);
		}
		~thread_attacher()
		{
			::AttachThreadInput(from, to, false);
		}
	private:
		DWORD from;
		DWORD to;
	};
	inline void set_foreground_window(handle_t hwnd)
	{
		::SetForegroundWindow(hwnd);
	}
	inline handle_t get_foreground_window()
	{
		return ::GetForegroundWindow();
	}
	namespace detail
	{
		struct find_window_data
		{
			find_window_data(const char* title)
				: title(title)
				, handle(0)
			{}
			const char* title;
			HWND handle;
		};
		struct wildcard_string
		{
			wildcard_string(const char* string)
				: str(string)
			{
				if (std::strlen(str) > 1)
					assert(!std::strchr(str + 1, '*') && "TODO");
			}
			bool operator== (const char* rhs) const
			{
				const char* lhs = str;
				if (*lhs == '*')
					return std::strstr(rhs, ++lhs) != nullptr;
				return std::strcmp(lhs, rhs) == 0;
			}
			bool operator!= (const char* rhs) const
			{
				return !(*this == rhs);
			}
		private:
			const char* str;
		};
		inline std::vector<char> get_title_from_hwnd(HWND hWnd)
		{
			const std::size_t MAX_LEN = 2048;
			std::vector<char> ret_val(MAX_LEN);
			int length = MAX_LEN - 1;
			auto size_copyed = GetWindowTextA(hWnd, &ret_val[0], length);
			ret_val.resize(static_cast<std::size_t>(size_copyed < 0 ? 0 : size_copyed + 1), '\0');
			return ret_val;
		}
		inline BOOL CALLBACK find_window_impl(HWND hWnd, LPARAM lParam)
		{
			const BOOL call_next = TRUE;
			const BOOL finished = FALSE;
			find_window_data* data = reinterpret_cast<find_window_data*>(lParam);
			assert(data && "invalid pointer");
			std::vector<char> this_title = get_title_from_hwnd(hWnd);
			if (this_title.empty())
				return call_next;
			wildcard_string lhs(data->title);
			const char* rhs = &this_title[0];
			if (lhs != rhs)
				return call_next;
			data->handle = hWnd;
			return finished;
		}
	}
	// Returns the window handle when found. if it returns 0 GetLastError() will return more information
	// title may contain '*' as wildcard for [0, n] characters
	inline handle_t find_window(const char* title)
	{
		assert(title && "invalid pointer");
		detail::find_window_data data(title);
		if( EnumWindows(detail::find_window_impl, reinterpret_cast<LPARAM>(&data)) )
		{
			SetLastError(ERROR_FILE_NOT_FOUND);
			return no_handle;
		}
		SetLastError(ERROR_SUCCESS);
		return data.handle;
	}
}
struct scoped_foreground
{
	using hwnd_t = window::handle_t;
	scoped_foreground(hwnd_t handle)
	:	old_foreground( window::get_foreground_window() )
	,	new_foreground( handle )
	{
		assert(new_foreground != window::no_handle && "bad handle");
		if( old_foreground != new_foreground )
			window::set_foreground_window(new_foreground);
	}
	~scoped_foreground()
	{
		if (old_foreground == new_foreground)
			return;
		window::thread_attacher attacher(old_foreground, new_foreground);
		window::set_foreground_window(old_foreground);
	}
private:
	hwnd_t old_foreground;
	hwnd_t new_foreground;
};
#include <iostream>
void real_main()
{
	auto notepad_handle = window::find_window("* - Editor");
	if(notepad_handle == window::no_handle)
		throw std::runtime_error("no window found");
	scoped_foreground focus( notepad_handle );
	{
		{
			key_send t1(keys::SHIFT);
			key_send t2(keys::H);
		}
		key_send t3(keys::E);
		key_send t4(keys::Y);
	}
	Sleep(1000); // !
}
int main()
{
	try
	{
		real_main();
	}
	catch (const std::exception& e)
	{
		std::cerr << e.what() << std::endl;
	}
	std::cout << "fertig" << std::endl;
	char x;
	std::cin >> x;
}