1use std::io;
4
5use num_enum::IntoPrimitive;
6use windows::Win32::Foundation::HANDLE;
7use windows::Win32::Graphics::Gdi::{
8 COLOR_3DDKSHADOW,
9 COLOR_3DLIGHT,
10 COLOR_ACTIVEBORDER,
11 COLOR_ACTIVECAPTION,
12 COLOR_APPWORKSPACE,
13 COLOR_BACKGROUND,
14 COLOR_BTNFACE,
15 COLOR_BTNHIGHLIGHT,
16 COLOR_BTNSHADOW,
17 COLOR_BTNTEXT,
18 COLOR_CAPTIONTEXT,
19 COLOR_GRADIENTACTIVECAPTION,
20 COLOR_GRADIENTINACTIVECAPTION,
21 COLOR_GRAYTEXT,
22 COLOR_HIGHLIGHT,
23 COLOR_HIGHLIGHTTEXT,
24 COLOR_HOTLIGHT,
25 COLOR_INACTIVEBORDER,
26 COLOR_INACTIVECAPTION,
27 COLOR_INACTIVECAPTIONTEXT,
28 COLOR_INFOBK,
29 COLOR_INFOTEXT,
30 COLOR_MENU,
31 COLOR_MENUBAR,
32 COLOR_MENUHILIGHT,
33 COLOR_MENUTEXT,
34 COLOR_SCROLLBAR,
35 COLOR_WINDOW,
36 COLOR_WINDOWFRAME,
37 COLOR_WINDOWTEXT,
38 HBRUSH,
39};
40use windows::Win32::UI::WindowsAndMessaging::{
41 LoadImageW,
42 GDI_IMAGE_TYPE,
43 HCURSOR,
44 HICON,
45 IMAGE_CURSOR,
46 IMAGE_ICON,
47 LR_DEFAULTSIZE,
48 LR_SHARED,
49 OCR_APPSTARTING,
50 OCR_CROSS,
51 OCR_HAND,
52 OCR_HELP,
53 OCR_IBEAM,
54 OCR_NO,
55 OCR_NORMAL,
56 OCR_SIZEALL,
57 OCR_SIZENESW,
58 OCR_SIZENS,
59 OCR_SIZENWSE,
60 OCR_SIZEWE,
61 OCR_UP,
62 OCR_WAIT,
63 OIC_ERROR,
64 OIC_INFORMATION,
65 OIC_QUES,
66 OIC_SAMPLE,
67 OIC_SHIELD,
68 OIC_WARNING,
69};
70
71use windows_missing::*;
72
73pub trait Icon {
74 fn as_handle(&self) -> io::Result<HICON>;
75}
76
77#[derive(IntoPrimitive, Copy, Clone, Eq, PartialEq, Default, Debug)]
78#[repr(u32)]
79pub enum BuiltinIcon {
80 #[default]
81 Application = OIC_SAMPLE,
82 QuestionMark = OIC_QUES,
83 Warning = OIC_WARNING,
84 Error = OIC_ERROR,
85 Information = OIC_INFORMATION,
86 Shield = OIC_SHIELD,
87}
88
89impl Icon for BuiltinIcon {
90 fn as_handle(&self) -> io::Result<HICON> {
91 let handle = get_shared_image_handle((*self).into(), IMAGE_ICON)?;
92 Ok(HICON(handle.0))
93 }
94}
95
96pub trait Cursor {
97 fn as_handle(&self) -> io::Result<HCURSOR>;
98}
99
100#[derive(IntoPrimitive, Copy, Clone, Eq, PartialEq, Default, Debug)]
101#[repr(u32)]
102pub enum BuiltinCursor {
103 #[default]
105 Normal = OCR_NORMAL.0,
106 NormalPlusWaiting = OCR_APPSTARTING.0,
108 Waiting = OCR_WAIT.0,
110 NormalPlusQuestionMark = OCR_HELP.0,
112 Crosshair = OCR_CROSS.0,
114 Hand = OCR_HAND.0,
116 IBeam = OCR_IBEAM.0,
118 SlashedCircle = OCR_NO.0,
120 ArrowAllDirections = OCR_SIZEALL.0,
122 ArrowNESW = OCR_SIZENESW.0,
124 ArrowNS = OCR_SIZENS.0,
126 ArrowNWSE = OCR_SIZENWSE.0,
128 ArrowWE = OCR_SIZEWE.0,
130 Up = OCR_UP.0,
132}
133
134impl Cursor for BuiltinCursor {
135 fn as_handle(&self) -> io::Result<HCURSOR> {
136 let handle = get_shared_image_handle((*self).into(), IMAGE_CURSOR)?;
137 Ok(HCURSOR(handle.0))
138 }
139}
140
141pub trait Brush {
142 fn as_handle(&self) -> io::Result<HBRUSH>;
143}
144
145#[derive(IntoPrimitive, Copy, Clone, Eq, PartialEq, Default, Debug)]
146#[repr(i32)]
147pub enum BuiltinColor {
148 #[default]
149 Scrollbar = COLOR_SCROLLBAR.0,
150 Background = COLOR_BACKGROUND.0,
151 ActiveCaption = COLOR_ACTIVECAPTION.0,
152 InactiveCaption = COLOR_INACTIVECAPTION.0,
153 Menu = COLOR_MENU.0,
154 Window = COLOR_WINDOW.0,
155 WindowFrame = COLOR_WINDOWFRAME.0,
156 MenuText = COLOR_MENUTEXT.0,
157 WindowText = COLOR_WINDOWTEXT.0,
158 CaptionText = COLOR_CAPTIONTEXT.0,
159 ActiveBorder = COLOR_ACTIVEBORDER.0,
160 InactiveBorder = COLOR_INACTIVEBORDER.0,
161 AppWorkspace = COLOR_APPWORKSPACE.0,
162 Highlight = COLOR_HIGHLIGHT.0,
163 HighlightText = COLOR_HIGHLIGHTTEXT.0,
164 ButtonFace = COLOR_BTNFACE.0,
165 ButtonShadow = COLOR_BTNSHADOW.0,
166 GrayText = COLOR_GRAYTEXT.0,
167 ButtonText = COLOR_BTNTEXT.0,
168 InactiveCaptionText = COLOR_INACTIVECAPTIONTEXT.0,
169 ButtonHighlight = COLOR_BTNHIGHLIGHT.0,
170 Shadow3DDark = COLOR_3DDKSHADOW.0,
171 Light3D = COLOR_3DLIGHT.0,
172 InfoText = COLOR_INFOTEXT.0,
173 InfoBlack = COLOR_INFOBK.0,
174 HotLight = COLOR_HOTLIGHT.0,
175 GradientActiveCaption = COLOR_GRADIENTACTIVECAPTION.0,
176 GradientInactiveCaption = COLOR_GRADIENTINACTIVECAPTION.0,
177 MenuHighlight = COLOR_MENUHILIGHT.0,
178 MenuBar = COLOR_MENUBAR.0,
179}
180
181impl Brush for BuiltinColor {
182 fn as_handle(&self) -> io::Result<HBRUSH> {
183 Ok(HBRUSH(i32::from(*self) as *mut std::ffi::c_void))
184 }
185}
186
187fn get_shared_image_handle(resource_id: u32, resource_type: GDI_IMAGE_TYPE) -> io::Result<HANDLE> {
188 let handle = unsafe {
189 LoadImageW(
190 None,
191 MAKEINTRESOURCEW(resource_id),
192 resource_type,
193 0,
194 0,
195 LR_SHARED | LR_DEFAULTSIZE,
196 )?
197 };
198 Ok(handle)
199}
200
201mod windows_missing {
202 use windows::core::PCWSTR;
203
204 #[allow(non_snake_case)]
206 #[inline]
207 pub fn MAKEINTRESOURCEW(i: u32) -> PCWSTR {
208 PCWSTR(i as usize as *const u16)
209 }
210}