티스토리 뷰

Win32(API)

[win32 API] 콜백, Invalid 무효영역 다시그리기 등

열혈허슬러 상추님 2019. 7. 2. 01:23
190625(2일차) - 콜백, 그리기(Invalid Region)
 
 
 

 
return 0; 생략시 0을 자동으로 반환한다.
 
caller : 호출 client
callee : 피호출 server
 
콜 : 서비스코드를 클라이언트에서 불러낸다
콜백 : 클라이언트코드를 서버에서 불러낸다.
 
특정 이벤트가 발생되면 OS가 알아차리고 해당 이벤트에 맞는 기능이 수행되도록 콜백한다.
 
#include <stdio.h>
void PrintList(const int arr[], int size) {
    for (int i = 0; i < size; ++i) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}
int FindList(const void* arr[], int size, bool(*cmp)(const void*)) {
    for (int i = 0; i < size; ++i) {
        if (cmp(arr[i]))
            return i;
    }
    return -1;
}
//////////////////
bool mycmp(const void* data) {
    printf("log data : %d\n", *(int*)data);
    return 80 < *(int*)data&& *(int*)data < 100;
}
int main() {
    int* list[10] = { // client는 알고있기 때문에 int* 로 표기해도 무방.
        new int(10),
        new int(20),
        new int(30),
        new int(40),
        new int(50),
        new int(60),
        new int(70),
        new int(80),
        new int(90),
        new int(100)
    };
 
    //PrintList(list, 10);
    int idx = FindList((const void**)list, 10, mycmp);
    if (idx != -1)
        printf("[%d] : %d\n", idx, *list[idx]);
 
 
    return 0;
}
 
일찍 끝나면, 개발방법론, Gof 디자인패턴 등 설계전략 해보겠다.
 

그리기
DC, Paint
  • GetDC()
  • BeginPaint()
 
- 텍스트 출력
  • TextOut() :x,y 점으로 출력
  • DrawText():영역으로 출력
마우스 좌표
  • WM_마우스 일때
    wParam은 마우스와 같이 눌린 키정보
    lParam은 좌표에 대한 정보이다.
    y(HIWORD) x(LOWORD)
- 클릭한 마우스좌표에 글자 출력
        hdc = GetDC(hwnd); // 그리기 준비(DC를 얻어온다.)
        
        TextOut(hdc, LOWORD(lParam)/*x*/, HIWORD(lParam)/*y*/, _T("Hello!"), 6/*글자수*/);
        ReleaseDC(hwnd, hdc);
 
-클릭한 곳에 좌표를 출력
case WM_LBUTTONDOWN:{
    hdc = GetDC(hwnd); // 그리기 준비(DC를 얻어온다.)
    TCHAR buf[500];
    int x = LOWORD(lParam);
    int y = HIWORD(lParam);
    wsprintf(buf, _T("(%d, %d)"), x, y);
    TextOut(hdc, x, y, buf, lstrlen(buf)/*글자수*/);
    ReleaseDC(hwnd, hdc);
}
    break;
- case문 안에서는 지역변수를 생성할 수 없게 되어 있어서 (지역)블럭을 추가한다.
 
GetDC는 화면에 그리기를 하고 화면을 흔들면 데이터가 모두 사라진다.
-> 다시그리기를 해야한다.
 
- GUI그리기는 크게 2개 방식이 있다.
  1. 애플리케이션이 그리기 정보를 복원해야하는 방식
    Win32API GDI, MFC GDI+, JAVA Swing, WinForm
    -> 데이터로 다시그리거나(일반적)
    -> 이미지형태로 저장했다가 다시 그리거나(듀얼도커링(?))
  2. 시스템이 애플리케이션의 그리기 정보를 자동 복원하는 방식
    WPF, java FX, android Control 그리기 등  
 
-> 다시그리기를 해야한다.
  • 무효영역(Invalid Region: 다시 그리기 해야하는 영역
    -> WM_PAINT 메세지를 만들어 낸다.
 
WM_PAINT 에서 다시 그리기를 한 뒤 요효한 영역으로 만들어 주어야한다.
WM_PAINT에서 GetDC()를 쓰지 않는다.
WM_PAINT에서 DC를 얻을 때는 BeginPatint를 사용한다.
WM_PAINT에서 lParam
WM_PAINT는 그리기만 해야한다. 데이터가 변경되는 코드가 들어가면안된다. (doc,view를 나누는 핵심규칙)
 
GetDC() : 그리기만 하고 그외에 아무것도 안한다.
 
BeginPaint(HWND,PAINTSTRUCT) : 백그라운드를 다시그린다 등의 역할도한다.
BeginPaint(HWND,PAINTSTRUCT) : 다시 그릴 때
 
cf. api에서는 구조체는 모두 대문자로 표기하도록 했다.
 
 
WM_LBUTTONDOWM: GetDC()로 그리기를 한 것이다.
WM_PAINT: BeginPatin()로 그리기를 한 것이다.
 
클릭했을 때 그릴려면 무효화 영역을 만들어 주면 된다.
InvalidateRect(hwnd, NULL, TRUE); // 무효한 사각형 영역을 만든다.
또는
InvalidateRgn
 

openCV는 C++과 C#으로 코딩을 많이한다.
openCV는 C++로 만들어져있다.
dll을 가지고 C#에서도 쓸 수 있다.
(포인터, 배열, 구조체, 클래스, 함수 중요)
프로그래머는 자신의무식함을 드러낼수있어야된다
 

 
누를 때 직접 그리기를 할 수 있고
 
WM_PAINT (Q메세지)
 
과제 해결 완료
#include <windows.h>
#include <TCHAR.H>
#include <vector> // 데이터를 저장하기 위한 벡터를 사용
#define SIZE 3
using namespace std;
 
//typedef struct Point {
//  int x;
//  int y;
//}Point;
 
void DrawString(HDC hdc, POINT pt) {
    TCHAR buf[500]; // 출력할 문자열
    wsprintf(buf, _T("(%d, %d)"), pt.x, pt.y); // 출력할 문자열 생성
    TextOut(hdc, pt.x, pt.y, buf, lstrlen(buf)/*글자수*/);
}
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpszCmdLine, int nCmdShow)
{
    HWND hwnd;
    MSG      msg;
    WNDCLASS WndClass;
    WndClass.style = CS_HREDRAW | CS_VREDRAW;
    WndClass.lpfnWndProc = WndProc;
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hInstance = hInstance;
    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.lpszMenuName = NULL;
    WndClass.lpszClassName = _T("Window Class Name");
    RegisterClass(&WndClass);
    hwnd = CreateWindow(_T("Window Class Name"),
        _T("Window Title Name"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL
    );
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}
 
 
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    POINT pt; // 좌표를 보관하는 Point구조체
    static vector<POINT> ptList; //좌표들 보과할 벡터
    static vector<vector<POINT>> polygonList;
 
    switch (iMsg)
    {
    case WM_CREATE:
        break;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
 
        //저장해 놓은 모든 폴리건을 무효영역 부분에 PAINT한다.
        for (vector<vector<POINT>>::size_type i = 0; i < polygonList.size(); ++i) {
            Polygon(hdc, &((polygonList[i])[0]), (polygonList[i]).size());
        }
        EndPaint(hwnd, &ps);
        break;
    case WM_RBUTTONDOWN:
        if (!ptList.empty()) {
            hdc = GetDC(hwnd);
            Polygon(hdc, &ptList[0]/*벡터만가능*/, ptList.size());
            ReleaseDC(hwnd, hdc);
            polygonList.push_back(ptList); // 폴리건 리스트에 이번에 생성한 폴리건을 넣는다.
            ptList.clear();
        }
        break;
    case WM_LBUTTONDOWN:
        pt.x = LOWORD(lParam);
        pt.y = HIWORD(lParam);
 
        hdc = GetDC(hwnd);
        Ellipse(hdc, pt.x - SIZE, pt.y - SIZE, pt.x + SIZE, pt.y + SIZE);
        ReleaseDC(hwnd, hdc);
        ptList.push_back(pt);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
 
 
new를 사용한 해결 (vector<vector<POINT>*>)
#include <windows.h>
#include <TCHAR.H>
#include <vector> // 데이터를 저장하기 위한 벡터를 사용
#define SIZE 3
using namespace std;
 
//typedef struct Point {
//  int x;
//  int y;
//}Point;
 
void DrawString(HDC hdc, POINT pt) {
    TCHAR buf[500]; // 출력할 문자열
    wsprintf(buf, _T("(%d, %d)"), pt.x, pt.y); // 출력할 문자열 생성
    TextOut(hdc, pt.x, pt.y, buf, lstrlen(buf)/*글자수*/);
}
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpszCmdLine, int nCmdShow)
{
    HWND hwnd;
    MSG      msg;
    WNDCLASS WndClass;
    WndClass.style = CS_HREDRAW | CS_VREDRAW;
    WndClass.lpfnWndProc = WndProc;
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hInstance = hInstance;
    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.lpszMenuName = NULL;
    WndClass.lpszClassName = _T("Window Class Name");
    RegisterClass(&WndClass);
    hwnd = CreateWindow(_T("Window Class Name"),
        _T("Window Title Name"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL
    );
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}
 
 
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
    WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    POINT pt; // 좌표를 보관하는 Point구조체
    static vector<POINT> ptList; //좌표들 보과할 벡터
    static vector<vector<POINT>*> polygonList;
    switch (iMsg)
    {
    case WM_CREATE:
        break;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        for (vector<vector<POINT>*>::size_type i = 0; i < polygonList.size(); ++i) {
            Polygon(hdc, &((*polygonList[i])[0])/*벡터만가능*/, (*polygonList[i]).size());
        }
        EndPaint(hwnd, &ps);
        break;
    case WM_RBUTTONDOWN:
        if (!ptList.empty()) {
            hdc = GetDC(hwnd);
            Polygon(hdc, &ptList[0]/*벡터만가능*/, ptList.size());
            ReleaseDC(hwnd, hdc);
            vector<POINT>* tmp = new vector <POINT>(ptList);
            polygonList.push_back(tmp);
            ptList.clear();
        }
        break;
    case WM_LBUTTONDOWN:
        pt.x = LOWORD(lParam);
        pt.y = HIWORD(lParam);
 
        hdc = GetDC(hwnd);
        Ellipse(hdc, pt.x - SIZE, pt.y - SIZE, pt.x + SIZE, pt.y + SIZE);
        ReleaseDC(hwnd, hdc);
        ptList.push_back(pt);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
댓글
댓글쓰기 폼
네이버 이웃추가
«   2021/01   »
          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            
글 보관함