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}