pacenotes_installer\wizard/
sheet.rs1use windows_sys::Win32::UI::Controls as ctl;
2use windows_sys::Win32::UI::WindowsAndMessaging as wm;
3
4const GAME_FOLDER_PAGE: u32 = 2;
6
7const SHEET_SUBCLASS: usize = 1;
8
9pub fn run(
12 base_url: &str,
13 cache_override: Option<std::path::PathBuf>,
14 restart: Option<crate::elevation::Restart>,
15) {
16 let mut state = crate::wizard::state::WizardState::new(base_url.to_string(), cache_override);
17 let start_page = match restart {
18 Some(restart) => {
19 state.resume(restart);
20 GAME_FOLDER_PAGE
21 }
22 None => 0,
23 };
24 let state_pointer = &mut state as *mut _ as windows_sys::Win32::Foundation::LPARAM;
25
26 let pages = [
27 page(
28 crate::wizard::control_ids::IDD_S1_LANGUAGE,
29 Some(crate::wizard::scene::language_page),
30 state_pointer,
31 ),
32 page(
33 crate::wizard::control_ids::IDD_S2_MOTD,
34 Some(crate::wizard::scene::motd_page),
35 state_pointer,
36 ),
37 page(
38 crate::wizard::control_ids::IDD_S3_FOLDER,
39 Some(crate::wizard::scene::game_folder_page),
40 state_pointer,
41 ),
42 page(
43 crate::wizard::control_ids::IDD_S4_DOWNLOAD,
44 Some(crate::wizard::scene::download_page),
45 state_pointer,
46 ),
47 page(
48 crate::wizard::control_ids::IDD_S4B_FETCH,
49 Some(crate::wizard::scene::fetching_page),
50 state_pointer,
51 ),
52 page(
53 crate::wizard::control_ids::IDD_S5_CONFIG,
54 Some(crate::wizard::scene::configuration_page),
55 state_pointer,
56 ),
57 page(
58 crate::wizard::control_ids::IDD_S6_INSTALL,
59 Some(crate::wizard::scene::installation_page),
60 state_pointer,
61 ),
62 page(
63 crate::wizard::control_ids::IDD_S7_SUMMARY,
64 Some(crate::wizard::scene::summary_page),
65 state_pointer,
66 ),
67 page(
70 crate::wizard::control_ids::IDD_RESTORE,
71 Some(crate::wizard::scene::restore_page),
72 state_pointer,
73 ),
74 ];
75
76 let caption = crate::i18n::to_wide(&crate::i18n::load_string(crate::i18n::IDS_APP_TITLE));
77 unsafe {
78 let mut header: ctl::PROPSHEETHEADERW_V2 = core::mem::zeroed();
79 header.dwSize = core::mem::size_of::<ctl::PROPSHEETHEADERW_V2>() as u32;
80 header.dwFlags =
81 ctl::PSH_WIZARD | ctl::PSH_PROPSHEETPAGE | ctl::PSH_USEHICON | ctl::PSH_USECALLBACK;
82 header.pfnCallback = Some(on_sheet_event);
83 header.hInstance = crate::i18n::instance();
84 header.pszCaption = caption.as_ptr();
85 header.nPages = pages.len() as u32;
86 header.Anonymous1.hIcon = crate::ui::load_app_icon();
87 header.Anonymous2.nStartPage = start_page;
88 header.Anonymous3.ppsp = pages.as_ptr() as *mut ctl::PROPSHEETPAGEW;
89 ctl::PropertySheetW(&mut header);
90 }
91}
92
93unsafe extern "system" fn on_sheet_event(
96 sheet: windows_sys::Win32::Foundation::HWND,
97 message: u32,
98 _lparam: windows_sys::Win32::Foundation::LPARAM,
99) -> i32 {
100 if message == ctl::PSCB_INITIALIZED {
101 windows_sys::Win32::UI::Shell::SetWindowSubclass(
102 sheet,
103 Some(paint_forward_buttons),
104 SHEET_SUBCLASS,
105 0,
106 );
107 }
108 0
109}
110
111unsafe extern "system" fn paint_forward_buttons(
113 sheet: windows_sys::Win32::Foundation::HWND,
114 message: u32,
115 wparam: windows_sys::Win32::Foundation::WPARAM,
116 lparam: windows_sys::Win32::Foundation::LPARAM,
117 _subclass: usize,
118 _reference: usize,
119) -> windows_sys::Win32::Foundation::LRESULT {
120 if message == wm::WM_NOTIFY {
121 let forward = [
122 crate::wizard::page::ID_WIZNEXT,
123 crate::wizard::page::ID_WIZFINISH,
124 ];
125 let header = &*(lparam as *const ctl::NMHDR);
127 if header.code == ctl::NM_CUSTOMDRAW && forward.contains(&(header.idFrom as u16)) {
128 return crate::ui::paint_forward_button(&*(lparam as *const ctl::NMCUSTOMDRAW));
129 }
130 }
131 windows_sys::Win32::UI::Shell::DefSubclassProc(sheet, message, wparam, lparam)
132}
133
134fn page(
136 template: u16,
137 dialog_proc: wm::DLGPROC,
138 state: windows_sys::Win32::Foundation::LPARAM,
139) -> ctl::PROPSHEETPAGEW {
140 unsafe {
141 let mut page: ctl::PROPSHEETPAGEW = core::mem::zeroed();
142 page.dwSize = core::mem::size_of::<ctl::PROPSHEETPAGEW>() as u32;
143 page.dwFlags = ctl::PSP_DEFAULT;
144 page.hInstance = crate::i18n::instance();
145 page.Anonymous1.pszTemplate = crate::ui::make_int_resource(template);
146 page.pfnDlgProc = dialog_proc;
147 page.lParam = state;
148 page
149 }
150}