윈도우 프로그래밍을 하는데 기본적으로 윈도우와 C언어의 차이점은 main 함수와 WinMain 함수를 사용하는것에서 차이가 있다. 라고 했었다.


 하지만, 차이점은 이것 뿐만 아니다.

 일반적으로 C언어에서는 while을 이용해서 프로그램의 키 입력을 항상 기다리고 있는 것이다.


 main.c 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    char data = 0;
    
    while(1)
    {
        data = getc(stdin);
        if(data == 'q')
        {
            break;
        }
        printf("%c", data);
    }
    
    return 0;
}
cs


 이렇게 하면 q을 받게 되면, 탈출하는 형태로 처리가 된다.


 이와 유사하게 윈도우에서도 메세지라는 장치를 이용해서 윈도우를 컨트롤한다.


전 소스를 보면, 다음과 같은 부분이 보일 것이다.


1
2
3
4
5
    while(GetMessage(&Message,0,0,0))
    {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
cs


 이 부분이 main.c에 적혀있는

 while(1) 부분과 동일하다고 볼 수 있다.

 GetMessage에는 Message에 대한 정보를 가지고 있고, 이 정보를 클래스에서 적용시킨

     WndClass.lpfnWndProc=(WNDPROC)WndProc;

 여기에 있는 WndProc라는 함수에 연결을 하도록 만들어 져 있다.


 WndProc은 운영체제에서 보내주는 이벤트를 받아서 해당 값을 처리하게 되어있다.


 여기서 이벤트란, 사용자가 컴퓨터에게 주는 행위들을 전부 다 이벤트라고 보면 된다.

 예을 들어서 키보드에 있는 키를 입력하는 것이나 마우스를 이동시키는 것 또한, 이벤트이다. 버튼을 누르는 것도 이벤트로 취급이 된다.

 이 이벤트를 개발자는 보고 원하는 형태로 작동하도록 만드는 것이고, 이것을 주고 받는 매개가 Message이다.


 이벤트에 관련된 정보를 WndProc에게 준 후에 WndProc에서 전부 다 컨트롤 하도록 되어 있다.


 그래서 이전 소스의 WndProc을 본다면,

 

1
2
3
4
5
6
7
8
9
10
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    switch(iMessage)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
cs


 여기서 iMessage로 해당 이벤트의 정보를 받아 들이고, 해당 이벤트에 맞춰서 프로그램이 행동하도록 하게 된다.

 WM_DESTORY는 윈도우가 파괴 되었을 경우. 즉, 윈도우 창을 닫게 했을 경우를 뜻한다. PostQuitMessage()을 사용하여, 프로그램을 종료하는 메세지를 보낸다.

 종료하는 메세지를 받은 프로그램은 결국 전체적인 프로그램을 종료하는 작업을 하게 된다.

Posted by JunkMam
,

 Win32을 이용해서 프로그래밍을 하는 이유는 기본적으로 C언어를 어느 정도 할 줄안다는 조건이 필요하다.

 여기서 Windows에 나오는 일반 프로그램 처럼 콘솔 이상의 프로그램을 사용하기 위해서 Win32 API을 이용한 프로그램을 거친다.

 Win32 API을 이용하는 이유는 일단 MS쪽에서 제공하는 Window OS에 맞게 프로그램을 작성 할 수 있기 때문이다.

 일단, Win32 API 없이도 작성을 할 수 있다.

 문제는 Win32 API 이전에 나온 것들은 Windows을 분석하여 OS에서 동작하는 방법을 어셈블리와 C언어 등을 이용해서 작성을 했을 것이다.

 이런것은 만들기 매우 어려울 뿐만 아니라. 생산성이 떨어진다. 그러므로 MS 측에서 제공하는 API을 이용해서 프로그램을 작성하는 것이 이득이다.


 Win32 API 말고도 MFC라는게 있다.

 MFC는 Win32의 객체형식으로 만든 API라고 인식하면 쉽게 이해 될 것 같다.


 필자는 Win32 API을 이용한 프로그래밍 책을 보면서 이 글을 작성할 것이다.


 필자가 Win32 API의 공부를 여기에 기록하는 것은, 차후에 나 자신이 읽고 보기 위해서이다.


 Windows 프로그래밍과 일단 C언어(콘솔)의 프로그래밍의 차이가 있다.


 Windows 프로그래밍은 Window라는 우리가 일반적으로 보는 창이라는 프레임이 나오게되어 있고, 콘솔 프로그래밍은 프로그래밍을 처음 접하면 나오는 창.이 나오게 되어 있다.


 과거에는 콘솔창으로 돌아가는 형식이였다.(Windows 98 이전 사용자들은 대부분 알 것이다. MDir[일명; M]을 알면 대부분 알것이다.)


 하지만, 최근에는 GUI의 발달로 사용자들이 일반적으로 보는 프레임이 띄워지는 프로그램.이 만들어 졌다.


 Win32 API는 이 프레임이 띄워지는 프로그램을 쉽게 만들기 위해서 도움을 주는 라이브러리들이 모여있는 것들이며, 그게 없는 경우는 콘솔로 동작하는 것이다.


 윈도우에서 코딩이 차이가 생기게 되는데, 일반적으로 C언어로 프로그래밍을 한다면 다음과 같은 형식이 된다.


 일반적으로 C언어를 이용해서 작성할 경우. 

1
2
3
4
5
6
7
#include <stdio.h>
 
int main()
{
    printf("Hello World!\n");
    return 0;
}
cs


 이렇게 사용할 경우엔 stdio.h라는 콘솔 입출력 관련된 헤더 파일을 참조하여 링커에서 콘솔 입출력 관련된 라이브러리를 연결하여 콘솔 창에서 Hello World!\n가 출력되는 역할을 한다.


 하지만, Win32에서는 콘솔을 컨트롤하는 것이 아니기 때문에 GUI에 맞춰서 프레임 출력등을 설정을 해줘야 한다.


 Win32에서 프레임이 출력되기 위해서는 먼저 윈도우 클래스(윈도우 프레임의 상태를 결정하는 구조체)를 작성하고, 해당 클래스를 이용해서 객체를 생성.

 그것을 이용해서 프레임을 윈도우 창에 띄우는 형태를 취한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <stdlib.h>
 
#include <tchar.h>
#include <windows.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpszCmdParam,
            int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    WNDCLASS WndClass;
    g_hInst = hInstance;
    
    //윈도우 클래스 초기화
    WndClass.cbClsExtra=0;
    WndClass.cbWndExtra=0;
    WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
    WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    WndClass.hInstance=hInstance;
    WndClass.lpfnWndProc=(WNDPROC)WndProc;
    WndClass.lpszClassName="ApiBase";
    WndClass.lpszMenuName=NULL;
    WndClass.style=CS_HREDRAW|CS_VREDRAW;
 
    //윈도우 클래스 생성.
    RegisterClass(&WndClass);
    
    //윈도우 객체 생성.
    hWnd = CreateWindow("ApiBase",
                        "ApiBase",
                        WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        NULL,
                        (HMENU)NULL,
                        hInstance,
                        NULL);
    
    //윈도우 창 띄우기.
    ShowWindow(hWnd,nCmdShow);
    
    while(GetMessage(&Message,0,0,0))
    {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
    
    return Message.wParam;
}
 
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    switch(iMessage)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
cs


 이렇게 하면, 윈도우 창만 띄워진다.


 참고로 gcc로 컴파일을 할려면, 다음과 같은 라이브러리가 필요해진다.

 GDI32.lib


 이유는 GetStockObject라는 함수가 정의 되어 있는 곳이 GDI32에 정의가 되어 있기 때문이다.

 그리고 Windowgdi.h을 사용하는데, 이 windowgdi는 Window.h에 포함되어 있기 때문에 사용을 할 수 있다.[각주:1]


 

1
2
gcc window_ex00.c -lgdi32
 
cs


 이렇게 하면, 결과적으로 gdi을 참조해서 Window창이 띄워진다.

  1. https://msdn.microsoft.com/ko-kr/library/windows/desktop/dd144925(v=vs.85).aspx(2016-06-12) [본문으로]
Posted by JunkMam
,

Win32 Text 출력.

연습 2015. 12. 1. 12:51
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif
 
#include <tchar.h>
#include <windows.h>
 
/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
 
/*  Make the class name into a global variable  */
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");
char strTitle[]="Text";
 
int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */
 
    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);
 
    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) WHITE_BRUSH;
    //wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
 
    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;
 
    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           _T("Code::Blocks Template Windows App"),       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );
 
    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);
 
    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 00))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }
 
    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}
 
 
/*  This function is called by the Windows function DispatchMessage()  */
 
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    RECT rc;
    PAINTSTRUCT ps;
 
    switch (message)                  /* handle the messages */
    {
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        case WM_PAINT :
            hdc=BeginPaint(hwnd,&ps);
            TextOut(hdc,10,10,strTitle, 4);
            EndPaint(hwnd,&ps);
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
 
    return 0;
}
 
 
cs


 이 방법에서 수정 및 처리가 필요할 것이다.

 윗 방법을 처리하는 방법을 생각하여 만든다면, Wini32형 Hexa Code Editor을 만들 수 있지 않을까 생각이 든다.

Posted by JunkMam
,

 WindowProcedure의 함수는 GUI에서 작동되는 함수이다.


 기본적으로 While로 계속 작동 하도록 만들어 져있다.


 이것은 매세지를 받아서 처리하는 함수이다.



 이걸 연결하는 방법으로 Windows Class에 설정이 되게 된다.


    /* The Window structure */

    wincl.hInstance = hThisInstance;

    wincl.lpszClassName = szClassName;

    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */

    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */

    wincl.cbSize = sizeof (WNDCLASSEX);


    /* Use default icon and mouse-pointer */

    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);

    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);

    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);

    wincl.lpszMenuName = NULL;                 /* No menu */

    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */

    wincl.cbWndExtra = 0;                      /* structure or the window instance */

    /* Use Windows's default colour as the background of the window */

    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;


 이렇게 설정이 된다.


 여기서 wincl.lpfnWndProc에서 설정이 함수를 설정이 된다.

 이걸로, 기본적으로 WIndows의 GUI의 메세지를 받아서 처리할 수 있게 한다.


 메세지는 운영체제에서 큐 자료형에서 받아들이는 것으로 사용자가 행동을 취하는 것을 받아들이는 매개체라고 보면 된다.


 예을 들어서 사용자가 마우스를 움직이면, 움직였다는 메세지가 생성되고, 그것을 프로그램이 받아들여서 사용하는 것이다.


     /* Run the message loop. It will run until GetMessage() returns 0 */

    while (GetMessage (&messages, NULL, 0, 0))

    {

        /* Translate virtual-key messages into character messages */

        TranslateMessage(&messages);

        /* Send message to WindowProcedure */

        DispatchMessage(&messages);

    }


 이걸 이용해서 프로그램이 항상 메세지를 받아들이도록하고, 만약, 종료 메세지가 들어오게 되면, 꺼지게 되게 하는 것은 WindowProcedure에 설정하여 종료 및 기타 이벤트를 사용할 수 있게한다.


'연습' 카테고리의 다른 글

Android Youtube API 사용하기 - 0. 라이브러리에 추가하기 -  (0) 2015.12.02
Win32 Text 출력.  (0) 2015.12.01
Win32 API 기본  (0) 2015.11.29
GCC 전처리 출력.  (0) 2015.11.28
GCC에서의 Inline ASM  (0) 2015.11.27
Posted by JunkMam
,

Win32 API 기본

연습 2015. 11. 29. 00:00

 Win32는 Windows가 제작한 32Bit 환경에서 작동하는 GUI용 라이브러리이다.


 과거 Windows가 dos에 작동되는 버전인 1.0과 2.0쯤에는 WIn16(Windows 16Bit용)이 존재하고, 그 다음 Windows 32bit가 작성되기 시작했다고 한다.


 Win32 API에서 대부분 윈도우에서 GUI의 프로그램은 다 작성된다고 보면 된다.


 기본적으로 Win32 API의 대표적으로 내보내는 방법을 기록하고자 한다.


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif
 
#include <tchar.h>
#include <windows.h>
 
/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
 
/*  Make the class name into a global variable  */
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");
 
int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */
 
    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);
 
    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
 
    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;
 
    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           _T("Code::Blocks Template Windows App"),       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );
 
    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);
 
    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 00))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }
 
    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}
 
 
/*  This function is called by the Windows function DispatchMessage()  */
 
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
 
    return 0;
}
 
 
cs


 이렇게해서 간단한 GUI을 출력할 수 있다.

 윗 소스는 CodeBlocks을 이용한

'연습' 카테고리의 다른 글

Win32 Text 출력.  (0) 2015.12.01
Win32 API의 기본 구성 설명.  (0) 2015.11.30
GCC 전처리 출력.  (0) 2015.11.28
GCC에서의 Inline ASM  (0) 2015.11.27
Hello World를 어셈블리어로 변환한 결과.  (0) 2015.11.26
Posted by JunkMam
,