diff --git a/GlimWork.sln b/GlimWork.sln new file mode 100644 index 0000000..c501a56 --- /dev/null +++ b/GlimWork.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.33027.164 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GlimWork", "GlimWork\GlimWork.vcxproj", "{61F95EA6-D645-4EE0-B5B7-1C6D8CFB19B1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {61F95EA6-D645-4EE0-B5B7-1C6D8CFB19B1}.Debug|x64.ActiveCfg = Debug|x64 + {61F95EA6-D645-4EE0-B5B7-1C6D8CFB19B1}.Debug|x64.Build.0 = Debug|x64 + {61F95EA6-D645-4EE0-B5B7-1C6D8CFB19B1}.Debug|x86.ActiveCfg = Debug|Win32 + {61F95EA6-D645-4EE0-B5B7-1C6D8CFB19B1}.Debug|x86.Build.0 = Debug|Win32 + {61F95EA6-D645-4EE0-B5B7-1C6D8CFB19B1}.Release|x64.ActiveCfg = Release|x64 + {61F95EA6-D645-4EE0-B5B7-1C6D8CFB19B1}.Release|x64.Build.0 = Release|x64 + {61F95EA6-D645-4EE0-B5B7-1C6D8CFB19B1}.Release|x86.ActiveCfg = Release|Win32 + {61F95EA6-D645-4EE0-B5B7-1C6D8CFB19B1}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4526E043-7B9A-46F2-9D3A-A8E4B9DC9856} + EndGlobalSection +EndGlobal diff --git a/GlimWork/GlimWork.cpp b/GlimWork/GlimWork.cpp new file mode 100644 index 0000000..00b7095 --- /dev/null +++ b/GlimWork/GlimWork.cpp @@ -0,0 +1,107 @@ + +// GlimWork.cpp: 애플리케이션에 대한 클래스 동작을 정의합니다. +// + +#include "pch.h" +#include "framework.h" +#include "GlimWork.h" +#include "GlimWorkDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CGlimWorkApp + +BEGIN_MESSAGE_MAP(CGlimWorkApp, CWinApp) + ON_COMMAND(ID_HELP, &CWinApp::OnHelp) +END_MESSAGE_MAP() + + +// CGlimWorkApp 생성 + +CGlimWorkApp::CGlimWorkApp() +{ + // 다시 시작 관리자 지원 + m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART; + + // TODO: 여기에 생성 코드를 추가합니다. + // InitInstance에 모든 중요한 초기화 작업을 배치합니다. +} + + +// 유일한 CGlimWorkApp 개체입니다. + +CGlimWorkApp theApp; + + +// CGlimWorkApp 초기화 + +BOOL CGlimWorkApp::InitInstance() +{ + // 애플리케이션 매니페스트가 ComCtl32.dll 버전 6 이상을 사용하여 비주얼 스타일을 + // 사용하도록 지정하는 경우, Windows XP 상에서 반드시 InitCommonControlsEx()가 필요합니다. + // InitCommonControlsEx()를 사용하지 않으면 창을 만들 수 없습니다. + INITCOMMONCONTROLSEX InitCtrls; + InitCtrls.dwSize = sizeof(InitCtrls); + // 응용 프로그램에서 사용할 모든 공용 컨트롤 클래스를 포함하도록 + // 이 항목을 설정하십시오. + InitCtrls.dwICC = ICC_WIN95_CLASSES; + InitCommonControlsEx(&InitCtrls); + + CWinApp::InitInstance(); + + + AfxEnableControlContainer(); + + // 대화 상자에 셸 트리 뷰 또는 + // 셸 목록 뷰 컨트롤이 포함되어 있는 경우 셸 관리자를 만듭니다. + CShellManager *pShellManager = new CShellManager; + + // MFC 컨트롤의 테마를 사용하기 위해 "Windows 원형" 비주얼 관리자 활성화 + CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows)); + + // 표준 초기화 + // 이들 기능을 사용하지 않고 최종 실행 파일의 크기를 줄이려면 + // 아래에서 필요 없는 특정 초기화 + // 루틴을 제거해야 합니다. + // 해당 설정이 저장된 레지스트리 키를 변경하십시오. + // TODO: 이 문자열을 회사 또는 조직의 이름과 같은 + // 적절한 내용으로 수정해야 합니다. + SetRegistryKey(_T("로컬 애플리케이션 마법사에서 생성된 애플리케이션")); + + CGlimWorkDlg dlg; + m_pMainWnd = &dlg; + INT_PTR nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: 여기에 [확인]을 클릭하여 대화 상자가 없어질 때 처리할 + // 코드를 배치합니다. + } + else if (nResponse == IDCANCEL) + { + // TODO: 여기에 [취소]를 클릭하여 대화 상자가 없어질 때 처리할 + // 코드를 배치합니다. + } + else if (nResponse == -1) + { + TRACE(traceAppMsg, 0, "경고: 대화 상자를 만들지 못했으므로 애플리케이션이 예기치 않게 종료됩니다.\n"); + TRACE(traceAppMsg, 0, "경고: 대화 상자에서 MFC 컨트롤을 사용하는 경우 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS를 수행할 수 없습니다.\n"); + } + + // 위에서 만든 셸 관리자를 삭제합니다. + if (pShellManager != nullptr) + { + delete pShellManager; + } + +#if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS) + ControlBarCleanUp(); +#endif + + // 대화 상자가 닫혔으므로 응용 프로그램의 메시지 펌프를 시작하지 않고 응용 프로그램을 끝낼 수 있도록 FALSE를 + // 반환합니다. + return FALSE; +} + diff --git a/GlimWork/GlimWork.h b/GlimWork/GlimWork.h new file mode 100644 index 0000000..278fe11 --- /dev/null +++ b/GlimWork/GlimWork.h @@ -0,0 +1,32 @@ + +// GlimWork.h: PROJECT_NAME 애플리케이션에 대한 주 헤더 파일입니다. +// + +#pragma once + +#ifndef __AFXWIN_H__ + #error "PCH에 대해 이 파일을 포함하기 전에 'pch.h'를 포함합니다." +#endif + +#include "resource.h" // 주 기호입니다. + + +// CGlimWorkApp: +// 이 클래스의 구현에 대해서는 GlimWork.cpp을(를) 참조하세요. +// + +class CGlimWorkApp : public CWinApp +{ +public: + CGlimWorkApp(); + +// 재정의입니다. +public: + virtual BOOL InitInstance(); + +// 구현입니다. + + DECLARE_MESSAGE_MAP() +}; + +extern CGlimWorkApp theApp; diff --git a/GlimWork/GlimWork.rc b/GlimWork/GlimWork.rc new file mode 100644 index 0000000..e6b6062 Binary files /dev/null and b/GlimWork/GlimWork.rc differ diff --git a/GlimWork/GlimWork.vcxproj b/GlimWork/GlimWork.vcxproj new file mode 100644 index 0000000..6dddb80 --- /dev/null +++ b/GlimWork/GlimWork.vcxproj @@ -0,0 +1,215 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {61F95EA6-D645-4EE0-B5B7-1C6D8CFB19B1} + MFCProj + GlimWork + 10.0 + + + + Application + true + v142 + Unicode + Dynamic + + + Application + false + v142 + true + Unicode + Dynamic + + + Application + true + v142 + Unicode + Dynamic + + + Application + false + v142 + true + Unicode + Dynamic + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + true + WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) + pch.h + + + Windows + + + false + true + _DEBUG;%(PreprocessorDefinitions) + + + 0x0412 + _DEBUG;%(PreprocessorDefinitions) + $(IntDir);%(AdditionalIncludeDirectories) + + + + + Use + Level3 + true + _WINDOWS;_DEBUG;%(PreprocessorDefinitions) + pch.h + + + Windows + + + false + true + _DEBUG;%(PreprocessorDefinitions) + + + 0x0412 + _DEBUG;%(PreprocessorDefinitions) + $(IntDir);%(AdditionalIncludeDirectories) + + + + + Use + Level3 + true + true + true + WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) + pch.h + + + Windows + true + true + + + false + true + NDEBUG;%(PreprocessorDefinitions) + + + 0x0412 + NDEBUG;%(PreprocessorDefinitions) + $(IntDir);%(AdditionalIncludeDirectories) + + + + + Use + Level3 + true + true + true + _WINDOWS;NDEBUG;%(PreprocessorDefinitions) + pch.h + + + Windows + true + true + + + false + true + NDEBUG;%(PreprocessorDefinitions) + + + 0x0412 + NDEBUG;%(PreprocessorDefinitions) + $(IntDir);%(AdditionalIncludeDirectories) + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GlimWork/GlimWork.vcxproj.filters b/GlimWork/GlimWork.vcxproj.filters new file mode 100644 index 0000000..e2b78aa --- /dev/null +++ b/GlimWork/GlimWork.vcxproj.filters @@ -0,0 +1,63 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 헤더 파일 + + + 헤더 파일 + + + 헤더 파일 + + + 헤더 파일 + + + 헤더 파일 + + + 헤더 파일 + + + + + 소스 파일 + + + 소스 파일 + + + 소스 파일 + + + + + 리소스 파일 + + + + + 리소스 파일 + + + + + 리소스 파일 + + + \ No newline at end of file diff --git a/GlimWork/GlimWorkDlg.cpp b/GlimWork/GlimWorkDlg.cpp new file mode 100644 index 0000000..73dca76 --- /dev/null +++ b/GlimWork/GlimWorkDlg.cpp @@ -0,0 +1,346 @@ + +// GlimWorkDlg.cpp: 구현 파일 +// + +#include "pch.h" +#include "framework.h" +#include "GlimWork.h" +#include "GlimWorkDlg.h" +#include "afxdialogex.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// 응용 프로그램 정보에 사용되는 CAboutDlg 대화 상자입니다. + +class CAboutDlg : public CDialogEx +{ +public: + CAboutDlg(); + +// 대화 상자 데이터입니다. +#ifdef AFX_DESIGN_TIME + enum { IDD = IDD_ABOUTBOX }; +#endif + + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다. + +// 구현입니다. +protected: + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX) +{ +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) +END_MESSAGE_MAP() + + +// CGlimWorkDlg 대화 상자 + + + +CGlimWorkDlg::CGlimWorkDlg(CWnd* pParent /*=nullptr*/) + : CDialogEx(IDD_GLIMWORK_DIALOG, pParent) +{ + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void CGlimWorkDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialogEx::DoDataExchange(pDX); +} + +BEGIN_MESSAGE_MAP(CGlimWorkDlg, CDialogEx) + ON_WM_SYSCOMMAND() + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_WM_LBUTTONUP() + ON_WM_LBUTTONDOWN() + ON_WM_MOUSEMOVE() +END_MESSAGE_MAP() + + +// CGlimWorkDlg 메시지 처리기 + +BOOL CGlimWorkDlg::OnInitDialog() +{ + CDialogEx::OnInitDialog(); + + // 시스템 메뉴에 "정보..." 메뉴 항목을 추가합니다. + + // IDM_ABOUTBOX는 시스템 명령 범위에 있어야 합니다. + ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); + ASSERT(IDM_ABOUTBOX < 0xF000); + + CMenu* pSysMenu = GetSystemMenu(FALSE); + if (pSysMenu != nullptr) + { + BOOL bNameValid; + CString strAboutMenu; + bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); + ASSERT(bNameValid); + if (!strAboutMenu.IsEmpty()) + { + pSysMenu->AppendMenu(MF_SEPARATOR); + pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); + } + } + + // 이 대화 상자의 아이콘을 설정합니다. 응용 프로그램의 주 창이 대화 상자가 아닐 경우에는 + // 프레임워크가 이 작업을 자동으로 수행합니다. + SetIcon(m_hIcon, TRUE); // 큰 아이콘을 설정합니다. + SetIcon(m_hIcon, FALSE); // 작은 아이콘을 설정합니다. + + // TODO: 여기에 추가 초기화 작업을 추가합니다. + + CRect rect; + GetDlgItem(IDC_STATIC)->GetWindowRect(&rect); + ScreenToClient(&rect); + + m_Image.Create(rect.Width(), rect.Height(), 8); + + static RGBQUAD rgb[256]; + for (int i = 0; i < 256; i++) + rgb[i].rgbRed = rgb[i].rgbGreen = rgb[i].rgbBlue = i; + m_Image.SetColorTable(0, 256, rgb); + + unsigned char* fm = (unsigned char*)m_Image.GetBits(); + + // '(전체 줄 - 1) * 한줄의 바이트수'를 빼서 시작 줄의 주소로 변경한다. + fm -= m_Image.GetWidth() * (m_Image.GetHeight() - 1) * (8 / 8); + + memset(fm, 0xFF, m_Image.GetWidth() * m_Image.GetHeight()); + + return TRUE; // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다. +} + +void CGlimWorkDlg::OnSysCommand(UINT nID, LPARAM lParam) +{ + if ((nID & 0xFFF0) == IDM_ABOUTBOX) + { + CAboutDlg dlgAbout; + dlgAbout.DoModal(); + } + else + { + CDialogEx::OnSysCommand(nID, lParam); + } +} + +// 대화 상자에 최소화 단추를 추가할 경우 아이콘을 그리려면 +// 아래 코드가 필요합니다. 문서/뷰 모델을 사용하는 MFC 애플리케이션의 경우에는 +// 프레임워크에서 이 작업을 자동으로 수행합니다. + +void CGlimWorkDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다. + + SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); + + // 클라이언트 사각형에서 아이콘을 가운데에 맞춥니다. + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // 아이콘을 그립니다. + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CRect rect; + GetDlgItem(IDC_STATIC)->GetWindowRect(&rect); + ScreenToClient(&rect); + + CClientDC DC(this); + m_Image.Draw(DC, rect); + + CDialogEx::OnPaint(); + } +} + +// 사용자가 최소화된 창을 끄는 동안에 커서가 표시되도록 시스템에서 +// 이 함수를 호출합니다. +HCURSOR CGlimWorkDlg::OnQueryDragIcon() +{ + return static_cast(m_hIcon); +} + +void CGlimWorkDlg::OnLButtonDown(UINT nFlags, CPoint point) +{ + // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다. + + // UI 반응 범주 + CRect rect; + GetDlgItem(IDC_STATIC)->GetWindowRect(&rect); + ScreenToClient(&rect); + + if (!rect.PtInRect(point)) + { + return; + } + + // 클릭 오브젝트 찾기 + for (int i = 0; i < CircleMaxCount; i++) + { + if (m_Circle[i]._Create && m_Circle[i].PtInRect(point)) + { + m_Circle[i]._Moving = true; + return; + } + } + + // 생성 + if (CircleMaxCount <= m_dCircleCnt) + { + return; + } + + m_Circle[m_dCircleCnt++].Create(rect, point); + + CirclePrc(); + + CDialogEx::OnLButtonDown(nFlags, point); +} + +// 오브젝트들에게 마우스 다운 노티 + +void CGlimWorkDlg::OnLButtonUp(UINT nFlags, CPoint point) +{ + // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다. + + // UI 반응 범주 + CRect rect; + GetDlgItem(IDC_STATIC)->GetWindowRect(&rect); + ScreenToClient(&rect); + + if (!rect.PtInRect(point)) + { + return; + } + + // 클릭 오브젝트 찾기 + for (int i = 0; i < CircleMaxCount; i++) + { + if (m_Circle[i]._Moving) + { + m_Circle[i]._Moving = false; + } + } + + CDialogEx::OnLButtonUp(nFlags, point); +} + +// 오브젝트들에게 마우스 업 노티 + +void CGlimWorkDlg::CirclePrc(void) +{ + // TODO: 여기에 구현 코드 추가. + + unsigned char* fm = (unsigned char*)m_Image.GetBits(); + + // '(전체 줄 - 1) * 한줄의 바이트수'를 빼서 시작 줄의 주소로 변경한다. + fm -= m_Image.GetWidth() * (m_Image.GetHeight() - 1) * (8 / 8); + memset(fm, 0xFF, m_Image.GetWidth() * m_Image.GetHeight()); + + for (int i = 0; i < m_dCircleCnt; i++) + { + if (m_Circle[i]._Create) + m_Circle[i]._Drwa((unsigned char *)m_Image.GetBits(), m_Image.GetPitch()); + } + + // 세점의 외접원 + if (CircleMaxCount <= m_dCircleCnt) + { + unsigned char* fm2 = (unsigned char*)m_Image.GetBits(); + + CPoint _Center = GetCenter(m_Circle[0]._ClickPoint, m_Circle[1]._ClickPoint, m_Circle[2]._ClickPoint); + + // 중심점에서 반지름 + int distance = sqrt(pow(_Center.x - m_Circle[0]._ClickPoint.x, 2) + pow(_Center.y - m_Circle[0]._ClickPoint.y, 2)); + + int nStartX = _Center.x - distance; + int nStartY = _Center.y - distance; + int nCenterX = _Center.x; + int nCenterY = _Center.y; + + for (int i = nStartX; i < nStartX + (distance * 2); i++) + { + for (int j = nStartY; j < nStartY + (distance * 2); j++) + { + // 픽셀단위로 원에 해당 여부를 판정 + if (isInCircle(i, j, nCenterX, nCenterY, distance)) + fm2[(j * m_Image.GetPitch()) + i] = 0x00; + } + } + } + + OnPaint(); +} + +bool CGlimWorkDlg::isInCircle(int i, int j, int nCenterX, int nCenterY, int nRadius) +{ + bool bRet = false; + + double dX = i - nCenterX; + double dY = j - nCenterY; + double dDist = dX * dX + dY * dY; + + if (dDist < nRadius * nRadius) { + bRet = true; + } + + return bRet; +} + +// 외접원 계산식 'https://m.blog.naver.com/hileejaeho/221751241141' +CPoint CGlimWorkDlg::GetCenter(CPoint pt1, CPoint pt2, CPoint pt3) +{ + double A = pt2.x - pt1.x; + double B = pt2.y - pt1.y; + double C = pt3.x - pt1.x; + double D = pt3.y - pt1.y; + double E = A * (pt1.x + pt2.x) + B * (pt1.y + pt2.y); + double F = C * (pt1.x + pt3.x) + D * (pt1.y + pt3.y); + double G = 2.0 * (A * (pt3.y - pt2.y) - B * (pt3.x - pt2.x)); + if (G == 0) + return pt1; + + CPoint ptCenter; + ptCenter.x = (D * E - B * F) / G; + ptCenter.y = (A * F - C * E) / G; + + return ptCenter; +} + +void CGlimWorkDlg::OnMouseMove(UINT nFlags, CPoint point) +{ + // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다. + + for (int i = 0; i < CircleMaxCount; i++) + { + if (m_Circle[i]._Moving) + { + m_Circle[i].Hold(point); + } + } + + CirclePrc(); + + CDialogEx::OnMouseMove(nFlags, point); +} diff --git a/GlimWork/GlimWorkDlg.h b/GlimWork/GlimWorkDlg.h new file mode 100644 index 0000000..04c2e31 --- /dev/null +++ b/GlimWork/GlimWorkDlg.h @@ -0,0 +1,165 @@ + +// GlimWorkDlg.h: 헤더 파일 +// + +#pragma once + + +// CGlimWorkDlg 대화 상자 +class CGlimWorkDlg : public CDialogEx +{ +// 생성입니다. +public: + CGlimWorkDlg(CWnd* pParent = nullptr); // 표준 생성자입니다. + +// 대화 상자 데이터입니다. +#ifdef AFX_DESIGN_TIME + enum { IDD = IDD_GLIMWORK_DIALOG }; +#endif + + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다. + + +// 구현입니다. +protected: + HICON m_hIcon; + + // 생성된 메시지 맵 함수 + virtual BOOL OnInitDialog(); + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); +private: + void CirclePrc(void); + bool isInCircle(int i, int j, int nCenterX, int nCenterY, int nRadius); + CPoint GetCenter(CPoint pt1, CPoint pt2, CPoint pt3); + int m_dCircleCnt; + CImage m_Image; + + static const int CircleMaxCount = 3; + + struct _Circle + { + CPoint _ClickPoint; + CRect _CirclePos; + int _nRadius; + bool _Moving; + bool _Create; + + // 계산하기 힘들고 일단 함수를 다 까먹어서 오프셋으로 한다. + int _Xoffset; + int _Yoffset; + + _Circle() + { + _nRadius = 20; + _Moving = false; + _Create = false; // 이게 뭐여 ㅋㅋㅋ + } + + void Create(CRect& rect/*offset*/, CPoint point) + { + _Xoffset = -rect.left; + _Yoffset = -rect.top; + + _Create = true; + + point.x += _Xoffset; + point.y += _Yoffset; + + _ClickPoint.x = point.x; + _ClickPoint.y = point.y; + + _CirclePos.left = point.x - _nRadius; + _CirclePos.right = _CirclePos.left + _nRadius; + _CirclePos.top = point.y - _nRadius; + _CirclePos.bottom = _CirclePos.top + _nRadius; + } + + void Hold(CPoint& point) + { + point.x += _Xoffset; + point.y += _Yoffset; + + _ClickPoint.x = point.x; + _ClickPoint.y = point.y; + + _CirclePos.left = point.x - _nRadius; + _CirclePos.right = _CirclePos.left + _nRadius; + _CirclePos.top = point.y - _nRadius; + _CirclePos.bottom = _CirclePos.top + _nRadius; + } + + bool PtInRect(CPoint point) + { + point.x += _Xoffset; + point.y += _Yoffset; + + CRect rect(_ClickPoint.x - _nRadius, _ClickPoint.y - _nRadius, _ClickPoint.x + _nRadius, _ClickPoint.y + _nRadius); + + return rect.PtInRect(point); + } + + void _Drwa(unsigned char *p, int nPitch) + { + int nStartX = _ClickPoint.x - _nRadius; + int nStartY = _ClickPoint.y - _nRadius; + int nCenterX = _ClickPoint.x; + int nCenterY = _ClickPoint.y; + + for (int i = nStartX; i < nStartX + (_nRadius * 2); i++) + { + for (int j = nStartY; j < nStartY + (_nRadius * 2); j++) + { + // 픽셀단위로 원에 해당 여부를 판정 + if (isInCircle(i, j, nCenterX, nCenterY, _nRadius)) + p[(j * nPitch) + i] = 0x00; + } + } + } + + bool isInCircle(int i, int j, int nCenterX, int nCenterY, int nRadius) + { + bool bRet = false; + + double dX = i - nCenterX; + double dY = j - nCenterY; + double dDist = dX * dX + dY * dY; + + if (dDist < nRadius * nRadius) { + bRet = true; + } + + return bRet; + } + }; + + // 리스트로 바꿔야 하는데 다 까먹었네, 비교 연산자 오버로딩 펑터 뭐더라;;; + _Circle m_Circle[CircleMaxCount]; + _Circle *ActiveCircle = NULL; +public: + afx_msg void OnMouseMove(UINT nFlags, CPoint point); +}; + +// ToDo +/* +-아래 그림의 순서대로 조작하여 요구사항들을 모두 만족하는 프로그램을 작성합니다. +- 세 번째 클릭 이후에 클릭 지점 3개를 모두 지나가는 정원 1개를 그립니다. +- 클릭 지점 원을 그릴 때의 반지름 크기는 사용자로부터 입력 받습니다. +- 각 클릭 지점 원의 중심 좌표를 UI에 표시합니다. +- 네 번째 클릭부터는 클릭 지점 원을 그리지 않습니다. +- 세 클릭 지점을 지나가는 정원의 내부는 채워지지 않아야 하며, 가장자리 두께는 사용자로부터 입력 받습니다. +- 클릭 지점 3개 중 하나를 클릭하고 드래그 했을 때 정원을 다시 그립니다. +- 이 때, 마우스 커서 좌표가 바뀌는 동안 즉, 마우스 드래그 상태가 끝날 때 까지 정원이 계속해서 이동하며 그려져야 합니다. +- [초기화] 버튼을 누르면 그려졌던 모든 내용들을 삭제하고 처음부터 입력 받을 수 있는 상태가 되어야 합니다. +- 정원이 그려진 상태에서[랜덤 이동] 버튼을 누르면 3개의 클릭 지점 원 모두를 랜덤한 위치로 이동시킵니다. +- 이 때, 정원 또한 마찬가지로 다시 그려져야 합니다. +- 랜덤한 위치로 이동 및 정원 그리기 동작을 초당 2회, 총 10번 자동으로 반복하되 메인UI가 프리징 상태가 되지 않도록 별도 쓰레드로 구현해야 합니다. +- MFC Dialog 기반 프로젝트로 작성해야 합니다. +- 클릭 지점 원과 정원을 그릴 때 CDC 클래스를 사용하면 안됩니다. (안내한 유튜브 영상 참고) +*/ \ No newline at end of file diff --git a/GlimWork/framework.h b/GlimWork/framework.h new file mode 100644 index 0000000..9fa85c6 --- /dev/null +++ b/GlimWork/framework.h @@ -0,0 +1,49 @@ +#pragma once + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // 거의 사용되지 않는 내용은 Windows 헤더에서 제외합니다. +#endif + +#include "targetver.h" + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 일부 CString 생성자는 명시적으로 선언됩니다. + +// MFC의 공통 부분과 무시 가능한 경고 메시지에 대한 숨기기를 해제합니다. +#define _AFX_ALL_WARNINGS + +#include // MFC 핵심 및 표준 구성 요소입니다. +#include // MFC 확장입니다. + + +#include // MFC 자동화 클래스입니다. + + + +#ifndef _AFX_NO_OLE_SUPPORT +#include // Internet Explorer 4 공용 컨트롤에 대한 MFC 지원입니다. +#endif +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // Windows 공용 컨트롤에 대한 MFC 지원입니다. +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include // MFC의 리본 및 컨트롤 막대 지원 + + + + + + + + + +#ifdef _UNICODE +#if defined _M_IX86 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_X64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#else +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif +#endif + + diff --git a/GlimWork/pch.cpp b/GlimWork/pch.cpp new file mode 100644 index 0000000..bd23a58 --- /dev/null +++ b/GlimWork/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: 미리 컴파일된 헤더에 해당하는 소스 파일 + +#include "pch.h" + +// 미리 컴파일된 헤더를 사용하는 경우 컴파일이 성공하려면 이 소스 파일이 필요합니다. diff --git a/GlimWork/pch.h b/GlimWork/pch.h new file mode 100644 index 0000000..d99e280 --- /dev/null +++ b/GlimWork/pch.h @@ -0,0 +1,13 @@ +// pch.h: 미리 컴파일된 헤더 파일입니다. +// 아래 나열된 파일은 한 번만 컴파일되었으며, 향후 빌드에 대한 빌드 성능을 향상합니다. +// 코드 컴파일 및 여러 코드 검색 기능을 포함하여 IntelliSense 성능에도 영향을 미칩니다. +// 그러나 여기에 나열된 파일은 빌드 간 업데이트되는 경우 모두 다시 컴파일됩니다. +// 여기에 자주 업데이트할 파일을 추가하지 마세요. 그러면 성능이 저하됩니다. + +#ifndef PCH_H +#define PCH_H + +// 여기에 미리 컴파일하려는 헤더 추가 +#include "framework.h" + +#endif //PCH_H diff --git a/GlimWork/res/GlimWork.ico b/GlimWork/res/GlimWork.ico new file mode 100644 index 0000000..d56fbcd Binary files /dev/null and b/GlimWork/res/GlimWork.ico differ diff --git a/GlimWork/res/GlimWork.rc2 b/GlimWork/res/GlimWork.rc2 new file mode 100644 index 0000000..790386e Binary files /dev/null and b/GlimWork/res/GlimWork.rc2 differ diff --git a/GlimWork/resource.h b/GlimWork/resource.h new file mode 100644 index 0000000..53a9b75 --- /dev/null +++ b/GlimWork/resource.h @@ -0,0 +1,20 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++에서 생성한 포함 파일입니다. +// GlimWork.rc에서 사용되고 있습니다. +// +#define IDM_ABOUTBOX 0x0010 +#define IDD_ABOUTBOX 100 +#define IDS_ABOUTBOX 101 +#define IDD_GLIMWORK_DIALOG 102 +#define IDR_MAINFRAME 128 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/GlimWork/targetver.h b/GlimWork/targetver.h new file mode 100644 index 0000000..331a6e2 --- /dev/null +++ b/GlimWork/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// SDKDDKVer.h를 포함하면 최고 수준의 가용성을 가진 Windows 플랫폼이 정의됩니다. + +// 이전 Windows 플랫폼에 대해 애플리케이션을 빌드하려는 경우에는 SDKDDKVer.h를 포함하기 전에 +// WinSDKVer.h를 포함하고 _WIN32_WINNT 매크로를 지원하려는 플랫폼으로 설정하십시오. + +#include