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개 방식이 있다.
-
애플리케이션이 그리기 정보를 복원해야하는 방식Win32API GDI, MFC GDI+, JAVA Swing, WinForm-> 데이터로 다시그리거나(일반적)-> 이미지형태로 저장했다가 다시 그리거나(듀얼도커링(?))
-
시스템이 애플리케이션의 그리기 정보를 자동 복원하는 방식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);
}
'Win32(API)' 카테고리의 다른 글
[win32 API] 다이얼로그 윈도우, 자식윈도우, 컨트롤 (0) | 2019.07.03 |
---|---|
[win32 API] DC 그리기 작업, bitmap (0) | 2019.07.02 |
[win32 api] 기본 동작 개념, 메세지 처리, 프로시저 등 (2) | 2019.07.01 |
[win32 api] EditBox, ListBoc Control (1) | 2018.03.17 |
[Win32] Modal dialog Modeless 대화상자 (생성 및 사용법) (0) | 2018.03.17 |