학교수업/윈도우즈 프로그래밍
선그리기 v.combo
허세98
2021. 1. 26. 20:50
반응형
v.combo
#include <windows.h>
#include <tchar.h>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass=TEXT("Mouse");
int APIENTRY 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;
WndClass.lpszClassName=lpszClass;
WndClass.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);
WndClass.style=CS_HREDRAW | CS_VREDRAW;// | CS_DBLCLKS;
RegisterClass(&WndClass);
hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,(HMENU)NULL,hInstance,NULL);
ShowWindow(hWnd,nCmdShow);
while (GetMessage(&Message,NULL,0,0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return (int)Message.wParam;
}
typedef struct _line {
POINT p[500];
int iCount;
COLORREF pColor;
int pWidth;
} line;
line lines[1000];
//int iTempCount;
int iLines;
int iCurrentPenWidth = 3;
COLORREF iCurrentPenColor = RGB(255, 0, 0);
enum { ID_R1 = 101, ID_R2, ID_R3 };
HWND r1, r2, r3;
#define ID_COMBOBOX 100
TCHAR *Items[] = { TEXT("3"), TEXT("6"), TEXT("9"), TEXT("12") };
HWND hCombo;
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static int x;
static int y;
//static BOOL bNowDraw=FALSE;
HPEN hPen;
TCHAR str[128];
switch (iMessage) {
case WM_CREATE:
CreateWindow(TEXT("button"), TEXT("Color"), WS_CHILD | WS_VISIBLE |
BS_GROUPBOX, 5, 5, 120, 110, hWnd, (HMENU)0, g_hInst, NULL);
r1 = CreateWindow(TEXT("button"), TEXT("Red"), WS_CHILD | WS_VISIBLE |
BS_AUTORADIOBUTTON | WS_GROUP,
10, 20, 100, 30, hWnd, (HMENU)ID_R1, g_hInst, NULL);
r2 = CreateWindow(TEXT("button"), TEXT("Green"), WS_CHILD | WS_VISIBLE |
BS_AUTORADIOBUTTON,
10, 50, 100, 30, hWnd, (HMENU)ID_R2, g_hInst, NULL);
r3 = CreateWindow(TEXT("button"), TEXT("Blue"), WS_CHILD | WS_VISIBLE |
BS_AUTORADIOBUTTON,
10, 80, 100, 30, hWnd, (HMENU)ID_R3, g_hInst, NULL);
CheckRadioButton(hWnd, ID_R1, ID_R3, ID_R1);
hCombo = CreateWindow(TEXT("combobox"), NULL, WS_CHILD | WS_VISIBLE |
CBS_DROPDOWN, 130, 10, 100, 200, hWnd, (HMENU)ID_COMBOBOX, g_hInst, NULL);
for (int i = 0; i<4; i++) {
SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)Items[i]);
}
SendMessage(hCombo, CB_SETCURSEL, (iCurrentPenWidth/3)-1, 0);
return 0;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDM_RED:
case ID_R1:
iCurrentPenColor = RGB(255, 0, 0);
SetFocus(hWnd);
CheckRadioButton(hWnd, ID_R1, ID_R3, ID_R1);
break;
case IDM_GREEN:
case ID_R2:
iCurrentPenColor = RGB(0,255, 0, 0);
SetFocus(hWnd);
CheckRadioButton(hWnd, ID_R1, ID_R3, ID_R2);
break;
case IDM_BLUE:
case ID_R3:
iCurrentPenColor = RGB(0,0, 255);
SetFocus(hWnd);
CheckRadioButton(hWnd, ID_R1, ID_R3, ID_R3);
break;
case ID_COMBOBOX:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
iCurrentPenWidth =
(SendMessage(hCombo, CB_GETCURSEL, 0, 0) + 1) * 3;
//SetFocus(hWnd);
break;
case CBN_EDITCHANGE:
GetWindowText(hCombo, str, 128);
iCurrentPenWidth = _ttoi(str);
//SetFocus(hWnd);
break;
}
}
return 0;
case WM_INITMENU:
if (iCurrentPenColor == RGB(255, 0, 0)){
CheckMenuItem((HMENU)wParam, IDM_RED, MF_BYCOMMAND | MF_CHECKED);
CheckMenuItem((HMENU)wParam, IDM_GREEN, MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem((HMENU)wParam, IDM_BLUE, MF_BYCOMMAND | MF_UNCHECKED);
}
else if (iCurrentPenColor == RGB(0, 255, 0)){
CheckMenuItem((HMENU)wParam, IDM_RED, MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem((HMENU)wParam, IDM_GREEN, MF_BYCOMMAND | MF_CHECKED);
CheckMenuItem((HMENU)wParam, IDM_BLUE, MF_BYCOMMAND | MF_UNCHECKED);
}
else if (iCurrentPenColor == RGB(0, 0, 255)){
CheckMenuItem((HMENU)wParam, IDM_RED, MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem((HMENU)wParam, IDM_GREEN, MF_BYCOMMAND | MF_UNCHECKED);
CheckMenuItem((HMENU)wParam, IDM_BLUE, MF_BYCOMMAND | MF_CHECKED);
}
return 0;
case WM_KEYDOWN:
switch (wParam) {
case VK_BACK:
if (iLines > 0)
{
iLines--; lines[iLines].iCount = 0;
}
InvalidateRect(hWnd, NULL, TRUE);
break;
}
return 0;
case WM_LBUTTONDOWN:
SetFocus(hWnd);
x=LOWORD(lParam);
y=HIWORD(lParam);
lines[iLines].pColor =iCurrentPenColor ;
lines[iLines].pWidth =iCurrentPenWidth;
lines[iLines].p[lines[iLines].iCount].x = x;
lines[iLines].p[lines[iLines].iCount].y = y;
lines[iLines].iCount++; ///
return 0;
case WM_MOUSEMOVE:
if (wParam & MK_LBUTTON) {
hdc=GetDC(hWnd);
hPen = CreatePen(PS_SOLID, iCurrentPenWidth, iCurrentPenColor);
hPen=(HPEN)SelectObject(hdc, hPen);
MoveToEx(hdc,x,y,NULL);
x=LOWORD(lParam);
y=HIWORD(lParam);
lines[iLines].p[lines[iLines].iCount].x = x;
lines[iLines].p[lines[iLines].iCount].y = y;
lines[iLines].iCount++;
LineTo(hdc,x,y);
DeleteObject(SelectObject(hdc, hPen));
ReleaseDC(hWnd,hdc);
}
return 0;
case WM_LBUTTONUP:
//lines[iLines].iCount = iTempCount;
//iTempCount = 0;
iLines++;
return 0;
// 내가 생성한 GDI Object는 사용후반드시 삭제한다, 단 선택해제후
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
for (int i = 0; i < iLines; i++)
{
hPen = CreatePen(PS_SOLID, lines[i].pWidth, lines[i].pColor);
hPen = (HPEN)SelectObject(hdc, hPen); //선택한다.
MoveToEx(hdc, lines[i].p[0].x,
lines[i].p[0].y, NULL);
for (int j = 0; j < lines[i].iCount-1; j++)
{
LineTo(hdc, lines[i].p[j+1].x,
lines[i].p[j+1].y);
}
//선택해제...
DeleteObject(SelectObject(hdc, hPen)); //그리고 삭제한다...
}
return 0;
case WM_LBUTTONDBLCLK:
InvalidateRect(hWnd, NULL, TRUE);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
Combo 버전에서 추가된 부분은 콤보박스와 에디트이다.
콤보 박스를 통해 선의 굵기를 정해주는 기능을 추가했다.
추가된 자료구조
#define ID_COMBOBOX 100
TCHAR *Items[] = { TEXT("3"), TEXT("6"), TEXT("9"), TEXT("12") };
HWND hCombo;
int iCurrentPenWidth = 3;
typedef struct _line {
int pWidth;
} line;
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
TCHAR str[128];
}
위에서 부터 순서대로
1. ID값을 저장하는 매크로
2. 문자열을 저장하는 배열
3. 컨트롤 윈도우를 저장하는 핸들
4. 팬의 굵기를 기록하는 전역변수
5. 선 마다 굵기를 기록하는 구조체
6. 자식 윈도우의 콤보박스 에디터에 기록되는 값을 저장하는 지역변수 str
WM_CREATE(콤보 박스 생성)
case WM_CREATE:
hCombo = CreateWindow(TEXT("combobox"), NULL, WS_CHILD | WS_VISIBLE |
CBS_DROPDOWN, 130, 10, 100, 200, hWnd, (HMENU)ID_COMBOBOX, g_hInst, NULL);
for (int i = 0; i<4; i++) {
SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)Items[i]);
}
SendMessage(hCombo, CB_SETCURSEL, (iCurrentPenWidth/3)-1, 0);
return 0;
콤보박스를 hCombo 핸들에 넣는다.
Items[0]에 텍스트를 넣는다 i가 3dl 될때까지 총 4회 반복
WM_COMMAN
case WM_COMMAND:
switch (LOWORD(wParam)) {//1
case ID_COMBOBOX:
switch (HIWORD(wParam)) {//2
case CBN_SELCHANGE://3
iCurrentPenWidth=(SendMessage(hCombo, CB_GETCURSEL, 0, 0) + 1) * 3;//4
//SetFocus(hWnd);//5
break;
case CBN_EDITCHANGE://6
GetWindowText(hCombo, str, 128);
iCurrentPenWidth = _ttoi(str);
//SetFocus(hWnd);
break;
}
}
부모 윈도우(메인 윈도우)에게 자식 윈도우(COMBOBOX)가 명령을 전달하는 내용이다
1. 부모윈도우에게 보낼 메시지
2. 자식 윈도우에서 일어나는 이벤트
3. 콤보박스(자식 윈도우)이벤트 - 셀 바꾸기
4. 콤보박스 셀이 바뀌면 전역 변수 iCurrentPenWidth의 정수를 (커서의 인덱스 값+1)*3으로 바꾼다
5. 콤보박스 이벤트 - 에디터 텍스트 변경
7. GetWindowText()함수는 CWnd 갭션 타이틀을 복사하는 것으로 CWnd 객체가 컨트롤이면 컨트롤 안에 있는 텍스트를 복사한다. 복사해서 str에 넣는다.
8. iCurrentPenWidth에 str의 값을 텍스트를 정수로 변환해준다.
9. 에디트의 텍스트를 입력하면 포커스를 바꿔준다. 숫자를 1개만 쳐도 포커스가 이동 됌 밑에서 해결
LBUTTONDOWN
case WM_LBUTTONDOWN:
SetFocus(hWnd);
x=LOWORD(lParam);
y=HIWORD(lParam);
lines[iLines].pColor =iCurrentPenColor ;
lines[iLines].pWidth =iCurrentPenWidth;
lines[iLines].p[lines[iLines].iCount].x = x;
lines[iLines].p[lines[iLines].iCount].y = y;
lines[iLines].iCount++;
return 0;
SetFocus(hWnd)
-메인 윈도우로 포커스 변경 컨트롤을 사용해서 바뀐 포커스를 메인 윈도우로 옮겨준다.
-대화상자를 쓰면 이렇게 포커스를 임의로 바뀌 줄 필요가 없다. 다음 시간에는 대화상자에 대해 배운다.
반응형