본문 바로가기
코스웨어/15년 스마트컨트롤러

20151116 업무일지 -여지윤-

by 알 수 없는 사용자 2015. 11. 16.
728x90
반응형

1~8교시

★S/W☆


● Win32 API


□ Translate Message


- GetMessage는 메시지 큐에서 메시지를 꺼내온 후 이 메시지를 TranslateMessage 함수로 넘겨 준다. 


- TranslateMessage 함수는 전달된 메시지가 WM_KEYDOWN인지와 눌려진 키가 문자키인지 검사해 보고 조건이 맞을 경우 WM_CHAR 메시지를 만들어 메시지 큐에 덧붙이는 역할을 한다. 


- 물론 문자 입력이 아닐 경우는 아무 일도 하지 않으며 이 메시지는 DispatchMessage 함수에 의해 WndProc으로 보내진다. 


- 만약 메시지 루프에서 TranslateMessage 함수를 빼 버리면 WM_CHAR 메시지는 절대로 WndProc으로 전달되지 않을 것이다. 과연 그런지 Key예제에서 이 함수 호출문을 주석으로 묶은 후 직접 실행해 보기 바란다.


□ 마우스 입력


- 윈도우즈와 같은 GUI운영체제에서는 키보드보다 마우스가 더 많이 사용된다. 


- 윈도우즈의 공식 입력 장치는 키보드이지만 그래픽 툴이나 DTP, CAD 등의 복잡한 프로그램에서는 마우스가 주요 입력 장치로 사용된다. 


- 여기서 마우스라고 함은 진짜 쥐새끼처럼 생긴 마우스는 물론이고 노트북의 터치패드, 트랙볼과 출판용 테블릿등을 모두 포함하는 명칭이다. 


- 키보드 입력 처리를 메시지로 하는 것과 마찬가지로 마우스 입력 처리도 메시지를 받아 처리한다. 마우스 입력에 관한 메시지는 다음과 같은 종류가 있다.



- 마우스도 좌표 정보를 이용하여 데이터를 가져 온다.


- 위의 내용을 토대로 이용하여 예제를 나타내면 다음과 같은 예제를 나타 낼 수 있다.


- 다음과 같은 결과 값을 얻을 수 있다.


- 마우스를 이용하여 그림을 그릴수도 있다.




- 이 예제는 그림을 그리기는 하되 WM_PAINT에 관한 처리는 하지 않고 있으므로 그려진 그림은 언제든지 지워질 가능성이 있다. 


- 즉 화면에 그림을 그리기는 해도 복구 능력이 없다. 


- 이 문제를 해결하려면 그려지는 그림을 일일이 저장해 두어야 하는데 현재 단계에서는 그 방법을 논하기 어렵다. 화면 전체를 비트맵으로 저장하든가 아니면 연결 리스트를 사용하여 마우스의 움직임을 일일이 보관해 두어야 한다.


- Text Out 과 마우스를 이용하여 조합을 할 수가 있다.


- LOWORD 같은 경우에는 위 그림에 나온결과를 Y에 0을 전부 집어넣고,X에만 값을 집어 넣는다.


- HIWORD 같은 경우는 그 반대인 경우를 추출한다.


- RelaseDC(hWnd,hdc); => 를 사용하면 해당 if문을 더 이상 사용 할 수 없다. (그렇기 때문에 우리 눈으로는 선을 긋는 것으로 보이게 된다)


- case 문 WM_MOUSEMOVE 에서는 마우스가 현재 눌려있는지 아닌지를 체크 하고 있다.


□ Textout & WM_PAINT를 조합한 코드


- TextOut 으로 문자열에 대한 값이 나오게 되면, 해당 마우스를 움직여서 그 해당 마우스에 대한 좌표값도 알 수가 있다.


- 다음과 같은 코드를 사용하면 마우스가 움직일때마다 값을 알 수가 있다.



- 이렇게 처리한 코드를 다음과 같은 결과를 얻을 수가 있다.



□ 더블클릭


- 화면을 지우는 것은 아주 간단하다. InvalidateRect 함수를 호출하여 작업 영역 전체를 무효화시켜 버리면 된다. 


- Mouse 예제의 경우 WM_PAINT 메시지를 처리하지 않고 있기 때문에 무효화 영역이 생기면 DefWindowProc이 WM_PAINT 메시지를 처리하게 되며 이 함수는 배경색으로 윈도우를 지워준다. 그래서 단순히 InvalidateRect 함수만 호출해 주면 화면이 지워지는 것이다. 


- 그럼 과연 이 코드를 추가해 주면 화면이 지워질까? 직접 프로그램을 실행하여 왼쪽 버튼을 더블클릭해보면 화면이 전혀 지워지지 않을 것이다. 


- 왜냐하면 우리가 만든 이 윈도우는 더블클릭에 대한 메시지를 지원하지 않기 때문이다.


- 마우스 왼쪽 버튼을 두번 누르면 WM_LBUTTONDOWN 메시지와 WM_LBUTTONUP 메시지가 교대로 두번 발생할 뿐이며 아무리 마우스 버튼을 잽싸게 눌러대도 더블클릭 메시지는 발생하지 않는다. 더블클릭 메시지를 받고자 하면 윈도우 클래스의 스타일에 "이 윈도우는 더블클릭 메시지를 원한다"는 의사 표시를 해 주어야 한다.


- 코드를 다음과 같이 수정하고 해보면 금방 알 수가 있다.



- 이렇게 할당시킨 코드를 가지고 다음과 같은 결과물을 얻을 수가 있다.


□ 타이머


- WM_CREATE -> 창이 열릴때 딱 한번 소환된다.


- settimer -> 1초당 한번씩 호출된다 마지막에 함수주소를 넣어야한다. (함수 주소를 적어두면 그 함수가 호출, 아무것도 적지 않으면 글자 하나만 나오게 된다)


- time -> 현재시간을 알아내는 주소 (시간을 초로 나타낸다)


- ctime -> 현재 시간을 문자열 주소로 알려준다.


- KillTimer(hWnd,1) -> 두번째 인자 번호가 일치 해야만 정상으로 작동 된다.


- 다음 코드와 같이 작성을 하면 다음과 같은 결과 값을 얻을 수가 있다.


- 위의 내용의 결과는 다음과 같다


- 1초마다 동작하게 된다.


- 이때 시간이 뜰때 발생하는 것은 저 시간이 동작하고 1초뒤에 뜬다는것이다.


□ 두 개의 타이머


- 타이머는 한꺼번에 여러개를 설치하여 사용할 수도 있다. 필요한만큼 SetTimer를 호출하되 두번째 인수인 타이머 ID를 각각 다르게 설정해 주어야 하며 타이머 간격은 물론 타이머의 용도에 따라 적절하게 설정하면 된다. 


- 여러개의 타이머를 설치했을 경우에도 하나의 타이머를 설치했을 때처럼 전달되는 메시지는 WM_TIMER 하나뿐이다. 어떤 타이머에 의해 WM_TIMER 메시지가 발생했는지는 wParam으로 전달되는 타이머의 ID로 구분한다. 이 타이머 ID는 곧 SetTimer 함수가 타이머를 설치할 때 두번째 인수로 지정한 값이다.


- 아까 했던 코드에 다음과 같은 코드를 입력하게 되면 된다.



- 이 코드를 작성하게 되면 시계는 한개만 뜨게 되지만 해당 시간 마다 알림음을 울려주는 Beep가 5초마다 작동 하게 된다.


-WM_TIMER 메시지 처리부분에서는 wParam값에 따라 어떤 타이머로부터 타이머 메시지가 발생했는지 보고 타이머 ID에 따른 처리를 하면 된다. 


- wParam이 1이면 시간을 갱신한 후 화면을 다시 그리도록 하고 wParam이 2면 MessageBeep 함수를 호출하여 비프음을 낸다. WM_DESTROY에서는 설치된 타이머를 모두 해제해 주어야 한다.


□ CallBack 함수


- 프로그램이 실행되는 동안 지속적으로 수행해야 할 작업이 있다고 해 보자. 예를 들어 로고 애니메이션이나 백그라운드 음악 연주 등을 들 수 있는데 도스에서라면 다음과 같이 코드를 작성할 것이다.


- 타이머 함수가 지정되면 메시지 대신 함수를 호출해준다. 타이머 함수는 다음과 같은 원형으로 작성 되어야 한다.


void CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);


- 4개의 인수를 가지는데 hWnd 는 타이머를 소유한 윈도우의 핸들이며, uMsg는 WM_TIMER, idEvent는 타이머 ID, dwTime은 윈도우가 실행된 후의 경과시간이다.


- 함수의 인수는 잘 사용되지 않으므로 구체적으로 알 필요는 없다.


- 다음과 같은 코드를 작성하여 실행하게 되면 창내부에서 점을 찍는다.





- 시간이 지나면 지날수록 해당되는 크기에 점이 지속적으로 찍혀서 화면 가득 덮는 것을 확인 할 수 있다.


- 만약 for문 내에 조건 없이 돌려버리면 무제한으로 돌지 않을까 하는 의문이 들기도 한다. 분명 무한정으로 돌기는하지만 무한정으로 돌기만할뿐 종료도 안되며, 점을 찍는 이외에 아무런 작업도 할 수가 없다.


- 그렇기 때문에 for문 내에 조건없이 돌리는 것은 시스템을 다운 시켜버리기 가장 좋은 방법중 하나이다.


- 콜백 함수(Callback Function)란 무엇인지 그 의미를 좀 더 정확하게 알아보자. 일반적으로 API 함수들은 운영체제가 제공하며 프로그램에서는 이 함수들을 호출해서 운영체제의 서비스를 받는다. 


- 예를 들어 도스의 시스템 콜 함수를 호출하여 디스크 입출력을 받는다든가 윈도우즈의 TextOut 함수를 호출하여 문자열을 출력하도록 하는 경우가 이에 해당한다. 반면 콜백 함수는 응용 프로그램이 제공하며 운영체제가 필요할 때 호출하는 함수이다. 


- 호출되는 방향이 거꾸로 되었기 때문에 콜백이라고 부르는 것이다. 위 예제에서 TimerProc 함수는 SetTimer에서 지정한 시간마다 운영체제에 의해 호출된다. 콜백 함수를 문장화하여 정의내린다면 "운영체제에 의해 호출되는 프로그램 내부의 함수"라고 할 수 있다.




- 윈도우즈에서는 이런 콜백 함수가 빈번하게 사용되고 있으므로 개념을 잘 알아두도록 하자. 타이머의 콜백 함수가 대표적이며 이 외에도 중요한 열거 함수들과 몇몇 그래픽 함수 등의 콜백 함수를 사용한다


□ 작업 영역


- 윈도우는 작업 영역(Client Area)과 비작업 영역(Non Client Area) 두 부분으로 구성되어 있다. 작업 영역이란 쉽게 말해서 윈도우 중앙의 흰 부분을 말하며 비작업 영역이란 그 외의 영역을 말한다. 비작업 영역에 속하는 부분은 일단 타이틀 바와 경계선이 있고 메뉴가 있을 경우 메뉴도 비작업 영역에 속한다


- 그래서 원하는 위치에 정확하게 출력하려면 윈도우가 차지하고 있는 영역의 좌표를 조사해야 하는 것이 아니라 작업 영역의 좌표를 조사해야 한다.



- 그럼 이 함수를 사용하여 문자열을 작업 영역의 정중앙에 출력하는 예제를 만들어 보자. 작업 영역의 중앙 좌표를 알려면 작업 영역의 크기를 구한후 우하단 좌표를 2로 나누어 구하면 된다. 소스는 다음과 같다



- 소스 코드의 결과는 다음과 같이 확인 할 수가 있다.



- WM_CREATE에서 GetClientRect 함수로 작업 영역의 좌표를 구해 rt에 대입해 주었다. 그리고 WM_PAINT에서는 작업 영역의 중앙 좌표를 구해 문자열을 출력하되 정확하게 중앙이 되도록 하기 위해 문자열을 중앙 정렬하였다.


□ 리소스 작성


- 비쥬얼 스튜디오를 이용하여 리소스를 작성 할 수가 있다.


- 리소스 작성하는 방법은 다음과 같이 생성을 할 수가 있다.




- 여기서 중요한점은 비쥬얼 스튜디오가 또 다른 변수나 번호 같은 것을 인간에게 맡기지 않고 자기가 한다는 것이다.


- 즉, 리소스 파일을 만들게 되면 개발자들에게 개발에만 신경쓰게끔 만들어준다. 해당 내용의 헤더 파일을 보면 알 수가 있다.



- 이 내용을 가지고 이후에 우리가 직접 소스를 가지고 코딩을 할 수가 있다.


- 코딩한 내용은 다음과 같다.


- 수정해야 하는 내용은 위쪽에서도 수정을 가해야하는데, 수정하는 코딩은 다음과 같이 변경시켜주면 된다

- 위의 내용의 결과 값은 다음과 같다.


□ 아이콘 , 커서


- 위와 같은 내용으로 아이콘이나 커서를 추가 할 수가 있다.


- 추가하는 방법은 다음 그림을 통해서 확인이 가능하다.


- 이 내용을 저장하고 나면 resource.h 에 IDC_CURSOR1 이라는 탭이 헤더 파일에 추가가 된다.


- 그렇게 저장하고 나서 코드 두줄만 바꾸게 되면 다음과 같은 결과 값을 얻을 수 있다.




728x90