Jump to content
  • Advertisement
Sign in to follow this  
matt77hias

VK_SNAPSHOT and KEYDOWN

Recommended Posts

I want to take a screenshot when the user presses "print screen" or ALT + "print screen". I succeed by listening for up keys:

case WM_KEYUP: {

	switch(wParam) {
	case VK_SNAPSHOT:
		SwapChain::Get()->TakeScreenShot();
    default:
    	return DefWindowProc(hWnd, msg, wParam, lParam);
	}
}
        
case WM_SYSKEYUP: {

	switch(wParam) {
	case VK_SNAPSHOT:
		SwapChain::Get()->TakeScreenShot();
	default:
		return DefWindowProc(hWnd, msg, wParam, lParam);
	}
}

This does not work for down keys for VK_SNAPSHOT. Why is this the case?

Edited by matt77hias

Share this post


Link to post
Share on other sites
Advertisement

I can't remember the exact reason, though I had this problem before (will search the forum-post that will hopefully contain the explanation). In the meanwhile, the solution for me was to install a hook, that checks for that specific keypress:

LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	if(nCode >= 0 && nCode == HC_ACTION)
	{
		KBDLLHOOKSTRUCT* p = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
		switch(wParam)
		{
		case WM_KEYDOWN:
			if(p->vkCode == VK_SNAPSHOT)
				input::WindowProcHook::SetRawButtonState(input::Keys::PRINT, true, false); // your code goes here
			break;
		}
	}

	return CallNextHookEx(impl::hKeyboardHook, nCode, wParam, lParam);
}

// call this somewhere at program startup
void registerPrintKeyHook(void)
{
	impl::hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, lowLevelKeyboardProc, GetModuleHandle(NULL), 0);
}

EDIT: There you go:

this should hopefully explain it :)

Share this post


Link to post
Share on other sites
7 minutes ago, matt77hias said:

Why not using if(HC_ACTION == nCode) ?

You're right, makes much more sense. That code was pretty much copy paste, as I happen to do with most Win32-related code :D

Share this post


Link to post
Share on other sites
14 hours ago, Juliean said:

return CallNextHookEx(impl::hKeyboardHook, nCode, wParam, lParam);

Since the first parameter is ignored according to MSDN, why also not providing nullptr?

The hook seems already nicer compared to other callbacks. I implemented the window callbacks as class methods. In order to support multiple instances, I always need to look for a way to smuggle the "this pointer" of the calling object into the function.

Edited by matt77hias

Share this post


Link to post
Share on other sites

I added the registration of the hook but I never get inside the proc:

temp = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, GetModuleHandle(NULL), 0);

(temp is non-null)

Edited by matt77hias

Share this post


Link to post
Share on other sites

Hm, not sure why it isn't being called for you, it definately worked for me. After looking through my code though, I noticed I wasn't even installing this hook anymore. From the commit that I wrote, there where some "responsiveness issues", so I just went with using WM_KEYUP for snapshots instead, oh well...

Share this post


Link to post
Share on other sites

I am doing this the following way, seems a bit more standard WinAPI usage for me:

First, I have this enum:

enum Hotkeys{ UNUSED = 0, PRINTSCREEN = 1,};

Then in the InitInstance winapi function I call this after creating the window:

RegisterHotKey(hWnd, PRINTSCREEN, 0, VK_SNAPSHOT);

The last step is to handle the message in the message loop (WndProc function) like this:

switch (message)
{
	// ...
	case WM_HOTKEY:
		switch (wParam)
		{
		case PRINTSCREEN:
			{
				Helper::screenshot();
			}
			break;
		default:
			break;
		}
		break;
}

This one handles it on keydown. It also overrides the PrtScn key completely, so you cannot for example copy paste into Paint afterwards.

Cheers!

Share this post


Link to post
Share on other sites
13 minutes ago, turanszkij said:

I am doing this the following way, seems a bit more standard WinAPI usage for me:

First, I have this enum:


enum Hotkeys{ UNUSED = 0, PRINTSCREEN = 1,};

Then in the InitInstance winapi function I call this after creating the window:


RegisterHotKey(hWnd, PRINTSCREEN, 0, VK_SNAPSHOT);

The last step is to handle the message in the message loop (WndProc function) like this:


switch (message)
{
	// ...
	case WM_HOTKEY:
		switch (wParam)
		{
		case PRINTSCREEN:
			{
				Helper::screenshot();
			}
			break;
		default:
			break;
		}
		break;
}

This one handles it on keydown. It also overrides the PrtScn key completely, so you cannot for example copy paste into Paint afterwards.

Cheers!

Nice and clean solution. I am going to give it a try as well :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!