캐럿이란, 우리가 윈도우스에서 글을 사용할때, 해당 글의 위치를 표시하는 것이다.


 대표적으로 메모장이나 그런 것이 있다.


 이걸 이용하면, 메모장처럼 출력하는 부분을 표현 할 수도 있게 된다.


 현재, 설정한 것에서는 내용물을 표시하는 것까지만 하고 메모장을 표현하는게 아닌 예제이다.


 이것과 함께 키보드의 특수 키까지 표현을 하도록 만든다면, 메모장을 간단하게 제작이 가능할 것이다.


 

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
107
108
109
110
111
112
113
114
115
116
#include <stdio.h>
#include <stdlib.h>
 
#include <tchar.h>
#include <windows.h>
 
#include <string.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
WNDCLASS WndClass;
 
int numbers = 0;
 
int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpszCmdParam,
            int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    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",
                        "Test",
                        WS_OVERLAPPEDWINDOW,
                        10,// X
                        100,// Y
                        400,// Width
                        400,// Height
                        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)
{    
    HDC hdc;
    PAINTSTRUCT ps;
    static char strChar[MAX_PATH];
    int nlen = 0;
    static int pos = 0;
    SIZE size;
    
    switch(iMessage)
    {
        case WM_CREATE:
            strcpy(strChar, "");
            break;
        case WM_CHAR:
            //문자 크기 설정/내용 추가.
            nlen = strlen(strChar);
            strChar[nlen] = (char)wParam;
            strChar[nlen+1]=0;
            
            //문자 출력.
            pos++;
            hdc = GetDC(hWnd);
            GetTextExtentPoint(hdc, strChar, pos, &size);
            ReleaseDC(hWnd, hdc);
            
            //캐럿 위치 조절.
            SetCaretPos(size.cx + 100100);
            
            //다시 그리기 설정.
            InvalidateRect(hWnd, NULL, FALSE);
            break;
        case WM_SETFOCUS:
            hdc = GetDC(hWnd);
            CreateCaret(hWnd, NULL214); // 캐럿 생성
            ShowCaret(hWnd); // 캐럿 보이기
            SetCaretPos(100100); // 캐럿의 위치 설정
            break;
        case WM_KILLFOCUS:
            HideCaret(hWnd); // 캐럿 숨기기
            DestroyCaret(); // 캐럿 파괴
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            TextOut(hdc, 100100, strChar, strlen(strChar));
            EndPaint(hWnd, &ps);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
 
 
cs


Posted by JunkMam
,

콘솔 위치 옮기기.

연습 2016. 7. 12. 00:00


 윈도우에서 콘솔을 컨롤하기 위해서는 출력부분을 초기에 받아서 사용한다.


 중요한 것은 컴퓨터에서 기본적으로 밖으로 출력하는 부분을 가지고오는 것인데, 이 함수는 다음과 같은 함수를 사용한다.


 GetStdHandle();[각주:1]


 이 함수는 핸들을 받아와서 개발자가 컨트롤을 할 수 있게 해주는 함수이다.


 GetStdHandle외에도 SetStdHandle이라고 해서 기본 핸들러를 수정할 수 있게 한다.


 여기서 StdHandle이란, 기본적으로 컴퓨터가 실행이 될때 설정이 되는 핸들이다.


 대표적으로 우리가 모니터에서 화면을 출력하게 만드는 것은 컴퓨터가 기본적으로 모니터에 출력값을 처리 할 수 있게 만들어 주기 때문이다.


 키보드와 마우스 또한, 컴퓨터에 입력을 받기 위해서 사용한다. 이게 가능한 것은 컴퓨터가 키보드의 입력을 기본적으로 받아들여서 처리하도록 입력이 받아져 있기 때문이다.


 그래서 출력하는 부분을 개발자가 받아서 이 것을 수정하도록 만들면 우리가 원하는 위치에 문자가 나오게 하거나, 커서가 이동되는 효과를 얻을 수 있게 되는 것이다.


 예제

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
 
#include <stdlib.h>
 
#include <windows.h>
 
int main(int argc, char* argv[]){
    int x = 10;
    int y = 1;
    
    COORD pos = {x, y};
    
    HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    
    SetConsoleCursorPosition(stdHandle, pos);
    printf("#\n");
    
    system("pause");
    
    return 0;
}
cs



 여기서 GetStdHandle이라는 것이 핸들을 반환한다고 했기 때문에, 우리는 HANDLE 형태의 변수를 사용해야된다. 그리고, 평면위의 위치이기에. x, y라는 독립 변수가 2개를 가지는 변수 pos을 가지고 있어야된다.


 이제, 캔퍼스와 연필을 얻었으니, 점을 직어야 될 것이다.


 이러한 행동을 하는 함수가 바로 SetConsoleCursorPosition이다.


 핸들과 위치를 가지고 위치가 이동되는걸 알 수 있다.


 이렇게 해서 로그라이크의 이동을 표현 할 수 있게되고, 로그라이크에서 기본적으로 이걸 이용해서 제작하는 경우도 있다.


 리눅스에서는 SetConsoleCursorPosition이라는 함수는 없기에 이와 유사한 함수가 있는 라이브러리를 사용한다.


 그것을 curses와 ncurses라는 라이브러리이다.

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

 Win32에서는 키보드 입력 메시지또한 처리 할 수 있다.


 C언어에서는 kbhit()라는 함수등을 사용한다.


 키보드는 키를 눌렀을때, 떼었을때, 문자일때로 나뉘어 져있다.


 키보드의 정보는 Virtual-Key라는 것을 이용해서 구분을 짓는다.[각주:1]


 예제

 

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
#include <stdio.h>
#include <stdlib.h>
 
#include <tchar.h>
#include <windows.h>
 
#include <string.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
WNDCLASS WndClass;
 
int numbers = 0;
 
int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpszCmdParam,
            int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    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",
                        "Test",
                        WS_OVERLAPPEDWINDOW,
                        10,// X
                        100,// Y
                        400,// Width
                        400,// Height
                        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_CREATE:
            strcpy(strTemp, "");
            break;
        case WM_KEYDOWN:
            switch(wParam)
            {
                case VK_HOME:
                    printf("Home\n");
                    break;
                case VK_END:
                    printf("End\n");
                    break;
                case VK_UP:
                    printf("Up Key\n");
                    break;
                case VK_F1:
                    printf("F1\n");
                    break;
                case 0x41:
                    printf("A\n");
                    break;
            }
            break;
        case WM_LBUTTONUP:
            printf("%d\n",ReleaseCapture());
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
 
cs


 하지만, 키보드 메시지를 사용한다면, 연속적으로 눌은 키에 대한 정보는 처리가 되지 않는다.


 쉽게 말해서 노트패드에 정보를 입력해보자.


 동시다발적으로 여러 키를 눌을 경우에, 해당 키의 정보를 다 읽지 못하고, 하나의 키만 처리하는걸 알 수 있을 것이다.(노트패드에서 이렇게 처리할 경우가 있을리도 만무하다.)


 이유는 메시지가 하나의 값만 계속 받아서 처리하기 떄문일것이다.


 그럴때는 어떻게 하는가?


 이것은 다음 네이버 카페에서 도움을 받았었다.[각주:2]


 여기서, GetKeyState 라는 함수를 사용하면 된다.[각주:3]


 해당 함수는 키의 눌음을 인식하는 함수이다.

  1. 참조 : https://msdn.microsoft.com/ko-kr/library/windows/desktop/dd375731(v=vs.85).aspx (2016-07-05) [본문으로]
  2. http://cafe.naver.com/cafec [본문으로]
  3. https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms646301(v=vs.85).aspx [본문으로]
Posted by JunkMam
,

 마우스 캡쳐란 마우스가 윈도우 영역을 벗어나 이동을 했을 경우에도 마우스의 위치를 알아내는 것을 말한다.


 MOUSE_DOWN 상태에서만 가능하고, MOUSE_UP 상태에서는 캡쳐는 무효화된다.


 각각의 윈도우 마다 마우스 이벤트를 받는 것은 동일한데, A윈도우에서 B윈도우위로 이동한다고 해도, 마우스 캡쳐가 동작하고 있는 것으로, A윈도우에서의 마우스 위치 값을 갖게 된다.


 B윈도우에서는 기본적인 마우스 동작 방식에 위배되어 B윈도우가 마우스 메세지를 가로 책 수 없게 된다.


 A의 마우스 캡쳐를 종료하는 시점이 필요한데, 이것이 MOUSE_UP으로 잡는것이다.


 참조 : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms646262.aspx


 HWND SetCapture(

HWND hWnd); // 윈도우 핸들


 리턴값은 이전의 마우스를 캡쳐하고 있던 윈도우 핸들을 리턴하되 캡쳐한 윈도우가 없으면 NULL을 리턴하게 된다.


 마우스 캡쳐를 종료하는 함수는


 참조 : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms646261.aspx


 ReleaseCapture(void)


 성공시 1을 실패시 0값을 리턴한다.


 case WM_LBUTTONDOWN:

SetCapture(hWnd);

break;

 case WM_LBUTTONUP:

ReleaseCapture();

break;


 마우스 왼쪽 버튼을 누르면 마우스 캡쳐가 시작되고, 버튼을 떼면 마우스 캡쳐가 종료된다.


 다음과 같은 예제로 마우스 왼쪽 버튼을 눌렀을 때 마우스 캡쳐를 시작하고, 버튼을 뗐을때 마우스 캡쳐를 종료하는 예제이다.


 WM_MOUSEMOVE 메시지 발생시 실시간으로 마우스 좌표를 윈도우 상에 출력하도록 되어있다.


 

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
107
108
109
#include <stdio.h>
#include <stdlib.h>
 
#include <tchar.h>
#include <windows.h>
 
#include <string.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
WNDCLASS WndClass;
 
int numbers = 0;
 
int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpszCmdParam,
            int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    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",
                        "Test",
                        WS_OVERLAPPEDWINDOW,
                        10,// X
                        100,// Y
                        400,// Width
                        400,// Height
                        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)
{
    HDC hdc;
    PAINTSTRUCT ps;
    static int nX = 0, nY = 0;
    static char strTemp[MAX_PATH];
    long dwStyle;
    
    RECT rc;
    HWND nHwnd;
    
    POINT polyline[5= {60,50,40,30,20};
    POINT polygon[5= {10,20,30,40,50};
    
    switch(iMessage)
    {
        case WM_CREATE:
            strcpy(strTemp, "");
            break;
        case WM_MOUSEMOVE:
            nHwnd=SetCapture(hWnd);
            printf("Cature : %d, hWnd : %d\n",SetCapture(), hWnd);
            if(nHwnd==hWnd)
            {
                nX=LOWORD(lParam);
                nY=HIWORD(lParam);
                sprintf(strTemp, "point (%d, %d), keyboard state %d\0", nX, nY, wParam);
                InvalidateRect(hWnd, NULL, TRUE);
            }
            break;
        case WM_LBUTTONUP:
            printf("%d\n",ReleaseCapture());
            //ReleaseCapture();
            break;
        case WM_PAINT:
            hdc=BeginPaint(hWnd,&ps);
            GetWindowRect(hWnd,&rc);
            SetTextAlign(hdc,TA_CENTER);
            TextOut(hdc, (rc.right - rc.left)/2, (rc.bottom - rc.top)/2, strTemp, strlen(strTemp));
            EndPaint(hWnd,&ps);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
 
cs


Posted by JunkMam
,

 참조 : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms645533(v=vs.85).aspx


 기본적으로 마우스는 GUI 기반의 운영체제인 윈도우스, X Windows, Mac등에 있는 입력 장치이다.


 마우스의 이벤트 메세지를 받아서 이용한다.


 WM에서 마우스 버튼을 클릭하거나 움직이는 용도로 사용한다.


 마우스 메세지는 좌표 정도는 lParam에 처리해준다.

 lParam에서 HIWORD(상위 16bit)는 y값을 LOWRD(하위 16bit)는 x좌표를 저장시켜 놓고 있다.


 이렇게 해서 마우스의 클릭 상태와 키보드 조합 상태의 데이터는 마우스 메세지에서 wParam에서 존재한다.


 여기서 키값은 MK을 가진다.


 예제소스


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
#include <stdio.h>
#include <stdlib.h>
 
#include <tchar.h>
#include <windows.h>
 
#include <string.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
WNDCLASS WndClass;
 
int numbers = 0;
 
int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpszCmdParam,
            int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    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",
                        "Test",
                        WS_OVERLAPPEDWINDOW,
                        10,// X
                        100,// Y
                        400,// Width
                        400,// Height
                        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)
{
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rt;
    static int nX = 0, nY = 0;
    static char strTemp[MAX_PATH];
    long dwStyle;
    
    POINT polyline[5= {60,50,40,30,20};
    POINT polygon[5= {10,20,30,40,50};
    
    switch(iMessage)
    {
        case WM_CREATE:
            strcpy(strTemp, "");
            break;
        case WM_LBUTTONDOWN:
            nX = LOWORD(lParam);
            nY = HIWORD(lParam);
            sprintf(strTemp, "point (%d, %d), keyboard state %d\0", nX, nY, wParam);
            printf("%s", strTemp);
            InvalidateRect(hWnd, NULL, TRUE);
            break;
        case WM_PAINT:
            hdc=BeginPaint(hWnd,&ps);
            TextOut(hdc, nX, nY, strTemp, strlen(strTemp));
            EndPaint(hWnd,&ps);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
 
cs


Posted by JunkMam
,

 윈도우스에서 처리해주는 메세지 비프음이라는게 있다.

 이것의 소리는 윈도우스의 환경설정에서 나오는 것이다.


 예제

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
#include <stdlib.h>
 
#include <tchar.h>
#include <windows.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
WNDCLASS WndClass;
 
int numbers = 0;
 
int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpszCmdParam,
            int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    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",
                        "Test",
                        WS_OVERLAPPEDWINDOW,
                        10,// X
                        100,// Y
                        400,// Width
                        400,// Height
                        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)
{
    HDC hdc;
    PAINTSTRUCT ps;
    long dwStyle;
    
    POINT polyline[5= {60,50,40,30,20};
    POINT polygon[5= {10,20,30,40,50};
    
    switch(iMessage)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_LBUTTONDOWN:
            hdc = GetDC(hWnd);
            MessageBeep(MB_ICONQUESTION);
            ReleaseDC(hWnd, hdc);
            break;
        case WM_PAINT:
            hdc = GetDC(hWnd);
            TextOut(hdc, 10050"Hello World",11);
            ReleaseDC(hWnd, hdc);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
 
cs


Posted by JunkMam
,

 앞에서 까지는 Frame(윈도우 창)에서 표현하는 것이라고 한다면, 이번에는 새로운 창

에서 띄우는 Dialog 형태로 처리가 된다.


 메시지 박스는 새 창을 띄워서 어떤 선택을 하거나, 경고문을 보여주는 용도로 쓰인다.


 함수 원본.

 MessageBox(

HWDN hwnd, // 윈도우 핸들

LPCTSTR lpText, // 메세지창의 명칭

LPCTSTR lpCaption, // 메세지창 타이틀바

UINT uType); // 메세지창 종류.



  메시지 창을 띄우는 예제


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
#include <stdlib.h>
 
#include <tchar.h>
#include <windows.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
WNDCLASS WndClass;
 
int numbers = 0;
 
int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpszCmdParam,
            int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    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",
                        "Test",
                        WS_OVERLAPPEDWINDOW,
                        10,// X
                        100,// Y
                        400,// Width
                        400,// Height
                        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)
{
    HDC hdc;
    PAINTSTRUCT ps;
    long dwStyle;
    
    POINT polyline[5= {60,50,40,30,20};
    POINT polygon[5= {10,20,30,40,50};
    
    switch(iMessage)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_LBUTTONDOWN:
            hdc = GetDC(hWnd);
            if(MessageBox(hWnd, "시스템을 종료 하시겠습니까?""시스템 끄기", MB_YESNO) == IDYES)
            {
                MessageBox(hWnd, "시스템을 종료합니다.""시스템 종료.", MB_OK);
            }
            else
            {
                MessageBox(hWnd, "시스템 종료가 취소 되었습니다.""원래대로", MB_OK);
            }
            ReleaseDC(hWnd, hdc);
            break;
        case WM_PAINT:
            hdc = GetDC(hWnd);
            TextOut(hdc, 10050"Hello World",11);
            ReleaseDC(hWnd, hdc);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
 
cs


Posted by JunkMam
,

 다각형은 Polygon이라고 한다.

 여기서, 다각형을 표현하기 위해서는 다음과 같은 함수를 사용한다.


 Polygon(

HDC hdc, // DC의 핸들.

CONST POINT *lpPoints, // 그릴 좌표.

int nCount); // 좌표의 수.


 Polyline(

HDC hdc, // DC의 핸들.

CONST POINT *lppt, //그릴 좌표.

int cPoints); // 좌표의 수.


 두개의 함수의 공통점은 다각형을 표현하는 것이지만, Polygon()은 다각형을 표현하는 것이고, Polyline()은 다각선을 표현하는 것이다.


 Polygon()은 첫 점과 끝 점이 합쳐지지만, Polyline()은 끝이 끊어져있다.


 POINT들은 포인트 배열을들 모아서 사용되는 것으로, x, y라는 것이 있다.


 

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
#include <stdlib.h>
 
#include <tchar.h>
#include <windows.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
WNDCLASS WndClass;
 
int numbers = 0;
 
int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpszCmdParam,
            int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    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",
                        "Test",
                        WS_OVERLAPPEDWINDOW,
                        10,// X
                        100,// Y
                        400,// Width
                        400,// Height
                        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)
{
    HDC hdc;
    PAINTSTRUCT ps;
    long dwStyle;
    
    POINT polyline[5= {60,50,40,30,20};
    POINT polygon[5= {10,20,30,40,50};
    
    switch(iMessage)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_LBUTTONDOWN:
            hdc = GetDC(hWnd);
            Polyline(hdc, polyline, 5);
            Polyline(hdc, polygon, 5);
            ReleaseDC(hWnd, hdc);
            break;
        case WM_PAINT:
            hdc = GetDC(hWnd);
            TextOut(hdc, 10050"Hello World",11);
            ReleaseDC(hWnd, hdc);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
 
cs


Posted by JunkMam
,

 Windows 프로그래밍을 할때는 WinMain을 이용해서 사용한다.

 하지만, C언어에서 나오는 WinMain이 아닌 Main 함수를 이용해서 호출하는데.

 만약, WinMain을 사용하지 않는다는 가정하게 한다면, 다음과 같은 함수가 필요하다.


 GetModuleHandle[각주:1]


 참조 : https://bobobobo.wordpress.com/2008/02/03/getting-the-hwnd-and-hinstance-of-the-console-window/


 여기서, 나오는 Console을 연결하는 소스에서 창을 띄우는 부분에 대한 소스가 있다.


 가장 중요한 것은 Console 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
#include <stdio.h>
 
#include <windows.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
WNDCLASS WndClass;
 
int numbers = 0;
 
int main()
{
    HINSTANCE hInstance;
    HWND hWnd;
    MSG Message;
    
    hInstance = GetModuleHandle(NULL);
    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",
                        "Test",
                        WS_OVERLAPPEDWINDOW,
                        10,// X
                        100,// Y
                        400,// Width
                        400,// Height
                        NULL,
                        (HMENU)NULL,
                        hInstance,
                        NULL);
    
    //윈도우 창 띄우기.
    ShowWindow(hWnd,1);
    
    while(GetMessage(&Message,0,0,0))
    {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
    
    return Message.wParam;
}
 
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    long dwStyle;
    
    switch(iMessage)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_PAINT:
            hdc = GetDC(hWnd);
            TextOut(hdc, 10050"Hello World",11);
            ReleaseDC(hWnd, hdc);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
 
cs


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

 원형으로 출력하는 것이다.


 원형으로 출력을 하기 위해서 수학적으로 어떻게 해서 출력이 되는가? 라는 것을 생각할 필요가 있다.


 원형을 출력하기 위해서는 3가지 방법이 있다. 하지만, 필자는 2가지 방법 밖에 기억이 나지 않는다.

 또 다른 방식은 기억이 안나지만, 제대로된 방식이 아니라서 표현이 안되는 것으로 알고 있다.


 2가지 방식의 문제점은 2개의 독립 변수를 한개의 독립 변수로 표현하기 위해서 사용하다가 생기는 문제가 있기 때문에 생기는 문제이다.


 1. y^2 + x^2 = r^2 을 이용한 방식.(피타고라스 방식을 이용하는 것이라고 이해하면 될것이다.)


 이 방식은 완벽하게 출력이 되지 않지만, 반 원을 출력할 수 있는 방식이다.

 쉽게 말해서 완벽하게 원형을 출력할 수가 없다.


 이유는

 y = ±√(r^2-x^2) 이렇게 사용이 된다.


 이것은 + 부분과 - 부분을 이용해야 된다.


 +부분과 -부분을 따로 계산해야되기 때문에, 문제가 발생 할 수 있다.


 고등학교에서 말하는 원형을 표현하는 방법이다.



 2. 이 방식은 매개 변수를 사용하는 방식이다.


 쉽게 말해서 x^2+y^2 = r^2을 이용하는 방식이 아니다. 앞써 말한 2개의 독립 변수를 1개의 독립 변수로 움직이게 만들기 위해서 사용하다보니, 생기는 문제점이 있었다고 했다.


 이것을 매개변수라는 하나의 독립 변수로만 만들도록하고, 두개끼리 영향을 안 끼치는 방식을 채택한 것이다.


 식은 다음과 같다.

 width * sin(θ) + height * cos(θ) = f(θ) 이라는 형식이다.


 여기서 f(θ)이란, 원형 함수이다.


 width = height 일 경우에는 원.

 widht <> height 일 경우에는 타원.


 이런 방식을 이용해서 원과 타원을 그리는 함수를 표현하게 된다.


 θ라는 독립 매개 변수 1개를 이용하여, 표현 하기 때문에 앞에 나온 방식과 차이가 생기게 된다.

 그리고 θ가 얼만큼 가느냐에 따라서 호를 표현 할 수 있기도 하다.


 그런데, 이렇게 사용할려면, 전체적으로 각 Pixel을 찍어줘야하는 문제점이 있다.(윗 방식은 알아 두면 좋은 것이기 때문에 작성한 것이다.)


 Windows에서는 다음과 같은 함수가 지원해주기 때문에 굳이 알 필요는 없기도하다.


 Ellipse(

HDC hdc, // DC의 핸들.

int nLeftRect, // 사각형의 왼쪽 x 좌표.

int nTopRect, // 사각형의 상단 y 좌표.

int nRightRect, // 사각형의 우측 x 좌표.

int nBottomRect); // 사각형의 하단 y 좌표.


Arc(

HDC hdc, // DC의 핸들.

int nLeftRect, // 사각형의 왼쪽 x 좌표.

int nTopRect, // 사각형의 상단 y 좌표.

int nRightRect, // 사각형의 우측 x 좌표.

int nBottomRect, // 사각형의 하단 y 좌표.

int nXStartArc, // 그리기를 시작하는 x 지점.

int nYStartArc, // 그리기를 시작하는 y 지점.

int nXEndArc, // 그리기를 종료하는 x 지점.

int nYEndArc); // 그리기를 종료하는 y 지점.


 Chord(

HDC hdc, // DC의 핸들.

int nLeftRect, // 사각형의 왼쪽 x 좌표.

int nTopRect, // 사각형의 상단 y 좌표.

int nRightRect, // 사각형의 우측 x 좌표.

int nBottomRect, // 사각형의 하단 y 좌표.

int nXRadial1, // 그리기를 시작하는 x 지점.

int nYRadial1, // 그리기를 시작하는 y 지점.

int nXRadial2, // 그리기를 종료하는 x 지점.

int nYRadial2); // 그리기를 종료하는 y 지점.


 Pie(

HDC hdc, // DC의 핸들.

int nLeftRect, // 사각형의 왼쪽 x 좌표.

int nTopRect, // 사각형의 상단 y 좌표.

int nRightRect, // 사각형의 우측 x 좌표.

int nBottomRect, // 사각형의 하단 y 좌표.

int nXRadial1, // 그리기를 시작하는 x 지점.

int nYRadial1, // 그리기를 시작하는 y 지점.

int nXRadial2, // 그리기를 종료하는 x 지점.

int nYRadial2); // 그리기를 종료하는 y 지점.


 다음과 같은 것을 표현 하기 위해서 사용하는 예제


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
#include <stdlib.h>
 
#include <tchar.h>
#include <windows.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
WNDCLASS WndClass;
 
int numbers = 0;
 
int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpszCmdParam,
            int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    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",
                        "Test",
                        WS_OVERLAPPEDWINDOW,
                        10,// X
                        100,// Y
                        400,// Width
                        400,// Height
                        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)
{
    HDC hdc;
    PAINTSTRUCT ps;
    long dwStyle;
    
    switch(iMessage)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_LBUTTONDOWN:
            hdc = GetDC(hWnd);
            switch(numbers)
            {
                case 0:
                    Ellipse(hdc, 100100200200);
                    numbers++;
                    break;
                case 1:
                    Arc(hdc, 100100200200150100200150);
                    numbers++;
                    break;
                case 2:
                    Chord(hdc, 100100200200100200100150);
                    numbers++;
                    break;
                case 3:
                    Pie(hdc, 100100200200150100100150);
                    numbers=0;
                    break;
            }
            ReleaseDC(hWnd, hdc);
            break;
        case WM_PAINT:
            hdc = GetDC(hWnd);
            TextOut(hdc, 10050"Hello World",11);
            ReleaseDC(hWnd, hdc);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
 
cs


Posted by JunkMam
,