winsafe\gui\events/window_events.rs
1use std::cell::UnsafeCell;
2use std::rc::Rc;
3
4use crate::co;
5use crate::decl::*;
6use crate::gui::privs::*;
7use crate::msg::*;
8use crate::prelude::*;
9
10struct StorageMsg {
11 id: co::WM,
12 fun: Box<dyn Fn(WndMsg) -> AnyResult<isize>>,
13}
14struct StorageCmd {
15 id: (u16, co::CMD),
16 fun: Box<dyn Fn() -> AnyResult<()>>,
17}
18struct StorageNfy {
19 id: (u16, NmhdrCode),
20 fun: Box<dyn Fn(wm::Notify) -> AnyResult<isize>>,
21}
22struct StorageTmr {
23 id: usize,
24 fun: Box<dyn Fn() -> AnyResult<()>>,
25}
26
27pub struct WindowEvents {
28 wnd_ty: WndTy,
29 msgs: UnsafeCell<Vec<StorageMsg>>, // ordinary WM messages
30 cmds: UnsafeCell<Vec<StorageCmd>>, // WM_COMMAND
31 nfys: UnsafeCell<Vec<StorageNfy>>, // WM_NOTIFY
32 tmrs: UnsafeCell<Vec<StorageTmr>>, // WM_TIMER
33}
34
35impl WindowEvents {
36 #[must_use]
37 pub(in crate::gui) const fn new(wnd_ty: WndTy) -> Self {
38 Self {
39 wnd_ty,
40 msgs: UnsafeCell::new(Vec::new()),
41 cmds: UnsafeCell::new(Vec::new()),
42 nfys: UnsafeCell::new(Vec::new()),
43 tmrs: UnsafeCell::new(Vec::new()),
44 }
45 }
46
47 pub(in crate::gui) fn clear(&self) {
48 unsafe {
49 { &mut *self.msgs.get() }.clear();
50 { &mut *self.cmds.get() }.clear();
51 { &mut *self.nfys.get() }.clear();
52 { &mut *self.tmrs.get() }.clear();
53 }
54 }
55
56 #[must_use]
57 pub(in crate::gui) fn has_message(&self) -> bool {
58 unsafe {
59 !{ &*self.msgs.get() }.is_empty()
60 || !{ &*self.cmds.get() }.is_empty()
61 || !{ &*self.nfys.get() }.is_empty()
62 || !{ &*self.tmrs.get() }.is_empty()
63 }
64 }
65
66 /// Returns `true` if at least one message was processed. Result values are
67 /// ignored.
68 ///
69 /// Stops on error. Since this is called only for internal messages, errors
70 /// shouldn't really happen.
71 #[must_use]
72 pub(in crate::gui) fn process_all_messages(&self, p: WndMsg) -> AnyResult<bool> {
73 let mut at_least_one = false;
74
75 if p.msg_id == co::WM::COMMAND {
76 let wm_cmd = unsafe { wm::Command::from_generic_wm(p) };
77 let key_cmd = (wm_cmd.event.ctrl_id(), wm_cmd.event.code());
78 let cmds = unsafe { &*self.cmds.get() };
79 for stored_cmd in cmds.iter().filter(|obj| obj.id == key_cmd) {
80 if let Err(e) = (stored_cmd.fun)() {
81 return Err(e); // stop on error
82 }
83 at_least_one = true;
84 }
85 } else if p.msg_id == co::WM::NOTIFY {
86 let wm_nfy = unsafe { wm::Notify::from_generic_wm(p) };
87 let key_nfy = (wm_nfy.nmhdr.idFrom(), wm_nfy.nmhdr.code);
88 let nfys = unsafe { &*self.nfys.get() };
89 for stored_nfy in nfys.iter().filter(|obj| obj.id == key_nfy) {
90 if let Err(e) = (stored_nfy.fun)(unsafe { wm::Notify::from_generic_wm(p) }) {
91 // wm::Notify cannot be Copy
92 return Err(e); // stop on error
93 }
94 at_least_one = true;
95 }
96 } else if p.msg_id == co::WM::TIMER {
97 let wm_tmr = unsafe { wm::Timer::from_generic_wm(p) };
98 let tmrs = unsafe { &*self.tmrs.get() };
99 for stored_tmr in tmrs.iter().filter(|obj| obj.id == wm_tmr.timer_id) {
100 if let Err(e) = (stored_tmr.fun)() {
101 return Err(e); // stop on error
102 }
103 at_least_one = true;
104 }
105 }
106
107 let msgs = unsafe { &*self.msgs.get() };
108 for stored_msg in msgs.iter().filter(|stored_msg| stored_msg.id == p.msg_id) {
109 if let Err(e) = (stored_msg.fun)(p) {
110 return Err(e); // stop on error
111 }
112 at_least_one = true;
113 }
114
115 Ok(at_least_one)
116 }
117
118 /// Returns the user return value, if processed.
119 #[must_use]
120 pub(in crate::gui) fn process_last_message(&self, p: WndMsg) -> Option<AnyResult<isize>> {
121 if p.msg_id == co::WM::COMMAND {
122 let wm_cmd = unsafe { wm::Command::from_generic_wm(p) };
123 let key_cmd = (wm_cmd.event.ctrl_id(), wm_cmd.event.code());
124 let cmds = unsafe { &*self.cmds.get() };
125 if let Some(stored_cmd) = cmds.iter().rev().find(|obj| obj.id == key_cmd) {
126 let ret = (stored_cmd.fun)().map(|_| self.wnd_ty.def_proc_val());
127 return Some(ret); // handled, stop here
128 }
129 } else if p.msg_id == co::WM::NOTIFY {
130 let wm_nfy = unsafe { wm::Notify::from_generic_wm(p) };
131 let key_nfy = (wm_nfy.nmhdr.idFrom(), wm_nfy.nmhdr.code);
132 let nfys = unsafe { &*self.nfys.get() };
133 if let Some(stored_nfy) = nfys.iter().rev().find(|obj| obj.id == key_nfy) {
134 let ret = (stored_nfy.fun)(unsafe { wm::Notify::from_generic_wm(p) }); // wm::Notify cannot be Copy
135 return Some(ret); // handled, stop here
136 }
137 } else if p.msg_id == co::WM::TIMER {
138 let wm_tmr = unsafe { wm::Timer::from_generic_wm(p) };
139 let tmrs = unsafe { &*self.tmrs.get() };
140 if let Some(stored_tmr) = tmrs.iter().rev().find(|obj| obj.id == wm_tmr.timer_id) {
141 let ret = (stored_tmr.fun)().map(|_| self.wnd_ty.def_proc_val());
142 return Some(ret); // handled, stop here
143 }
144 }
145
146 let msgs = unsafe { &*self.msgs.get() };
147 if let Some(stored_msg) = msgs
148 .iter()
149 .rev()
150 .find(|stored_msg| stored_msg.id == p.msg_id)
151 {
152 let ret = (stored_msg.fun)(p);
153 return Some(ret); // handled, stop here
154 }
155
156 None
157 }
158
159 /// Event to any [window message](crate::co::WM).
160 ///
161 /// Instead of using this event, you should always prefer the specific
162 /// events, which will give you the correct message parameters. This generic
163 /// method should be used only when you have a custom, non-standard window
164 /// message – which should be pretty rare.
165 ///
166 /// # Examples
167 ///
168 /// Handling a custom, user-defined message:
169 ///
170 /// ```no_run
171 /// use winsafe::{self as w, prelude::*, co, gui, msg};
172 ///
173 /// let wnd: gui::WindowMain; // initialized somewhere
174 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
175 ///
176 /// let CUSTOM_MSG = unsafe { co::WM::from_raw(0x1234) };
177 ///
178 /// wnd.on().wm(
179 /// CUSTOM_MSG,
180 /// move |p: msg::WndMsg| -> w::AnyResult<isize> {
181 /// println!("Msg ID: {}", p.msg_id);
182 /// Ok(0)
183 /// },
184 /// );
185 /// ```
186 pub fn wm<F>(&self, ident: co::WM, func: F) -> &Self
187 where
188 F: Fn(WndMsg) -> AnyResult<isize> + 'static,
189 {
190 unsafe { &mut *self.msgs.get() }.push(StorageMsg { id: ident, fun: Box::new(func) });
191 self
192 }
193
194 /// [`WM_COMMAND`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-command)
195 /// message, for specific code and control ID.
196 ///
197 /// A command notification must be narrowed by the
198 /// [command code](crate::co::CMD) and the control ID, so the closure will
199 /// be fired for that specific control at that specific event.
200 ///
201 /// Instead of using this event, you should always prefer the specific
202 /// command notifications, which will give you the correct message
203 /// parameters. This generic method should be used only when you have a
204 /// custom, non-standard window notification.
205 ///
206 /// ```no_run
207 /// use winsafe::{self as w, prelude::*, co, gui};
208 ///
209 /// let wnd: gui::WindowMain; // initialized somewhere
210 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
211 ///
212 /// const CTRL_ID: u16 = 1010;
213 ///
214 /// wnd.on().wm_command(
215 /// CTRL_ID,
216 /// co::BN::CLICKED,
217 /// move || -> w::AnyResult<()> {
218 /// println!("Button clicked!");
219 /// Ok(())
220 /// },
221 /// );
222 /// ```
223 pub fn wm_command<F>(&self, ctrl_id: impl Into<u16>, code: impl Into<co::CMD>, func: F) -> &Self
224 where
225 F: Fn() -> AnyResult<()> + 'static,
226 {
227 let code: co::CMD = code.into();
228 unsafe { &mut *self.cmds.get() }.push(StorageCmd {
229 id: (ctrl_id.into(), code),
230 fun: Box::new(func),
231 });
232 self
233 }
234
235 /// [`WM_COMMAND`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-command)
236 /// message, handling both `CMD::Accelerator` and `CMD::Menu`, for a
237 /// specific command ID.
238 ///
239 /// Ideal to be used with menu commands whose IDs are shared with
240 /// accelerators, like menu items.
241 ///
242 /// # Examples
243 ///
244 /// ```no_run
245 /// use winsafe::{self as w, prelude::*, co, gui};
246 ///
247 /// let wnd: gui::WindowMain; // initialized somewhere
248 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
249 ///
250 /// const CTRL_ID: u16 = 1010;
251 ///
252 /// wnd.on().wm_command_acc_menu(
253 /// CTRL_ID,
254 /// move || -> w::AnyResult<()> {
255 /// println!("Hello!");
256 /// Ok(())
257 /// },
258 /// );
259 /// ```
260 pub fn wm_command_acc_menu<F>(&self, ctrl_id: impl Into<u16> + Copy, func: F) -> &Self
261 where
262 F: Fn() -> AnyResult<()> + 'static,
263 {
264 let shared_func = Rc::new(func);
265
266 self.wm_command(ctrl_id, co::CMD::Menu, {
267 let shared_func = shared_func.clone();
268 move || {
269 shared_func()?;
270 Ok(())
271 }
272 });
273
274 self.wm_command(ctrl_id, co::CMD::Accelerator, {
275 let shared_func = shared_func.clone();
276 move || {
277 shared_func()?;
278 Ok(())
279 }
280 });
281
282 self
283 }
284
285 /// [`WM_NOTIFY`](crate::msg::wm::Notify) message, for specific ID and
286 /// notification code.
287 ///
288 /// Instead of using this event, you should always prefer the specific
289 /// notifications, which will give you the correct notification struct. This
290 /// generic method should be used only when you have a custom, non-standard
291 /// window notification.
292 ///
293 /// ```no_run
294 /// use winsafe::{self as w, prelude::*, co, gui};
295 ///
296 /// let wnd: gui::WindowMain; // initialized somewhere
297 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
298 ///
299 /// const CTRL_ID: u16 = 1010;
300 ///
301 /// wnd.on().wm_notify(
302 /// CTRL_ID,
303 /// co::NM::DBLCLK,
304 /// move |_| -> w::AnyResult<isize> {
305 /// println!("Status bar double clicked!");
306 /// Ok(0)
307 /// },
308 /// );
309 /// ```
310 pub fn wm_notify<F>(
311 &self,
312 id_from: impl Into<u16>,
313 code: impl Into<NmhdrCode>,
314 func: F,
315 ) -> &Self
316 where
317 F: Fn(wm::Notify) -> AnyResult<isize> + 'static,
318 {
319 unsafe { &mut *self.nfys.get() }.push(StorageNfy {
320 id: (id_from.into(), code.into()),
321 fun: Box::new(func),
322 });
323 self
324 }
325
326 /// [`WM_TIMER`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-timer)
327 /// message, narrowed to a specific timer ID.
328 pub fn wm_timer<F>(&self, timer_id: usize, func: F) -> &Self
329 where
330 F: Fn() -> AnyResult<()> + 'static,
331 {
332 unsafe { &mut *self.tmrs.get() }.push(StorageTmr { id: timer_id, fun: Box::new(func) });
333 self
334 }
335
336 pub_fn_wm_withparm_noret! { wm_activate, co::WM::ACTIVATE, wm::Activate;
337 /// [`WM_ACTIVATE`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-activate)
338 /// message.
339 }
340
341 pub_fn_wm_withparm_noret! { wm_activate_app, co::WM::ACTIVATEAPP, wm::ActivateApp;
342 /// [`WM_ACTIVATEAPP`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-activateapp)
343 /// message.
344 }
345
346 /// [`WM_APPCOMMAND`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-appcommand)
347 /// message.
348 pub fn wm_app_command<F>(&self, func: F) -> &Self
349 where
350 F: Fn(wm::AppCommand) -> AnyResult<()> + 'static,
351 {
352 self.wm(co::WM::APPCOMMAND, move |p| {
353 func(unsafe { wm::AppCommand::from_generic_wm(p) })?;
354 Ok(1) // TRUE
355 });
356 self
357 }
358
359 pub_fn_wm_noparm_noret! { wm_cancel_mode, co::WM::CANCELMODE;
360 /// [`WM_CANCELMODE`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-cancelmode)
361 /// message.
362 }
363
364 pub_fn_wm_withparm_noret! { wm_capture_changed, co::WM::CAPTURECHANGED, wm::CaptureChanged;
365 /// [`WM_CAPTURECHANGED`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-capturechanged)
366 /// message.
367 }
368
369 pub_fn_wm_withparm_noret! { wm_char, co::WM::CHAR, wm::Char;
370 /// [`WM_CHAR`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-char)
371 /// message.
372 }
373
374 pub_fn_wm_noparm_noret! { wm_child_activate, co::WM::CHILDACTIVATE;
375 /// [`WM_CHILDACTIVATE`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-childactivate)
376 /// message.
377 }
378
379 pub_fn_wm_noparm_noret! { wm_close, co::WM::CLOSE;
380 /// [`WM_CLOSE`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-close)
381 /// message.
382 ///
383 /// # Default handling
384 ///
385 /// If you handle this event, you'll overwrite the default handling in:
386 ///
387 /// * dialog [`WindowMain`](crate::gui::WindowMain) – calls [`DestroyWindow`](crate::prelude::user_Hwnd::DestroyWindow);
388 /// * dialog [`WindowModal`](crate::gui::WindowModal) – calls [`EndDialog`](crate::prelude::user_Hwnd::EndDialog);
389 /// * non-dialog [`WindowModal`](crate::gui::WindowModal) – re-enables parent and calls [`DestroyWindow`](crate::prelude::user_Hwnd::DestroyWindow).
390 }
391
392 pub_fn_wm_noparm_noret! { wm_context_menu, co::WM::CONTEXTMENU;
393 /// [`WM_CONTEXTMENU`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-contextmenu)
394 /// message.
395 }
396
397 /// [`WM_CREATE`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-create)
398 /// message, sent only to non-dialog windows. Dialog windows must handle
399 /// [`wm_init_dialog`](crate::gui::events::WindowEvents::wm_init_dialog)
400 /// instead.
401 ///
402 /// # Examples
403 ///
404 /// ```no_run
405 /// use winsafe::{self as w, prelude::*, gui, msg};
406 ///
407 /// let wnd: gui::WindowMain; // initialized somewhere
408 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
409 ///
410 /// wnd.on().wm_create(
411 /// move |p: msg::wm::Create| -> w::AnyResult<i32> {
412 /// println!("Client area: {}x{}",
413 /// p.createstruct.cx,
414 /// p.createstruct.cy,
415 /// );
416 /// Ok(0)
417 /// },
418 /// );
419 /// ```
420 pub fn wm_create<F>(&self, func: F) -> &Self
421 where
422 F: Fn(wm::Create) -> AnyResult<i32> + 'static,
423 {
424 self.wm(co::WM::CREATE, move |p| Ok(func(unsafe { wm::Create::from_generic_wm(p) })? as _));
425 self
426 }
427
428 pub_fn_wm_ctlcolor! { wm_ctl_color_btn, co::WM::CTLCOLORBTN, wm::CtlColorBtn;
429 /// [`WM_CTLCOLORBTN`](https://learn.microsoft.com/en-us/windows/win32/controls/wm-ctlcolorbtn)
430 /// message.
431 }
432
433 pub_fn_wm_ctlcolor! { wm_ctl_color_dlg, co::WM::CTLCOLORDLG, wm::CtlColorDlg;
434 /// [`WM_CTLCOLORDLG`](https://learn.microsoft.com/en-us/windows/win32/dlgbox/wm-ctlcolordlg)
435 /// message.
436 }
437
438 pub_fn_wm_ctlcolor! { wm_ctl_color_edit, co::WM::CTLCOLOREDIT, wm::CtlColorEdit;
439 /// [`WM_CTLCOLOREDIT`](https://learn.microsoft.com/en-us/windows/win32/controls/wm-ctlcoloredit)
440 /// message.
441 }
442
443 pub_fn_wm_ctlcolor! { wm_ctl_color_list_box, co::WM::CTLCOLORLISTBOX, wm::CtlColorListBox;
444 /// [`WM_CTLCOLORLISTBOX`](https://learn.microsoft.com/en-us/windows/win32/controls/wm-ctlcolorlistbox)
445 /// message.
446 }
447
448 pub_fn_wm_ctlcolor! { wm_ctl_color_scroll_bar, co::WM::CTLCOLORSCROLLBAR, wm::CtlColorScrollBar;
449 /// [`WM_CTLCOLORSCROLLBAR`](https://learn.microsoft.com/en-us/windows/win32/controls/wm-ctlcolorscrollbar)
450 /// message.
451 }
452
453 pub_fn_wm_ctlcolor! { wm_ctl_color_static, co::WM::CTLCOLORSTATIC, wm::CtlColorStatic;
454 /// [`WM_CTLCOLORSTATIC`](https://learn.microsoft.com/en-us/windows/win32/controls/wm-ctlcolorstatic)
455 /// message.
456 }
457
458 pub_fn_wm_withparm_noret! { wm_dead_char, co::WM::DEADCHAR, wm::DeadChar;
459 /// [`WM_DEADCHAR`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-deadchar)
460 /// message.
461 }
462
463 pub_fn_wm_withparm_boolret! { wm_delete_item, co::WM::DELETEITEM, wm::DeleteItem;
464 /// [`WM_DELETEITEM`](https://learn.microsoft.com/en-us/windows/win32/controls/wm-deleteitem)
465 /// message.
466 }
467
468 pub_fn_wm_noparm_noret! { wm_destroy, co::WM::DESTROY;
469 /// [`WM_DESTROY`](crate::msg::wm::Destroy) message.
470 ///
471 /// # Examples
472 ///
473 /// ```no_run
474 /// use winsafe::{self as w, prelude::*, gui};
475 ///
476 /// let wnd: gui::WindowMain; // initialized somewhere
477 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
478 ///
479 /// wnd.on().wm_destroy(
480 /// move || -> w::AnyResult<()> {
481 /// println!("Window is gone, goodbye!");
482 /// Ok(())
483 /// },
484 /// );
485 /// ```
486 }
487
488 pub_fn_wm_withparm_noret! { wm_device_change, co::WM::DEVICECHANGE, wm::DeviceChange;
489 /// [`WM_DEVICECHANGE`](https://learn.microsoft.com/en-us/windows/win32/devio/wm-devicechange)
490 /// message.
491 }
492
493 pub_fn_wm_withparm_noret! { wm_display_change, co::WM::DISPLAYCHANGE, wm::DisplayChange;
494 /// [`WM_DISPLAYCHANGE`](https://learn.microsoft.com/en-us/windows/win32/gdi/wm-displaychange)
495 /// message.
496 }
497
498 #[cfg(feature = "shell")]
499 pub_fn_wm_withparm_noret! { wm_drop_files, co::WM::DROPFILES, wm::DropFiles;
500 /// [`WM_DROPFILES`](https://learn.microsoft.com/en-us/windows/win32/shell/wm-dropfiles)
501 /// message.
502 ///
503 /// **Note:** To use this method, enable the `shell`
504 /// [Cargo feature](https://doc.rust-lang.org/cargo/reference/features.html#the-features-section).
505 ///
506 /// # Examples
507 ///
508 /// ```no_run
509 /// use winsafe::{self as w, prelude::*, gui, msg};
510 ///
511 /// let wnd: gui::WindowMain; // initialized somewhere
512 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
513 ///
514 /// wnd.on().wm_drop_files(
515 /// move |p: msg::wm::DropFiles| -> w::AnyResult<()> {
516 /// for dropped_file in p.hdrop.DragQueryFile()? {
517 /// let dropped_file = dropped_file?;
518 /// println!("Dropped: {}", dropped_file);
519 /// }
520 /// Ok(())
521 /// },
522 /// );
523 /// ```
524 }
525
526 pub_fn_wm_withparm_noret! { wm_enable, co::WM::ENABLE, wm::Enable;
527 /// [`WM_ENABLE`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-enable)
528 /// message.
529 }
530
531 pub_fn_wm_withparm_noret! { wm_end_session, co::WM::ENDSESSION, wm::EndSession;
532 /// [`WM_ENDSESSION`](https://learn.microsoft.com/en-us/windows/win32/shutdown/wm-endsession)
533 /// message.
534 }
535
536 pub_fn_wm_withparm_noret! { wm_enter_idle, co::WM::ENTERIDLE, wm::EnterIdle;
537 /// [`WM_ENTERIDLE`](https://learn.microsoft.com/en-us/windows/win32/dlgbox/wm-enteridle)
538 /// message.
539 }
540
541 pub_fn_wm_withparm_noret! { wm_enter_menu_loop, co::WM::ENTERMENULOOP, wm::EnterMenuLoop;
542 /// [`WM_ENTERMENULOOP`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-entermenuloop)
543 /// message.
544 }
545
546 pub_fn_wm_noparm_noret! { wm_enter_size_move, co::WM::ENTERSIZEMOVE;
547 /// [`WM_ENTERSIZEMOVE`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-entersizemove)
548 /// message.
549 }
550
551 /// [`WM_ERASEBKGND`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-erasebkgnd)
552 /// message.
553 pub fn wm_erase_bkgnd<F>(&self, func: F) -> &Self
554 where
555 F: Fn(wm::EraseBkgnd) -> AnyResult<i32> + 'static,
556 {
557 self.wm(co::WM::ERASEBKGND, move |p| {
558 Ok(func(unsafe { wm::EraseBkgnd::from_generic_wm(p) })? as _)
559 });
560 self
561 }
562
563 pub_fn_wm_withparm_noret! { wm_exit_menu_loop, co::WM::EXITMENULOOP, wm::ExitMenuLoop;
564 /// [`WM_EXITMENULOOP`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-exitmenuloop)
565 /// message.
566 }
567
568 pub_fn_wm_noparm_noret! { wm_exit_size_move, co::WM::EXITSIZEMOVE;
569 /// [`WM_EXITSIZEMOVE`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-exitsizemove)
570 /// message.
571 }
572
573 pub_fn_wm_withparm_coret! { wm_get_dlg_code, co::WM::GETDLGCODE, wm::GetDlgCode, co::DLGC;
574 /// [`WM_GETDLGCODE`](https://learn.microsoft.com/en-us/windows/win32/dlgbox/wm-getdlgcode)
575 /// message.
576 }
577
578 /// [`WM_GETFONT`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-getfont)
579 /// message.
580 pub fn wm_get_font<F>(&self, func: F) -> &Self
581 where
582 F: Fn() -> AnyResult<Option<HFONT>> + 'static,
583 {
584 self.wm(co::WM::GETFONT, move |_| Ok(func()?.map_or(0, |h| h.ptr() as _)));
585 self
586 }
587
588 /// [`WM_GETHMENU`](https://learn.microsoft.com/en-us/windows/win32/winmsg/mn-gethmenu)
589 /// message. Originally has `MN` prefix.
590 pub fn wm_get_hmenu<F>(&self, func: F) -> &Self
591 where
592 F: Fn() -> AnyResult<Option<HMENU>> + 'static,
593 {
594 self.wm(co::WM::MN_GETHMENU, move |_| Ok(func()?.map_or(0, |h| h.ptr() as _)));
595 self
596 }
597
598 pub_fn_wm_withparm_noret! { wm_get_min_max_info, co::WM::GETMINMAXINFO, wm::GetMinMaxInfo;
599 /// [`WM_GETMINMAXINFO`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-getminmaxinfo)
600 /// message.
601 }
602
603 /// [`WM_GETTEXT`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-gettext)
604 /// message.
605 pub fn wm_get_text<F>(&self, func: F) -> &Self
606 where
607 F: Fn(wm::GetText) -> AnyResult<u32> + 'static,
608 {
609 self.wm(co::WM::GETTEXT, move |p| {
610 Ok(func(unsafe { wm::GetText::from_generic_wm(p) })? as _)
611 });
612 self
613 }
614
615 /// [`WM_GETTEXTLENGTH`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-gettextlength)
616 /// message.
617 pub fn wm_get_text_length<F>(&self, func: F) -> &Self
618 where
619 F: Fn() -> AnyResult<u32> + 'static,
620 {
621 self.wm(co::WM::GETTEXTLENGTH, move |_| Ok(func()? as _));
622 self
623 }
624
625 pub_fn_wm_withparm_noret! { wm_get_title_bar_info_ex, co::WM::GETTITLEBARINFOEX, wm::GetTitleBarInfoEx;
626 /// [`WM_GETTITLEBARINFOEX`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-gettitlebarinfoex)
627 /// message.
628 }
629
630 pub_fn_wm_withparm_noret! { wm_h_scroll, co::WM::HSCROLL, wm::HScroll;
631 /// [`WM_HSCROLL`](https://learn.microsoft.com/en-us/windows/win32/controls/wm-hscroll)
632 /// message.
633 }
634
635 pub_fn_wm_withparm_noret! { wm_help, co::WM::HELP, wm::Help;
636 /// [`WM_HELP`](https://learn.microsoft.com/en-us/windows/win32/shell/wm-help)
637 /// message.
638 }
639
640 pub_fn_wm_withparm_boolret! { wm_init_dialog, co::WM::INITDIALOG, wm::InitDialog;
641 /// [`WM_INITDIALOG`](https://learn.microsoft.com/en-us/windows/win32/dlgbox/wm-initdialog)
642 /// message, sent only to dialog windows. Non-dialog windows must handle
643 /// [`wm_create`](crate::gui::events::WindowEvents::wm_create) instead.
644 ///
645 /// Return `true` to set the focus to the first control in the dialog.
646 ///
647 /// # Examples
648 ///
649 /// ```no_run
650 /// use winsafe::{self as w, prelude::*, gui, msg};
651 ///
652 /// let wnd: gui::WindowMain; // initialized somewhere
653 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
654 ///
655 /// wnd.on().wm_init_dialog(
656 /// move |p: msg::wm::InitDialog| -> w::AnyResult<bool> {
657 /// println!("Focused HWND: {}", p.hwnd_focus);
658 /// Ok(true)
659 /// },
660 /// );
661 /// ```
662 }
663
664 pub_fn_wm_withparm_noret! { wm_init_menu_popup, co::WM::INITMENUPOPUP, wm::InitMenuPopup;
665 /// [`WM_INITMENUPOPUP`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-initmenupopup)
666 /// message.
667 ///
668 /// # Examples
669 ///
670 /// ```no_run
671 /// use winsafe::{self as w, prelude::*, gui, msg};
672 ///
673 /// let wnd: gui::WindowMain; // initialized somewhere
674 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
675 ///
676 /// wnd.on().wm_init_menu_popup(
677 /// move |p: msg::wm::InitMenuPopup| -> w::AnyResult<()> {
678 /// if p.hmenu.GetMenuItemID(0).unwrap() == 3001 { // check ID of 1st item
679 /// p.hmenu.EnableMenuItem(w::IdPos::Id(3001), false)?;
680 /// }
681 /// Ok(())
682 /// },
683 /// );
684 /// ```
685 }
686
687 pub_fn_wm_withparm_noret! { wm_key_down, co::WM::KEYDOWN, wm::KeyDown;
688 /// [`WM_KEYDOWN`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-keydown)
689 /// message.
690 }
691
692 pub_fn_wm_withparm_noret! { wm_key_up, co::WM::KEYUP, wm::KeyUp;
693 /// [`WM_KEYUP`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-keyup)
694 /// message.
695 }
696
697 pub_fn_wm_withparm_noret! { wm_kill_focus, co::WM::KILLFOCUS, wm::KillFocus;
698 /// [`WM_KILLFOCUS`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-killfocus)
699 /// message.
700 }
701
702 pub_fn_wm_withparm_noret! { wm_l_button_dbl_clk, co::WM::LBUTTONDBLCLK, wm::LButtonDblClk;
703 /// [`WM_LBUTTONDBLCLK`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-lbuttondblclk)
704 /// message.
705 ///
706 /// # Examples
707 ///
708 /// ```no_run
709 /// use winsafe::{self as w, prelude::*, gui, msg};
710 ///
711 /// let wnd: gui::WindowMain; // initialized somewhere
712 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
713 ///
714 /// wnd.on().wm_l_button_dbl_clk(
715 /// move |p: msg::wm::LButtonDblClk| -> w::AnyResult<()> {
716 /// println!("Point: {}x{}", p.coords.x, p.coords.y);
717 /// Ok(())
718 /// },
719 /// );
720 /// ```
721 }
722
723 pub_fn_wm_withparm_noret! { wm_l_button_down, co::WM::LBUTTONDOWN, wm::LButtonDown;
724 /// [`WM_LBUTTONDOWN`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-lbuttondown)
725 /// message.
726 ///
727 /// # Examples
728 ///
729 /// ```no_run
730 /// use winsafe::{self as w, prelude::*, gui, msg};
731 ///
732 /// let wnd: gui::WindowMain; // initialized somewhere
733 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
734 ///
735 /// wnd.on().wm_l_button_down(
736 /// move |p: msg::wm::LButtonDown| -> w::AnyResult<()> {
737 /// println!("Point: {}x{}", p.coords.x, p.coords.y);
738 /// Ok(())
739 /// },
740 /// );
741 /// ```
742 }
743
744 pub_fn_wm_withparm_noret! { wm_l_button_up, co::WM::LBUTTONUP, wm::LButtonUp;
745 /// [`WM_LBUTTONUP`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-lbuttonup)
746 /// message.
747 }
748
749 pub_fn_wm_withparm_noret! { wm_m_button_dbl_clk, co::WM::MBUTTONDBLCLK, wm::MButtonDblClk;
750 /// [`WM_MBUTTONDBLCLK`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-mbuttondblclk)
751 /// message.
752 }
753
754 pub_fn_wm_withparm_noret! { wm_m_button_down, co::WM::MBUTTONDOWN, wm::MButtonDown;
755 /// [`WM_MBUTTONDOWN`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-mbuttondown)
756 /// message.
757 }
758
759 pub_fn_wm_withparm_noret! { wm_m_button_up, co::WM::MBUTTONUP, wm::MButtonUp;
760 /// [`WM_MBUTTONUP`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-mbuttonup)
761 /// message.
762 }
763
764 pub_fn_wm_withparm_noret! { wm_menu_command, co::WM::MENUCOMMAND, wm::MenuCommand;
765 /// [`WM_MENUCOMMAND`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-menucommand)
766 /// message.
767 }
768
769 pub_fn_wm_withparm_coret! { wm_menu_drag, co::WM::MENUDRAG, wm::MenuDrag, co::MND;
770 /// [`WM_MENUDRAG`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-menudrag)
771 /// message.
772 }
773
774 pub_fn_wm_withparm_noret! { wm_menu_r_button_up, co::WM::MENURBUTTONUP, wm::MenuRButtonUp;
775 /// [`WM_MENURBUTTONUP`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-menurbuttonup)
776 /// message.
777 }
778
779 pub_fn_wm_withparm_noret! { wm_mouse_h_wheel, co::WM::MOUSEHWHEEL, wm::MouseHWheel;
780 /// [`WM_MOUSEHWHEEL`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-mousehwheel)
781 /// message.
782 }
783
784 pub_fn_wm_withparm_noret! { wm_mouse_hover, co::WM::MOUSEHOVER, wm::MouseHover;
785 /// [`WM_MOUSEHOVER`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-mousehover)
786 /// message.
787 }
788
789 pub_fn_wm_noparm_noret! { wm_mouse_leave, co::WM::MOUSELEAVE;
790 /// [`WM_MOUSELEAVE`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-mouseleave)
791 /// message.
792 }
793
794 pub_fn_wm_withparm_noret! { wm_mouse_move, co::WM::MOUSEMOVE, wm::MouseMove;
795 /// [`WM_MOUSEMOVE`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-mousemove)
796 /// message.
797 }
798
799 pub_fn_wm_withparm_noret! { wm_move, co::WM::MOVE, wm::Move;
800 /// [`WM_MOVE`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-move)
801 /// message.
802 }
803
804 pub_fn_wm_withparm_noret! { wm_mouse_wheel, co::WM::MOUSEWHEEL, wm::MouseWheel;
805 /// [`WM_MOUSEWHEEL`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-mousewheel)
806 /// message.
807 }
808
809 pub_fn_wm_withparm_noret! { wm_moving, co::WM::MOVING, wm::Moving;
810 /// [`WM_MOVING`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-moving)
811 /// message.
812 }
813
814 pub_fn_wm_withparm_coret! { wm_nc_calc_size, co::WM::NCCALCSIZE, wm::NcCalcSize, co::WVR;
815 /// [`WM_NCCALCSIZE`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize)
816 /// message.
817 }
818
819 pub_fn_wm_withparm_boolret! { wm_nc_create, co::WM::NCCREATE, wm::NcCreate;
820 /// [`WM_NCCREATE`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-nccreate)
821 /// message.
822 }
823
824 pub_fn_wm_noparm_noret! { wm_nc_destroy, co::WM::NCDESTROY;
825 /// [`WM_NCDESTROY`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-ncdestroy)
826 /// message.
827 ///
828 /// # Default handling
829 ///
830 /// If you handle this event, you'll overwrite the default handling in:
831 ///
832 /// * non-dialog [`WindowMain`](crate::gui::WindowMain);
833 /// * dialog [`WindowMain`](crate::gui::WindowMain).
834 ///
835 /// In both cases, [`PostQuitMessage`](crate::PostQuitMessage) is called.
836 }
837
838 pub_fn_wm_withparm_coret! { wm_nc_hit_test, co::WM::NCHITTEST, wm::NcHitTest, co::HT;
839 /// [`WM_NCHITTEST`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest)
840 /// message.
841 }
842
843 pub_fn_wm_withparm_noret! { wm_nc_paint, co::WM::NCPAINT, wm::NcPaint;
844 /// [`WM_NCPAINT`](https://learn.microsoft.com/en-us/windows/win32/gdi/wm-ncpaint)
845 /// message.
846 }
847
848 pub_fn_wm_withparm_noret! { wm_next_dlg_ctl, co::WM::NEXTDLGCTL, wm::NextDlgCtl;
849 /// [`WM_NEXTDLGCTL`](https://learn.microsoft.com/en-us/windows/win32/dlgbox/wm-nextdlgctl)
850 /// message.
851 }
852
853 pub_fn_wm_noparm_noret! { wm_null, co::WM::NULL;
854 /// [`WM_NULL`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-null)
855 /// message.
856 }
857
858 pub_fn_wm_noparm_noret! { wm_paint, co::WM::PAINT;
859 /// [`WM_PAINT`](https://learn.microsoft.com/en-us/windows/win32/gdi/wm-paint)
860 /// message.
861 ///
862 /// # Examples
863 ///
864 /// ```no_run
865 /// use winsafe::{self as w, prelude::*, gui};
866 ///
867 /// let wnd: gui::WindowMain; // initialized somewhere
868 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
869 ///
870 /// let wnd2 = wnd.clone(); // to pass into the closure
871 ///
872 /// wnd.on().wm_paint(
873 /// move || -> w::AnyResult<()> {
874 /// let hdc = wnd2.hwnd().BeginPaint()?;
875 ///
876 /// // hdc painting...
877 ///
878 /// Ok(())
879 ///
880 /// // EndPaint() automatically called
881 /// },
882 /// );
883 /// ```
884 }
885
886 pub_fn_wm_withparm_noret! { wm_parent_notify, co::WM::PARENTNOTIFY, wm::ParentNotify;
887 /// [`WM_PARENTNOTIFY`](https://learn.microsoft.com/en-us/windows/win32/inputmsg/wm-parentnotify)
888 /// message.
889 }
890
891 pub_fn_wm_withparm_noret! { wm_power_broadcast, co::WM::POWERBROADCAST, wm::PowerBroadcast;
892 /// [`WM_POWERBROADCAST`](https://learn.microsoft.com/en-us/windows/win32/power/wm-powerbroadcast)
893 /// message.
894 }
895
896 pub_fn_wm_noparm_boolret! { wm_query_open, co::WM::QUERYOPEN;
897 /// [`WM_QUERYOPEN`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-queryopen)
898 /// message.
899 }
900
901 pub_fn_wm_withparm_noret! { wm_r_button_dbl_clk, co::WM::RBUTTONDBLCLK, wm::RButtonDblClk;
902 /// [`WM_RBUTTONDBLCLK`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-rbuttondblclk)
903 /// message.
904 }
905
906 pub_fn_wm_withparm_noret! { wm_r_button_down, co::WM::RBUTTONDOWN, wm::RButtonDown;
907 /// [`WM_RBUTTONDOWN`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-rbuttondown)
908 /// message.
909 }
910
911 pub_fn_wm_withparm_noret! { wm_r_button_up, co::WM::RBUTTONUP, wm::RButtonUp;
912 /// [`WM_RBUTTONUP`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-rbuttonup)
913 }
914
915 pub_fn_wm_withparm_boolret! { wm_set_cursor, co::WM::SETCURSOR, wm::SetCursor;
916 /// [`WM_SETCURSOR`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-setcursor)
917 /// message.
918 }
919
920 pub_fn_wm_withparm_noret! { wm_set_focus, co::WM::SETFOCUS, wm::SetFocus;
921 /// [`WM_SETFOCUS`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-setfocus)
922 /// message.
923 }
924
925 pub_fn_wm_withparm_noret! { wm_set_font, co::WM::SETFONT, wm::SetFont;
926 /// [`WM_SETFONT`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-setfont)
927 /// message.
928 }
929
930 /// [`WM_SETICON`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-seticon)
931 /// message.
932 pub fn wm_set_icon<F>(&self, func: F) -> &Self
933 where
934 F: Fn(wm::SetIcon) -> AnyResult<Option<HICON>> + 'static,
935 {
936 self.wm(co::WM::SETICON, move |p| {
937 Ok(func(unsafe { wm::SetIcon::from_generic_wm(p) })?.map_or(0, |h| h.ptr() as _))
938 });
939 self
940 }
941
942 pub_fn_wm_withparm_noret! { wm_set_redraw, co::WM::SETREDRAW, wm::SetRedraw;
943 /// [`WM_SETREDRAW`](https://learn.microsoft.com/en-us/windows/win32/gdi/wm-setredraw)
944 /// message.
945 }
946
947 pub_fn_wm_withparm_boolret! { wm_set_text, co::WM::SETTEXT, wm::SetText;
948 /// [`WM_SETTEXT`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-settext)
949 /// message.
950 }
951
952 pub_fn_wm_withparm_noret! { wm_show_window, co::WM::SHOWWINDOW, wm::ShowWindow;
953 /// [`WM_SHOWWINDOW`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-showwindow)
954 /// message.
955 }
956
957 pub_fn_wm_withparm_noret! { wm_size, co::WM::SIZE, wm::Size;
958 /// [`WM_SIZE`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-size)
959 /// message.
960 ///
961 /// # Examples
962 ///
963 /// ```no_run
964 /// use winsafe::{self as w, prelude::*, gui, msg};
965 ///
966 /// let wnd: gui::WindowMain; // initialized somewhere
967 /// # let wnd = gui::WindowMain::new(gui::WindowMainOpts::default());
968 ///
969 /// wnd.on().wm_size(
970 /// move |p: msg::wm::Size| -> w::AnyResult<()> {
971 /// println!("Client area: {}x{}",
972 /// p.client_area.cx,
973 /// p.client_area.cy,
974 /// );
975 /// Ok(())
976 /// },
977 /// );
978 /// ```
979 }
980
981 pub_fn_wm_withparm_noret! { wm_sizing, co::WM::SIZING, wm::Sizing;
982 /// [`WM_SIZING`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-sizing)
983 /// message.
984 }
985
986 pub_fn_wm_withparm_noret! { wm_style_changed, co::WM::STYLECHANGED, wm::StyleChanged;
987 /// [`WM_STYLECHANGED`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-stylechanged)
988 /// message.
989 }
990
991 pub_fn_wm_withparm_noret! { wm_style_changing, co::WM::STYLECHANGING, wm::StyleChanging;
992 /// [`WM_STYLECHANGING`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-stylechanging)
993 /// message.
994 }
995
996 pub_fn_wm_noparm_noret! { wm_sync_paint, co::WM::SYNCPAINT;
997 /// [`WM_SYNCPAINT`](https://learn.microsoft.com/en-us/windows/win32/gdi/wm-syncpaint)
998 /// message.
999 }
1000
1001 pub_fn_wm_withparm_noret! { wm_sys_char, co::WM::SYSCHAR, wm::SysChar;
1002 /// [`WM_SYSCHAR`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-syschar)
1003 /// message.
1004 }
1005
1006 pub_fn_wm_withparm_noret! { wm_sys_command, co::WM::SYSCOMMAND, wm::SysCommand;
1007 /// [`WM_SYSCOMMAND`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-syscommand)
1008 /// message.
1009 }
1010
1011 pub_fn_wm_withparm_noret! { wm_sys_dead_char, co::WM::SYSDEADCHAR, wm::SysDeadChar;
1012 /// [`WM_SYSDEADCHAR`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-sysdeadchar)
1013 /// message.
1014 }
1015
1016 pub_fn_wm_withparm_noret! { wm_sys_key_down, co::WM::SYSKEYDOWN, wm::SysKeyDown;
1017 /// [`WM_SYSKEYDOWN`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-syskeydown)
1018 /// message.
1019 }
1020
1021 pub_fn_wm_withparm_noret! { wm_sys_key_up, co::WM::SYSKEYUP, wm::SysKeyUp;
1022 /// [`WM_SYSKEYUP`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-syskeyup)
1023 /// message.
1024 }
1025
1026 pub_fn_wm_noparm_noret! { wm_theme_changed, co::WM::THEMECHANGED;
1027 /// [`WM_THEMECHANGED`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-themechanged)
1028 /// message.
1029 }
1030
1031 pub_fn_wm_withparm_noret! { wm_uninit_menu_popup, co::WM::UNINITMENUPOPUP, wm::UninitMenuPopup;
1032 /// [`WM_UNINITMENUPOPUP`](https://learn.microsoft.com/en-us/windows/win32/menurc/wm-uninitmenupopup)
1033 /// message.
1034 }
1035
1036 pub_fn_wm_noparm_boolret! { wm_undo, co::WM::UNDO;
1037 /// [`WM_UNDO`](https://learn.microsoft.com/en-us/windows/win32/controls/wm-undo)
1038 /// message.
1039 }
1040
1041 pub_fn_wm_withparm_noret! { wm_v_scroll, co::WM::VSCROLL, wm::VScroll;
1042 /// [`WM_VSCROLL`](https://learn.microsoft.com/en-us/windows/win32/controls/wm-vscroll)
1043 /// message.
1044 }
1045
1046 pub_fn_wm_withparm_noret! { wm_window_pos_changed, co::WM::WINDOWPOSCHANGED, wm::WindowPosChanged;
1047 /// [`WM_WINDOWPOSCHANGED`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-windowposchanged)
1048 /// message.
1049 }
1050
1051 pub_fn_wm_withparm_noret! { wm_window_pos_changing, co::WM::WINDOWPOSCHANGING, wm::WindowPosChanging;
1052 /// [`WM_WINDOWPOSCHANGING`](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-windowposchanging)
1053 /// message.
1054 }
1055
1056 pub_fn_wm_withparm_noret! { wm_wts_session_change, co::WM::WTSSESSION_CHANGE, wm::WtsSessionChange;
1057 /// [`WM_WTSSESSION_CHANGE`](https://learn.microsoft.com/en-us/windows/win32/termserv/wm-wtssession-change)
1058 /// message.
1059 }
1060
1061 pub_fn_wm_withparm_noret! { wm_x_button_dbl_clk, co::WM::XBUTTONDBLCLK, wm::XButtonDblClk;
1062 /// [`WM_XBUTTONDBLCLK`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-xbuttondblclk)
1063 /// message.
1064 }
1065
1066 pub_fn_wm_withparm_noret! { wm_x_button_down, co::WM::XBUTTONDOWN, wm::XButtonDown;
1067 /// [`WM_XBUTTONDOWN`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-xbuttondown)
1068 /// message.
1069 }
1070
1071 pub_fn_wm_withparm_noret! { wm_x_button_up, co::WM::XBUTTONUP, wm::XButtonUp;
1072 /// [`WM_XBUTTONUP`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-xbuttonup)
1073 /// message.
1074 }
1075}