728x90
Windows Message
여기서 말하는 Message는 MessageBox에 출력되는 문자열이 아니다. Message는 Windows 안에서 이용되는 구조체이다. Windows는 그 안에 값들을 담아서 자신이 제어할 대상에 보낸다. 예를 들어 윈도우즈를 이용하는 사람이 메모장을 실행한 상태에서 키보드의 키를 누르면 윈도우즈는 이 키에 대한 여러 값들 즉 어떤 문자에 해당하는 키인지 키를 누른 건지 뗀 건지 등을 넣어서 메모장의 편집 영역으로 보낸다.
Windows로 메시지를 보낼 땐 SendMessage와 PostMessage 함수를 쓴다. 이것들은 win32 api에 들어있다. 전자는 메시지를 윈도우즈로 보내는 거다. 처리가 오래 걸리면 프로시저가 멈추지만 이를 감수하고라도 바로 처리해야 할 때 쓴다. 후자는 윈도우즈로 보내서 처리하지 않고 큐에 담는다. 그러면 윈도우즈가 처리할 수 있을 때 큐에 담긴 순서대로 처리한다. 데드록을 막기 위해서다.
SendMessage | PostMessage |
윈도우 프로시저를 직접 호출하며, 프로시저가 메시지를 처리할 때 까지 반환하지 않는다. | 메시지 큐에 메시지가 삽입되며, 윈도우 프로시저에서 메시지를 처리한다. 해당 메시지가 언제 처리될 지 예측이 어렵다. |
순차적으로 처리(sequentially) | 비 순차적으로 처리(not sequentially) |
동기 방식(synchronous) | 비동기 방식(asynchronous) |
Windows로부터 메시지를 받아서 처리할 때에는 WndProc 메서드를 이용한다.
WndProc 메서드
WndProc은 Win32 API에 들어있는 콜백 함수이다. 가만히 있을 땐 실행되지 않고 Windows가 메시지를 보낼 때 작동하는 메서드가 WndProc이다.
C#에서 WndProc 사용하기 - WndProc 오버라이드하기
int MessageID;
protected override void WndProc(ref Message m)
{
if (m.Msg == 12345) // 원하는 메시지 id
{
MessageID = m.Msg;
}
else
{
base.WndProc(ref m);
}
}
private void label1_Click(object sender, EventArgs e)
{
label1.Text = MessageID.ToString();
}
주의할 점
- 멀티스레드 이용 시 주의할 점
- 메세지를 argument로 스레드에 실어서 보낼 때 주의해야 한다. Message는 struct 즉, value 타입이라 원칙적으로 문제될게 없지만 WndProc에서는 ref 키워드가 붙어서 레퍼런스 타입으로 처리되는데 유의한다. 문제를 피하기 위해서는 메시지 자체를 argument로 사용하면 안 되고 인스턴스를 만들어서 고유하게 한 다음에 이 인스턴스를 argumetn로 사용해야 한다.
- MessageBox 이용 시 주의할 점
- WndProc은 끊임없이 작동하는데 그 안에서 MessageBox를 실행하면 이후의 작업들이 멈춘다. MessageBox를 클릭하여 없애면 기다리던 작업들이 실행이 되기는 하는데 오작동한다.
- WPF의 경우
- WndProc은 System.Windows.Forms에 있는거라 WPF로는 이용할 수 없다. WPF에서 윈도우즈 메시지를 제어하려면 조금 더 복잡해진다.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
hwndSource.AddHook(WindowsMessageHook);
}
private IntPtr WindowsMessageHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
TextBlock1.Text = msg.ToString();
return IntPtr.Zero;
}
[출처]
728x90
'C# > Windows' 카테고리의 다른 글
윈도우 프로그래밍 동작 방식 (0) | 2023.11.05 |
---|---|
Win32 API에서 제공하는 자료형 (0) | 2023.11.05 |
Win64 API가 있나요? (0) | 2023.11.05 |
Windows API (0) | 2023.11.05 |