825 lines
21 KiB
C
825 lines
21 KiB
C
|
/**
|
|||
|
* @file win32drv.c
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
/*********************
|
|||
|
* INCLUDES
|
|||
|
*********************/
|
|||
|
|
|||
|
#include "win32drv.h"
|
|||
|
|
|||
|
#if USE_WIN32DRV
|
|||
|
|
|||
|
#include <windowsx.h>
|
|||
|
#include <VersionHelpers.h>
|
|||
|
|
|||
|
#include <stdbool.h>
|
|||
|
#include <stdint.h>
|
|||
|
|
|||
|
lv_indev_t * indev_keypad;
|
|||
|
|
|||
|
|
|||
|
/*********************
|
|||
|
* DEFINES
|
|||
|
*********************/
|
|||
|
#define WINDOW_EX_STYLE \
|
|||
|
WS_EX_CLIENTEDGE
|
|||
|
|
|||
|
#define WINDOW_STYLE \
|
|||
|
(WS_OVERLAPPEDWINDOW & ~(WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME))
|
|||
|
|
|||
|
#ifndef WIN32DRV_MONITOR_ZOOM
|
|||
|
#define WIN32DRV_MONITOR_ZOOM 1
|
|||
|
#endif
|
|||
|
|
|||
|
/**********************
|
|||
|
* TYPEDEFS
|
|||
|
**********************/
|
|||
|
|
|||
|
/**********************
|
|||
|
* STATIC PROTOTYPES
|
|||
|
**********************/
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Creates a B8G8R8A8 frame buffer.
|
|||
|
* @param WindowHandle A handle to the window for the creation of the frame
|
|||
|
* buffer. If this value is NULL, the entire screen will be
|
|||
|
* referenced.
|
|||
|
* @param Width The width of the frame buffer.
|
|||
|
* @param Height The height of the frame buffer.
|
|||
|
* @param PixelBuffer The raw pixel buffer of the frame buffer you created.
|
|||
|
* @param PixelBufferSize The size of the frame buffer you created.
|
|||
|
* @return If the function succeeds, the return value is a handle to the device
|
|||
|
* context (DC) for the frame buffer. If the function fails, the return
|
|||
|
* value is NULL, and PixelBuffer parameter is NULL.
|
|||
|
*/
|
|||
|
static HDC lv_win32_create_frame_buffer(
|
|||
|
_In_opt_ HWND WindowHandle,
|
|||
|
_In_ LONG Width,
|
|||
|
_In_ LONG Height,
|
|||
|
_Out_ UINT32** PixelBuffer,
|
|||
|
_Out_ SIZE_T* PixelBufferSize);
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Enables WM_DPICHANGED message for child window for the associated
|
|||
|
* window.
|
|||
|
* @param WindowHandle The window you want to enable WM_DPICHANGED message for
|
|||
|
* child window.
|
|||
|
* @return If the function succeeds, the return value is non-zero. If the
|
|||
|
* function fails, the return value is zero.
|
|||
|
* @remarks You need to use this function in Windows 10 Threshold 1 or Windows
|
|||
|
* 10 Threshold 2.
|
|||
|
*/
|
|||
|
static BOOL lv_win32_enable_child_window_dpi_message(
|
|||
|
_In_ HWND WindowHandle);
|
|||
|
|
|||
|
static void lv_win32_display_driver_flush_callback(
|
|||
|
lv_disp_drv_t* disp_drv,
|
|||
|
const lv_area_t* area,
|
|||
|
lv_color_t* color_p);
|
|||
|
|
|||
|
static void lv_win32_display_driver_rounder_callback(
|
|||
|
lv_disp_drv_t* disp_drv,
|
|||
|
lv_area_t* area);
|
|||
|
|
|||
|
static void lv_win32_mouse_driver_read_callback(
|
|||
|
lv_indev_drv_t* indev_drv,
|
|||
|
lv_indev_data_t* data);
|
|||
|
|
|||
|
static void lv_win32_keyboard_driver_read_callback(
|
|||
|
lv_indev_drv_t* indev_drv,
|
|||
|
lv_indev_data_t* data);
|
|||
|
|
|||
|
static void lv_win32_mousewheel_driver_read_callback(
|
|||
|
lv_indev_drv_t* indev_drv,
|
|||
|
lv_indev_data_t* data);
|
|||
|
|
|||
|
static LRESULT CALLBACK lv_win32_window_message_callback(
|
|||
|
HWND hWnd,
|
|||
|
UINT uMsg,
|
|||
|
WPARAM wParam,
|
|||
|
LPARAM lParam);
|
|||
|
|
|||
|
#if LV_VERSION_CHECK(8, 0, 0)
|
|||
|
static void lv_win32_message_handler(
|
|||
|
lv_timer_t* param);
|
|||
|
#else
|
|||
|
static void lv_win32_message_handler(
|
|||
|
lv_task_t* param);
|
|||
|
#endif
|
|||
|
|
|||
|
/**********************
|
|||
|
* GLOBAL VARIABLES
|
|||
|
**********************/
|
|||
|
|
|||
|
EXTERN_C bool lv_win32_quit_signal = false;
|
|||
|
|
|||
|
EXTERN_C lv_indev_t* lv_win32_pointer_device_object = NULL;
|
|||
|
EXTERN_C lv_indev_t* lv_win32_keypad_device_object = NULL;
|
|||
|
EXTERN_C lv_indev_t* lv_win32_encoder_device_object = NULL;
|
|||
|
|
|||
|
#ifndef USER_DEFAULT_SCREEN_DPI
|
|||
|
#define USER_DEFAULT_SCREEN_DPI 96
|
|||
|
#endif
|
|||
|
|
|||
|
static int volatile g_dpi_value = USER_DEFAULT_SCREEN_DPI;
|
|||
|
|
|||
|
/**********************
|
|||
|
* STATIC VARIABLES
|
|||
|
**********************/
|
|||
|
|
|||
|
static HINSTANCE g_instance_handle = NULL;
|
|||
|
static HWND g_window_handle = NULL;
|
|||
|
|
|||
|
static HDC g_buffer_dc_handle = NULL;
|
|||
|
static UINT32* g_pixel_buffer = NULL;
|
|||
|
static SIZE_T g_pixel_buffer_size = 0;
|
|||
|
|
|||
|
static lv_disp_t* g_display = NULL;
|
|||
|
|
|||
|
static bool volatile g_mouse_pressed = false;
|
|||
|
static LPARAM volatile g_mouse_value = 0;
|
|||
|
|
|||
|
static bool volatile g_mousewheel_pressed = false;
|
|||
|
static int16_t volatile g_mousewheel_value = 0;
|
|||
|
|
|||
|
static bool volatile g_keyboard_pressed = false;
|
|||
|
static WPARAM volatile g_keyboard_value = 0;
|
|||
|
|
|||
|
/**********************
|
|||
|
* MACROS
|
|||
|
**********************/
|
|||
|
|
|||
|
/**********************
|
|||
|
* GLOBAL FUNCTIONS
|
|||
|
**********************/
|
|||
|
|
|||
|
EXTERN_C void lv_win32_add_all_input_devices_to_group(
|
|||
|
lv_group_t* group)
|
|||
|
{
|
|||
|
if (!group)
|
|||
|
{
|
|||
|
LV_LOG_WARN(
|
|||
|
"The group object is NULL. Get the default group object instead.");
|
|||
|
|
|||
|
group = lv_group_get_default();
|
|||
|
if (!group)
|
|||
|
{
|
|||
|
LV_LOG_WARN(
|
|||
|
"The default group object is NULL. Create a new group object "
|
|||
|
"and set it to default instead.");
|
|||
|
|
|||
|
group = lv_group_create();
|
|||
|
if (group)
|
|||
|
{
|
|||
|
lv_group_set_default(group);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LV_ASSERT_MSG(group, "Cannot obtain an available group object.");
|
|||
|
|
|||
|
lv_indev_set_group(lv_win32_pointer_device_object, group);
|
|||
|
lv_indev_set_group(lv_win32_keypad_device_object, group);
|
|||
|
lv_indev_set_group(lv_win32_encoder_device_object, group);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
static void lv_win32_pointer_driver_read_callback(
|
|||
|
lv_indev_drv_t* indev_drv,
|
|||
|
lv_indev_data_t* data)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(indev_drv);
|
|||
|
|
|||
|
data->state = (lv_indev_state_t)(
|
|||
|
g_mouse_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
|
|||
|
|
|||
|
data->point.x = MulDiv(
|
|||
|
GET_X_LPARAM(g_mouse_value),
|
|||
|
USER_DEFAULT_SCREEN_DPI,
|
|||
|
WIN32DRV_MONITOR_ZOOM * g_dpi_value);
|
|||
|
data->point.y = MulDiv(
|
|||
|
GET_Y_LPARAM(g_mouse_value),
|
|||
|
USER_DEFAULT_SCREEN_DPI,
|
|||
|
WIN32DRV_MONITOR_ZOOM * g_dpi_value);
|
|||
|
|
|||
|
if (data->point.x < 0)
|
|||
|
{
|
|||
|
data->point.x = 0;
|
|||
|
}
|
|||
|
if (data->point.x > g_display->driver->hor_res - 1)
|
|||
|
{
|
|||
|
data->point.x = g_display->driver->hor_res - 1;
|
|||
|
}
|
|||
|
if (data->point.y < 0)
|
|||
|
{
|
|||
|
data->point.y = 0;
|
|||
|
}
|
|||
|
if (data->point.y > g_display->driver->ver_res - 1)
|
|||
|
{
|
|||
|
data->point.y = g_display->driver->ver_res - 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void lv_win32_keypad_driver_read_callback(
|
|||
|
lv_indev_drv_t* indev_drv,
|
|||
|
lv_indev_data_t* data)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(indev_drv);
|
|||
|
|
|||
|
data->state = (lv_indev_state_t)(
|
|||
|
g_keyboard_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
|
|||
|
|
|||
|
WPARAM KeyboardValue = g_keyboard_value;
|
|||
|
|
|||
|
switch (KeyboardValue)
|
|||
|
{
|
|||
|
case VK_UP:
|
|||
|
data->key = LV_KEY_UP;
|
|||
|
break;
|
|||
|
case VK_DOWN:
|
|||
|
data->key = LV_KEY_DOWN;
|
|||
|
break;
|
|||
|
case VK_LEFT:
|
|||
|
data->key = LV_KEY_LEFT;
|
|||
|
break;
|
|||
|
case VK_RIGHT:
|
|||
|
data->key = LV_KEY_RIGHT;
|
|||
|
break;
|
|||
|
case VK_ESCAPE:
|
|||
|
data->key = LV_KEY_ESC;
|
|||
|
break;
|
|||
|
case VK_DELETE:
|
|||
|
data->key = LV_KEY_DEL;
|
|||
|
break;
|
|||
|
case VK_BACK:
|
|||
|
data->key = LV_KEY_BACKSPACE;
|
|||
|
break;
|
|||
|
case VK_RETURN:
|
|||
|
data->key = LV_KEY_ENTER;
|
|||
|
break;
|
|||
|
case VK_NEXT:
|
|||
|
data->key = LV_KEY_NEXT;
|
|||
|
break;
|
|||
|
case VK_PRIOR:
|
|||
|
data->key = LV_KEY_PREV;
|
|||
|
break;
|
|||
|
case VK_HOME:
|
|||
|
data->key = LV_KEY_HOME;
|
|||
|
break;
|
|||
|
case VK_END:
|
|||
|
data->key = LV_KEY_END;
|
|||
|
break;
|
|||
|
default:
|
|||
|
if (KeyboardValue >= 'A' && KeyboardValue <= 'Z')
|
|||
|
{
|
|||
|
KeyboardValue += 0x20;
|
|||
|
}
|
|||
|
|
|||
|
data->key = (uint32_t)KeyboardValue;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
static void lv_win32_encoder_driver_read_callback(
|
|||
|
lv_indev_drv_t* indev_drv,
|
|||
|
lv_indev_data_t* data)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(indev_drv);
|
|||
|
|
|||
|
data->state = (lv_indev_state_t)(
|
|||
|
g_mousewheel_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
|
|||
|
data->enc_diff = g_mousewheel_value;
|
|||
|
g_mousewheel_value = 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
EXTERN_C bool lv_win32_init(
|
|||
|
HINSTANCE instance_handle,
|
|||
|
int show_window_mode,
|
|||
|
lv_coord_t hor_res,
|
|||
|
lv_coord_t ver_res,
|
|||
|
HICON icon_handle)
|
|||
|
{
|
|||
|
WNDCLASSEXW WindowClass;
|
|||
|
|
|||
|
WindowClass.cbSize = sizeof(WNDCLASSEX);
|
|||
|
|
|||
|
WindowClass.style = 0;
|
|||
|
WindowClass.lpfnWndProc = lv_win32_window_message_callback;
|
|||
|
WindowClass.cbClsExtra = 0;
|
|||
|
WindowClass.cbWndExtra = 0;
|
|||
|
WindowClass.hInstance = instance_handle;
|
|||
|
WindowClass.hIcon = icon_handle;
|
|||
|
WindowClass.hCursor = LoadCursorW(NULL, IDC_ARROW);
|
|||
|
WindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|||
|
WindowClass.lpszMenuName = NULL;
|
|||
|
WindowClass.lpszClassName = L"lv_sim_visual_studio";
|
|||
|
WindowClass.hIconSm = icon_handle;
|
|||
|
|
|||
|
if (!RegisterClassExW(&WindowClass))
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
g_instance_handle = instance_handle;
|
|||
|
|
|||
|
RECT NewWindowSize;
|
|||
|
|
|||
|
NewWindowSize.left = 0;
|
|||
|
NewWindowSize.right = hor_res * WIN32DRV_MONITOR_ZOOM;
|
|||
|
NewWindowSize.top = 0;
|
|||
|
NewWindowSize.bottom = ver_res * WIN32DRV_MONITOR_ZOOM;
|
|||
|
|
|||
|
AdjustWindowRectEx(
|
|||
|
&NewWindowSize,
|
|||
|
WINDOW_STYLE,
|
|||
|
FALSE,
|
|||
|
WINDOW_EX_STYLE);
|
|||
|
OffsetRect(
|
|||
|
&NewWindowSize,
|
|||
|
-NewWindowSize.left,
|
|||
|
-NewWindowSize.top);
|
|||
|
|
|||
|
g_window_handle = CreateWindowExW(
|
|||
|
WINDOW_EX_STYLE,
|
|||
|
WindowClass.lpszClassName,
|
|||
|
L"LVGL Simulator for Windows Desktop",
|
|||
|
WINDOW_STYLE,
|
|||
|
CW_USEDEFAULT,
|
|||
|
0,
|
|||
|
NewWindowSize.right,
|
|||
|
NewWindowSize.bottom,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
instance_handle,
|
|||
|
NULL);
|
|||
|
|
|||
|
if (!g_window_handle)
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
#if LV_VERSION_CHECK(8, 0, 0)
|
|||
|
lv_timer_create(lv_win32_message_handler, 0, NULL);
|
|||
|
#else
|
|||
|
lv_task_create(lv_win32_message_handler, 0, LV_TASK_PRIO_HIGHEST, NULL);
|
|||
|
#endif
|
|||
|
|
|||
|
lv_win32_enable_child_window_dpi_message(g_window_handle);
|
|||
|
|
|||
|
HDC hNewBufferDC = lv_win32_create_frame_buffer(
|
|||
|
g_window_handle,
|
|||
|
hor_res,
|
|||
|
ver_res,
|
|||
|
&g_pixel_buffer,
|
|||
|
&g_pixel_buffer_size);
|
|||
|
|
|||
|
DeleteDC(g_buffer_dc_handle);
|
|||
|
g_buffer_dc_handle = hNewBufferDC;
|
|||
|
|
|||
|
#if LV_VERSION_CHECK(8, 0, 0)
|
|||
|
static lv_disp_draw_buf_t disp_buf;
|
|||
|
lv_disp_draw_buf_init(
|
|||
|
&disp_buf,
|
|||
|
(lv_color_t*)malloc(hor_res * ver_res * sizeof(lv_color_t)),
|
|||
|
NULL,
|
|||
|
hor_res * ver_res);
|
|||
|
|
|||
|
static lv_disp_drv_t disp_drv;
|
|||
|
lv_disp_drv_init(&disp_drv);
|
|||
|
disp_drv.hor_res = hor_res;
|
|||
|
disp_drv.ver_res = ver_res;
|
|||
|
disp_drv.flush_cb = lv_win32_display_driver_flush_callback;
|
|||
|
disp_drv.draw_buf = &disp_buf;
|
|||
|
disp_drv.rounder_cb = lv_win32_display_driver_rounder_callback;
|
|||
|
g_display = lv_disp_drv_register(&disp_drv);
|
|||
|
|
|||
|
static lv_indev_drv_t indev_drv;
|
|||
|
lv_indev_drv_init(&indev_drv);
|
|||
|
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
|||
|
indev_drv.read_cb = lv_win32_mouse_driver_read_callback;
|
|||
|
lv_indev_drv_register(&indev_drv);
|
|||
|
|
|||
|
static lv_indev_drv_t kb_drv;
|
|||
|
lv_indev_drv_init(&kb_drv);
|
|||
|
kb_drv.type = LV_INDEV_TYPE_KEYPAD;
|
|||
|
kb_drv.read_cb = lv_win32_keyboard_driver_read_callback;
|
|||
|
// lv_indev_drv_register(&kb_drv);
|
|||
|
indev_keypad = lv_indev_drv_register(&kb_drv);
|
|||
|
|
|||
|
static lv_indev_drv_t enc_drv;
|
|||
|
lv_indev_drv_init(&enc_drv);
|
|||
|
enc_drv.type = LV_INDEV_TYPE_ENCODER;
|
|||
|
enc_drv.read_cb = lv_win32_mousewheel_driver_read_callback;
|
|||
|
lv_indev_drv_register(&enc_drv);
|
|||
|
#else
|
|||
|
static lv_disp_buf_t disp_buf;
|
|||
|
lv_disp_buf_init(
|
|||
|
&disp_buf,
|
|||
|
(lv_color_t*)malloc(hor_res * ver_res * sizeof(lv_color_t)),
|
|||
|
NULL,
|
|||
|
hor_res * ver_res);
|
|||
|
|
|||
|
lv_disp_drv_t disp_drv;
|
|||
|
lv_disp_drv_init(&disp_drv);
|
|||
|
disp_drv.hor_res = hor_res;
|
|||
|
disp_drv.ver_res = ver_res;
|
|||
|
disp_drv.flush_cb = lv_win32_display_driver_flush_callback;
|
|||
|
disp_drv.buffer = &disp_buf;
|
|||
|
disp_drv.rounder_cb = lv_win32_display_driver_rounder_callback;
|
|||
|
g_display = lv_disp_drv_register(&disp_drv);
|
|||
|
|
|||
|
lv_indev_drv_t indev_drv;
|
|||
|
lv_indev_drv_init(&indev_drv);
|
|||
|
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
|||
|
indev_drv.read_cb = lv_win32_mouse_driver_read_callback;
|
|||
|
lv_indev_drv_register(&indev_drv);
|
|||
|
|
|||
|
lv_indev_drv_t kb_drv;
|
|||
|
lv_indev_drv_init(&kb_drv);
|
|||
|
kb_drv.type = LV_INDEV_TYPE_KEYPAD;
|
|||
|
kb_drv.read_cb = lv_win32_keyboard_driver_read_callback;
|
|||
|
lv_indev_drv_register(&kb_drv);
|
|||
|
|
|||
|
lv_indev_drv_t enc_drv;
|
|||
|
lv_indev_drv_init(&enc_drv);
|
|||
|
enc_drv.type = LV_INDEV_TYPE_ENCODER;
|
|||
|
enc_drv.read_cb = lv_win32_mousewheel_driver_read_callback;
|
|||
|
lv_indev_drv_register(&enc_drv);
|
|||
|
#endif
|
|||
|
|
|||
|
ShowWindow(g_window_handle, show_window_mode);
|
|||
|
UpdateWindow(g_window_handle);
|
|||
|
|
|||
|
static lv_indev_drv_t pointer_driver;
|
|||
|
lv_indev_drv_init(&pointer_driver);
|
|||
|
pointer_driver.type = LV_INDEV_TYPE_POINTER;
|
|||
|
pointer_driver.read_cb = lv_win32_pointer_driver_read_callback;
|
|||
|
lv_win32_pointer_device_object = lv_indev_drv_register(&pointer_driver);
|
|||
|
|
|||
|
static lv_indev_drv_t keypad_driver;
|
|||
|
lv_indev_drv_init(&keypad_driver);
|
|||
|
keypad_driver.type = LV_INDEV_TYPE_KEYPAD;
|
|||
|
keypad_driver.read_cb = lv_win32_keypad_driver_read_callback;
|
|||
|
lv_win32_keypad_device_object = lv_indev_drv_register(&keypad_driver);
|
|||
|
|
|||
|
static lv_indev_drv_t encoder_driver;
|
|||
|
lv_indev_drv_init(&encoder_driver);
|
|||
|
encoder_driver.type = LV_INDEV_TYPE_ENCODER;
|
|||
|
encoder_driver.read_cb = lv_win32_encoder_driver_read_callback;
|
|||
|
lv_win32_encoder_device_object = lv_indev_drv_register(&encoder_driver);
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/**********************
|
|||
|
* STATIC FUNCTIONS
|
|||
|
**********************/
|
|||
|
|
|||
|
static HDC lv_win32_create_frame_buffer(
|
|||
|
HWND WindowHandle,
|
|||
|
LONG Width,
|
|||
|
LONG Height,
|
|||
|
UINT32** PixelBuffer,
|
|||
|
SIZE_T* PixelBufferSize)
|
|||
|
{
|
|||
|
HDC hFrameBufferDC = NULL;
|
|||
|
|
|||
|
if (PixelBuffer && PixelBufferSize)
|
|||
|
{
|
|||
|
HDC hWindowDC = GetDC(WindowHandle);
|
|||
|
if (hWindowDC)
|
|||
|
{
|
|||
|
hFrameBufferDC = CreateCompatibleDC(hWindowDC);
|
|||
|
ReleaseDC(WindowHandle, hWindowDC);
|
|||
|
}
|
|||
|
|
|||
|
if (hFrameBufferDC)
|
|||
|
{
|
|||
|
BITMAPINFO BitmapInfo = { 0 };
|
|||
|
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|||
|
BitmapInfo.bmiHeader.biWidth = Width;
|
|||
|
BitmapInfo.bmiHeader.biHeight = -Height;
|
|||
|
BitmapInfo.bmiHeader.biPlanes = 1;
|
|||
|
BitmapInfo.bmiHeader.biBitCount = 32;
|
|||
|
BitmapInfo.bmiHeader.biCompression = BI_RGB;
|
|||
|
|
|||
|
HBITMAP hBitmap = CreateDIBSection(
|
|||
|
hFrameBufferDC,
|
|||
|
&BitmapInfo,
|
|||
|
DIB_RGB_COLORS,
|
|||
|
(void**)PixelBuffer,
|
|||
|
NULL,
|
|||
|
0);
|
|||
|
if (hBitmap)
|
|||
|
{
|
|||
|
*PixelBufferSize = Width * Height * sizeof(UINT32);
|
|||
|
DeleteObject(SelectObject(hFrameBufferDC, hBitmap));
|
|||
|
DeleteObject(hBitmap);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
DeleteDC(hFrameBufferDC);
|
|||
|
hFrameBufferDC = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return hFrameBufferDC;
|
|||
|
}
|
|||
|
|
|||
|
static BOOL lv_win32_enable_child_window_dpi_message(
|
|||
|
HWND WindowHandle)
|
|||
|
{
|
|||
|
// This hack is only for Windows 10 only.
|
|||
|
if (!IsWindowsVersionOrGreater(10, 0, 0))
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// We don't need this hack if the Per Monitor Aware V2 is existed.
|
|||
|
OSVERSIONINFOEXW OSVersionInfoEx = { 0 };
|
|||
|
OSVersionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
|
|||
|
OSVersionInfoEx.dwBuildNumber = 14393;
|
|||
|
if (VerifyVersionInfoW(
|
|||
|
&OSVersionInfoEx,
|
|||
|
VER_BUILDNUMBER,
|
|||
|
VerSetConditionMask(0, VER_BUILDNUMBER, VER_GREATER_EQUAL)))
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
HMODULE ModuleHandle = GetModuleHandleW(L"user32.dll");
|
|||
|
if (!ModuleHandle)
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
typedef BOOL(WINAPI* FunctionType)(HWND, BOOL);
|
|||
|
|
|||
|
FunctionType pFunction = (FunctionType)(
|
|||
|
GetProcAddress(ModuleHandle, "EnableChildWindowDpiMessage"));
|
|||
|
if (!pFunction)
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return pFunction(WindowHandle, TRUE);
|
|||
|
}
|
|||
|
uint16_t rgb565_to_bgr(uint16_t rgb565) {
|
|||
|
unsigned char r = (rgb565 >> 11) & 0x1F; // 取出高5位,代表红色
|
|||
|
unsigned char g = (rgb565 >> 5) & 0x3F; // 取出中间6位,代表绿色
|
|||
|
unsigned char b = rgb565 & 0x1F; // 取出低5位,代表蓝
|
|||
|
uint16_t bgr565 = (b << 11) | (g << 5) | r;
|
|||
|
return bgr565;
|
|||
|
}
|
|||
|
static void lv_win32_display_driver_flush_callback(
|
|||
|
lv_disp_drv_t* disp_drv,
|
|||
|
const lv_area_t* area,
|
|||
|
lv_color_t* color_p)
|
|||
|
{
|
|||
|
#if LV_COLOR_DEPTH == 32
|
|||
|
UNREFERENCED_PARAMETER(area);
|
|||
|
memcpy(g_pixel_buffer, color_p, g_pixel_buffer_size);
|
|||
|
#else
|
|||
|
for (int y = area->y1; y <= area->y2; ++y)
|
|||
|
{
|
|||
|
for (int x = area->x1; x <= area->x2; ++x)
|
|||
|
{
|
|||
|
g_pixel_buffer[y * disp_drv->hor_res + x] = lv_color_to32(*color_p);
|
|||
|
|
|||
|
color_p++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
HDC hWindowDC = GetDC(g_window_handle);
|
|||
|
if (hWindowDC)
|
|||
|
{
|
|||
|
StretchBlt(
|
|||
|
hWindowDC,
|
|||
|
0,
|
|||
|
0,
|
|||
|
disp_drv->hor_res * WIN32DRV_MONITOR_ZOOM,
|
|||
|
disp_drv->ver_res * WIN32DRV_MONITOR_ZOOM,
|
|||
|
g_buffer_dc_handle,
|
|||
|
0,
|
|||
|
0,
|
|||
|
disp_drv->hor_res,
|
|||
|
disp_drv->ver_res,
|
|||
|
SRCCOPY);
|
|||
|
|
|||
|
ReleaseDC(g_window_handle, hWindowDC);
|
|||
|
}
|
|||
|
|
|||
|
lv_disp_flush_ready(disp_drv);
|
|||
|
}
|
|||
|
|
|||
|
static void lv_win32_display_driver_rounder_callback(
|
|||
|
lv_disp_drv_t* disp_drv,
|
|||
|
lv_area_t* area)
|
|||
|
{
|
|||
|
area->x1 = 0;
|
|||
|
area->x2 = disp_drv->hor_res - 1;
|
|||
|
area->y1 = 0;
|
|||
|
area->y2 = disp_drv->ver_res - 1;
|
|||
|
}
|
|||
|
|
|||
|
static void lv_win32_mouse_driver_read_callback(
|
|||
|
lv_indev_drv_t* indev_drv,
|
|||
|
lv_indev_data_t* data)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(indev_drv);
|
|||
|
|
|||
|
data->state = (lv_indev_state_t)(
|
|||
|
g_mouse_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
|
|||
|
data->point.x = GET_X_LPARAM(g_mouse_value) / WIN32DRV_MONITOR_ZOOM;
|
|||
|
data->point.y = GET_Y_LPARAM(g_mouse_value) / WIN32DRV_MONITOR_ZOOM;
|
|||
|
}
|
|||
|
|
|||
|
static void lv_win32_keyboard_driver_read_callback(
|
|||
|
lv_indev_drv_t* indev_drv,
|
|||
|
lv_indev_data_t* data)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(indev_drv);
|
|||
|
|
|||
|
data->state = (lv_indev_state_t)(
|
|||
|
g_keyboard_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
|
|||
|
|
|||
|
WPARAM KeyboardValue = g_keyboard_value;
|
|||
|
|
|||
|
switch (KeyboardValue)
|
|||
|
{
|
|||
|
case VK_UP:
|
|||
|
data->key = LV_KEY_UP;
|
|||
|
break;
|
|||
|
case VK_DOWN:
|
|||
|
data->key = LV_KEY_DOWN;
|
|||
|
break;
|
|||
|
case VK_LEFT:
|
|||
|
data->key = LV_KEY_LEFT;
|
|||
|
break;
|
|||
|
case VK_RIGHT:
|
|||
|
data->key = LV_KEY_RIGHT;
|
|||
|
break;
|
|||
|
case VK_ESCAPE:
|
|||
|
data->key = LV_KEY_ESC;
|
|||
|
break;
|
|||
|
case VK_DELETE:
|
|||
|
data->key = LV_KEY_DEL;
|
|||
|
break;
|
|||
|
case VK_BACK:
|
|||
|
data->key = LV_KEY_BACKSPACE;
|
|||
|
break;
|
|||
|
case VK_RETURN:
|
|||
|
data->key = LV_KEY_ENTER;
|
|||
|
break;
|
|||
|
case VK_NEXT:
|
|||
|
data->key = LV_KEY_NEXT;
|
|||
|
break;
|
|||
|
case VK_PRIOR:
|
|||
|
data->key = LV_KEY_PREV;
|
|||
|
break;
|
|||
|
case VK_HOME:
|
|||
|
data->key = LV_KEY_HOME;
|
|||
|
break;
|
|||
|
case VK_END:
|
|||
|
data->key = LV_KEY_END;
|
|||
|
break;
|
|||
|
default:
|
|||
|
if (KeyboardValue >= 'A' && KeyboardValue <= 'Z')
|
|||
|
{
|
|||
|
KeyboardValue += 0x20;
|
|||
|
}
|
|||
|
|
|||
|
data->key = (uint32_t)KeyboardValue;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void lv_win32_mousewheel_driver_read_callback(
|
|||
|
lv_indev_drv_t* indev_drv,
|
|||
|
lv_indev_data_t* data)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(indev_drv);
|
|||
|
|
|||
|
data->state = (lv_indev_state_t)(
|
|||
|
g_mousewheel_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL);
|
|||
|
data->enc_diff = g_mousewheel_value;
|
|||
|
g_mousewheel_value = 0;
|
|||
|
}
|
|||
|
|
|||
|
static LRESULT CALLBACK lv_win32_window_message_callback(
|
|||
|
HWND hWnd,
|
|||
|
UINT uMsg,
|
|||
|
WPARAM wParam,
|
|||
|
LPARAM lParam)
|
|||
|
{
|
|||
|
switch (uMsg)
|
|||
|
{
|
|||
|
case WM_MOUSEMOVE:
|
|||
|
case WM_LBUTTONDOWN:
|
|||
|
case WM_LBUTTONUP:
|
|||
|
case WM_MBUTTONDOWN:
|
|||
|
case WM_MBUTTONUP:
|
|||
|
{
|
|||
|
g_mouse_value = lParam;
|
|||
|
if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
|
|||
|
{
|
|||
|
g_mouse_pressed = (uMsg == WM_LBUTTONDOWN);
|
|||
|
}
|
|||
|
else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP)
|
|||
|
{
|
|||
|
g_mousewheel_pressed = (uMsg == WM_MBUTTONDOWN);
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
case WM_KEYDOWN:
|
|||
|
case WM_KEYUP:
|
|||
|
{
|
|||
|
g_keyboard_pressed = (uMsg == WM_KEYDOWN);
|
|||
|
g_keyboard_value = wParam;
|
|||
|
break;
|
|||
|
}
|
|||
|
case WM_MOUSEWHEEL:
|
|||
|
{
|
|||
|
g_mousewheel_value = -(GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA);
|
|||
|
break;
|
|||
|
}
|
|||
|
case WM_DPICHANGED:
|
|||
|
{
|
|||
|
LPRECT SuggestedRect = (LPRECT)lParam;
|
|||
|
|
|||
|
SetWindowPos(
|
|||
|
hWnd,
|
|||
|
NULL,
|
|||
|
SuggestedRect->left,
|
|||
|
SuggestedRect->top,
|
|||
|
SuggestedRect->right,
|
|||
|
SuggestedRect->bottom,
|
|||
|
SWP_NOZORDER | SWP_NOACTIVATE);
|
|||
|
|
|||
|
RECT ClientRect;
|
|||
|
GetClientRect(hWnd, &ClientRect);
|
|||
|
|
|||
|
#if LV_VERSION_CHECK(8, 0, 0)
|
|||
|
int WindowWidth = g_display->driver->hor_res;
|
|||
|
int WindowHeight = g_display->driver->ver_res;
|
|||
|
#else
|
|||
|
int WindowWidth = g_display->driver.hor_res;
|
|||
|
int WindowHeight = g_display->driver.ver_res;
|
|||
|
#endif
|
|||
|
|
|||
|
SetWindowPos(
|
|||
|
hWnd,
|
|||
|
NULL,
|
|||
|
SuggestedRect->left,
|
|||
|
SuggestedRect->top,
|
|||
|
SuggestedRect->right + (WindowWidth - ClientRect.right),
|
|||
|
SuggestedRect->bottom + (WindowHeight - ClientRect.bottom),
|
|||
|
SWP_NOZORDER | SWP_NOACTIVATE);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
case WM_DESTROY:
|
|||
|
PostQuitMessage(0);
|
|||
|
break;
|
|||
|
default:
|
|||
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
#if LV_VERSION_CHECK(8, 0, 0)
|
|||
|
static void lv_win32_message_handler(
|
|||
|
lv_timer_t* param)
|
|||
|
#else
|
|||
|
static void lv_win32_message_handler(
|
|||
|
lv_task_t* param)
|
|||
|
#endif
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(param);
|
|||
|
|
|||
|
MSG Message;
|
|||
|
BOOL Result = PeekMessageW(&Message, NULL, 0, 0, TRUE);
|
|||
|
if (Result != 0 && Result != -1)
|
|||
|
{
|
|||
|
TranslateMessage(&Message);
|
|||
|
DispatchMessageW(&Message);
|
|||
|
|
|||
|
if (Message.message == WM_QUIT)
|
|||
|
{
|
|||
|
lv_win32_quit_signal = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif /*USE_WIN32DRV*/
|