MFC/개념 정리

[MFC] WM_COMMAND 메시지

luckybee 2022. 12. 31. 15:34
728x90
반응형

WM_COMMAND 메시지

1. 대화상자나 윈도우에 만들어진 버튼 같은 컨트롤을 누르거나 리소스에 등록된 단축키를 사용하거나 메뉴에서 항목을 선택하면 WM_COMMAND 메시지가 발생한다.

 

2. WM_COMMAND 메시지는 다양한 상황에서 발생하기 때문에 메시지와 함께 전달되는 wParam과 lParam에 저장된 정보로 구분한다. 

 

3. lParam이란? 

 

  - 컨트롤의 핸들 값이다. 

  - 버튼과 같은 컨트롤을 눌러서 WM_COMMAND 메시지가 발생했으면 lParam 변수에는 이 메시지를 발생한 컨트롤의          HWND 값이 저장되어 있다. 그러나 단축키와 같은 컨트롤이 아닌 경우에는 lParam에 NULL이 저장되어 있다.

 

4. wParam이란?

 

  - 상위 16비트에는 대부분 통보 코드(Notification code)가 저장되어 있다. -> 단축키, 메뉴 제외

  - 버튼 컨트롤을 눌러서 WM_COMMAND 메시지가 발생했다면 BN_CLICKED 값이 저장되어 있다. 

  - 단축키를 누른 경우는 1이 저장되고 메뉴를 누른 경우에는 0이 저장

  - 하위 16비트에는 Command ID가 포함되어 있다. 

  - 버튼을 눌러서 WM_COMMAND 메시지가 발생했다면 해당 버튼의 ID가 저장되어 있다.

       EX) 아이디가 IDC_TEST_BTN이면 wParam의 하위 16비트에는 IDC_TEST_BTN이 저장되어 있다.

       ps) 단축키는 단축키를 등록할 때 등록한 ID값이 들어있고, 메뉴는 메뉴 항목을 등록할 때 사용한 ID가 저장되어 있다. 

 

예시 코드를 들어보면 아래 사진처럼 TEST버튼이 다이어로그에 추가되어 있다. 

 

이제 이 버튼을 더블클릭하면 Message Map에 아래와 같은 매크로 함수가 추가되고,

BEGIN_MESSAGE_MAP(CTESTPARAMDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_TEST_BTN, &CTESTPARAMDlg::OnBnClickedTestBtn)  //추가
END_MESSAGE_MAP()

 

IDC_TEST_BTN 버튼이 눌렸을 때 실행되는 함수도 추가가 된다.

void CTESTPARAMDlg::OnBnClickedTestBtn()   //추가
{
	
}

이제 내가 IDC_TEST_BTN라는 ID를 가진 TEST 버튼을 누르면 WM_COMMAND가 발생하고, 이 메시지와 함께

 wParam(상위 16비트: BN_CLICKED, 하위 16비트: IDC_TEST_BTN), lParam(버튼의 핸들 값)이 전달된다.

 

이제 WM_COMMAND 메시지를 직접 처리하기 위해 클래스 마법사에서 가상함수를 클릭한 후 OnCommand 함수를 추가하겠다. 아래는 추가되면 나오는 코드이다.

BOOL CTESTPARAMDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
	
	return CDialogEx::OnCommand(wParam, lParam);
}

 

아래 코드는 클릭했을 때 OnCommand함수에 메시지가 잘 들어왔는지 테스트를 해보기 위해 작성했다.

void CTESTPARAMDlg::OnBnClickedTestBtn()   //아까 추가한 버튼 함수
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
}


BOOL CTESTPARAMDlg::OnCommand(WPARAM wParam, LPARAM lParam)  //OnCommand
{
	
	if (LOWORD(wParam)==IDC_TEST_BTN&&HIWORD(wParam)==BN_CLICKED)
	{
		AfxMessageBox(L"command clicked");
		return 1;
	}
	return CDialogEx::OnCommand(wParam, lParam);
}

실행화면

단순하게 비교하면 OnCommand보다 일반적인 클래스 마법사가 더 편해 보이지만 계산기 예제와 같이 버튼을 나열해야 하는 상황이 생길 때는 OnCommand함수를 사용해서 범위로 체크하는 것이 더 편하다.

 

마지막으로 Win32 프로그래밍에서는 PostMessage 또는 SendMessage 함수를 사용하여 사용자가 버튼이 누른 것처럼 메시지를 발생시킬 수 있다. 코드는 아래와 같다.

SendMessage(WM_COMMAND, MAKEWPARAM(IDC_TEST_BTN,BN_CLICKED),(LPARAM)(GetDlgItem(IDC_TEST_BTN)->m_hWnd));

MAKEWPARAM 매크로 함수는 WPARAM 형식의 데이터를 하위 16비트, 상위 16비트로 나누어서 적을 수 있도록  만들어진 함수이다.

 

아래는 위 코드를 OnInit함수에 넣고 실행한 결과이다.

 

실행화면

시작하자마자 위의 메시지박스가 출력되고, 메시지 박스를 끄면 기본 윈도우가 생성된다.

728x90
반응형