ch10. GUI 소켓 응용 프로그램: 윈도우

해담·2024년 10월 16일

GUI 응용 프로그램

GUI 응용 프로그램 구조와 동작 원리

GUI 응용 프로그램 특징은 다양한 API로 구현된 편리하고 화려한 사용자 인터페이스 제공과 메시지 구동 구조로 동작한다는 점입니다. API(Application Programming Interface)란 윈도우 운영체제가 응용 프로그램에 제공하는 함수 집합입니다. 또한 메시지(Message)란 윈도우 운영체제가 응용 프로그램의 외부나 내부에 변화가 생겼음을 해당 응용 프로그램에 알리는 데 사용하는 개념입니다.

간단한 메시지 구동 구조 동작에 대해 설명하겠습니다.
1. 이벤트가 발생하면 운영체제가 관리하는 시스템 메시지 큐에 저장됩니다
2. 운영체제는 시스템 메시지 큐에 저장된 메시지를 적절한 응용 프로그램의 메시지 큐에 보냅니다.
3. 응용 프로그램은 자신의 메시지 큐를 감시하다가 메시지가 발생해서 큐에 들어오면 하나씩 꺼내 처리하고, 메시지가 없을 때는 대기합니다.

상세한 메시지 구동 구조 동작은 다음과 같습니다.
1. GUI 응용 프로그램은 윈도우 프로시저에 전달된 메시지를 (메시지 핸들러에서) 자신만의 방식으로 처리합니다.
2. 처리하지 않은 메시지는 윈도우 운영체제에 맡겨서 자동으로 처리합니다.

여기서 메시지 핸들러(Message Handler)란 메시지를 받았을 때 동작을 결정하는 코드이며, 윈도우 프로시저(Window Procedure)란 메시지 핸들러의 집합을 뜻합니다.


교재 346~347쪽에서의 WinMain() 함수는 콘솔 응용 프로그램의 main() 함수와 같은 기능을 하는 GUI 응용 프로그램의 실행 시작점입니다. 아래는 WinMain() 함수에 전달되는 각 인수의 의미입니다.

인수 의미
hinstance 인스턴스 핸들(Instance Handle)이라고 부르는 값으로, 실행 파일에 포함된 각종 리소스에
접근할 때 사용한다. 여러 함수에서 필요하므로 전역 변수에 저장해두고 사용하면 편리하다.
IpCmdLine 프로그램 실행 시 전달된 명령행 인수를 담고 있는 문자열이다.
nCmdShow 프로그램이 시작할 때 메인 윈도우를 보일 방법(최대화, 최소화 등)을 제어하는 값이다.

교재 346~347쪽에서의 윈도우 프로시저는 윈도우 메시지를 처리하는 핵심 함수입니다. 아래는 윈도우 프로시저에 전달되는 인수의 의미입니다.

인수 의미
hWnd 메시지가 발생한 윈도우를 나타내는 핸들값이다.
윈도우 프로시저에서 윈도우를 조작할 때는 항상 이 값을 사용해야 한다.
uMsg 발생한 메시지를 나타내는 값이다. WM_* 형태의 상수로 정의되어 있다.
wParam
Iparam
메시지와 더불어 전달되는 두 개의 부가 정보다(윈도우 운영체제에 따라 32비트
또는 64비트 크기). 메시지마다 의미가 다르므로 도움말을 참조하여 해석하고 처리해야 한다.

앞에서 살펴본 코드는 사용자 입력을 받지도 않고 출력도 하지 않으므로 그다지 유용하지 않습니다. 사용자 입력을 받고 출력을 할 수 있는 효과적인 방법은 컨트롤을 이용하는 것입니다. 컨트롤이란 표준화된 형태와 특성을 제공하는 일종의 윈도우로, 사용자의 입력을 받거나 출력할 수 있습니다. 이는 어떤 경우든 독립적인 윈도우가 아닌 자식 윈도우로 존재하며, 부모 윈도우는 SendMessage() 함수를 사용해 컨트롤에 메시지를 보냄으로써 컨트롤을 기정의된 방식으로 제어합니다.

GUI 응용 프로그램 작성 및 코드 분석 (자세한 예시는 교재 353~357쪽 참고)

이 절에서 작성할 모든 예제는 콘솔 응용 프로그램의 printf() 함수와 fgets() 함수 기능을 대체하기 위한 에디트 컨트롤(edit control)과, 특정 작업의 시작이나 종료를 지시하는 목적의 버튼 컨트롤(button control)만을 이용하여 사용자 입력 및 출력을 합니다.

GUI 소켓 응용 프로그램

GUI 소켓 응용 프로그램 구조와 동작 원리

윈도우 메시지를 잘못 처리했을 때 발생하는 문제점을 살펴보기 위해 Sleep(3000) 함수를 호출하여 메인 스레드를 3초 동안 정지하게 하겠습니다. 실행 직후 약 3초 동안 화면이 제대로 표시되지 않으며, 마우스로 윈도우의 크기를 변경하려고 해도 약 3초간 지연되는 것을 경험할 수 있습니다. 이는 WM_SIZE 메시지 이후에 발생하는 메시지를 제시간에 처리하지 못하기 때문에 나타나는 결과입니다.

이처럼 함수를 호출할 때 조건이 만족하지 않으면 스레드는 대기 상태가 되므로 윈도우의 메시지 루프 처리가 지나치게 지연될 수 있습니다. 이런 문제를 해결하려면 소켓 코드를 별도의 스레드로 분리해야 하며, 윈도우 프로시저와 소켓 코드가 공유하는 데이터가 있을 때는 스레드 동기화 기법을 사용하여 보호해야 합니다. 그렇기 때문에 GUI 소켓 응용 프로그램은 윈도우 메시지를 처리하는 스레드 외에 소켓 통신 및 데이터를 처리하는 스레드가 별도로 존재합니다.

GUI 소켓 응용 프로그램 작성 및 코드 분석 (자세한 예시는 교재 360~367쪽 참고)

대화상자 기반 응용 프로그램

대화상자(Dialog Box)는 다양한 컨트롤을 포함하는 일종의 윈도우로, 사용자의 입력을 받거나 정보를 출력하는 목적으로 사용합니다. 대화상자는 독립적인 응용 프로그램으로 존재할 수도 있는데, 이를 대화상자 기반 응용 프로그램이라고 부릅니다.

대화상자 기반 응용 프로그램 구조와 동작 원리

대화사자 기반 응용 프로그램을 작성하려면 코드와 더불어 대화상자 템플릿을 만들어야 합니다. 대화상자 템플릿이란 대화상자 자체와 대화상자에 포함된 컨트롤에 대한 정보를 담고 있는 이진 데이터입니다. 윈도우 운영체제는 사용자가 디자인하고 컴파일하여 실행 파일에 넣어둔 대화상자 템플릿을 토대로 대화상자를 생성합니다.

다음은 대화상자 디자인부터 최종적으로 화면에 보이기까지 절차입니다.
1. 프로젝트에 리소스 파일(*.rc)을 추가합니다. 리소스 파일이란 대화상자 자체와 대화상자에 포함된 컨트롤에 관한 정보를 담고 있는 텍스트 데이터입니다.
2. 리소스 파일에 대화상자 리소스를 추가하고 비주얼 스튜디오의 리소스 편집기를 이용하여 시각적으로 디자인합니다.
3. 프로젝트를 빌드하면 컴파일 단계에서 리소스 컴파일러가 실행되어 *.rc 파일을 이진형식인 *.res로 변환합니다. *.res 파일은 링크 단계에서 실행 파일 내부에 리소스로 포함됩니다.
4. 프로그램 실행 중 대화상자 생성을 요청하는 윈도우 API 함수를 호출하면, 윈도우 운영체제는 실행 파일 내부의 대화상자 리소스(대화상자 템플릿)를 토대로 대화상자를 생성합니다.

간단한 대화상자 기반 응용 프로그램으로, 대화상자를 표시하고 [확인] 또는 [취소] 버튼을 누르면 종료하는 기능을 하는 코드는 교재 370~371쪽에서 확인 가능합니다.

대화상자 기반 응용 프로그램 작성 및 코드 분석 (자세한 예시는 교재 374~376쪽 참고)

대화상자 기반 소켓 응용 프로그램

대화상자 기반 소켓 응용 프로그램 구조와 동작 원리

대화상자 기반 응용 프로그램도 일반 GUI 응용 프로그램처럼 메시지 구동 방식으로 동작합니다. 따라서 소켓 코드를 별도의 스레드로 분리해야 하며, 대화상자 프로시저와 소켓 코드가 공유하는 데이터가 있을 때는 스레드 동기화 기법을 사용하여 보호해야 합니다.

해당 응용 프로그램(교재 377쪽의 그림 10-11 참고)은 윈도우 메시지 처리를 하는 스레드1, 소켓 통신을 담당하는 스레드2로 나뉘어져 있습니다. 이 응용 프로그램이 올바르게 동작하기 위해서는 두 가지 문제(해당 문제는 378쪽 참고)를 해결해야 합니다. 해결 방법에는 이벤트를 위한 동기화버튼 비활성화 방법이 존재합니다.

대화상자 기반 소켓 응용 프로그램 작성 및 코드 분석 (자세한 예시는 교재 380~385쪽 참고)

추가

서버 단에 GUI 소켓 프로그래밍이 만들어졌다 → O
클라이언트 단에 GUI 소켓 프로그래밍이 만들어졌다 → X

profile
해담이를먹여살리기위한..

0개의 댓글