Advertisement
Val_Kir

Лекция 3

Apr 21st, 2021
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.08 KB | None | 0 0
  1. Lec3Pg6
  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 <d2d1.h>
  63. #pragma comment(lib, "d2d1")
  64. #include "basewin.h"
  65. template <class T> void SafeRelease(T **ppT)
  66. {
  67. if (*ppT)
  68. {
  69. (*ppT)->Release();
  70. *ppT = NULL;
  71. }
  72. }
  73. class MainWindow : public BaseWindow<MainWindow>
  74. {
  75. ID2D1Factory *pFactory;
  76. ID2D1HwndRenderTarget *pRenderTarget;
  77. ID2D1SolidColorBrush *pBrush;
  78. D2D1_ELLIPSE ellipse;
  79. void CalculateLayout();
  80. HRESULT CreateGraphicsResources();
  81. void DiscardGraphicsResources();
  82. void OnPaint();
  83. void Resize();
  84. public:
  85. MainWindow() : pFactory(NULL), pRenderTarget(NULL), pBrush(NULL)
  86. {
  87. }
  88. PCWSTR ClassName() const { return L"Circle Window Class"; }
  89. LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
  90. };
  91. // Пересчет изображения при изменении размера окна.
  92. void MainWindow::CalculateLayout()
  93. {
  94. if (pRenderTarget != NULL)
  95. {
  96. D2D1_SIZE_F size = pRenderTarget->GetSize();
  97. const float x = size.width / 2;
  98. const float y = size.height / 2;
  99. const float radius = min(x, y);
  100. ellipse = D2D1::Ellipse(D2D1::Point2F(x, y), radius, radius);
  101. }
  102. }
  103. HRESULT MainWindow::CreateGraphicsResources()
  104. {
  105. HRESULT hr = S_OK;
  106. if (pRenderTarget == NULL)
  107. {
  108. RECT rc;
  109. GetClientRect(m_hwnd, &rc);
  110. D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
  111. hr = pFactory->CreateHwndRenderTarget(
  112. D2D1::RenderTargetProperties(),
  113. D2D1::HwndRenderTargetProperties(m_hwnd, size),
  114. &pRenderTarget);
  115. if (SUCCEEDED(hr))
  116. {
  117. const D2D1_COLOR_F color = D2D1::ColorF(1.0f, 1.0f, 0);
  118. hr = pRenderTarget->CreateSolidColorBrush(color, &pBrush);
  119. if (SUCCEEDED(hr))
  120. {
  121. CalculateLayout();
  122. }
  123. }
  124. }
  125. return hr;
  126. }
  127. void MainWindow::DiscardGraphicsResources()
  128. {
  129. SafeRelease(&pRenderTarget);
  130. SafeRelease(&pBrush);
  131. }
  132. void MainWindow::OnPaint()
  133. {
  134. HRESULT hr = CreateGraphicsResources();
  135. if (SUCCEEDED(hr))
  136. {
  137. PAINTSTRUCT ps;
  138. BeginPaint(m_hwnd, &ps);
  139. pRenderTarget->BeginDraw();
  140. pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::SkyBlue));
  141. pRenderTarget->FillEllipse(ellipse, pBrush);
  142. hr = pRenderTarget->EndDraw();
  143. if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET)
  144. {
  145. DiscardGraphicsResources();
  146. }
  147. EndPaint(m_hwnd, &ps);
  148. }
  149. }
  150. void MainWindow::Resize()
  151. {
  152. if (pRenderTarget != NULL)
  153. {
  154. RECT rc;
  155. GetClientRect(m_hwnd, &rc);
  156. D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
  157. pRenderTarget->Resize(size);
  158. CalculateLayout();
  159. InvalidateRect(m_hwnd, NULL, FALSE);
  160. }
  161. }
  162. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow)
  163. {
  164. MainWindow win;
  165. if (!win.Create(L"Circle", WS_OVERLAPPEDWINDOW))
  166. {
  167. return 0;
  168. }
  169. ShowWindow(win.Window(), nCmdShow);
  170. // Цикл обработки сообщений.
  171. MSG msg = {};
  172. while (GetMessage(&msg, NULL, 0, 0))
  173. {
  174. TranslateMessage(&msg);
  175. DispatchMessage(&msg);
  176. }
  177. return 0;
  178. }
  179. LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  180. {
  181. switch (uMsg)
  182. {
  183. case WM_CREATE:
  184. if (FAILED(D2D1CreateFactory(
  185. D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory)))
  186. {
  187. return -1; // Неудача CreateWindowEx.
  188. }
  189. return 0;
  190. case WM_DESTROY:
  191. DiscardGraphicsResources();
  192. SafeRelease(&pFactory);
  193. PostQuitMessage(0);
  194. return 0;
  195. case WM_PAINT:
  196. OnPaint();
  197. return 0;
  198.  
  199. case WM_SIZE:
  200. Resize();
  201. return 0;
  202. }
  203. return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
  204. }
  205. Lec3Pg25
  206. basewin.h
  207. #pragma once
  208. template <class DERIVED_TYPE>
  209. class BaseWindow
  210. {
  211. public:
  212. static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  213. {
  214. DERIVED_TYPE *pThis = NULL;
  215. if (uMsg == WM_NCCREATE)
  216. {
  217. CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
  218. pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
  219. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
  220. pThis->m_hwnd = hwnd;
  221. }
  222. else
  223. {
  224. pThis = (DERIVED_TYPE*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  225. }
  226. if (pThis)
  227. {
  228. return pThis->HandleMessage(uMsg, wParam, lParam);
  229. }
  230. else
  231. {
  232. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  233. }
  234. }
  235. BaseWindow() : m_hwnd(NULL) { }
  236. BOOL Create(
  237. PCWSTR lpWindowName,
  238. DWORD dwStyle,
  239. DWORD dwExStyle = 0,
  240. int x = CW_USEDEFAULT,
  241. int y = CW_USEDEFAULT,
  242. int nWidth = CW_USEDEFAULT,
  243. int nHeight = CW_USEDEFAULT,
  244. HWND hWndParent = 0,
  245. HMENU hMenu = 0
  246. )
  247. {
  248. WNDCLASS wc = { 0 };
  249. wc.lpfnWndProc = DERIVED_TYPE::WindowProc;
  250. wc.hInstance = GetModuleHandle(NULL);
  251. wc.lpszClassName = ClassName();
  252. RegisterClass(&wc);
  253. m_hwnd = CreateWindowEx(
  254. dwExStyle, ClassName(), lpWindowName, dwStyle, x, y,
  255. nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this
  256. );
  257. return (m_hwnd ? TRUE : FALSE);
  258. }
  259. HWND Window() const { return m_hwnd; }
  260. protected:
  261. virtual PCWSTR ClassName() const = 0;
  262. HWND m_hwnd;
  263. };
  264. Source.cpp
  265. #include <windows.h>
  266. #include <d2d1.h>
  267. #pragma comment(lib, "d2d1")
  268. #include "basewin.h"
  269. template <class T> void SafeRelease(T **ppT)
  270. {
  271. if (*ppT)
  272. {
  273. (*ppT)->Release();
  274. *ppT = NULL;
  275. }
  276. }
  277. class MainWindow : public BaseWindow<MainWindow>
  278. {
  279. ID2D1Factory *pFactory;
  280. ID2D1HwndRenderTarget *pRenderTarget;
  281. ID2D1SolidColorBrush *pBrush;
  282. D2D1_ELLIPSE ellipse;
  283. ID2D1SolidColorBrush *pStroke;
  284. void CalculateLayout();
  285. HRESULT CreateGraphicsResources();
  286. void DiscardGraphicsResources();
  287. void OnPaint();
  288. void Resize();
  289. void DrawClockHand(float fHandLength, float fAngle, float fStrokeWidth);
  290. void RenderScene();
  291. public:
  292. MainWindow() : pFactory(NULL), pRenderTarget(NULL), pBrush(NULL)
  293. {
  294. }
  295. PCWSTR ClassName() const { return L"Analog Clock Window Class"; }
  296. LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
  297. };
  298. // Пересчет изображения при изменении размера окна.
  299. void MainWindow::CalculateLayout()
  300. {
  301. if (pRenderTarget != NULL)
  302. {
  303. D2D1_SIZE_F size = pRenderTarget->GetSize();
  304. const float x = size.width / 2;
  305. const float y = size.height / 2;
  306. const float radius = min(x, y);
  307. ellipse = D2D1::Ellipse(D2D1::Point2F(x, y), radius, radius);
  308. }
  309. }
  310. HRESULT MainWindow::CreateGraphicsResources()
  311. {
  312. HRESULT hr = S_OK;
  313. if (pRenderTarget == NULL)
  314. {
  315. RECT rc;
  316. GetClientRect(m_hwnd, &rc);
  317. D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
  318. hr = pFactory->CreateHwndRenderTarget(
  319. D2D1::RenderTargetProperties(),
  320. D2D1::HwndRenderTargetProperties(m_hwnd, size),
  321. &pRenderTarget);
  322. if (SUCCEEDED(hr))
  323. {
  324. const D2D1_COLOR_F color = D2D1::ColorF(1.0f, 1.0f, 0);
  325. hr = pRenderTarget->CreateSolidColorBrush(color, &pBrush);
  326. if (SUCCEEDED(hr))
  327. {
  328. const D2D1_COLOR_F handcolor = D2D1::ColorF(0, 0, 0);
  329. hr = pRenderTarget->CreateSolidColorBrush(handcolor, &pStroke);
  330. if (SUCCEEDED(hr))
  331. {
  332. CalculateLayout();
  333. }
  334. }
  335. }
  336. }
  337. return hr;
  338. }
  339. void MainWindow::DiscardGraphicsResources()
  340. {
  341. SafeRelease(&pRenderTarget);
  342. SafeRelease(&pBrush);
  343. }
  344. void MainWindow::OnPaint()
  345. {
  346. HRESULT hr = CreateGraphicsResources();
  347. if (SUCCEEDED(hr))
  348. {
  349. PAINTSTRUCT ps;
  350. BeginPaint(m_hwnd, &ps);
  351. pRenderTarget->BeginDraw();
  352. RenderScene();
  353. hr = pRenderTarget->EndDraw();
  354. if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET)
  355. {
  356. DiscardGraphicsResources();
  357. }
  358. EndPaint(m_hwnd, &ps);
  359. }
  360. }
  361. void MainWindow::Resize()
  362. {
  363. if (pRenderTarget != NULL)
  364. {
  365. RECT rc;
  366. GetClientRect(m_hwnd, &rc);
  367. D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
  368. pRenderTarget->Resize(size);
  369. CalculateLayout();
  370. InvalidateRect(m_hwnd, NULL, FALSE);
  371. }
  372. }
  373. void MainWindow::DrawClockHand(float fHandLength, float fAngle, float fStrokeWidth)
  374. {
  375. pRenderTarget->SetTransform(
  376. D2D1::Matrix3x2F::Rotation(fAngle, ellipse.point)
  377. );
  378. // endPoint определяет один конец стрелки.
  379. D2D_POINT_2F endPoint = D2D1::Point2F(
  380. ellipse.point.x,
  381. ellipse.point.y - (ellipse.radiusY * fHandLength)
  382. );
  383. // Нарисовать прямую из центра эллипса к endPoint.
  384. pRenderTarget->DrawLine(
  385. ellipse.point, endPoint, pStroke, fStrokeWidth);
  386. }
  387. void MainWindow::RenderScene()
  388. {
  389. pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::SkyBlue));
  390. pRenderTarget->FillEllipse(ellipse, pBrush);
  391. pRenderTarget->DrawEllipse(ellipse, pStroke);
  392.  
  393. // Стрелки
  394. SYSTEMTIME time;
  395. GetLocalTime(&time);
  396. // 60 минут = 30 градусов, 1 минута = 0.5 градуса
  397. const float fHourAngle = (360.0f / 12) * (time.wHour) + (time.wMinute * 0.5f);
  398. const float fMinuteAngle = (360.0f / 60) * (time.wMinute);
  399. DrawClockHand(0.6f, fHourAngle, 6);
  400. DrawClockHand(0.85f, fMinuteAngle, 4);
  401. // Восстановить идентичность трансформации.
  402. pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
  403. }
  404. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow)
  405. {
  406. MainWindow win;
  407. if (!win.Create(L"Analog Clock", WS_OVERLAPPEDWINDOW))
  408. {
  409. return 0;
  410. }
  411. ShowWindow(win.Window(), nCmdShow);
  412. // Цикл обработки сообщений.
  413. MSG msg = {};
  414. while (GetMessage(&msg, NULL, 0, 0))
  415. {
  416. TranslateMessage(&msg);
  417. DispatchMessage(&msg);
  418. }
  419. return 0;
  420. }
  421. LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  422. {
  423. switch (uMsg)
  424. {
  425. case WM_CREATE:
  426. if (FAILED(D2D1CreateFactory(
  427. D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory)))
  428. {
  429. return -1; // Неудача CreateWindowEx.
  430. }
  431. return 0;
  432. case WM_DESTROY:
  433. DiscardGraphicsResources();
  434. SafeRelease(&pFactory);
  435. PostQuitMessage(0);
  436. return 0;
  437. case WM_PAINT:
  438. OnPaint();
  439. return 0;
  440.  
  441. case WM_SIZE:
  442. Resize();
  443. return 0;
  444. }
  445. return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
  446. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement