1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use crate::*;
use *;
/// \[[learn.microsoft.com](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-destroywindow)\]
/// DestroyWindow
///
/// Destroys the specified window.
///
/// ### Safety
/// * Destroying a window out from underneath a 3D rendering API such as Direct3D is generally unsound.
/// * Destroying a window from it's own WM_DESTROY is unlikely to be sound.
/// While windows itself appears able to handle it, it results in multiple WM_DESTROY and WM_NCDESTROY events for the same [HWnd], and I suspect many C++ WndProcs can't tolerate that.
/// * You should probably only destroy windows you created, and even then be careful!
/// * See [HWnd] for more rants/details.
///
/// ### Errors
/// * [ERROR::ACCESS_DENIED] If `hwnd` belongs to another process
/// * [ERROR::ACCESS_DENIED] If `hwnd` belongs to another thread
/// * [ERROR::INVALID_WINDOW_HANDLE] If `hwnd` is not a valid window handle
///
/// ### Examples
/// ```rust
/// # use hwnd::*;
/// # use winresult::*;
/// # use std::ptr::*;
/// # let desktop = get_desktop_window();
/// # fn create_window(_: std::ops::RangeFull) -> HWnd {
/// # unsafe { create_window_a(
/// # abistr::cstr!("Message"), (), 0,
/// # 0, 0, 0, 0,
/// # HWnd::MESSAGE, null_mut(), None, null_mut()
/// # )}.unwrap()
/// # }
/// #
/// // "Typical" usage:
/// let window = create_window(..);
/// // ...
/// unsafe { destroy_window(window) }.unwrap();
///
///
/// // Edge cases:
/// assert_eq!(
/// ERROR::INVALID_WINDOW_HANDLE, // already destroyed
/// unsafe { destroy_window(window) }.unwrap_err(),
/// );
///
/// assert_eq!(
/// ERROR::INVALID_WINDOW_HANDLE, // invalid handle
/// unsafe { destroy_window(null_mut()) }.unwrap_err(),
/// );
///
/// assert_eq!(
/// ERROR::ACCESS_DENIED, // wrong process
/// unsafe { destroy_window(desktop) }.unwrap_err(),
/// );
///
/// let window = create_window(..);
/// assert_eq!(
/// ERROR::ACCESS_DENIED, // wrong thread
/// std::thread::spawn(move || unsafe {
/// destroy_window(window)
/// }).join().unwrap().unwrap_err(),
/// );
/// unsafe { destroy_window(window) }.unwrap();
/// ```
pub unsafe