0
votes

I am trying to detect when a user alt tabs out of my window. I have tried several messages (WM_ACTIVATE, WM_KILLFOCUS, WM_ACTIVATEAPP, WM_NCACTIVATE, WM_CANCELMODE, and WM_SYSCOMMAND checking for SC_MINIMIZE). But the same problem still occurs. The following happens.

  1. My application is in focus, and I hold down alt and press tab.
  2. The next window is brought forth.
  3. I keep holding down alt and then press tab again, but this time, only tab is recognized and so I end up tabbing in the new window rather than alt tabbing again as is the usual behavior.

I am using a low level keyboard hook, and if I uninstall that this alt tabbing behavior described above works perfectly. I basically want to uninstall the keyboard hook as soon as the user leaves my window in this fashion. As soon as I release alt tab while in another window, my window receives several of the messages I look for and the hook is uninstalled. But when you hold the keys in this manner, it does not work as expected while the hook is installed.

2
If I understand correctly, you're using a global hook and trying to recreate the behaviour of a local one.chris

2 Answers

0
votes

why do you need to remove the keyboard hook? The SetWindowsHook is local to your application and not affect the other apps, therefore it already does nothing if your app doesn't have the focus.

Edit make sure you call the next hook in your callback with CallNextHookEx to not screw up screen readers

0
votes

I used the following code and it seems to be catching the focus changes, and I am not getting any problem with regard to holding down ALT or TAB in various combinations. But I didn't thoroughly test it yet.

EDIT: I read your post again and see that your problem is probably an interaction between the two different hooks. So I am also hooking the keyboard in my app, but I am using an Import Address Table hook of DispatchMessage. My hooks don't interact the way yours do, but my solution may not be appropriate for you.

bool AddHookToKeyboardFocusChanges()
{
  HHOOK hhookFocusChange = NULL;

  hhookFocusChange = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWindowProcHook, NULL, GetCurrentThreadId());    // the last parameter makes it a local, not global hook

  if(hhookFocusChange == NULL)
    return false;

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// This is the routine that we register to be called on every call to a
// WindowProc in our application; we use it to catch WM_SETFOCUS and 
// WM_KILLFOCUS messages that indicate gaining or losing keyboard input focus.
// Unlike keyboard, mouse, paint, and timer messages, the focus messages are not
// posted to the message queue. Instead they are sent directly to WindowProc.
// We must hook them here.
//
LRESULT WINAPI CallWindowProcHook(int nCode, WPARAM wParam, LPARAM lParam) 
{
  UINT message = ((CWPSTRUCT*)lParam)->message;

  switch(message)
  {
    case WM_ACTIVATE:
      OutputDebugString(L"Window activated.\n");
      break;
    case WM_SETFOCUS:
      OutputDebugString(L"Window focused.\n");
      break;
    case WM_KILLFOCUS:
      OutputDebugString(L"Window focus lost.\n");
      break;
    default:
      break;
  }

    // CallNextHookEx calls the next hook in the chain.
    return CallNextHookEx(NULL, nCode, wParam, lParam); 
}