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