-
Notifications
You must be signed in to change notification settings - Fork 27
/
window_main.rs
144 lines (124 loc) · 3.66 KB
/
window_main.rs
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use std::any::Any;
use crate::co;
use crate::comctl::decl::InitCommonControls;
use crate::ffi_types::BOOL;
use crate::gui::dlg_main::DlgMain;
use crate::gui::events::WindowEventsAll;
use crate::gui::privs::{create_ui_font, delete_ui_font};
use crate::gui::raw_main::{RawMain, WindowMainOpts};
use crate::gui::runtime_error::RunResult;
use crate::kernel::decl::{ErrResult, HPROCESS, IsWindowsVistaOrGreater};
use crate::prelude::{
GuiParent, GuiThread, GuiWindow, GuiWindowText, KernelHprocess,
UserHprocess,
};
use crate::user::decl::{HWND, SetProcessDPIAware};
/// Keeps a raw or dialog window.
#[derive(Clone)]
enum RawDlg { Raw(RawMain), Dlg(DlgMain) }
//------------------------------------------------------------------------------
/// An user main window, which can handle events. Usually, this is the first
/// window of your application, launched directly from the `main` function. Can
/// be programmatically created or load a dialog resource from a `.res` file.
#[cfg_attr(docsrs, doc(cfg(feature = "gui")))]
#[derive(Clone)]
pub struct WindowMain(RawDlg);
unsafe impl Send for WindowMain {}
impl GuiWindow for WindowMain {
fn hwnd(&self) -> HWND {
match &self.0 {
RawDlg::Raw(r) => r.hwnd(),
RawDlg::Dlg(d) => d.hwnd(),
}
}
fn as_any(&self) -> &dyn Any {
self
}
}
impl GuiWindowText for WindowMain {}
impl GuiParent for WindowMain {
fn on(&self) -> &WindowEventsAll {
match &self.0 {
RawDlg::Raw(r) => r.on(),
RawDlg::Dlg(d) => d.on(),
}
}
unsafe fn as_base(&self) -> *mut std::ffi::c_void {
match &self.0 {
RawDlg::Raw(r) => r.as_base(),
RawDlg::Dlg(d) => d.as_base(),
}
}
}
impl GuiThread for WindowMain {
fn spawn_new_thread<F>(&self, func: F)
where F: FnOnce() -> ErrResult<()> + Send + 'static,
{
match &self.0 {
RawDlg::Raw(r) => r.spawn_new_thread(func),
RawDlg::Dlg(d) => d.spawn_new_thread(func),
}
}
fn run_ui_thread<F>(&self, func: F)
where F: FnOnce() -> ErrResult<()> + Send + 'static
{
match &self.0 {
RawDlg::Raw(r) => r.run_ui_thread(func),
RawDlg::Dlg(d) => d.run_ui_thread(func),
}
}
}
impl WindowMain {
/// Instantiates a new `WindowMain` object, to be created internally with
/// [`HWND::CreateWindowEx`](crate::prelude::UserHwnd::CreateWindowEx).
#[must_use]
pub fn new(opts: WindowMainOpts) -> WindowMain {
Self(
RawDlg::Raw(
RawMain::new(opts),
),
)
}
/// Instantiates a new `WindowMain` object, to be loaded from a dialog
/// resource with
/// [`HWND::GetDlgItem`](crate::prelude::UserHwnd::GetDlgItem).
#[must_use]
pub fn new_dlg(
dialog_id: u16,
icon_id: Option<u16>,
accel_table_id: Option<u16>) -> WindowMain
{
Self(
RawDlg::Dlg(
DlgMain::new(dialog_id, icon_id, accel_table_id),
),
)
}
/// Physically creates the window, then runs the main application loop. This
/// method will block until the window is closed.
///
/// The `cmd_show` parameter defaults to
/// [`co::SW::SHOW`](crate::co::SW::SHOW).
///
/// # Panics
///
/// Panics if the window is already created.
pub fn run_main(&self, cmd_show: Option<co::SW>) -> RunResult<i32> {
if IsWindowsVistaOrGreater().unwrap() {
SetProcessDPIAware().unwrap();
}
InitCommonControls();
let mut b_val: BOOL = 0; // false
unsafe {
HPROCESS::GetCurrentProcess().SetUserObjectInformation( // SetTimer() safety
co::UOI::TIMERPROC_EXCEPTION_SUPPRESSION, &mut b_val).unwrap();
}
create_ui_font();
let res = match &self.0 {
RawDlg::Raw(r) => r.run_main(cmd_show),
RawDlg::Dlg(d) => d.run_main(cmd_show),
};
delete_ui_font(); // cleanup
res
}
}