native_windows_gui2/controls/
extern_canvas.rs1use winapi::um::winuser::{
2 WS_CAPTION, WS_CLIPCHILDREN, WS_CLIPSIBLINGS, WS_DISABLED, WS_MAXIMIZE, WS_MAXIMIZEBOX,
3 WS_MINIMIZE, WS_MINIMIZEBOX, WS_OVERLAPPEDWINDOW, WS_SYSMENU, WS_THICKFRAME, WS_VISIBLE,
4};
5
6use super::{ControlBase, ControlHandle};
7use crate::win32::base_helper::check_hwnd;
8use crate::win32::window_helper as wh;
9use crate::{Icon, NwgError};
10
11const NOT_BOUND: &'static str = "ExternCanvas is not yet bound to a winapi object";
12const BAD_HANDLE: &'static str = "INTERNAL ERROR: ExternCanvas handle is not HWND!";
13
14bitflags! {
15
16 pub struct ExternCanvasFlags: u32 {
35 const NONE = 0;
36 const MAIN_WINDOW = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_THICKFRAME | WS_MAXIMIZEBOX;
37 const WINDOW = WS_CAPTION | WS_SYSMENU;
38 const MINIMIZE_BOX = WS_MINIMIZEBOX;
39 const MAXIMIZE_BOX = WS_MAXIMIZEBOX;
40 const SYS_MENU = WS_SYSMENU;
41 const VISIBLE = WS_VISIBLE;
42 const DISABLED = WS_DISABLED;
43 const MAXIMIZED = WS_MAXIMIZE;
44 const MINIMIZED = WS_MINIMIZE;
45 const RESIZABLE = WS_THICKFRAME | WS_MAXIMIZEBOX;
46 }
47}
48
49#[derive(Default)]
88pub struct ExternCanvas {
89 pub handle: ControlHandle,
90}
91
92impl ExternCanvas {
93 pub fn builder<'a>() -> ExternCanvasBuilder<'a> {
94 ExternCanvasBuilder {
95 title: "New Canvas",
96 size: (500, 500),
97 position: (300, 300),
98 flags: None,
99 ex_flags: 0,
100 icon: None,
101 parent: None,
102 }
103 }
104
105 pub fn invalidate(&self) {
107 use std::ptr;
108 use winapi::um::winuser::InvalidateRect;
109
110 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
111 unsafe {
112 InvalidateRect(handle, ptr::null(), 1);
113 }
114 }
115
116 pub fn icon(&self) -> Option<Icon> {
118 use winapi::um::winnt::HANDLE;
119 use winapi::um::winuser::WM_GETICON;
120
121 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
122
123 let icon_handle = wh::send_message(handle, WM_GETICON, 0, 0);
124 if icon_handle == 0 {
125 None
126 } else {
127 Some(Icon {
128 handle: icon_handle as HANDLE,
129 owned: false,
130 })
131 }
132 }
133
134 pub fn set_icon(&self, icon: Option<&Icon>) {
137 use std::ptr;
138 use winapi::shared::minwindef::LPARAM;
139 use winapi::um::winuser::WM_SETICON;
140
141 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
142
143 let image_handle = icon.map(|i| i.handle).unwrap_or(ptr::null_mut());
144 wh::send_message(handle, WM_SETICON, 0, image_handle as LPARAM);
145 }
146
147 pub fn focus(&self) -> bool {
149 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
150 wh::get_focus(handle)
151 }
152
153 pub fn set_focus(&self) {
155 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
156
157 wh::set_focus(handle);
158 }
159
160 pub fn enabled(&self) -> bool {
162 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
163 wh::get_window_enabled(handle)
164 }
165
166 pub fn set_enabled(&self, v: bool) {
168 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
169 wh::set_window_enabled(handle, v)
170 }
171
172 pub fn visible(&self) -> bool {
175 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
176 wh::get_window_visibility(handle)
177 }
178
179 pub fn set_visible(&self, v: bool) {
181 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
182 wh::set_window_visibility(handle, v)
183 }
184
185 pub fn size(&self) -> (u32, u32) {
187 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
188 wh::get_window_size(handle)
189 }
190
191 pub fn physical_size(&self) -> (u32, u32) {
193 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
194 wh::get_window_physical_size(handle)
195 }
196
197 pub fn set_size(&self, x: u32, y: u32) {
199 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
200 wh::set_window_size(handle, x, y, true)
201 }
202
203 pub fn position(&self) -> (i32, i32) {
205 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
206 wh::get_window_position(handle)
207 }
208
209 pub fn set_position(&self, x: i32, y: i32) {
211 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
212 wh::set_window_position(handle, x, y)
213 }
214
215 pub fn text(&self) -> String {
217 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
218 wh::get_window_text(handle)
219 }
220
221 pub fn set_text<'a>(&self, v: &'a str) {
223 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
224 wh::set_window_text(handle, v)
225 }
226
227 pub fn class_name(&self) -> &'static str {
229 "NWG_EXTERN_CANVAS"
230 }
231
232 pub fn flags(&self) -> u32 {
234 WS_OVERLAPPEDWINDOW | WS_VISIBLE
235 }
236
237 pub fn forced_flags(&self) -> u32 {
239 WS_CLIPCHILDREN | WS_CLIPSIBLINGS
240 }
241}
242
243impl Drop for ExternCanvas {
244 fn drop(&mut self) {
245 self.handle.destroy();
246 }
247}
248
249#[cfg(feature = "raw-win-handle")]
250use raw_window_handle::{HasRawWindowHandle, RawWindowHandle, windows::WindowsHandle};
251
252#[cfg(feature = "raw-win-handle")]
253unsafe impl HasRawWindowHandle for ExternCanvas {
254 fn raw_window_handle(&self) -> RawWindowHandle {
255 use winapi::um::winuser::GWL_HINSTANCE;
256
257 match self.handle {
258 ControlHandle::Hwnd(hwnd) => {
259 let hinstance = wh::get_window_long(hwnd, GWL_HINSTANCE);
260
261 RawWindowHandle::Windows(WindowsHandle {
262 hwnd: hwnd as _,
263 hinstance: hinstance as _,
264 ..WindowsHandle::empty()
265 })
266 }
267 _ => RawWindowHandle::Windows(WindowsHandle::empty()),
269 }
270 }
271}
272
273pub struct ExternCanvasBuilder<'a> {
274 title: &'a str,
275 size: (i32, i32),
276 position: (i32, i32),
277 flags: Option<ExternCanvasFlags>,
278 ex_flags: u32,
279 icon: Option<&'a Icon>,
280 parent: Option<ControlHandle>,
281}
282
283impl<'a> ExternCanvasBuilder<'a> {
284 pub fn flags(mut self, flags: ExternCanvasFlags) -> ExternCanvasBuilder<'a> {
285 self.flags = Some(flags);
286 self
287 }
288
289 pub fn ex_flags(mut self, flags: u32) -> ExternCanvasBuilder<'a> {
290 self.ex_flags = flags;
291 self
292 }
293
294 pub fn title(mut self, text: &'a str) -> ExternCanvasBuilder<'a> {
295 self.title = text;
296 self
297 }
298
299 pub fn size(mut self, size: (i32, i32)) -> ExternCanvasBuilder<'a> {
300 self.size = size;
301 self
302 }
303
304 pub fn position(mut self, pos: (i32, i32)) -> ExternCanvasBuilder<'a> {
305 self.position = pos;
306 self
307 }
308
309 pub fn icon(mut self, ico: Option<&'a Icon>) -> ExternCanvasBuilder<'a> {
310 self.icon = ico;
311 self
312 }
313
314 pub fn parent<C: Into<ControlHandle>>(mut self, p: Option<C>) -> ExternCanvasBuilder<'a> {
315 self.parent = p.map(|p2| p2.into());
316 self
317 }
318
319 pub fn build(self, out: &mut ExternCanvas) -> Result<(), NwgError> {
320 use winapi::um::winuser::WS_CHILD;
321
322 let mut flags = self.flags.map(|f| f.bits()).unwrap_or(out.flags());
323
324 if self.parent.is_some() {
326 flags &= !(WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_THICKFRAME | WS_MAXIMIZEBOX);
327 flags |= WS_CHILD;
328 }
329
330 *out = Default::default();
331
332 out.handle = ControlBase::build_hwnd()
333 .class_name(out.class_name())
334 .forced_flags(out.forced_flags())
335 .flags(flags)
336 .ex_flags(self.ex_flags)
337 .size(self.size)
338 .position(self.position)
339 .text(self.title)
340 .parent(self.parent)
341 .build()?;
342
343 if self.icon.is_some() {
344 out.set_icon(self.icon);
345 }
346
347 Ok(())
348 }
349}