본문 바로가기

My Study/Programming&Theory

콘솔모드에서 메시지 처리

우리가 보통 C언어를 처음 시작하건 C++을 처음 시작하건 Visual Studio에선 아래와 같이 시작할 것입니다.

콘솔 응용 프로그램을 선택해서 프로그래밍 하면 항상 검은화면에 하얀글씨만 뜨죠..;;


이렇게 말이죠.

그래서 Windows API를 처음 접했을 때 신기했습니다. 더이상 콘솔 모드가 아닌 직접 메시지 처리를 하며 창을 띄우고 버튼을 누르며 원하는 결과를 하얀화면에 뽑아냈기 때문이죠.
Windows API로 프로그래밍 하는 경우 위 그림에서 옆에 있는 Win32 프로젝트를 선택할것입니다.

하지만 이번엔 콘솔모드에서 메시지 처리를 해보고 싶었습니다.
어려운건 아니더라도 콘솔창에서 메시지 창 정돈 띄워보기로 말이죠.

제가 구현해본 내용입니다... 다른 좋은 방법이 있을수도 있는데 Windows API에서 사용했던 방법에서 따왔습니다.
지속적인 메시지 처리를 위해서 CALLBACK함수를 하나 만듭니다.
이 함수는 WndProc이라고하죠.
그리고 처음에 메시지발생을 시키기위해 CreatWindow함수를 호출합니다.
하지만 CreateWindow하기전에 윈도우가 등록되어 있어야합니다. 
바로 RegisterClass함수를 그 전에 호출시켜줘야하죠.
RegisterClass함수 인자로 WNDCLASS구조체 변수가 들어가는데.. 
넣기위해 해당 구조체변수를 적당한 값으로 초기화시켜줍니다.

이제 CreateWindow함수를 호출시켜 WM_CREATE메시지를 발생시킵니다.
아까 생성했던 CALLBACK함수로 메시지가 넘어가겠죠.

이제 CALLBACK함수로 들어왔으니 맘대로 주물럭주물럭 하면 됩니다.
다른 메시지를 발생시키고 싶으면 SendMessage 혹은 PostMessage를 사용하면됩니다.

처음엔
while(GetMessage(&Message,NULL,0,0))	
{
	TranslateMessage(&Message);	
	DispatchMessage(&Message);	
}
위와같이 main함수에 구현해서 메시지처리를 하고 싶었으나.. 메시지큐에 메시지를 넣어주는 문제에서 막히더군요.
Windows API에선 버튼이 있고 마우스 클릭이 가능한데.. 콘솔창에선 그런게 안되기 때문이죠.
어짜피 CALLBACK함수에서 SendMessage나 PostMessage를 사용해 주물럭 주물럭 하면 되기 때문에 큰 상관은 없습니다.
( 아래에서 WM_TIMER 메시지 처리 테스트를 해보았는데 그 때는 사용했습니다. 아래 코드는 GetMessage가 필요없어서 그냥 뺀거구요. )

이제 구현이 완료된 소스코드를 보시겠습니다.
CALLBACK함수를 보면 printf나 scanf를 그대로 쓴것을 볼수 있습니다.

이제 출력 결과를 보시겠습니다.

이렇게 콘솔모드에서 메시지 창 띄우기가 성공했습니다. -_-;;

근데 그냥 메시지 처리를 하는것을 보여주기 위해서 해본 것입니다. 
보통 콘솔 창에서 메시지박스만 띄울 때는 MessageBox 첫번째 인자로 NULL을 전달해 버리고 쓰면 됩니다.

이제 다른 메시지를 하나만 더 처리해보겠습니다.
바로 WM_TIMER입니다. SetTimer에 의해 셋팅된 타이머가 지정된 시간 간격으로 계속해서 WM_TIMER메시지가 발생하죠.
그런데 그렇게 발생된 메시지를 WndProc함수로 전달하기 위해선..위에서 사용하지 않은 
GetMessage, TranslateMessage, DispatchMessage를 사용해야겠군요.

코드는 그렇게 어려운게 아니니 그냥 코드만 적어보겠습니다.

실행 결과입니다.

콘솔창에서도 띄우고 메시지창으로도 띄우고 있습니다.

C#을 하는 제 친구는 간단하게 구현하는거 같은데..;; 전 C나 C++, Windows API밖에 몰라서;;ㅠㅠ 
어렵게 구현한거 같습니다.

그리고 멀티스레드를 이용해 하는 방법이 있다는데.. 다른 좋은 방법이 있다면 조언부탁드리겠습니다 ^^