C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[1104] 마우스 앞으로/뒤로 버튼과 키보드 미디어키 감지하기
박지훈.임프 [cbuilder] 12608 읽음    2012-09-10 03:23
요즘 나오는 마우스들 대부분에는 미디어 키가 추가되어 있습니다. 키보드 상단에 하드웨어 키가 따로 있는 경우도 있고, 오른쪽 사진의 제 키보드처럼 펑션키의 조합인 경우도 있는데요. 보통은 볼륨 업/다운, 다음곡/이전곡 이런 기능들이 연결되어 있지요.

또 요즘엔 마우스에도 웹브라우저의 앞으로, 뒤로튼이 추가되어 있는 경우가 많습니다. 저도 이 버튼 기능을 최근에야 쓰기 시작했는데, 한번 맛들이니 아주아주 편리하더군요. ^^

그럼, 델파이나 C++빌더 애플리케이션에서 이들 버튼과 키 동작을 감지할 수는 없을까요? 제 경우엔, 마우스의 앞으로/뒤로 버튼을 페이지컨트롤의 앞 페이지, 뒤 페이지 이런 기능에 연결하고 싶었습니다.

이런 특수 키, 버튼의 감지는 생각보다 아주 간단합니다. WM_APPCOMMAND라는 메시지를 검출하면 되는데요. 키가 눌려진 순간 현재 활성화된 프로그램으로 이 메시지가 날아옵니다. 따라서 메시지 핸들러 함수를만들고 이 메시지를 검출하면 됩니다.

이 WM_APPCOMMAND 메시지의 lParam을 GET_APPCOMMAND_LPARAM()이라는 API 함수로 걸러내면 어떤 키보드 키나 마우스 버튼이 눌려졌는지 알아낼 수 있습니다.
또 lParam을 GET_DEVICE_LPARAM() 함수로 거르면 어떤 디바이스(마우스/키보드/제3의 디바이스)에서 이벤트가 발생했는지 알 수 있지요. GET_KEYSTATE_LPARAM() 함수를 쓰면 해당 버튼/키가 눌린 순간에 컨트롤키나 마우스의 다른 버튼이 눌려진 상태인지도 알아낼 수 있습니다.

간단한 예제를 보지요. 아래는 델파이 예제입니다.
procedure TForm1.WMAppCommand(var Msg: TMessage);
var
  sMessage: string;
begin
  case GET_APPCOMMAND_LPARAM(Msg.LParam) of
    APPCOMMAND_BROWSER_BACKWARD:
    begin
      PageControl1.ActivePageIndex := PageControl1.ActivePageIndex - 1;
      sMessage := 'Browser backward';
    end;
    APPCOMMAND_BROWSER_FORWARD:
    begin
      PageControl1.ActivePageIndex := PageControl1.ActivePageIndex + 1;
      sMessage := 'Browser forward';
    end;

    APPCOMMAND_BROWSER_HOME:        sMessage := 'Browser Home';
    APPCOMMAND_BROWSER_SEARCH:      sMessage := 'Browser Search';

    APPCOMMAND_VOLUME_MUTE:         sMessage := 'Volume Mute';
    APPCOMMAND_VOLUME_UP:           sMessage := 'Volume Up';
    APPCOMMAND_VOLUME_DOWN:         sMessage := 'Volume Down';

    APPCOMMAND_MEDIA_PREVIOUSTRACK: sMessage := 'Media Previous Track';
    APPCOMMAND_MEDIA_NEXTTRACK:     sMessage := 'Media Next Track';

    APPCOMMAND_LAUNCH_MEDIA_SELECT: sMessage := 'Media Select';
    APPCOMMAND_MEDIA_PAUSE:         sMessage := 'Media Pause';
    APPCOMMAND_MEDIA_PLAY:          sMessage := 'Media Play';
    APPCOMMAND_MEDIA_PLAY_PAUSE:    sMessage := 'Media Paly/Pause';

    APPCOMMAND_LAUNCH_APP1:         sMessage := 'Launch App1';
    APPCOMMAND_LAUNCH_APP2:         sMessage := 'Launch App2';
    APPCOMMAND_LAUNCH_MAIL:         sMessage := 'Launch Mail';
  end;

  sMessage := sMessage + ' with ';
  case GET_DEVICE_LPARAM(Msg.LParam) of
    FAPPCOMMAND_KEY:   sMessage := sMessage + 'Keyboard key';
    FAPPCOMMAND_MOUSE: sMessage := sMessage + 'mouse button';
    FAPPCOMMAND_OEM:   sMessage := sMessage + 'unknown device';
  end;

  ShowMessage(sMessage);
  inherited;
end;

C++빌더 버전의 예제는 아래와 같습니다.
// 헤더 파일
class TForm1 : public TForm
{
  ...  // 생략
public:
	__fastcall TForm1(TComponent* Owner);
	void __fastcall WMAppCommand(TMessage &Msg);

BEGIN_MESSAGE_MAP
	MESSAGE_HANDLER(WM_APPCOMMAND, TMessage, WMAppCommand)
END_MESSAGE_MAP(TForm)
};

//cpp 파일 
void __fastcall TForm1::WMAppCommand(TMessage &Msg)
{
  String sMessage;
  switch GET_APPCOMMAND_LPARAM(Msg.LParam)
  {
	case APPCOMMAND_BROWSER_BACKWARD:
	  PageControl1->ActivePageIndex = PageControl1->ActivePageIndex - 1;
	  sMessage = "Browser backward";
	  break;
	case APPCOMMAND_BROWSER_FORWARD:
	  PageControl1->ActivePageIndex = PageControl1->ActivePageIndex + 1;
	  sMessage = "Browser forward";
	  break;

	case APPCOMMAND_BROWSER_HOME:        sMessage = "Browser Home"; break;
	case APPCOMMAND_BROWSER_SEARCH:      sMessage = "Browser Search"; break;

	case APPCOMMAND_VOLUME_MUTE:         sMessage = "Volume Mute"; break;
	case APPCOMMAND_VOLUME_UP:           sMessage = "Volume Up"; break;
	case APPCOMMAND_VOLUME_DOWN:         sMessage = "Volume Down"; break;

	case APPCOMMAND_MEDIA_PREVIOUSTRACK: sMessage = "Media Previous Track"; break;
	case APPCOMMAND_MEDIA_NEXTTRACK:     sMessage = "Media Next Track"; break;

	case APPCOMMAND_LAUNCH_MEDIA_SELECT: sMessage = "Media Select"; break;
	case APPCOMMAND_MEDIA_PAUSE:         sMessage = "Media Pause"; break;
	case APPCOMMAND_MEDIA_PLAY:          sMessage = "Media Play"; break;
	case APPCOMMAND_MEDIA_PLAY_PAUSE:    sMessage = "Media Paly/Pause"; break;

	case APPCOMMAND_LAUNCH_APP1:         sMessage = "Launch App1"; break;
	case APPCOMMAND_LAUNCH_APP2:         sMessage = "Launch App2"; break;
	case APPCOMMAND_LAUNCH_MAIL:         sMessage = "Launch Mail"; break;
  }

  sMessage = sMessage + " with ";
  switch GET_DEVICE_LPARAM(Msg.LParam)
  {
	case FAPPCOMMAND_KEY:   sMessage = sMessage + "Keyboard key"; break;
	case FAPPCOMMAND_MOUSE: sMessage = sMessage + "mouse button"; break;
	case FAPPCOMMAND_OEM:   sMessage = sMessage + "unknown device"; break;
  }

  ShowMessage(sMessage);
}

(델파이 코드에서 가장 아래의 inherited를 없애버릴 경우, 기본 동작이 막히게 됩니다.)

위 코드를 실제로 실행해보시면 아시겠지만, 이 코드를 활용하면 애플리케이션에서 볼륨 업다운이나 트랙 앞/뒤 등의 키보드 동작이 발생할 때 애플리케이션에서 특정 동작으로 연결할 수 있습니다. 예를 들자면, MDI 애플리케이션에서 여러 차일드 창을 열어놨을 때, 트랙 앞/뒤 키를 누르면 다음 창, 이전 창 이렇게 이동하게 할 수 있게 되지요.

위에서 나열한 키는 모두는 아니고 제 마우스와 키보드에 있는 것들만 추린 거구요. 전체 리스트를 보시려면 MSDN의 WM_APPCOMMAND 메시지에 대한 설명 페이지에서 보실 수 있습니다.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx
DCAS [simulica]   2012-09-12 01:44 X
궁금했었는데, 좋은 정보 감사합니다.
우와 [awesome]   2012-09-12 09:21 X
좋은정보 감사합니다.

+ -

관련 글 리스트
1104 마우스 앞으로/뒤로 버튼과 키보드 미디어키 감지하기 박지훈.임프 12608 2012/09/10
(링크)     Delphi Tip'N Tricks > 마우스 앞으로/뒤로 버튼과 키보드 미디어키 감지하기
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.