win32drv.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366
  1. /**
  2. * @file win32drv.c
  3. *
  4. */
  5. /*********************
  6. * INCLUDES
  7. *********************/
  8. #include "win32drv.h"
  9. #if USE_WIN32DRV
  10. #include <windowsx.h>
  11. #include <malloc.h>
  12. #include <process.h>
  13. #include <stdbool.h>
  14. #include <stdint.h>
  15. /*********************
  16. * DEFINES
  17. *********************/
  18. #define WINDOW_EX_STYLE \
  19. WS_EX_CLIENTEDGE
  20. #define WINDOW_STYLE \
  21. (WS_OVERLAPPEDWINDOW & ~(WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME))
  22. #ifndef WIN32DRV_MONITOR_ZOOM
  23. #define WIN32DRV_MONITOR_ZOOM 1
  24. #endif
  25. #ifndef USER_DEFAULT_SCREEN_DPI
  26. #define USER_DEFAULT_SCREEN_DPI 96
  27. #endif
  28. /**********************
  29. * TYPEDEFS
  30. **********************/
  31. typedef struct _WINDOW_THREAD_PARAMETER
  32. {
  33. HANDLE window_mutex;
  34. HINSTANCE instance_handle;
  35. HICON icon_handle;
  36. lv_coord_t hor_res;
  37. lv_coord_t ver_res;
  38. int show_window_mode;
  39. } WINDOW_THREAD_PARAMETER, * PWINDOW_THREAD_PARAMETER;
  40. /**********************
  41. * STATIC PROTOTYPES
  42. **********************/
  43. /**
  44. * @brief Creates a B8G8R8A8 frame buffer.
  45. * @param WindowHandle A handle to the window for the creation of the frame
  46. * buffer. If this value is NULL, the entire screen will be
  47. * referenced.
  48. * @param Width The width of the frame buffer.
  49. * @param Height The height of the frame buffer.
  50. * @param PixelBuffer The raw pixel buffer of the frame buffer you created.
  51. * @param PixelBufferSize The size of the frame buffer you created.
  52. * @return If the function succeeds, the return value is a handle to the device
  53. * context (DC) for the frame buffer. If the function fails, the return
  54. * value is NULL, and PixelBuffer parameter is NULL.
  55. */
  56. static HDC lv_win32_create_frame_buffer(
  57. _In_opt_ HWND WindowHandle,
  58. _In_ LONG Width,
  59. _In_ LONG Height,
  60. _Out_ UINT32** PixelBuffer,
  61. _Out_ SIZE_T* PixelBufferSize);
  62. /**
  63. * @brief Enables WM_DPICHANGED message for child window for the associated
  64. * window.
  65. * @param WindowHandle The window you want to enable WM_DPICHANGED message for
  66. * child window.
  67. * @return If the function succeeds, the return value is non-zero. If the
  68. * function fails, the return value is zero.
  69. * @remarks You need to use this function in Windows 10 Threshold 1 or Windows
  70. * 10 Threshold 2.
  71. */
  72. static BOOL lv_win32_enable_child_window_dpi_message(
  73. _In_ HWND WindowHandle);
  74. /**
  75. * @brief Registers a window as being touch-capable.
  76. * @param hWnd The handle of the window being registered.
  77. * @param ulFlags A set of bit flags that specify optional modifications.
  78. * @return If the function succeeds, the return value is nonzero. If the
  79. * function fails, the return value is zero.
  80. * @remark For more information, see RegisterTouchWindow.
  81. */
  82. static BOOL lv_win32_register_touch_window(
  83. HWND hWnd,
  84. ULONG ulFlags);
  85. /**
  86. * @brief Retrieves detailed information about touch inputs associated with a
  87. * particular touch input handle.
  88. * @param hTouchInput The touch input handle received in the LPARAM of a touch
  89. * message.
  90. * @param cInputs The number of structures in the pInputs array.
  91. * @param pInputs A pointer to an array of TOUCHINPUT structures to receive
  92. * information about the touch points associated with the
  93. * specified touch input handle.
  94. * @param cbSize The size, in bytes, of a single TOUCHINPUT structure.
  95. * @return If the function succeeds, the return value is nonzero. If the
  96. * function fails, the return value is zero.
  97. * @remark For more information, see GetTouchInputInfo.
  98. */
  99. static BOOL lv_win32_get_touch_input_info(
  100. HTOUCHINPUT hTouchInput,
  101. UINT cInputs,
  102. PTOUCHINPUT pInputs,
  103. int cbSize);
  104. /**
  105. * @brief Closes a touch input handle, frees process memory associated with it,
  106. and invalidates the handle.
  107. * @param hTouchInput The touch input handle received in the LPARAM of a touch
  108. * message.
  109. * @return If the function succeeds, the return value is nonzero. If the
  110. * function fails, the return value is zero.
  111. * @remark For more information, see CloseTouchInputHandle.
  112. */
  113. static BOOL lv_win32_close_touch_input_handle(
  114. HTOUCHINPUT hTouchInput);
  115. /**
  116. * @brief Returns the dots per inch (dpi) value for the associated window.
  117. * @param WindowHandle The window you want to get information about.
  118. * @return The DPI for the window.
  119. */
  120. static UINT lv_win32_get_dpi_for_window(
  121. _In_ HWND WindowHandle);
  122. static void lv_win32_display_driver_flush_callback(
  123. lv_disp_drv_t* disp_drv,
  124. const lv_area_t* area,
  125. lv_color_t* color_p);
  126. static void lv_win32_pointer_driver_read_callback(
  127. lv_indev_drv_t* indev_drv,
  128. lv_indev_data_t* data);
  129. static void lv_win32_keypad_driver_read_callback(
  130. lv_indev_drv_t* indev_drv,
  131. lv_indev_data_t* data);
  132. static void lv_win32_encoder_driver_read_callback(
  133. lv_indev_drv_t* indev_drv,
  134. lv_indev_data_t* data);
  135. static lv_win32_window_context_t* lv_win32_get_display_context(
  136. lv_disp_t* display);
  137. static LRESULT CALLBACK lv_win32_window_message_callback(
  138. HWND hWnd,
  139. UINT uMsg,
  140. WPARAM wParam,
  141. LPARAM lParam);
  142. static unsigned int __stdcall lv_win32_window_thread_entrypoint(
  143. void* raw_parameter);
  144. static void lv_win32_push_key_to_keyboard_queue(
  145. lv_win32_window_context_t* context,
  146. uint32_t key,
  147. lv_indev_state_t state)
  148. {
  149. lv_win32_keyboard_queue_item_t* current =
  150. (lv_win32_keyboard_queue_item_t*)(_aligned_malloc(
  151. sizeof(lv_win32_keyboard_queue_item_t),
  152. MEMORY_ALLOCATION_ALIGNMENT));
  153. if (current)
  154. {
  155. current->key = key;
  156. current->state = state;
  157. InterlockedPushEntrySList(
  158. context->keyboard_queue,
  159. &current->ItemEntry);
  160. }
  161. }
  162. /**********************
  163. * GLOBAL VARIABLES
  164. **********************/
  165. EXTERN_C bool lv_win32_quit_signal = false;
  166. EXTERN_C lv_indev_t* lv_win32_pointer_device_object = NULL;
  167. EXTERN_C lv_indev_t* lv_win32_keypad_device_object = NULL;
  168. EXTERN_C lv_indev_t* lv_win32_encoder_device_object = NULL;
  169. /**********************
  170. * STATIC VARIABLES
  171. **********************/
  172. static HWND g_window_handle = NULL;
  173. /**********************
  174. * MACROS
  175. **********************/
  176. /**********************
  177. * GLOBAL FUNCTIONS
  178. **********************/
  179. EXTERN_C void lv_win32_add_all_input_devices_to_group(
  180. lv_group_t* group)
  181. {
  182. if (!group)
  183. {
  184. LV_LOG_WARN(
  185. "The group object is NULL. Get the default group object instead.");
  186. group = lv_group_get_default();
  187. if (!group)
  188. {
  189. LV_LOG_WARN(
  190. "The default group object is NULL. Create a new group object "
  191. "and set it to default instead.");
  192. group = lv_group_create();
  193. if (group)
  194. {
  195. lv_group_set_default(group);
  196. }
  197. }
  198. }
  199. LV_ASSERT_MSG(group, "Cannot obtain an available group object.");
  200. lv_indev_set_group(lv_win32_pointer_device_object, group);
  201. lv_indev_set_group(lv_win32_keypad_device_object, group);
  202. lv_indev_set_group(lv_win32_encoder_device_object, group);
  203. }
  204. EXTERN_C lv_win32_window_context_t* lv_win32_get_window_context(
  205. HWND window_handle)
  206. {
  207. return (lv_win32_window_context_t*)(
  208. GetPropW(window_handle, L"LVGL.SimulatorWindow.WindowContext"));
  209. }
  210. EXTERN_C bool lv_win32_init_window_class()
  211. {
  212. WNDCLASSEXW window_class;
  213. window_class.cbSize = sizeof(WNDCLASSEXW);
  214. window_class.style = 0;
  215. window_class.lpfnWndProc = lv_win32_window_message_callback;
  216. window_class.cbClsExtra = 0;
  217. window_class.cbWndExtra = 0;
  218. window_class.hInstance = NULL;
  219. window_class.hIcon = NULL;
  220. window_class.hCursor = LoadCursorW(NULL, IDC_ARROW);
  221. window_class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  222. window_class.lpszMenuName = NULL;
  223. window_class.lpszClassName = LVGL_SIMULATOR_WINDOW_CLASS;
  224. window_class.hIconSm = NULL;
  225. return RegisterClassExW(&window_class);
  226. }
  227. EXTERN_C HWND lv_win32_create_display_window(
  228. const wchar_t* window_title,
  229. lv_coord_t hor_res,
  230. lv_coord_t ver_res,
  231. HINSTANCE instance_handle,
  232. HICON icon_handle,
  233. int show_window_mode)
  234. {
  235. HWND display_window_handle = CreateWindowExW(
  236. WINDOW_EX_STYLE,
  237. LVGL_SIMULATOR_WINDOW_CLASS,
  238. window_title,
  239. WINDOW_STYLE,
  240. CW_USEDEFAULT,
  241. 0,
  242. hor_res,
  243. ver_res,
  244. NULL,
  245. NULL,
  246. instance_handle,
  247. NULL);
  248. if (display_window_handle)
  249. {
  250. SendMessageW(
  251. display_window_handle,
  252. WM_SETICON,
  253. TRUE,
  254. (LPARAM)icon_handle);
  255. SendMessageW(
  256. display_window_handle,
  257. WM_SETICON,
  258. FALSE,
  259. (LPARAM)icon_handle);
  260. ShowWindow(display_window_handle, show_window_mode);
  261. UpdateWindow(display_window_handle);
  262. }
  263. return display_window_handle;
  264. }
  265. EXTERN_C bool lv_win32_init(
  266. HINSTANCE instance_handle,
  267. int show_window_mode,
  268. lv_coord_t hor_res,
  269. lv_coord_t ver_res,
  270. HICON icon_handle)
  271. {
  272. if (!lv_win32_init_window_class())
  273. {
  274. return false;
  275. }
  276. PWINDOW_THREAD_PARAMETER parameter =
  277. (PWINDOW_THREAD_PARAMETER)malloc(sizeof(WINDOW_THREAD_PARAMETER));
  278. parameter->window_mutex = CreateEventExW(NULL, NULL, 0, EVENT_ALL_ACCESS);
  279. parameter->instance_handle = instance_handle;
  280. parameter->icon_handle = icon_handle;
  281. parameter->hor_res = hor_res;
  282. parameter->ver_res = ver_res;
  283. parameter->show_window_mode = show_window_mode;
  284. _beginthreadex(
  285. NULL,
  286. 0,
  287. lv_win32_window_thread_entrypoint,
  288. parameter,
  289. 0,
  290. NULL);
  291. WaitForSingleObjectEx(parameter->window_mutex, INFINITE, FALSE);
  292. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  293. lv_win32_get_window_context(g_window_handle));
  294. if (!context)
  295. {
  296. return false;
  297. }
  298. lv_win32_pointer_device_object = context->mouse_device_object;
  299. lv_win32_keypad_device_object = context->keyboard_device_object;
  300. lv_win32_encoder_device_object = context->mousewheel_device_object;
  301. return true;
  302. }
  303. /**********************
  304. * STATIC FUNCTIONS
  305. **********************/
  306. static HDC lv_win32_create_frame_buffer(
  307. HWND WindowHandle,
  308. LONG Width,
  309. LONG Height,
  310. UINT32** PixelBuffer,
  311. SIZE_T* PixelBufferSize)
  312. {
  313. HDC hFrameBufferDC = NULL;
  314. if (PixelBuffer && PixelBufferSize)
  315. {
  316. HDC hWindowDC = GetDC(WindowHandle);
  317. if (hWindowDC)
  318. {
  319. hFrameBufferDC = CreateCompatibleDC(hWindowDC);
  320. ReleaseDC(WindowHandle, hWindowDC);
  321. }
  322. if (hFrameBufferDC)
  323. {
  324. #if LV_COLOR_DEPTH == 32
  325. BITMAPINFO BitmapInfo = { 0 };
  326. #elif LV_COLOR_DEPTH == 16
  327. typedef struct _BITMAPINFO_16BPP {
  328. BITMAPINFOHEADER bmiHeader;
  329. DWORD bmiColorMask[3];
  330. } BITMAPINFO_16BPP, *PBITMAPINFO_16BPP;
  331. BITMAPINFO_16BPP BitmapInfo = { 0 };
  332. #elif LV_COLOR_DEPTH == 8
  333. typedef struct _BITMAPINFO_8BPP {
  334. BITMAPINFOHEADER bmiHeader;
  335. RGBQUAD bmiColors[256];
  336. } BITMAPINFO_8BPP, *PBITMAPINFO_8BPP;
  337. BITMAPINFO_8BPP BitmapInfo = { 0 };
  338. #elif LV_COLOR_DEPTH == 1
  339. typedef struct _BITMAPINFO_1BPP {
  340. BITMAPINFOHEADER bmiHeader;
  341. RGBQUAD bmiColors[2];
  342. } BITMAPINFO_1BPP, *PBITMAPINFO_1BPP;
  343. BITMAPINFO_1BPP BitmapInfo = { 0 };
  344. #else
  345. BITMAPINFO BitmapInfo = { 0 };
  346. #endif
  347. BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  348. BitmapInfo.bmiHeader.biWidth = Width;
  349. BitmapInfo.bmiHeader.biHeight = -Height;
  350. BitmapInfo.bmiHeader.biPlanes = 1;
  351. #if LV_COLOR_DEPTH == 32
  352. BitmapInfo.bmiHeader.biBitCount = 32;
  353. BitmapInfo.bmiHeader.biCompression = BI_RGB;
  354. #elif LV_COLOR_DEPTH == 16
  355. BitmapInfo.bmiHeader.biBitCount = 16;
  356. BitmapInfo.bmiHeader.biCompression = BI_BITFIELDS;
  357. BitmapInfo.bmiColorMask[0] = 0xF800;
  358. BitmapInfo.bmiColorMask[1] = 0x07E0;
  359. BitmapInfo.bmiColorMask[2] = 0x001F;
  360. #elif LV_COLOR_DEPTH == 8
  361. BitmapInfo.bmiHeader.biBitCount = 8;
  362. BitmapInfo.bmiHeader.biCompression = BI_RGB;
  363. for (size_t i = 0; i < 256; ++i)
  364. {
  365. lv_color8_t color;
  366. color.full = i;
  367. BitmapInfo.bmiColors[i].rgbRed = LV_COLOR_GET_R(color) * 36;
  368. BitmapInfo.bmiColors[i].rgbGreen = LV_COLOR_GET_G(color) * 36;
  369. BitmapInfo.bmiColors[i].rgbBlue = LV_COLOR_GET_B(color) * 85;
  370. BitmapInfo.bmiColors[i].rgbReserved = 0xFF;
  371. }
  372. #elif LV_COLOR_DEPTH == 1
  373. BitmapInfo.bmiHeader.biBitCount = 8;
  374. BitmapInfo.bmiHeader.biCompression = BI_RGB;
  375. BitmapInfo.bmiHeader.biClrUsed = 2;
  376. BitmapInfo.bmiHeader.biClrImportant = 2;
  377. BitmapInfo.bmiColors[0].rgbRed = 0x00;
  378. BitmapInfo.bmiColors[0].rgbGreen = 0x00;
  379. BitmapInfo.bmiColors[0].rgbBlue = 0x00;
  380. BitmapInfo.bmiColors[0].rgbReserved = 0xFF;
  381. BitmapInfo.bmiColors[1].rgbRed = 0xFF;
  382. BitmapInfo.bmiColors[1].rgbGreen = 0xFF;
  383. BitmapInfo.bmiColors[1].rgbBlue = 0xFF;
  384. BitmapInfo.bmiColors[1].rgbReserved = 0xFF;
  385. #else
  386. BitmapInfo.bmiHeader.biBitCount = 32;
  387. BitmapInfo.bmiHeader.biCompression = BI_RGB;
  388. #endif
  389. HBITMAP hBitmap = CreateDIBSection(
  390. hFrameBufferDC,
  391. (PBITMAPINFO)(&BitmapInfo),
  392. DIB_RGB_COLORS,
  393. (void**)PixelBuffer,
  394. NULL,
  395. 0);
  396. if (hBitmap)
  397. {
  398. #if LV_COLOR_DEPTH == 32
  399. *PixelBufferSize = Width * Height * sizeof(UINT32);
  400. #elif LV_COLOR_DEPTH == 16
  401. *PixelBufferSize = Width * Height * sizeof(UINT16);
  402. #elif LV_COLOR_DEPTH == 8
  403. *PixelBufferSize = Width * Height * sizeof(UINT8);
  404. #elif LV_COLOR_DEPTH == 1
  405. *PixelBufferSize = Width * Height * sizeof(UINT8);
  406. #else
  407. *PixelBufferSize = Width * Height * sizeof(UINT32);
  408. #endif
  409. DeleteObject(SelectObject(hFrameBufferDC, hBitmap));
  410. DeleteObject(hBitmap);
  411. }
  412. else
  413. {
  414. DeleteDC(hFrameBufferDC);
  415. hFrameBufferDC = NULL;
  416. }
  417. }
  418. }
  419. return hFrameBufferDC;
  420. }
  421. static BOOL lv_win32_enable_child_window_dpi_message(
  422. HWND WindowHandle)
  423. {
  424. // This hack is only for Windows 10 TH1/TH2 only.
  425. // We don't need this hack if the Per Monitor Aware V2 is existed.
  426. OSVERSIONINFOEXW OSVersionInfoEx = { 0 };
  427. OSVersionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
  428. OSVersionInfoEx.dwMajorVersion = 10;
  429. OSVersionInfoEx.dwMinorVersion = 0;
  430. OSVersionInfoEx.dwBuildNumber = 14393;
  431. if (!VerifyVersionInfoW(
  432. &OSVersionInfoEx,
  433. VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER,
  434. VerSetConditionMask(
  435. VerSetConditionMask(
  436. VerSetConditionMask(
  437. 0,
  438. VER_MAJORVERSION,
  439. VER_GREATER_EQUAL),
  440. VER_MINORVERSION,
  441. VER_GREATER_EQUAL),
  442. VER_BUILDNUMBER,
  443. VER_LESS)))
  444. {
  445. return FALSE;
  446. }
  447. HMODULE ModuleHandle = GetModuleHandleW(L"user32.dll");
  448. if (!ModuleHandle)
  449. {
  450. return FALSE;
  451. }
  452. typedef BOOL(WINAPI* FunctionType)(HWND, BOOL);
  453. FunctionType pFunction = (FunctionType)(
  454. GetProcAddress(ModuleHandle, "EnableChildWindowDpiMessage"));
  455. if (!pFunction)
  456. {
  457. return FALSE;
  458. }
  459. return pFunction(WindowHandle, TRUE);
  460. }
  461. static BOOL lv_win32_register_touch_window(
  462. HWND hWnd,
  463. ULONG ulFlags)
  464. {
  465. HMODULE ModuleHandle = GetModuleHandleW(L"user32.dll");
  466. if (!ModuleHandle)
  467. {
  468. return FALSE;
  469. }
  470. typedef BOOL(WINAPI* FunctionType)(HWND, ULONG);
  471. FunctionType pFunction = (FunctionType)(
  472. GetProcAddress(ModuleHandle, "RegisterTouchWindow"));
  473. if (!pFunction)
  474. {
  475. return FALSE;
  476. }
  477. return pFunction(hWnd, ulFlags);
  478. }
  479. static BOOL lv_win32_get_touch_input_info(
  480. HTOUCHINPUT hTouchInput,
  481. UINT cInputs,
  482. PTOUCHINPUT pInputs,
  483. int cbSize)
  484. {
  485. HMODULE ModuleHandle = GetModuleHandleW(L"user32.dll");
  486. if (!ModuleHandle)
  487. {
  488. return FALSE;
  489. }
  490. typedef BOOL(WINAPI* FunctionType)(HTOUCHINPUT, UINT, PTOUCHINPUT, int);
  491. FunctionType pFunction = (FunctionType)(
  492. GetProcAddress(ModuleHandle, "GetTouchInputInfo"));
  493. if (!pFunction)
  494. {
  495. return FALSE;
  496. }
  497. return pFunction(hTouchInput, cInputs, pInputs, cbSize);
  498. }
  499. static BOOL lv_win32_close_touch_input_handle(
  500. HTOUCHINPUT hTouchInput)
  501. {
  502. HMODULE ModuleHandle = GetModuleHandleW(L"user32.dll");
  503. if (!ModuleHandle)
  504. {
  505. return FALSE;
  506. }
  507. typedef BOOL(WINAPI* FunctionType)(HTOUCHINPUT);
  508. FunctionType pFunction = (FunctionType)(
  509. GetProcAddress(ModuleHandle, "CloseTouchInputHandle"));
  510. if (!pFunction)
  511. {
  512. return FALSE;
  513. }
  514. return pFunction(hTouchInput);
  515. }
  516. static UINT lv_win32_get_dpi_for_window(
  517. _In_ HWND WindowHandle)
  518. {
  519. UINT Result = (UINT)(-1);
  520. HMODULE ModuleHandle = LoadLibraryW(L"SHCore.dll");
  521. if (ModuleHandle)
  522. {
  523. typedef enum MONITOR_DPI_TYPE_PRIVATE {
  524. MDT_EFFECTIVE_DPI = 0,
  525. MDT_ANGULAR_DPI = 1,
  526. MDT_RAW_DPI = 2,
  527. MDT_DEFAULT = MDT_EFFECTIVE_DPI
  528. } MONITOR_DPI_TYPE_PRIVATE;
  529. typedef HRESULT(WINAPI* FunctionType)(
  530. HMONITOR, MONITOR_DPI_TYPE_PRIVATE, UINT*, UINT*);
  531. FunctionType pFunction = (FunctionType)(
  532. GetProcAddress(ModuleHandle, "GetDpiForMonitor"));
  533. if (pFunction)
  534. {
  535. HMONITOR MonitorHandle = MonitorFromWindow(
  536. WindowHandle,
  537. MONITOR_DEFAULTTONEAREST);
  538. UINT dpiX = 0;
  539. UINT dpiY = 0;
  540. if (SUCCEEDED(pFunction(
  541. MonitorHandle,
  542. MDT_EFFECTIVE_DPI,
  543. &dpiX,
  544. &dpiY)))
  545. {
  546. Result = dpiX;
  547. }
  548. }
  549. FreeLibrary(ModuleHandle);
  550. }
  551. if (Result == (UINT)(-1))
  552. {
  553. HDC hWindowDC = GetDC(WindowHandle);
  554. if (hWindowDC)
  555. {
  556. Result = GetDeviceCaps(hWindowDC, LOGPIXELSX);
  557. ReleaseDC(WindowHandle, hWindowDC);
  558. }
  559. }
  560. if (Result == (UINT)(-1))
  561. {
  562. Result = USER_DEFAULT_SCREEN_DPI;
  563. }
  564. return Result;
  565. }
  566. static void lv_win32_display_driver_flush_callback(
  567. lv_disp_drv_t* disp_drv,
  568. const lv_area_t* area,
  569. lv_color_t* color_p)
  570. {
  571. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  572. lv_win32_get_window_context((HWND)disp_drv->user_data));
  573. if (context)
  574. {
  575. if (lv_disp_flush_is_last(disp_drv))
  576. {
  577. #if (LV_COLOR_DEPTH == 32) || \
  578. (LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0) || \
  579. (LV_COLOR_DEPTH == 8) || \
  580. (LV_COLOR_DEPTH == 1)
  581. UNREFERENCED_PARAMETER(color_p);
  582. #elif (LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP != 0)
  583. SIZE_T count = context->display_framebuffer_size / sizeof(UINT16);
  584. PUINT16 source = (PUINT16)color_p;
  585. PUINT16 destination = (PUINT16)context->display_framebuffer_base;
  586. for (SIZE_T i = 0; i < count; ++i)
  587. {
  588. UINT16 current = *source;
  589. *destination = (LOBYTE(current) << 8) | HIBYTE(current);
  590. ++source;
  591. ++destination;
  592. }
  593. #else
  594. uint32_t* destination = context->display_framebuffer_base;
  595. for (int y = area->y1; y <= area->y2; ++y)
  596. {
  597. for (int x = area->x1; x <= area->x2; ++x)
  598. {
  599. destination[y * disp_drv->hor_res + x] =
  600. lv_color_to32(*color_p);
  601. color_p++;
  602. }
  603. }
  604. #endif
  605. InvalidateRect(disp_drv->user_data, NULL, FALSE);
  606. }
  607. }
  608. lv_disp_flush_ready(disp_drv);
  609. }
  610. static void lv_win32_pointer_driver_read_callback(
  611. lv_indev_drv_t* indev_drv,
  612. lv_indev_data_t* data)
  613. {
  614. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  615. lv_win32_get_display_context(indev_drv->disp));
  616. if (!context)
  617. {
  618. return;
  619. }
  620. data->state = context->mouse_state;
  621. data->point = context->mouse_point;
  622. }
  623. static void lv_win32_keypad_driver_read_callback(
  624. lv_indev_drv_t* indev_drv,
  625. lv_indev_data_t* data)
  626. {
  627. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  628. lv_win32_get_display_context(indev_drv->disp));
  629. if (!context)
  630. {
  631. return;
  632. }
  633. EnterCriticalSection(&context->keyboard_mutex);
  634. lv_win32_keyboard_queue_item_t* current =
  635. (lv_win32_keyboard_queue_item_t*)(InterlockedPopEntrySList(
  636. context->keyboard_queue));
  637. if (current)
  638. {
  639. data->key = current->key;
  640. data->state = current->state;
  641. _aligned_free(current);
  642. data->continue_reading = true;
  643. }
  644. LeaveCriticalSection(&context->keyboard_mutex);
  645. }
  646. static void lv_win32_encoder_driver_read_callback(
  647. lv_indev_drv_t* indev_drv,
  648. lv_indev_data_t* data)
  649. {
  650. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  651. lv_win32_get_display_context(indev_drv->disp));
  652. if (!context)
  653. {
  654. return;
  655. }
  656. data->state = context->mousewheel_state;
  657. data->enc_diff = context->mousewheel_enc_diff;
  658. context->mousewheel_enc_diff = 0;
  659. }
  660. static lv_win32_window_context_t* lv_win32_get_display_context(
  661. lv_disp_t* display)
  662. {
  663. if (display)
  664. {
  665. return lv_win32_get_window_context((HWND)display->driver->user_data);
  666. }
  667. return NULL;
  668. }
  669. static LRESULT CALLBACK lv_win32_window_message_callback(
  670. HWND hWnd,
  671. UINT uMsg,
  672. WPARAM wParam,
  673. LPARAM lParam)
  674. {
  675. switch (uMsg)
  676. {
  677. case WM_CREATE:
  678. {
  679. // Note: Return -1 directly because WM_DESTROY message will be sent
  680. // when destroy the window automatically. We free the resource when
  681. // processing the WM_DESTROY message of this window.
  682. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  683. malloc(sizeof(lv_win32_window_context_t)));
  684. if (!context)
  685. {
  686. return -1;
  687. }
  688. RECT request_content_size;
  689. GetWindowRect(hWnd, &request_content_size);
  690. context->display_hor_res =
  691. request_content_size.right - request_content_size.left;
  692. context->display_ver_res =
  693. request_content_size.bottom - request_content_size.top;
  694. context->display_dpi = lv_win32_get_dpi_for_window(hWnd);
  695. context->display_framebuffer_context_handle =
  696. lv_win32_create_frame_buffer(
  697. hWnd,
  698. context->display_hor_res,
  699. context->display_ver_res,
  700. &context->display_framebuffer_base,
  701. &context->display_framebuffer_size);
  702. #if (LV_COLOR_DEPTH == 32) || \
  703. (LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0) || \
  704. (LV_COLOR_DEPTH == 8) || \
  705. (LV_COLOR_DEPTH == 1)
  706. lv_disp_draw_buf_init(
  707. &context->display_buffer,
  708. (lv_color_t*)context->display_framebuffer_base,
  709. NULL,
  710. context->display_hor_res * context->display_ver_res);
  711. #else
  712. size_t draw_buffer_size = sizeof(lv_color_t);
  713. draw_buffer_size *= context->display_hor_res;
  714. draw_buffer_size *= context->display_ver_res;
  715. lv_disp_draw_buf_init(
  716. &context->display_buffer,
  717. (lv_color_t*)malloc(draw_buffer_size),
  718. NULL,
  719. context->display_hor_res * context->display_ver_res);
  720. #endif
  721. lv_disp_drv_init(&context->display_driver);
  722. context->display_driver.hor_res = context->display_hor_res;
  723. context->display_driver.ver_res = context->display_ver_res;
  724. context->display_driver.flush_cb =
  725. lv_win32_display_driver_flush_callback;
  726. context->display_driver.draw_buf = &context->display_buffer;
  727. context->display_driver.direct_mode = 1;
  728. context->display_driver.user_data = hWnd;
  729. context->display_device_object =
  730. lv_disp_drv_register(&context->display_driver);
  731. if (!context->display_device_object)
  732. {
  733. return -1;
  734. }
  735. context->mouse_state = LV_INDEV_STATE_REL;
  736. context->mouse_point.x = 0;
  737. context->mouse_point.y = 0;
  738. lv_indev_drv_init(&context->mouse_driver);
  739. context->mouse_driver.type = LV_INDEV_TYPE_POINTER;
  740. context->mouse_driver.disp = context->display_device_object;
  741. context->mouse_driver.read_cb =
  742. lv_win32_pointer_driver_read_callback;
  743. context->mouse_device_object =
  744. lv_indev_drv_register(&context->mouse_driver);
  745. if (!context->mouse_device_object)
  746. {
  747. return -1;
  748. }
  749. context->mousewheel_state = LV_INDEV_STATE_REL;
  750. context->mousewheel_enc_diff = 0;
  751. lv_indev_drv_init(&context->mousewheel_driver);
  752. context->mousewheel_driver.type = LV_INDEV_TYPE_ENCODER;
  753. context->mousewheel_driver.disp = context->display_device_object;
  754. context->mousewheel_driver.read_cb =
  755. lv_win32_encoder_driver_read_callback;
  756. context->mousewheel_device_object =
  757. lv_indev_drv_register(&context->mousewheel_driver);
  758. if (!context->mousewheel_device_object)
  759. {
  760. return -1;
  761. }
  762. InitializeCriticalSection(&context->keyboard_mutex);
  763. context->keyboard_queue = _aligned_malloc(
  764. sizeof(SLIST_HEADER),
  765. MEMORY_ALLOCATION_ALIGNMENT);
  766. if (!context->keyboard_queue)
  767. {
  768. return -1;
  769. }
  770. InitializeSListHead(context->keyboard_queue);
  771. context->keyboard_utf16_high_surrogate = 0;
  772. context->keyboard_utf16_low_surrogate = 0;
  773. lv_indev_drv_init(&context->keyboard_driver);
  774. context->keyboard_driver.type = LV_INDEV_TYPE_KEYPAD;
  775. context->keyboard_driver.disp = context->display_device_object;
  776. context->keyboard_driver.read_cb =
  777. lv_win32_keypad_driver_read_callback;
  778. context->keyboard_device_object =
  779. lv_indev_drv_register(&context->keyboard_driver);
  780. if (!context->keyboard_device_object)
  781. {
  782. return -1;
  783. }
  784. if (!SetPropW(
  785. hWnd,
  786. L"LVGL.SimulatorWindow.WindowContext",
  787. (HANDLE)(context)))
  788. {
  789. return -1;
  790. }
  791. RECT calculated_window_size;
  792. calculated_window_size.left = 0;
  793. calculated_window_size.right = MulDiv(
  794. context->display_hor_res * WIN32DRV_MONITOR_ZOOM,
  795. context->display_dpi,
  796. USER_DEFAULT_SCREEN_DPI);
  797. calculated_window_size.top = 0;
  798. calculated_window_size.bottom = MulDiv(
  799. context->display_ver_res * WIN32DRV_MONITOR_ZOOM,
  800. context->display_dpi,
  801. USER_DEFAULT_SCREEN_DPI);
  802. AdjustWindowRectEx(
  803. &calculated_window_size,
  804. WINDOW_STYLE,
  805. FALSE,
  806. WINDOW_EX_STYLE);
  807. OffsetRect(
  808. &calculated_window_size,
  809. -calculated_window_size.left,
  810. -calculated_window_size.top);
  811. SetWindowPos(
  812. hWnd,
  813. NULL,
  814. 0,
  815. 0,
  816. calculated_window_size.right,
  817. calculated_window_size.bottom,
  818. SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
  819. lv_win32_register_touch_window(hWnd, 0);
  820. lv_win32_enable_child_window_dpi_message(hWnd);
  821. break;
  822. }
  823. case WM_MOUSEMOVE:
  824. case WM_LBUTTONDOWN:
  825. case WM_LBUTTONUP:
  826. case WM_MBUTTONDOWN:
  827. case WM_MBUTTONUP:
  828. {
  829. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  830. lv_win32_get_window_context(hWnd));
  831. if (!context)
  832. {
  833. return 0;
  834. }
  835. context->mouse_point.x = MulDiv(
  836. GET_X_LPARAM(lParam),
  837. USER_DEFAULT_SCREEN_DPI,
  838. WIN32DRV_MONITOR_ZOOM * context->display_dpi);
  839. context->mouse_point.y = MulDiv(
  840. GET_Y_LPARAM(lParam),
  841. USER_DEFAULT_SCREEN_DPI,
  842. WIN32DRV_MONITOR_ZOOM * context->display_dpi);
  843. if (context->mouse_point.x < 0)
  844. {
  845. context->mouse_point.x = 0;
  846. }
  847. if (context->mouse_point.x > context->display_hor_res - 1)
  848. {
  849. context->mouse_point.x = context->display_hor_res - 1;
  850. }
  851. if (context->mouse_point.y < 0)
  852. {
  853. context->mouse_point.y = 0;
  854. }
  855. if (context->mouse_point.y > context->display_ver_res - 1)
  856. {
  857. context->mouse_point.y = context->display_ver_res - 1;
  858. }
  859. if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
  860. {
  861. context->mouse_state = (
  862. uMsg == WM_LBUTTONDOWN
  863. ? LV_INDEV_STATE_PR
  864. : LV_INDEV_STATE_REL);
  865. }
  866. else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP)
  867. {
  868. context->mousewheel_state = (
  869. uMsg == WM_MBUTTONDOWN
  870. ? LV_INDEV_STATE_PR
  871. : LV_INDEV_STATE_REL);
  872. }
  873. return 0;
  874. }
  875. case WM_KEYDOWN:
  876. case WM_KEYUP:
  877. {
  878. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  879. lv_win32_get_window_context(hWnd));
  880. if (context)
  881. {
  882. EnterCriticalSection(&context->keyboard_mutex);
  883. bool skip_translation = false;
  884. uint32_t translated_key = 0;
  885. switch (wParam)
  886. {
  887. case VK_UP:
  888. translated_key = LV_KEY_UP;
  889. break;
  890. case VK_DOWN:
  891. translated_key = LV_KEY_DOWN;
  892. break;
  893. case VK_LEFT:
  894. translated_key = LV_KEY_LEFT;
  895. break;
  896. case VK_RIGHT:
  897. translated_key = LV_KEY_RIGHT;
  898. break;
  899. case VK_ESCAPE:
  900. translated_key = LV_KEY_ESC;
  901. break;
  902. case VK_DELETE:
  903. translated_key = LV_KEY_DEL;
  904. break;
  905. case VK_BACK:
  906. translated_key = LV_KEY_BACKSPACE;
  907. break;
  908. case VK_RETURN:
  909. translated_key = LV_KEY_ENTER;
  910. break;
  911. case VK_TAB:
  912. case VK_NEXT:
  913. translated_key = LV_KEY_NEXT;
  914. break;
  915. case VK_PRIOR:
  916. translated_key = LV_KEY_PREV;
  917. break;
  918. case VK_HOME:
  919. translated_key = LV_KEY_HOME;
  920. break;
  921. case VK_END:
  922. translated_key = LV_KEY_END;
  923. break;
  924. default:
  925. skip_translation = true;
  926. break;
  927. }
  928. if (!skip_translation)
  929. {
  930. lv_win32_push_key_to_keyboard_queue(
  931. context,
  932. translated_key,
  933. ((uMsg == WM_KEYUP)
  934. ? LV_INDEV_STATE_REL
  935. : LV_INDEV_STATE_PR));
  936. }
  937. LeaveCriticalSection(&context->keyboard_mutex);
  938. }
  939. break;
  940. }
  941. case WM_CHAR:
  942. {
  943. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  944. lv_win32_get_window_context(hWnd));
  945. if (context)
  946. {
  947. EnterCriticalSection(&context->keyboard_mutex);
  948. uint16_t raw_code_point = (uint16_t)(wParam);
  949. if (raw_code_point >= 0x20 && raw_code_point != 0x7F)
  950. {
  951. if (IS_HIGH_SURROGATE(raw_code_point))
  952. {
  953. context->keyboard_utf16_high_surrogate = raw_code_point;
  954. }
  955. else if (IS_LOW_SURROGATE(raw_code_point))
  956. {
  957. context->keyboard_utf16_low_surrogate = raw_code_point;
  958. }
  959. uint32_t code_point = raw_code_point;
  960. if (context->keyboard_utf16_high_surrogate &&
  961. context->keyboard_utf16_low_surrogate)
  962. {
  963. uint16_t high_surrogate =
  964. context->keyboard_utf16_high_surrogate;
  965. uint16_t low_surrogate =
  966. context->keyboard_utf16_low_surrogate;
  967. code_point = (low_surrogate & 0x03FF);
  968. code_point += (((high_surrogate & 0x03FF) + 0x40) << 10);
  969. context->keyboard_utf16_high_surrogate = 0;
  970. context->keyboard_utf16_low_surrogate = 0;
  971. }
  972. uint32_t lvgl_code_point =
  973. _lv_txt_unicode_to_encoded(code_point);
  974. lv_win32_push_key_to_keyboard_queue(
  975. context,
  976. lvgl_code_point,
  977. LV_INDEV_STATE_PR);
  978. lv_win32_push_key_to_keyboard_queue(
  979. context,
  980. lvgl_code_point,
  981. LV_INDEV_STATE_REL);
  982. }
  983. LeaveCriticalSection(&context->keyboard_mutex);
  984. }
  985. break;
  986. }
  987. case WM_MOUSEWHEEL:
  988. {
  989. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  990. lv_win32_get_window_context(hWnd));
  991. if (context)
  992. {
  993. context->mousewheel_enc_diff =
  994. -(GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA);
  995. }
  996. break;
  997. }
  998. case WM_TOUCH:
  999. {
  1000. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  1001. lv_win32_get_window_context(hWnd));
  1002. if (context)
  1003. {
  1004. UINT cInputs = LOWORD(wParam);
  1005. HTOUCHINPUT hTouchInput = (HTOUCHINPUT)(lParam);
  1006. PTOUCHINPUT pInputs = malloc(cInputs * sizeof(TOUCHINPUT));
  1007. if (pInputs)
  1008. {
  1009. if (lv_win32_get_touch_input_info(
  1010. hTouchInput,
  1011. cInputs,
  1012. pInputs,
  1013. sizeof(TOUCHINPUT)))
  1014. {
  1015. for (UINT i = 0; i < cInputs; ++i)
  1016. {
  1017. POINT Point;
  1018. Point.x = TOUCH_COORD_TO_PIXEL(pInputs[i].x);
  1019. Point.y = TOUCH_COORD_TO_PIXEL(pInputs[i].y);
  1020. if (!ScreenToClient(hWnd, &Point))
  1021. {
  1022. continue;
  1023. }
  1024. context->mouse_point.x = MulDiv(
  1025. Point.x,
  1026. USER_DEFAULT_SCREEN_DPI,
  1027. WIN32DRV_MONITOR_ZOOM * context->display_dpi);
  1028. context->mouse_point.y = MulDiv(
  1029. Point.y,
  1030. USER_DEFAULT_SCREEN_DPI,
  1031. WIN32DRV_MONITOR_ZOOM * context->display_dpi);
  1032. DWORD MousePressedMask =
  1033. TOUCHEVENTF_MOVE | TOUCHEVENTF_DOWN;
  1034. context->mouse_state = (
  1035. pInputs[i].dwFlags & MousePressedMask
  1036. ? LV_INDEV_STATE_PR
  1037. : LV_INDEV_STATE_REL);
  1038. }
  1039. }
  1040. free(pInputs);
  1041. }
  1042. lv_win32_close_touch_input_handle(hTouchInput);
  1043. }
  1044. break;
  1045. }
  1046. case WM_DPICHANGED:
  1047. {
  1048. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  1049. lv_win32_get_window_context(hWnd));
  1050. if (context)
  1051. {
  1052. context->display_dpi = HIWORD(wParam);
  1053. LPRECT SuggestedRect = (LPRECT)lParam;
  1054. SetWindowPos(
  1055. hWnd,
  1056. NULL,
  1057. SuggestedRect->left,
  1058. SuggestedRect->top,
  1059. SuggestedRect->right,
  1060. SuggestedRect->bottom,
  1061. SWP_NOZORDER | SWP_NOACTIVATE);
  1062. RECT ClientRect;
  1063. GetClientRect(hWnd, &ClientRect);
  1064. int WindowWidth = MulDiv(
  1065. context->display_hor_res * WIN32DRV_MONITOR_ZOOM,
  1066. context->display_dpi,
  1067. USER_DEFAULT_SCREEN_DPI);
  1068. int WindowHeight = MulDiv(
  1069. context->display_ver_res * WIN32DRV_MONITOR_ZOOM,
  1070. context->display_dpi,
  1071. USER_DEFAULT_SCREEN_DPI);
  1072. SetWindowPos(
  1073. hWnd,
  1074. NULL,
  1075. SuggestedRect->left,
  1076. SuggestedRect->top,
  1077. SuggestedRect->right + (WindowWidth - ClientRect.right),
  1078. SuggestedRect->bottom + (WindowHeight - ClientRect.bottom),
  1079. SWP_NOZORDER | SWP_NOACTIVATE);
  1080. }
  1081. break;
  1082. }
  1083. case WM_PAINT:
  1084. {
  1085. PAINTSTRUCT ps;
  1086. HDC hdc = BeginPaint(hWnd, &ps);
  1087. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  1088. lv_win32_get_window_context(hWnd));
  1089. if (context)
  1090. {
  1091. if (context->display_framebuffer_context_handle)
  1092. {
  1093. SetStretchBltMode(hdc, HALFTONE);
  1094. StretchBlt(
  1095. hdc,
  1096. ps.rcPaint.left,
  1097. ps.rcPaint.top,
  1098. ps.rcPaint.right - ps.rcPaint.left,
  1099. ps.rcPaint.bottom - ps.rcPaint.top,
  1100. context->display_framebuffer_context_handle,
  1101. 0,
  1102. 0,
  1103. MulDiv(
  1104. ps.rcPaint.right - ps.rcPaint.left,
  1105. USER_DEFAULT_SCREEN_DPI,
  1106. WIN32DRV_MONITOR_ZOOM * context->display_dpi),
  1107. MulDiv(
  1108. ps.rcPaint.bottom - ps.rcPaint.top,
  1109. USER_DEFAULT_SCREEN_DPI,
  1110. WIN32DRV_MONITOR_ZOOM * context->display_dpi),
  1111. SRCCOPY);
  1112. }
  1113. }
  1114. EndPaint(hWnd, &ps);
  1115. break;
  1116. }
  1117. case WM_DESTROY:
  1118. {
  1119. lv_win32_window_context_t* context = (lv_win32_window_context_t*)(
  1120. RemovePropW(hWnd, L"LVGL.SimulatorWindow.WindowContext"));
  1121. if (context)
  1122. {
  1123. lv_disp_t* display_device_object = context->display_device_object;
  1124. context->display_device_object = NULL;
  1125. lv_disp_remove(display_device_object);
  1126. #if (LV_COLOR_DEPTH == 32) || \
  1127. (LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0) || \
  1128. (LV_COLOR_DEPTH == 8) || \
  1129. (LV_COLOR_DEPTH == 1)
  1130. #else
  1131. free(context->display_buffer.buf1);
  1132. #endif
  1133. DeleteDC(context->display_framebuffer_context_handle);
  1134. lv_indev_t* mouse_device_object =
  1135. context->mouse_device_object;
  1136. context->mouse_device_object = NULL;
  1137. lv_indev_delete(mouse_device_object);
  1138. lv_indev_t* mousewheel_device_object =
  1139. context->mousewheel_device_object;
  1140. context->mousewheel_device_object = NULL;
  1141. lv_indev_delete(mousewheel_device_object);
  1142. lv_indev_t* keyboard_device_object =
  1143. context->keyboard_device_object;
  1144. context->keyboard_device_object = NULL;
  1145. lv_indev_delete(keyboard_device_object);
  1146. do
  1147. {
  1148. PSLIST_ENTRY current = InterlockedPopEntrySList(
  1149. context->keyboard_queue);
  1150. if (!current)
  1151. {
  1152. _aligned_free(context->keyboard_queue);
  1153. context->keyboard_queue = NULL;
  1154. break;
  1155. }
  1156. _aligned_free(current);
  1157. } while (true);
  1158. DeleteCriticalSection(&context->keyboard_mutex);
  1159. free(context);
  1160. }
  1161. PostQuitMessage(0);
  1162. break;
  1163. }
  1164. default:
  1165. return DefWindowProcW(hWnd, uMsg, wParam, lParam);
  1166. }
  1167. return 0;
  1168. }
  1169. static unsigned int __stdcall lv_win32_window_thread_entrypoint(
  1170. void* raw_parameter)
  1171. {
  1172. PWINDOW_THREAD_PARAMETER parameter =
  1173. (PWINDOW_THREAD_PARAMETER)raw_parameter;
  1174. g_window_handle = lv_win32_create_display_window(
  1175. L"LVGL Simulator for Windows Desktop (Display 1)",
  1176. parameter->hor_res,
  1177. parameter->ver_res,
  1178. parameter->instance_handle,
  1179. parameter->icon_handle,
  1180. parameter->show_window_mode);
  1181. if (!g_window_handle)
  1182. {
  1183. return 0;
  1184. }
  1185. SetEvent(parameter->window_mutex);
  1186. MSG message;
  1187. while (GetMessageW(&message, NULL, 0, 0))
  1188. {
  1189. TranslateMessage(&message);
  1190. DispatchMessageW(&message);
  1191. }
  1192. lv_win32_quit_signal = true;
  1193. return 0;
  1194. }
  1195. #endif /*USE_WIN32DRV*/