프로그램이 두번 열리는 것을 방지하는 것이다.

프로그램을 실행 시키고나서, 의도적이든 실수든 또 실행 시킬 수 있다.
여러 프로그램을 동시에 돌리듯, 한 프로그램을 여러개를 동시에 실행하는 것이다.
그것을 막기 위한 방법이다.

아래와 같은 함수를 사용할 것이다.


(함수 선언)



함수 내용은 다음과 같다.



(mutex)



뮤텍스는 한 번에 하나의 스레드만 소유할 수 있는 객체로써
고유 문자열의 뮤텍스를 생성시킨다. 그리고 뮤텍스가 생성되면 false를, 중복이 되면 ERROR_ALREADY_EXISTS 에러가 뜨는데 이 에러가 나면 true를 return한다.

윈도우즈 창을 생성하기 전에 아래와 같은 코드를 추가하면 된다.



(중복 체크)



중복이지 않을 때
아래의 코드로 넘어가서 윈도우즈 창이 생성되게 된다.

컴파일 후 실행해본다.



(실행)



이 프로그램을 실행시키고, 같은 프로그램을 다시 한번 실행하면 실행되지 않는다.
즉, 하나만 실행이 된다.

(*참조 - 2D 게임프로그래밍, 찰스 켈리)


Windows 창에서 키보드의 입력을 받고 화면에 그리는 작업을 해볼 것이다. 

윈도우즈에서 특정 장치에 접근하기 위해 애플리케이션은 GDI(Graphics Device Interface)에게 적절한 디바이스 드라이버를 로드하고, 그리기 위한 장치를 준비해야한다고 알려준다.

이 과정은 디바이스컨텍스트(DC, Device Context)를 만들어서 수행한다.
DC는 Graphics객체와 속성을 정의하는 구조체이다.
윈도우즈 운영체제는 윈도우를 만들 때, DC를 만들어서 화면에 그린다.

그렇다면 키보드의 입력을 받아 윈도우 창에 입력받은 문자를 그리는 프로그램을 작성해 볼 것이다.

전에 포스팅했던 창 만들기 프로그램에서 다른 부분을 위주로 설명한다.

전역 변수와, 상수 부분이다.


(전역변수, 상수)



WinMain 함수이다.



(WinMain 함수)



동작은 창 만들기 프로그램과 같다.

다만 이제 이벤트 콜백 함수부분이 달라진다.



(추가된 부분)



바로 전에는 WM_DESTROY 메시지만 우리가 처리하였다. (종료되는 메시지)

이제 키보드의 입력을 받을 때인 WM_CHAR 메시지에 대한 처리를 추가해주면 된다.



(키보드 입력)



문자가 아닌 부분의 경우 비프음을 내고, 아무 동작을 하지 않게 끝난다.
하지만 표시할 수 있는 문자의 경우 ch 변수에 문자를 가져온다.

여기서 InvalidateRect 함수가 나오는데, 이는 윈도우즈 프로그램의 특징을 이해해야한다.

WM_PAINT 메시지를 발생시키기 위한 것인데, WM_PAINT 메시지는 flag 타입의 메시지이다. 메시지큐에 들어가서 처리되는 것이 아니라 해당 flag를 표시한다.
그리고 프로그램은 메시지큐를 처리한 후 해당 flag를 확인하고 표시 되어있으면
WM_PAINT를 처리한다.

WM_PAINT는 화면을 다시 그려주라는 메시지이다.
그래서 InvalidateRect 함수를 통해 WM_PAINT flag를 on 해준다.

그렇게 되면 메시지큐가 다 처리된 후 해당 비트를 확인하여 WM_PAINT를 처리할 때 아래와 같이 처리하도록 처리한다.



(WM_PAINT)



DC 핸들을 가져온다.
hdc에 가져오는 것이다.
그리고 윈도우 창에 사각형을 가져온다.

이제 TextOut을 통해 hdc를 가지고 화면에 그려준다.

다음은 CreateMainWindow 함수인데, 이전 창 만들기의 부분과 같다.




(CreateMainWindow)



등록까지 마쳤으면

윈도우를 생성하고 화면에 표시하는 부분이다.



(창 생성)



컴파일 후 실행해본다.



(실행)



해당 화면은 D 라는 키보드를 입력했을 때의 모습이다.
잘 동작한다.


그렇다면 키를 누르고 있는 것은 어떻게 인식시켜야할까?
바로 윈도우 메시지 중 WM_KEYDOWN, WM_KEYUP을 처리해주면 된다.

키보드를 눌렀을 때 현재 눌린 것을 T로 표시, 그렇지 않은 것을 F로 표시하는 프로그램을 작성해본다.

번저 키 입력에 대한 배열을 만들어준다.



(키 배열)



main함수에서 처음에 초기화 과정을 거친다.


(초기화)



WM_CREATE 부분이다.


(WM_CREATE)



WM_CREATE는 창이 생성될 때 발생하는 메시지로
창이 생성될 때, 화면에 배열을 그려주는 역할을 한다.

그 다음 키가 눌릴 때이다.



(키가 눌릴 때)



위 사진은 키가 눌렸을 때의 처리이다.
아래 스위치는 shift 키와 control 키를 누르는 것에 대한 처리이다.
아래 if문은 왼쪽과 오른쪽 shift 키를 구분하기 위한것이다.


(키 땔때)



키를 땔때의 메시지 처리는 해당 키 배열값을 false로 만들어준다.

WM_PAINT 메시지 처리 중 다른점은 배열 출력이다.



(WM_PAINT)



기존에는 해당 문자를 출력하는 것이었지만

이젠 배열에서 눌렸으면 T를 안눌렸으면 F를 출력하는 것으로 다르다.



(*참조 - 2D 게임 프로그래밍, 찰스 켈리)

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
위 코드는 windows 프로그래밍에서 많이 사용된다.

windows 프로그래밍하는 방법은 크게 두가지가 있는데
MFC(Microsoft Foundation Class)를 사용하는 방법과
SDK(Software Development Kit)를 사용하는 방법이다.

MFC는 SDK와 비교하면 복잡하고 많은 기능들이 들어가있다.

만약 MFC를 사용하지 않는다면 MFC에 있는 많은 자료구조와 새로운 데이터 정의, 데이터타입은 필요하지 않다. 그렇기에 만약 MFC를 사용하지 않는다면 이 모든것을 헤더에 포함시킨다면 큰 오버헤드가 되는 것이다.

그렇기에
#define WIN32_LEAN_AND_MEAN
는 컴파일러에게 외부 MFC 오버헤드를 포함하지 말라고 알려준다.

위 문장을 #include <windows.h> 이전에 선언해 주면 많은 헤더를 include하면서 중복되는 헤더를 방지하고 데이터의 중복정의를 제거해준다. 전체적으로 프로그램의 사이즈를 줄여주고, 빌드 속도를 높여주는 효과가 있다.


Windows Programing 중 가장 기초인 창만들어서 띄우는 것을 할 것이다.
창 이름은 Hellow World로 만들것이다.

먼저, 함수 선언과 전역변수, 상수 선언이다.



(선언)



윈도우 프로그래밍에서는 보통 windows.h 헤더를 include한다.
우리는 MFC를 사용하지 않을 것이므로, WIN32_LEAN_AND_MEAN을 define해준다.

윈도우 프로그래밍에서의 시작점은 WinMain 함수이다.



(WinMain)



기존 C코딩에서 main 함수와 같다.
보면 우리는 CreateMainWindow 함수를 만들어 두어 이 함수로 창을 만들것이고
그 아래에는 메인 메시지 루프가 있다. 메시지 루프는 윈도우 프로그래밍에서 중요한 부분이다.
윈도우 프로그램은 윈도우와의 메시지를 주고 받으면서 동작을 한다. 그렇기에 오고 가는 윈도우 메시지를 확인하는 부분이라고 생각하면 된다.

그렇다면 CreateMainWindow 함수를 보자.
윈도우를 표시하기 전에 Window 클래스를 만들고 등록해야하는데 그 작업을 하는 함수이다.

윈도우의 초기 설정을 하는 클래스가 바로 WNDCLASSEX 구조체이고 이 안의 멤버값들을 채워넣어 윈도우를 설정한다.



(WNDCLASSEX 설정)



설정이 끝나면 클래스를 등록하는 부분이 이어진다.




(클래스 등록)



설정한 wcx 구조체를 넣어주어 클래스를 등록한다.

그 후 창을 생성하는 CreateWindow 함수가 나온다. (각 인자에 대한 설명은 따로 포스팅할 것이다.)



(창 생성)



창을 생성하고 ShowWindow 함수를 이용하여 윈도우를 표시하고
UpdateWindow를 통해 윈도우 프로시저에게 자기 자신을 그리라고 메시지를 보낸다.

* WinProc 함수
중요한 함수이다.
위에서 윈도우 프로그램은 윈도우와 메시지를 주고 받으면서 동작한다고 했다. 그 메시지를 처리하는데 사용되는 함수이다.
위에서 설정한 WNDCLASSEX 구조체 안에 명시된 이름과 동일해야한다. 여기서는 WinProc

무시하는 메시지들은 윈도우가 알아서 처리한다. 여기서는 윈도우가 종료될 때의 메시지만 작성할 것이다.



(WinProc)



메시지가 WM_DESTORY라면 (윈도우가 종료되는 메시지)
PostQuitMessage(0)을 통해 프로그램이 종료를 요청한다고 윈도우에게 신호를 보내는 것이다.
그러면 메시지큐에 WM_QUIT이 추가되고 WinMain에서 이 메시지를 보게 되면 루프를 빠져나가 프로그램이 종료되게 되는 것이다.

컴파일 해서 프로그램을 실행해본다.



(윈도우 창 생성)



우리가 원하는 Hello World 창이 생성되었다.

(*참조 - 2D 게임 프로그래밍, 찰스 켈리)

+ Recent posts