2021년 3월 20일 토요일

GetKeyboardState 와 Message Loop

참고할 StackOverflow 문서

GetKeyState 문서


GetKeyboardState() 는 Keyboard 관련 Message 를 처리할때마다 업데이트 되는 값을 들고옴.

GetKeyState 는 바로 이 Message 가 처리될 때 마다 호출이 되며 위 함수가 참조하는 값을 업데이트 하기도 함.

GetAsyncKeyState 는 Interupt 차원에서 값을 처리해서 Message 와는 크게 관계가 없음.


int main() {
	byte keyState[256];
	ZeroMemory(keyState, sizeof(byte) * 255);

	byte pressed = (keyState[KEY_0] & 0x80);
	while (pressed == false)
	{
		ZeroMemory(keyState, sizeof(byte) * 255);
		//GetKeyState(0);
		//GetAsyncKeyState(KEY_0);
		std::cout << GetKeyboardState(keyState) << std::endl;
		pressed = (keyState[KEY_0] & 0x80);
		Sleep(10000);
	};
}

그래서 무한루프를 도는 위 함수는 GetKeyState 가 있는 줄의 주석만 풀면 잘 작동함.

이에 반해 GetAsyncKeyState 로는 작동하지 않음.



const int KEY_0 = 0x30;

int main() {
	byte keyState[256];
	ZeroMemory(keyState, sizeof(byte) * 255);

	auto func = [](byte* keyState, DWORD threadID) {
		DWORD my_id = GetCurrentThreadId();
		AttachThreadInput(my_id, threadID, true); // 없어도 작동함
		byte pressed = (keyState[KEY_0] & 0x80);
		while (pressed == false)
		{
			ZeroMemory(keyState, sizeof(byte) * 255);
			GetKeyState(0); 
			//GetAsyncKeyState(KEY_0);
			std::cout << GetKeyboardState(keyState) << std::endl;
			pressed = (keyState[KEY_0] & 0x80);
			//Sleep(10000);
		};
	};

	//func(keyState, GetCurrentThreadId());
	auto t = std::thread(func, keyState, GetCurrentThreadId());
	t.join();
}

 위 코드는 재현다하가 뻘짓한 코드로 아래 설명에 대한 코드 아님.

 GetKeyboardState 가 참조하는 값들은 멀티스레드 환경에서 실험하면 알 수 있듯이 스레드마다 독립적으로 갖음. 만약 window message 펌프를 한 스레드에서 실행하면 GetKeyState() 없이도 잘 될거임. 이때 딴 스레드에서 GetKeyboardState() 를 호출하면 이건 잘 작동하지 않음. 이때 그 스레드에서도 GetKeyState() 를 호출하면 잘 작동하게 됨.


List