본문 바로가기
프로그래밍/C, C++

Visual C++ 윈도우 키 막기

by 꾸션 2022. 7. 18.

전체 화면으로 게임을 하거나, 작업 중에 "Win 키"가 눌리면서 화면이 아래로 내려가서 방해가 되는 경우가 있습니다.

이를 방지하기 위한 게임 및 애플리케이션 개발 시 사용할 수 있는 소스를 공개합니다.

 

아래의 소스는 Windows hook이라는 기술을 이용한 방법입니다.

(Hook 이란 "가로채기"라는 뜻으로써, 시스템에 전달되는 이벤트를 먼저 가로채는 기술입니다.

보통은 가로챈 이벤트의 처리가 끝나면 반드시 CallNextHookEx함수를 호출하여 시스템에 전달 될 수 있도록 해야합니다.)

 

핵심 소스 부분

아래와 같이 "왼쪽 Windows 키"나 "오른쪽 Windows 키"가 눌린 경우 "CallNextHookEx(...)"함수를 호출하여 시스템으로 넘겨 해당 키에 대한 이벤트 처리를 하도록 넘기지 않고, "return 1;"로 처리함으로 써 처리를 못 하도록 하는 것입니다.

switch (wParam) 
{
  case WM_KEYDOWN:  
  case WM_KEYUP:    
  {
    bEatKeystroke = (g_bFullscreen && g_bWindowActive && ((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)));
    break;
  }
}

if( bEatKeystroke )
  return 1;
 
return CallNextHookEx(g_hKeyboardHook, nCode, wParam, lParam);

 

전체 소스

윈도우 키 눌림 방지를 위한 전체 소스와 주석입니다.

HHOOK g_hKeyboardHook = nullptr;
bool g_bWindowActive = false; // 애플리케이션 활성화 여부
bool g_bFullscreen = false; // full screen 여부

// main 함수
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
  // 키 훅 초기화
  g_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(nullptr), 0);

  //
  // 사용자 소스 부분...
  //

  // 키 훅 종료
  UnhookWindowsHookEx(g_hKeyboardHook);
  g_hKeyboardHook = nullptr;

  return 0;
}

// 키 훅 프로시저 함수
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
  // 키 이벤트와 관련 없는 경우 바로 시스템으로 넘김
  if (nCode < 0 || nCode != HC_ACTION)
    return CallNextHookEx(g_hKeyboardHook, nCode, wParam, lParam);

  bool bEatKeystroke = false;
  auto p = reinterpret_cast<KBDLLHOOKSTRUCT *>(lParam);
  switch (wParam)
  {
      case WM_KEYDOWN:
      case WM_KEYUP:
      {
        // 왼/오른쪽 윈도우 키가 Down/Up인 경우 플래그 설정
        bEatKeystroke = (g_bFullscreen && g_bWindowActive && ((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)));
        break;
      }
  }

  // 키 이벤트를 시스템에 전달하지 않음
  if (bEatKeystroke) {
    return 1;
  }
  
  // 키 이벤트를 시스템에 전달
  return CallNextHookEx(g_hKeyboardHook, nCode, wParam, lParam);
}

// 윈도우 프로시저 함수
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  switch (uMsg)
  {
  case WM_ACTIVATEAPP:
 	 // 애플리케이션 활성화 여부 플래그 설정
    if (wParam)
      g_bWindowActive = true;
    else
      g_bWindowActive = false;
    break;

  case WM_SYSKEYDOWN:
    // "Alt + Enter"키 조합으로 전체화면모드를 지원하는 경우
    // Direct X를 사용하는 경우, DXGI MakeWindowAssociation, DXGI_MWA_NO_ALT_ENTER를 사용해야 함.
    if (wParam == VK_RETURN && (lParam & 0x60000000) == 0x20000000)
    {
      // 전체 화면 여부 플래그 설정
      g_bFullscreen = !g_bFullscreen;
    }
    break;
  }
}
반응형

댓글