slint/examples/cpp/platform_native/windowadapter_win.h
crai0 3f3ac7e347
common: add support for back and forward pointing-device buttons (#6149)
Closes #6043

ChangeLog: add support for back and forward pointing-device buttons
2024-09-18 07:48:30 +02:00

183 lines
5.8 KiB
C++

// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: MIT
#pragma once
#include <optional>
#include <slint-platform.h>
#include "appview.h"
#include <cassert>
#include <windows.h>
struct Geometry
{
int x = 0;
int y = 0;
uint32_t width = 0;
uint32_t height = 0;
};
struct MyWindowAdapter : public slint::platform::WindowAdapter
{
HWND hwnd;
Geometry geometry = { 0, 0, 600, 300 };
std::optional<slint::platform::SkiaRenderer> m_renderer;
MyWindowAdapter(HWND winId)
{
HINSTANCE hInstance = GetModuleHandleW(nullptr);
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = {};
wc.lpfnWndProc = MyWindowAdapter::windowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
hwnd = CreateWindowEx(0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_CHILDWINDOW, // Window style
// Size and position
0, 0, 600, 300,
winId,
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
m_renderer.emplace(slint::platform::NativeWindowHandle::from_win32(hwnd, hInstance),
slint::PhysicalSize({ 600, 300 }));
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
}
slint::platform::AbstractRenderer &renderer() override { return m_renderer.value(); }
slint::PhysicalSize size() override
{
RECT r;
GetWindowRect(hwnd, &r);
return slint::PhysicalSize({ uint32_t(r.right - r.left), uint32_t(r.bottom - r.top) });
}
void set_visible(bool visible) override { ShowWindow(hwnd, visible ? SW_SHOWNORMAL : SW_HIDE); }
void request_redraw() override { InvalidateRect(hwnd, nullptr, false); }
void render()
{
m_renderer->render();
if (window().has_active_animations())
request_redraw();
}
void resize(uint32_t width, uint32_t height)
{
window().dispatch_resize_event(slint::LogicalSize({ (float)width, (float)height }));
}
void setGeometry(int x, int y, int width, int height)
{
SetWindowPos(hwnd, nullptr, x, y, width, height, 0);
}
void mouse_event(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
using slint::LogicalPosition;
using slint::PointerEventButton;
float x = float(LOWORD(lParam));
float y = float(HIWORD(lParam));
switch (uMsg) {
case WM_LBUTTONUP:
window().dispatch_pointer_release_event(LogicalPosition({ x, y }),
PointerEventButton::Left);
break;
case WM_MBUTTONUP:
window().dispatch_pointer_release_event(LogicalPosition({ x, y }),
PointerEventButton::Middle);
break;
case WM_RBUTTONUP:
window().dispatch_pointer_release_event(LogicalPosition({ x, y }),
PointerEventButton::Right);
break;
case WM_LBUTTONDOWN:
window().dispatch_pointer_press_event(LogicalPosition({ x, y }),
PointerEventButton::Left);
break;
case WM_MBUTTONDOWN:
window().dispatch_pointer_press_event(LogicalPosition({ x, y }),
PointerEventButton::Middle);
break;
case WM_RBUTTONDOWN:
window().dispatch_pointer_press_event(LogicalPosition({ x, y }),
PointerEventButton::Right);
break;
case WM_XBUTTONDOWN:
switch (GET_XBUTTON_WPARAM(wParam)) {
case XBUTTON1:
window().dispatch_pointer_press_event(LogicalPosition({ x, y }),
PointerEventButton::Back);
break;
case XBUTTON2:
window().dispatch_pointer_press_event(LogicalPosition({ x, y }),
PointerEventButton::Forward);
break;
}
case WM_MOUSEMOVE:
window().dispatch_pointer_move_event(LogicalPosition({ x, y }));
break;
default:
break;
}
}
static LRESULT CALLBACK windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
MyWindowAdapter *self =
reinterpret_cast<MyWindowAdapter *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
if (self == nullptr) {
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT: {
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
slint::platform::update_timers_and_animations();
self->render();
EndPaint(hwnd, &ps);
return 0;
}
case WM_SIZE:
self->resize(LOWORD(lParam), HIWORD(lParam));
return 0;
case WM_LBUTTONUP:
case WM_LBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MBUTTONDOWN:
case WM_RBUTTONUP:
case WM_RBUTTONDOWN:
case WM_MOUSEMOVE:
slint::platform::update_timers_and_animations();
self->mouse_event(uMsg, wParam, lParam);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
private:
};