-
-
Save sylveon/5bc68b2801333b24f7b3165c3f098cc9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "picker.hpp" | |
#include <dwmapi.h> | |
#include <ShellScalingApi.h> | |
#include <windows.ui.xaml.hosting.desktopwindowxamlsource.h> | |
#include <winrt/Windows.UI.Xaml.Media.h> | |
using namespace winrt; | |
using namespace Windows::UI; | |
using namespace Windows::UI::Xaml; | |
extern "C" IMAGE_DOS_HEADER __ImageBase; | |
LRESULT ColorPicker::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | |
{ | |
auto pThis = reinterpret_cast<ColorPicker *>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); | |
if (uMsg == WM_NCCREATE) | |
{ | |
auto cs = reinterpret_cast<CREATESTRUCT *>(lParam); | |
pThis = static_cast<ColorPicker *>(cs->lpCreateParams); | |
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pThis)); | |
} | |
else if (pThis) | |
{ | |
switch (uMsg) | |
{ | |
case WM_NCCALCSIZE: | |
return pThis->OnNonClientCalculateSize(); | |
case WM_SIZE: | |
return pThis->OnSizeChanged(LOWORD(lParam), HIWORD(lParam)); | |
case WM_DPICHANGED: | |
return pThis->OnDpiChanged(LOWORD(wParam)); | |
case WM_DWMCOMPOSITIONCHANGED: | |
return pThis->OnCompositionChanged(); | |
} | |
} | |
return DefWindowProc(hwnd, uMsg, wParam, lParam); | |
} | |
UIElement ColorPicker::CreateContent(COLORREF col) | |
{ | |
Controls::StackPanel root; | |
root.RenderTransform(m_scaler); | |
root.Padding(ThicknessHelper::FromUniformLength(12)); | |
if (auto system_brush = root.Resources().Lookup(box_value(L"SystemControlAcrylicWindowBrush")).try_as<Media::Brush>()) | |
{ | |
root.Background(system_brush); | |
} | |
Controls::ColorPicker picker; | |
picker.IsAlphaEnabled(true); | |
picker.Color(ColorHelper::FromArgb((col & 0xFF000000) >> 24, col & 0xFF, (col & 0xFF00) >> 8, (col & 0xFF0000) >> 16)); | |
root.Children().Append(picker); | |
Controls::StackPanel buttons; | |
buttons.HorizontalAlignment(HorizontalAlignment::Right); | |
buttons.Orientation(Controls::Orientation::Horizontal); | |
Controls::Button ok; | |
ok.Margin(ThicknessHelper::FromLengths(0, 12, 6, 0)); | |
ok.Width(100); | |
ok.Content(box_value(L"OK")); | |
buttons.Children().Append(ok); | |
Controls::Button cancel; | |
cancel.Margin(ThicknessHelper::FromLengths(6, 12, 0, 0)); | |
cancel.Width(100); | |
cancel.Content(box_value(L"Cancel")); | |
buttons.Children().Append(cancel); | |
root.Children().Append(buttons); | |
return root; | |
} | |
LRESULT ColorPicker::OnNonClientCalculateSize() | |
{ | |
return 0; | |
} | |
LRESULT ColorPicker::OnSizeChanged(int width, int height) | |
{ | |
SetWindowPos(m_interopHwnd, NULL, 0, 0, width, height, SWP_NOZORDER | SWP_NOOWNERZORDER); | |
return 0; | |
} | |
LRESULT ColorPicker::OnDpiChanged(unsigned int dpi) | |
{ | |
m_scaler.ScaleX(dpi / static_cast<double>(USER_DEFAULT_SCREEN_DPI)); | |
m_scaler.ScaleY(dpi / static_cast<double>(USER_DEFAULT_SCREEN_DPI)); | |
return 0; | |
} | |
LRESULT ColorPicker::OnCompositionChanged() | |
{ | |
const MARGINS mar = { -1 }; | |
DwmExtendFrameIntoClientArea(m_hWnd, &mar); | |
return 0; | |
} | |
ColorPicker::ColorPicker(COLORREF col) : | |
m_manager(Hosting::WindowsXamlManager::InitializeForCurrentThread()), | |
m_interopHwnd(nullptr), | |
m_hWnd(nullptr) | |
{ | |
m_hWnd = CreateWindowEx( | |
WS_EX_TOPMOST, | |
CLASS_NAME, | |
L"Color Picker", | |
WS_OVERLAPPEDWINDOW, | |
CW_USEDEFAULT, | |
CW_USEDEFAULT, | |
CW_USEDEFAULT, | |
CW_USEDEFAULT, | |
nullptr, | |
nullptr, | |
reinterpret_cast<HINSTANCE>(&__ImageBase), // TODO: better way of getting instance handle | |
this | |
); | |
if (!m_hWnd) | |
{ | |
throw_last_error(); | |
} | |
OnCompositionChanged(); | |
winrt::com_ptr<IDesktopWindowXamlSourceNative> native_source; | |
check_hresult(get_unknown(m_source)->QueryInterface(IID_PPV_ARGS(native_source.put()))); | |
check_hresult(native_source->AttachToWindow(m_hWnd)); | |
check_hresult(native_source->get_WindowHandle(&m_interopHwnd)); | |
POINT point; | |
if (!GetCursorPos(&point)) | |
{ | |
throw_last_error(); | |
} | |
HMONITOR mon = MonitorFromPoint(point, MONITOR_DEFAULTTONEAREST); | |
UINT dpiX, dpiY; | |
check_hresult(GetDpiForMonitor(mon, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)); | |
OnDpiChanged(dpiX); | |
m_source.Content(CreateContent(col)); | |
// TODO: get right size to use | |
// https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/using-the-xaml-hosting-api#how-to-handle-layout-changes | |
SetWindowPos(m_hWnd, NULL, 0, 0, 600, 900, SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); | |
ShowWindow(m_interopHwnd, SW_SHOW); | |
ShowWindow(m_hWnd, SW_SHOW); | |
} | |
ColorPicker::~ColorPicker() | |
{ | |
m_manager.Close(); | |
} | |
bool ColorPicker::RegisterWindowClass(HINSTANCE hInst) | |
{ | |
WNDCLASSEX wc = { | |
sizeof(wc), | |
CS_HREDRAW | CS_VREDRAW, | |
WindowProc, | |
0, | |
0, | |
hInst, | |
nullptr, | |
LoadCursor(nullptr, IDC_ARROW), | |
nullptr, | |
nullptr, | |
CLASS_NAME, | |
nullptr | |
}; | |
return RegisterClassEx(&wc); | |
} | |
void ColorPicker::UnregisterWindowClass(HINSTANCE hInst) | |
{ | |
UnregisterClass(CLASS_NAME, hInst); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "../TranslucentTB/arch.h" | |
#include <windef.h> | |
#include <Unknwn.h> | |
#undef GetCurrentTime | |
#include <winrt/Windows.UI.Xaml.Controls.h> | |
#include <winrt/Windows.UI.Xaml.Hosting.h> | |
#ifdef _COLORPICKER_DLL | |
#define COLORPICKER_EXPORT dllexport | |
#else | |
#define COLORPICKER_EXPORT dllimport | |
#endif | |
class ColorPicker { | |
private: | |
static constexpr wchar_t CLASS_NAME[] = L"TTBColorPicker"; | |
winrt::Windows::UI::Xaml::Hosting::WindowsXamlManager m_manager; | |
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource m_source; | |
winrt::Windows::UI::Xaml::Media::ScaleTransform m_scaler; | |
HWND m_interopHwnd, m_hWnd; | |
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); | |
winrt::Windows::UI::Xaml::UIElement CreateContent(COLORREF col); | |
LRESULT OnNonClientCalculateSize(); | |
LRESULT OnSizeChanged(int width, int height); | |
LRESULT OnDpiChanged(unsigned int dpi); | |
LRESULT OnCompositionChanged(); | |
public: | |
__declspec(COLORPICKER_EXPORT) ColorPicker(COLORREF col); | |
~ColorPicker(); | |
ColorPicker(const ColorPicker &) = delete; | |
ColorPicker &operator =(const ColorPicker &) = delete; | |
static bool RegisterWindowClass(HINSTANCE hInst); | |
static void UnregisterWindowClass(HINSTANCE hInst); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment