MenuIcon

Owl-Networks Archive

LoginIcon

Perl / Win32::GUI : 현재 NumLock / CapsLock 키가 토글 상태인지를 확인하기

| 분류: Perl | 최초 작성: 2012-03-25 00:47:33 |

이 글은 "Win32::GUI 1.06 의 GetKeyState 의 오동작 사례" 라는 제목으로, 네이버 카페 "Perl Community & Study" 카페에 먼저 등록(2012/01/19)되었던 글을 일부 수정한 것입니다.

이 글에서는 NUMLOCK 키를 기준으로 설명합니다만 역시 토글 모드가 존재하는 CAPSLOCK 이나 SCROLLLOCK 키 역시 모두 동일한 방법으로 사용이 가능합니다.



NUMLOCK 키가 토글 상태인지 확인하기


시작은 키보드의 숫자 키패드를 이용하는 가상 마우스를 만들어보려던 것이었습니다. 숫자 키패드의 키들을 눌러서 마우스 포인터를 움직이려 했던 것이지요. 윈도우에서 키 눌림을 모니터링할 때, 숫자 키패드의 키가 눌린 것으로 인식되는 경우는 NumLock키가 토글(불 들어옴) 상태에서 숫자 키패드의 키를 누를 때입니다. 따라서 공연한 번거로움을 막기 위해서는, (1) 프로그램을 실행한 후 가상 마우스의 기능이 켜질 때에 현재의 NumLock키의 상태를 확인하여 만약 켜져 있지 않다면 이를 켜 주고, (2) 가상 마우스 기능이 꺼질 때에는 반대로 NumLock이 켜져 있다면 꺼 주는 절차가 필요합니다. 그런 고로,

"Perl 에서 현재 NumLock 이 토글 상태인지 해제 상태인지를 확인하라."

가 오늘의 문제 되겠습니다.

처음 생각하기에는 간단한 문제 같았는데, 생각외로 답이 안 나옵니다. 구글신께 문의해봐도 미묘하게 답이 나오질 않더군요. 단순히 키가 눌림(Pressed) 상태인지를 판단하는 걸로는 안 됩니다. 토글 상태인지 확인하는 건 또 다른 문제가 됩니다.

한참을 삽질하다가 드디어 방법을 찾았습니다. 등잔 밑이 어둡다고, 의외로 사용하던 Win32::GUI 모듈 안에 해결책이 있었지요

use Win32::GUI qw( VK_NUMLOCK );
Win32::GUI::GetKeyState( VK_NUMLOCK );


GetKeyState 를 이용하면 되었습니다. Win32::GUI 레퍼런스에 의하면, GetKeyState 는 스칼라 문맥에서는 해당 키가 눌림 상태인지 아닌지를 판단한다고 했습니다. 그러나 이것이 배열 문맥이 되면, KeyPressed 이외에 해당 키가 토글 상태인지 해제 상태인지를 (함께)넘겨준다고 합니다.

(In scalar context returns a value specifying whether the key is up(0) or down(1). In list context, returns a 2 element list with the first element as in scalar context and the second member specifying whether the key is toggled(1) or not(0) - this is only meaningful for keys that have a toggled state: Caps Lock, Num Lock etc.)


따라서, 이에 따라 간단히 기능을 구현해 보면 다음과 같은 코드 조각이 됩니다.

use Win32::GUI qw( VK_NUMLOCK );

my @NumLockState = Win32::GUI::GetKeyState( VK_NUMLOCK );

if ( $NumLockState[1] == 1 ) {
    print "NumLock 이 켜져 있습니다!";
}
else {
    print "NumLock 이 꺼져 있습니다!";
}


print 문 위치에는 그 대신 적절한 처리문을 넣을 수 있습니다. NumLock 이 꺼져 있는 경우 이를 켜는(여러 가지 방법이 있습니다) 코드를 넣으면 되겠네요.


Strawberry Perl 5.10.1.5 버전에서 발생하는 오류


...이대로만 끝났으면 참 좋았을 텐데, 의외의 복병을 만납니다.

아시는 분은 아시겠지만, 저는 일반 환경에서 ActivePerl 5.10.1 을 사용합니다. 코드를 짜고 테스트할 때 이쪽에서 작업을 하지요. 그러나, 최근 PAR::Packer 를 버리고 aero 님의 패키징 방법론(아이디어가 번뜩이는 멋진 방법이었습니다)을 받아들인 결과, 공개를 위해 패키징을 할 때에는 Strawberry Perl 5.10.1 을 사용하고 있습니다. (AcrivePerl 에서는 이 방법을 사용할 수 없기 때문입니다.)

문제는 ActivePerl 에서 문제 없이 돌아간 코드를 패키지 빌드를 위해 Strawberry Perl 에서 테스트를 하는 도중에 발견되었습니다. 가상 마우스 모드가 해제되었음에도 NumLock 이 정상적으로 꺼지지 않는 현상이 발견되었습니다. 코드상에는 분명, 가상 마우스 모드가 해제될 때, NumLock 이 켜져 있는지를 확인하여 만약 켜져 있다면 이를 끄도록 코딩이 되어 있었습니다.

이상하다 싶어서 오류를 확인해 보니, Strawberry Perl 에서 $NumLockState[1] 의 값을 계속적으로 undef 값으로 반환하고 있더군요. 즉, Win32::GUI 레퍼런스 페이지의 설명과는 다르게, 배열 문맥임에도 불구하고 GetKeyState 메서드의 반환값이 스칼라 문맥에서의 경우와 동일하게 나타나고 있었습니다. 두 번째 반환값이 계속 누락되고 있는 것이죠.

Warning 메시지를 확인해 보면, 배열 @NumLockState 의 두 번째 값이 계속적으로 undef(정의되지 않음)으로 리턴되고 있음을 발견할 수 있고, 실제로 값을 찍어 보면 아무 값도 들어있지 않습니다.
Warning 메시지를 확인해 보면, 배열 @NumLockState 의 두 번째 값이 계속적으로 undef(정의되지 않음)으로 리턴되고 있음을 발견할 수 있고, 실제로 값을 찍어 보면 아무 값도 들어있지 않습니다.


결론적으로, Strawberry Perl 의 5.10.1 버전에서는 GetKeyState 메서드를 이용하여 NumLock 이 켜져 있는지 확인이 불가능합니다. Win32::GUI 자체적인 문제가 아니라 Strawberry Perl 의 문제라고 단정할 수 있는 이유는, (1) 정상적으로 동작하는 ActivePerl 쪽에 설치되어 있던 Win32::GUI 를 가져다가 Strawberry Perl 에 적용해 보아도 이 기능이 동작하지 않았으며, (2) 결정적으로, 패키징이 완료된 상태에서 패키지 내에 포함된 Strawberry Perl의 Perl510.dll 파일을 ActivePerl 의 그것으로 교체해 본 결과 기능이 정상적으로 동작하였기 때문입니다. 이 기능에 대해 기술한 Win32::GUI 매뉴얼이 잘못된 것이 아니라면, Strawberry Perl 쪽에서 잘못된 결과값을 반환하고 있는 것이 거의 확실한 것이죠.


덧붙임. 일단 Strawberry Perl 의 다른 버전에서는 어떤 결과가 나오는지는 직접 확인해보지 않았습니다. 다만 Strawberry Perl 5.12.3 버전에서는 정상적으로 코드가 동작한다는 aero 님의 피드백이 있었기 때문에, 아마도 Strawberry Perl 5.10.1 버전대(혹은 5.10.1.5 버전)에서 발견되는 특유한 문제라고 짐작하고 있습니다.


내부 링크. 이 글에서 설명한 방법이 적용된 키보드 가상 마우스 프로그램은 다음의 경로에 공개되어 있습니다.

* 키보드 가상 마우스 : http://www.nightowl.pe.kr/software/kvmouse

☞ 태그: NumLock Toggle, Win32::GUI, GetKeyState,

☞ 트랙백 접수 모듈이 설치되지 않았습니다.

☞ 덧글이 없고, 트랙백이 없습니다.

덧글을 남기시려면 여기를 클릭하십시오.
[483] < [426] [424] [423] [422] [421] ... [420] ... [419] [418] [416] [415] [413] > [19]

(C) 2000-2018, Owl-Networks. Powered by Perl. 이 페이지는 HTML 5 표준에 따라 작성되었습니다.