Val_Kir

Лекция 4

Apr 21st, 2021
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.70 KB | None | 0 0
  1. Lec4Pg6
  2. basewin.h
  3. #pragma once
  4. template <class DERIVED_TYPE>
  5. class BaseWindow
  6. {
  7. public:
  8. static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  9. {
  10. DERIVED_TYPE *pThis = NULL;
  11. if (uMsg == WM_NCCREATE)
  12. {
  13. CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
  14. pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
  15. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
  16. pThis->m_hwnd = hwnd;
  17. }
  18. else
  19. {
  20. pThis = (DERIVED_TYPE*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  21. }
  22. if (pThis)
  23. {
  24. return pThis->HandleMessage(uMsg, wParam, lParam);
  25. }
  26. else
  27. {
  28. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  29. }
  30. }
  31. BaseWindow() : m_hwnd(NULL) { }
  32. BOOL Create(
  33. PCWSTR lpWindowName,
  34. DWORD dwStyle,
  35. DWORD dwExStyle = 0,
  36. int x = CW_USEDEFAULT,
  37. int y = CW_USEDEFAULT,
  38. int nWidth = CW_USEDEFAULT,
  39. int nHeight = CW_USEDEFAULT,
  40. HWND hWndParent = 0,
  41. HMENU hMenu = 0
  42. )
  43. {
  44. WNDCLASS wc = { 0 };
  45. wc.lpfnWndProc = DERIVED_TYPE::WindowProc;
  46. wc.hInstance = GetModuleHandle(NULL);
  47. wc.lpszClassName = ClassName();
  48. RegisterClass(&wc);
  49. m_hwnd = CreateWindowEx(
  50. dwExStyle, ClassName(), lpWindowName, dwStyle, x, y,
  51. nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this
  52. );
  53. return (m_hwnd ? TRUE : FALSE);
  54. }
  55. HWND Window() const { return m_hwnd; }
  56. protected:
  57. virtual PCWSTR ClassName() const = 0;
  58. HWND m_hwnd;
  59. };
  60. Source.cpp
  61. #include <windows.h>
  62. #include <windowsx.h>
  63. #include <d2d1.h>
  64. #pragma comment(lib, "d2d1")
  65. #include "basewin.h"
  66. template <class T> void SafeRelease(T **ppT)
  67. {
  68. if (*ppT)
  69. {
  70. (*ppT)->Release();
  71. *ppT = NULL;
  72. }
  73. }
  74. class DPIScale
  75. {
  76. static float scaleX;
  77. static float scaleY;
  78. public:
  79. static void Initialize(ID2D1Factory *pFactory)
  80. {
  81. FLOAT dpiX, dpiY;
  82. pFactory->GetDesktopDpi(&dpiX, &dpiY);
  83. scaleX = dpiX / 96.0f;
  84. scaleY = dpiY / 96.0f;
  85. }
  86. template <typename T>
  87. static D2D1_POINT_2F PixelsToDips(T x, T y)
  88. {
  89. return D2D1::Point2F(static_cast<float>(x) / scaleX, static_cast<float>(y) / scaleY);
  90. }
  91. };
  92. float DPIScale::scaleX = 1.0f;
  93. float DPIScale::scaleY = 1.0f;
  94. class MainWindow : public BaseWindow<MainWindow>
  95. {
  96. ID2D1Factory *pFactory;
  97. ID2D1HwndRenderTarget *pRenderTarget;
  98. ID2D1SolidColorBrush *pBrush;
  99. D2D1_ELLIPSE ellipse;
  100. D2D1_POINT_2F ptMouse;
  101. void CalculateLayout() { }
  102. HRESULT CreateGraphicsResources();
  103. void DiscardGraphicsResources();
  104. void OnPaint();
  105. void Resize();
  106. public:
  107. MainWindow() : pFactory(NULL), pRenderTarget(NULL),
  108. ellipse(D2D1::Ellipse(D2D1::Point2F(), 0, 0)),
  109. ptMouse(D2D1::Point2F())
  110. {
  111. }
  112. PCWSTR ClassName() const { return L"Ellipse Window Class"; }
  113. LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
  114. void OnLButtonDown(int pixelX, int pixelY, DWORD flags);
  115. void OnLButtonUp();
  116. void OnMouseMove(int pixelX, int pixelY, DWORD flags);
  117. };
  118. HRESULT MainWindow::CreateGraphicsResources()
  119. {
  120. HRESULT hr = S_OK;
  121. if (pRenderTarget == NULL)
  122. {
  123. RECT rc;
  124. GetClientRect(m_hwnd, &rc);
  125. D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
  126. hr = pFactory->CreateHwndRenderTarget(
  127. D2D1::RenderTargetProperties(),
  128. D2D1::HwndRenderTargetProperties(m_hwnd, size),
  129. &pRenderTarget);
  130. if (SUCCEEDED(hr))
  131. {
  132. const D2D1_COLOR_F color = D2D1::ColorF(1.0f, 1.0f, 0);
  133. hr = pRenderTarget->CreateSolidColorBrush(color, &pBrush);
  134. if (SUCCEEDED(hr))
  135. {
  136. CalculateLayout();
  137. }
  138. }
  139. }
  140. return hr;
  141. }
  142. void MainWindow::DiscardGraphicsResources()
  143. {
  144. SafeRelease(&pRenderTarget);
  145. SafeRelease(&pBrush);
  146. }
  147. void MainWindow::OnPaint()
  148. {
  149. HRESULT hr = CreateGraphicsResources();
  150. if (SUCCEEDED(hr))
  151. {
  152. PAINTSTRUCT ps;
  153. BeginPaint(m_hwnd, &ps);
  154. pRenderTarget->BeginDraw();
  155. pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::SkyBlue));
  156. pRenderTarget->FillEllipse(ellipse, pBrush);
  157. hr = pRenderTarget->EndDraw();
  158. if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET)
  159. {
  160. DiscardGraphicsResources();
  161. }
  162. EndPaint(m_hwnd, &ps);
  163. }
  164. }
  165. void MainWindow::Resize()
  166. {
  167. if (pRenderTarget != NULL)
  168. {
  169. RECT rc;
  170. GetClientRect(m_hwnd, &rc);
  171. D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
  172. pRenderTarget->Resize(size);
  173. CalculateLayout();
  174. InvalidateRect(m_hwnd, NULL, FALSE);
  175. }
  176. }
  177. void MainWindow::OnLButtonDown(int pixelX, int pixelY, DWORD flags)
  178. {
  179. SetCapture(m_hwnd);
  180. ellipse.point = ptMouse = DPIScale::PixelsToDips(pixelX, pixelY);
  181. ellipse.radiusX = ellipse.radiusY = 1.0f;
  182. InvalidateRect(m_hwnd, NULL, FALSE);
  183. }
  184. void MainWindow::OnMouseMove(int pixelX, int pixelY, DWORD flags)
  185. {
  186. if (flags & MK_LBUTTON)
  187. {
  188. const D2D1_POINT_2F dips = DPIScale::PixelsToDips(pixelX, pixelY);
  189. const float width = (dips.x - ptMouse.x) / 2;
  190. const float height = (dips.y - ptMouse.y) / 2;
  191. const float x1 = ptMouse.x + width;
  192. const float y1 = ptMouse.y + height;
  193. ellipse = D2D1::Ellipse(D2D1::Point2F(x1, y1), width, height);
  194. InvalidateRect(m_hwnd, NULL, FALSE);
  195. }
  196. }
  197. void MainWindow::OnLButtonUp()
  198. {
  199. ReleaseCapture();
  200. }
  201. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow)
  202. {
  203. MainWindow win;
  204. if (!win.Create(L"Ellipse", WS_OVERLAPPEDWINDOW))
  205. {
  206. return 0;
  207. }
  208. ShowWindow(win.Window(), nCmdShow);
  209. // Цикл обработки сообщений.
  210. MSG msg = {};
  211. while (GetMessage(&msg, NULL, 0, 0))
  212. {
  213. TranslateMessage(&msg);
  214. DispatchMessage(&msg);
  215. }
  216. return 0;
  217. }
  218. LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  219. {
  220. switch (uMsg)
  221. {
  222. case WM_CREATE:
  223. if (FAILED(D2D1CreateFactory(
  224. D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory)))
  225. {
  226. return -1; // Неудача CreateWindowEx.
  227. }
  228. DPIScale::Initialize(pFactory);
  229. return 0;
  230. case WM_DESTROY:
  231. DiscardGraphicsResources();
  232. SafeRelease(&pFactory);
  233. PostQuitMessage(0);
  234. return 0;
  235. case WM_PAINT:
  236. OnPaint();
  237. return 0;
  238. case WM_SIZE:
  239. Resize();
  240. return 0;
  241. case WM_LBUTTONDOWN:
  242. OnLButtonDown(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), (DWORD)wParam);
  243. return 0;
  244. case WM_LBUTTONUP:
  245. OnLButtonUp();
  246. return 0;
  247. case WM_MOUSEMOVE:
  248. OnMouseMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), (DWORD)wParam);
  249. return 0;
  250. }
  251. return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
  252. }
  253. Lec4Pg16
  254. basewin.h
  255. #pragma once
  256. template <class DERIVED_TYPE>
  257. class BaseWindow
  258. {
  259. public:
  260. static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  261. {
  262. DERIVED_TYPE *pThis = NULL;
  263. if (uMsg == WM_NCCREATE)
  264. {
  265. CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
  266. pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
  267. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
  268. pThis->m_hwnd = hwnd;
  269. }
  270. else
  271. {
  272. pThis = (DERIVED_TYPE*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  273. }
  274. if (pThis)
  275. {
  276. return pThis->HandleMessage(uMsg, wParam, lParam);
  277. }
  278. else
  279. {
  280. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  281. }
  282. }
  283. BaseWindow() : m_hwnd(NULL) { }
  284. BOOL Create(
  285. PCWSTR lpWindowName,
  286. DWORD dwStyle,
  287. DWORD dwExStyle = 0,
  288. int x = CW_USEDEFAULT,
  289. int y = CW_USEDEFAULT,
  290. int nWidth = CW_USEDEFAULT,
  291. int nHeight = CW_USEDEFAULT,
  292. HWND hWndParent = 0,
  293. HMENU hMenu = 0
  294. )
  295. {
  296. WNDCLASS wc = { 0 };
  297. wc.lpfnWndProc = DERIVED_TYPE::WindowProc;
  298. wc.hInstance = GetModuleHandle(NULL);
  299. wc.lpszClassName = ClassName();
  300. RegisterClass(&wc);
  301. m_hwnd = CreateWindowEx(
  302. dwExStyle, ClassName(), lpWindowName, dwStyle, x, y,
  303. nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this
  304. );
  305. return (m_hwnd ? TRUE : FALSE);
  306. }
  307. HWND Window() const { return m_hwnd; }
  308. protected:
  309. virtual PCWSTR ClassName() const = 0;
  310. HWND m_hwnd;
  311. };
  312. Source.cpp
  313. #include <windows.h>
  314. #include <tchar.h>
  315. #include "basewin.h"
  316. class MainWindow : public BaseWindow<MainWindow>
  317. {
  318. public:
  319. PCWSTR ClassName() const { return L"WMKeyChar Window Class"; }
  320. LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
  321. };
  322. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow)
  323. {
  324. MainWindow win;
  325. if (!win.Create(L"WMKeyChar", WS_OVERLAPPEDWINDOW))
  326. {
  327. return 0;
  328. }
  329. ShowWindow(win.Window(), nCmdShow);
  330. // Цикл обработки сообщений.
  331. MSG msg = {};
  332. while (GetMessage(&msg, NULL, 0, 0))
  333. {
  334. TranslateMessage(&msg);
  335. DispatchMessage(&msg);
  336. }
  337. return 0;
  338. }
  339. LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  340. {
  341. wchar_t msg[32];
  342. switch (uMsg)
  343. {
  344. case WM_SYSKEYDOWN:
  345. swprintf_s(msg, L"WM_SYSKEYDOWN: 0x%x\n", wParam);
  346. OutputDebugString(msg);
  347. break;
  348. case WM_SYSCHAR:
  349. swprintf_s(msg, L"WM_SYSCHAR: %c\n", (wchar_t)wParam);
  350. OutputDebugString(msg);
  351. break;
  352. case WM_SYSKEYUP:
  353. swprintf_s(msg, L"WM_SYSKEYUP: 0x%x\n", wParam);
  354. OutputDebugString(msg);
  355. break;
  356. case WM_KEYDOWN:
  357. swprintf_s(msg, L"WM_KEYDOWN: 0x%x\n", wParam);
  358. OutputDebugString(msg);
  359. break;
  360. case WM_KEYUP:
  361. swprintf_s(msg, L"WM_KEYUP: 0x%x\n", wParam);
  362. OutputDebugString(msg);
  363. break;
  364. case WM_CHAR:
  365. swprintf_s(msg, L"WM_CHAR: %c\n", (wchar_t)wParam);
  366. OutputDebugString(msg);
  367. break;
  368. case WM_PAINT:
  369. {
  370. PAINTSTRUCT ps;
  371. HDC hdc = BeginPaint(m_hwnd, &ps);
  372. // TODO: Add any drawing code that uses hdc here...
  373. EndPaint(m_hwnd, &ps);
  374. }
  375. return 0;
  376. case WM_DESTROY:
  377. PostQuitMessage(0);
  378. return 0;
  379. }
  380. return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
  381. }
  382. Lec4Pg23
  383. basewin.h
  384. #pragma once
  385. template <class DERIVED_TYPE>
  386. class BaseWindow
  387. {
  388. public:
  389. static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  390. {
  391. DERIVED_TYPE *pThis = NULL;
  392. if (uMsg == WM_NCCREATE)
  393. {
  394. CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
  395. pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
  396. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
  397. pThis->m_hwnd = hwnd;
  398. }
  399. else
  400. {
  401. pThis = (DERIVED_TYPE*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  402. }
  403. if (pThis)
  404. {
  405. return pThis->HandleMessage(uMsg, wParam, lParam);
  406. }
  407. else
  408. {
  409. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  410. }
  411. }
  412. BaseWindow() : m_hwnd(NULL) { }
  413. BOOL Create(
  414. PCWSTR lpWindowName,
  415. DWORD dwStyle,
  416. DWORD dwExStyle = 0,
  417. int x = CW_USEDEFAULT,
  418. int y = CW_USEDEFAULT,
  419. int nWidth = CW_USEDEFAULT,
  420. int nHeight = CW_USEDEFAULT,
  421. HWND hWndParent = 0,
  422. HMENU hMenu = 0
  423. )
  424. {
  425. WNDCLASS wc = { 0 };
  426. wc.lpfnWndProc = DERIVED_TYPE::WindowProc;
  427. wc.hInstance = GetModuleHandle(NULL);
  428. wc.lpszClassName = ClassName();
  429. //wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  430. RegisterClass(&wc);
  431. m_hwnd = CreateWindowEx(
  432. dwExStyle, ClassName(), lpWindowName, dwStyle, x, y,
  433. nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this
  434. );
  435. return (m_hwnd ? TRUE : FALSE);
  436. }
  437. HWND Window() const { return m_hwnd; }
  438. protected:
  439. virtual PCWSTR ClassName() const = 0;
  440. HWND m_hwnd;
  441. };
  442. resource.h
  443. //{{NO_DEPENDENCIES}}
  444. // Включаемый файл, созданный в Microsoft Visual C++.
  445. // Используется Lec4Pg23.rc
  446. //
  447. #define IDR_ACCEL1 101
  448. #define ID_TOGGLE_MODE 40001
  449. #define ID_DRAW_MODE 40002
  450. #define ID_SELECT_MODE 40003
  451. #define ID_DELETE 40005
  452. // Next default values for new objects
  453. //
  454. #ifdef APSTUDIO_INVOKED
  455. #ifndef APSTUDIO_READONLY_SYMBOLS
  456. #define _APS_NEXT_RESOURCE_VALUE 102
  457. #define _APS_NEXT_COMMAND_VALUE 40007
  458. #define _APS_NEXT_CONTROL_VALUE 1001
  459. #define _APS_NEXT_SYMED_VALUE 101
  460. #endif
  461. #endif
  462. Source.cpp
  463. #include <windows.h>
  464. #include <windowsx.h>
  465. #include <d2d1.h>
  466. #include <list>
  467. #include <memory>
  468. #include "resource.h"
  469. #pragma comment(lib, "d2d1")
  470. #include "basewin.h"
  471. using namespace std;
  472. template <class T> void SafeRelease(T **ppT)
  473. {
  474. if (*ppT)
  475. {
  476. (*ppT)->Release();
  477. *ppT = NULL;
  478. }
  479. }
  480. class DPIScale
  481. {
  482. static float scaleX;
  483. static float scaleY;
  484. public:
  485. static void Initialize(ID2D1Factory *pFactory)
  486. {
  487. FLOAT dpiX, dpiY;
  488. pFactory->GetDesktopDpi(&dpiX, &dpiY);
  489. scaleX = dpiX / 96.0f;
  490. scaleY = dpiY / 96.0f;
  491. }
  492. template <typename T>
  493. static float PixelsToDipsX(T x)
  494. {
  495. return static_cast<float>(x) / scaleX;
  496. }
  497. template <typename T>
  498. static float PixelsToDipsY(T y)
  499. {
  500. return static_cast<float>(y) / scaleY;
  501. }
  502. template <typename T>
  503. static D2D1_POINT_2F PixelsToDips(T x, T y)
  504. {
  505. return D2D1::Point2F(static_cast<float>(x) / scaleX, static_cast<float>(y) / scaleY);
  506. }
  507. };
  508. float DPIScale::scaleX = 1.0f;
  509. float DPIScale::scaleY = 1.0f;
  510. struct MyEllipse
  511. {
  512. D2D1_ELLIPSE ellipse;
  513. D2D1_COLOR_F color;
  514. void Draw(ID2D1RenderTarget *pRT, ID2D1SolidColorBrush *pBrush, BOOL isSelect)
  515. {
  516. pBrush->SetColor(color);
  517. pRT->FillEllipse(ellipse, pBrush);
  518. pBrush->SetColor(isSelect ? D2D1::ColorF(D2D1::ColorF::White) :
  519. D2D1::ColorF(D2D1::ColorF::Black));
  520. pRT->DrawEllipse(ellipse, pBrush, 1.0f);
  521. }
  522. BOOL HitTest(float x, float y)
  523. {
  524. const float a = ellipse.radiusX;
  525. const float b = ellipse.radiusY;
  526. const float x1 = x - ellipse.point.x;
  527. const float y1 = y - ellipse.point.y;
  528. const float d = ((x1 * x1) / (a * a)) + ((y1 * y1) / (b * b));
  529. return d <= 1.0f;
  530. }
  531. };
  532. class MainWindow : public BaseWindow<MainWindow>
  533. {
  534. ID2D1Factory *pFactory;
  535. ID2D1HwndRenderTarget *pRenderTarget;
  536. ID2D1SolidColorBrush *pBrush;
  537. D2D1_ELLIPSE ellipse;
  538. D2D1_POINT_2F ptMouse;
  539. HCURSOR hCursor;
  540. list<shared_ptr<MyEllipse>> ellipses;
  541. list<shared_ptr<MyEllipse>>::iterator selection;
  542. enum Mode { DrawMode, SelectMode, DragMode } mode;
  543. int numColor;
  544. static D2D1::ColorF colors[7];
  545. void CalculateLayout() { }
  546. HRESULT CreateGraphicsResources();
  547. void DiscardGraphicsResources();
  548. void Resize();
  549. shared_ptr<MyEllipse> Selection()
  550. {
  551. if (selection == ellipses.end())
  552. {
  553. return nullptr;
  554. }
  555. else
  556. {
  557. return (*selection);
  558. }
  559. }
  560. void ClearSelection() { selection = ellipses.end(); }
  561. void SetMode(Mode m)
  562. {
  563. mode = m;
  564. // Update the cursor
  565. LPWSTR cursor = IDC_ARROW;
  566. switch (mode)
  567. {
  568. case DrawMode:
  569. cursor = IDC_CROSS;
  570. break;
  571. case SelectMode:
  572. cursor = IDC_HAND;
  573. break;
  574. case DragMode:
  575. cursor = IDC_SIZEALL;
  576. break;
  577. }
  578. hCursor = LoadCursor(NULL, cursor);
  579. SetCursor(hCursor);
  580. }
  581. void InsertEllipse(float x, float y);
  582. void DeleteEllipse();
  583. BOOL HitTest(float x, float y);
  584. void OnPaintScene();
  585. public:
  586. MainWindow() : pFactory(NULL), pRenderTarget(NULL),
  587. ptMouse(D2D1::Point2F()),
  588. numColor(0)
  589. {
  590. ClearSelection();
  591. SetMode(DrawMode);
  592. }
  593. PCWSTR ClassName() const { return L"Ellipses Window Class"; }
  594. LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
  595. void OnLButtonDown(int pixelX, int pixelY, DWORD flags);
  596. void OnLButtonUp();
  597. void OnMouseMove(int pixelX, int pixelY, DWORD flags);
  598. void OnPaint();
  599. };
  600. D2D1::ColorF MainWindow::colors[7] = { D2D1::ColorF::Red,D2D1::ColorF::Orange,D2D1::ColorF::Yellow,
  601. D2D1::ColorF::Green,D2D1::ColorF::Cyan,D2D1::ColorF::Blue,D2D1::ColorF::Violet };
  602. void MainWindow::InsertEllipse(float x, float y)
  603. {
  604. shared_ptr<MyEllipse> pme(new MyEllipse);
  605. D2D1_POINT_2F pt = { x,y };
  606. pme->ellipse.point = ptMouse = pt;
  607. pme->ellipse.radiusX = pme->ellipse.radiusY = 1.0f;
  608. pme->color = colors[numColor++]; numColor %= 7;
  609. ellipses.push_front(pme);
  610. selection = ellipses.begin();
  611. }
  612. void MainWindow::DeleteEllipse()
  613. {
  614. ellipses.erase(selection);
  615. ClearSelection();
  616. }
  617. BOOL MainWindow::HitTest(float x, float y)
  618. {
  619. list<shared_ptr<MyEllipse>>::iterator iter;
  620. for (iter = ellipses.begin(); iter != ellipses.end(); iter++)
  621. if ((*iter)->HitTest(x, y)) { selection = iter; return TRUE; }
  622. return 0;
  623. }
  624. HRESULT MainWindow::CreateGraphicsResources()
  625. {
  626. HRESULT hr = S_OK;
  627. if (pRenderTarget == NULL)
  628. {
  629. RECT rc;
  630. GetClientRect(m_hwnd, &rc);
  631. D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
  632. hr = pFactory->CreateHwndRenderTarget(
  633. D2D1::RenderTargetProperties(),
  634. D2D1::HwndRenderTargetProperties(m_hwnd, size),
  635. &pRenderTarget);
  636. if (SUCCEEDED(hr))
  637. {
  638. const D2D1_COLOR_F color = D2D1::ColorF(1.0f, 1.0f, 0);
  639. hr = pRenderTarget->CreateSolidColorBrush(color, &pBrush);
  640. if (SUCCEEDED(hr))
  641. {
  642. CalculateLayout();
  643. }
  644. }
  645. }
  646. return hr;
  647. }
  648. void MainWindow::DiscardGraphicsResources()
  649. {
  650. SafeRelease(&pRenderTarget);
  651. SafeRelease(&pBrush);
  652. }
  653. void MainWindow::OnPaintScene()
  654. {
  655. list<shared_ptr<MyEllipse>>::reverse_iterator riter;
  656. for (riter = ellipses.rbegin(); riter != ellipses.rend(); riter++)
  657. (*riter)->Draw(pRenderTarget, pBrush, (Selection() && (*riter == *selection)));
  658. }
  659. void MainWindow::OnLButtonDown(int pixelX, int pixelY, DWORD flags)
  660. {
  661. const float dipX = DPIScale::PixelsToDipsX(pixelX);
  662. const float dipY = DPIScale::PixelsToDipsY(pixelY);
  663. if (mode == DrawMode)
  664. {
  665. POINT pt = { pixelX, pixelY };
  666. if (DragDetect(m_hwnd, pt))
  667. {
  668. SetCapture(m_hwnd);
  669. // Start a new ellipse.
  670. InsertEllipse(dipX, dipY);
  671. }
  672. }
  673. else
  674. {
  675. ClearSelection();
  676. if (HitTest(dipX, dipY))
  677. {
  678. SetCapture(m_hwnd);
  679. ptMouse = Selection()->ellipse.point;
  680. ptMouse.x -= dipX;
  681. ptMouse.y -= dipY;
  682. SetMode(DragMode);
  683. }
  684. }
  685. InvalidateRect(m_hwnd, NULL, FALSE);
  686. }
  687. void MainWindow::OnMouseMove(int pixelX, int pixelY, DWORD flags)
  688. {
  689. const float dipX = DPIScale::PixelsToDipsX(pixelX);
  690. const float dipY = DPIScale::PixelsToDipsY(pixelY);
  691. if ((flags & MK_LBUTTON) && Selection())
  692. {
  693. if (mode == DrawMode)
  694. {
  695. // Resize the ellipse.
  696. const float width = (dipX - ptMouse.x) / 2;
  697. const float height = (dipY - ptMouse.y) / 2;
  698. const float x1 = ptMouse.x + width;
  699. const float y1 = ptMouse.y + height;
  700. Selection()->ellipse = D2D1::Ellipse(D2D1::Point2F(x1, y1), width, height);
  701. }
  702. else if (mode == DragMode)
  703. {
  704. // Move the ellipse.
  705. Selection()->ellipse.point.x = dipX + ptMouse.x;
  706. Selection()->ellipse.point.y = dipY + ptMouse.y;
  707. }
  708. InvalidateRect(m_hwnd, NULL, FALSE);
  709. }
  710. }
  711. void MainWindow::OnLButtonUp()
  712. {
  713. if ((mode == DrawMode) && Selection())
  714. {
  715. ClearSelection();
  716. InvalidateRect(m_hwnd, NULL, FALSE);
  717. }
  718. else if (mode == DragMode)
  719. {
  720. SetMode(SelectMode);
  721. }
  722. ReleaseCapture();
  723. }
  724. void MainWindow::OnPaint()
  725. {
  726. HRESULT hr = CreateGraphicsResources();
  727. if (SUCCEEDED(hr))
  728. {
  729. PAINTSTRUCT ps;
  730. BeginPaint(m_hwnd, &ps);
  731. pRenderTarget->BeginDraw();
  732. pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::SkyBlue));
  733. OnPaintScene();
  734. hr = pRenderTarget->EndDraw();
  735. if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET)
  736. {
  737. DiscardGraphicsResources();
  738. }
  739. EndPaint(m_hwnd, &ps);
  740. }
  741. }
  742. void MainWindow::Resize()
  743. {
  744. if (pRenderTarget != NULL)
  745. {
  746. RECT rc;
  747. GetClientRect(m_hwnd, &rc);
  748. D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
  749. pRenderTarget->Resize(size);
  750. CalculateLayout();
  751. InvalidateRect(m_hwnd, NULL, FALSE);
  752. }
  753. }
  754. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow)
  755. {
  756. MainWindow win;
  757. HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCEL1));
  758. if (!win.Create(L"Ellipses", WS_OVERLAPPEDWINDOW))
  759. {
  760. return 0;
  761. }
  762. ShowWindow(win.Window(), nCmdShow);
  763. // Цикл обработки сообщений.
  764. MSG msg = {};
  765. while (GetMessage(&msg, NULL, 0, 0))
  766. {
  767. if (!TranslateAccelerator(win.Window(), hAccel, &msg))
  768. {
  769. TranslateMessage(&msg);
  770. DispatchMessage(&msg);
  771. }
  772. }
  773. return 0;
  774. }
  775. LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  776. {
  777. switch (uMsg)
  778. {
  779. case WM_CREATE:
  780. if (FAILED(D2D1CreateFactory(
  781. D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory)))
  782. {
  783. return -1; // Неудача CreateWindowEx.
  784. }
  785. DPIScale::Initialize(pFactory);
  786. return 0;
  787. case WM_DESTROY:
  788. DiscardGraphicsResources();
  789. SafeRelease(&pFactory);
  790. PostQuitMessage(0);
  791. return 0;
  792. case WM_PAINT:
  793. OnPaint();
  794. return 0;
  795. case WM_SIZE:
  796. Resize();
  797. return 0;
  798. case WM_LBUTTONDOWN:
  799. OnLButtonDown(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), (DWORD)wParam);
  800. return 0;
  801. case WM_LBUTTONUP:
  802. OnLButtonUp();
  803. return 0;
  804. case WM_MOUSEMOVE:
  805. OnMouseMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), (DWORD)wParam);
  806. return 0;
  807. case WM_COMMAND:
  808. switch (LOWORD(wParam))
  809. {
  810. case ID_DRAW_MODE:
  811. SetMode(DrawMode);
  812. break;
  813. case ID_SELECT_MODE:
  814. SetMode(SelectMode);
  815. break;
  816. case ID_TOGGLE_MODE:
  817. if (mode == DrawMode)
  818. {
  819. SetMode(SelectMode);
  820. }
  821. else
  822. {
  823. SetMode(DrawMode);
  824. }
  825. break;
  826. case ID_DELETE:
  827. if (Selection())
  828. {
  829. DeleteEllipse();
  830. InvalidateRect(m_hwnd, NULL, FALSE);
  831. }
  832. break;
  833. }
  834. return 0;
  835. case WM_SETCURSOR:
  836. if (LOWORD(lParam) == HTCLIENT)
  837. {
  838. SetCursor(hCursor);
  839. return TRUE;
  840. }
  841. return 0;
  842. }
  843. return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
  844. }
Advertisement
Add Comment
Please, Sign In to add comment