native_windows_gui2/resources/
embed.rs1use super::{Bitmap, Cursor, Icon};
2use crate::NwgError;
3use crate::win32::base_helper::{from_utf16, to_utf16};
4use std::{ptr, slice};
5use winapi::ctypes::c_void;
6use winapi::shared::minwindef::{HGLOBAL, HINSTANCE, HRSRC};
7use winapi::um::winuser::{LR_CREATEDIBSECTION, LR_DEFAULTSIZE, LoadImageW};
8
9#[derive(Copy, Clone, Debug)]
11pub enum RawResourceType {
12 Cursor,
13 Bitmap,
14 Icon,
15 Menu,
16 Dialog,
17 String,
18 FontDir,
19 Font,
20 Accelerator,
21 RawData,
22 MessageTable,
23 Version,
24 DlgInclude,
25 PlugPlay,
26 Vxd,
27 AnimatedCursor,
28 AnimatedIcon,
29 Html,
30 Manifest,
31 Other(&'static str),
32}
33
34pub struct RawResource {
41 module: HINSTANCE,
42 handle: HRSRC,
43 data_handle: HGLOBAL,
44 ty: RawResourceType,
45}
46
47impl RawResource {
48 pub fn handle(&self) -> HRSRC {
50 self.handle
51 }
52
53 pub fn data_handle(&self) -> HGLOBAL {
55 self.data_handle
56 }
57
58 pub fn resource_type(&self) -> RawResourceType {
60 self.ty
61 }
62
63 pub fn len(&self) -> usize {
65 use winapi::um::libloaderapi::SizeofResource;
66
67 unsafe { SizeofResource(self.module, self.handle) as usize }
68 }
69
70 pub unsafe fn as_mut_ptr(&mut self) -> *mut c_void {
72 self.lock()
73 }
74
75 pub fn as_mut_slice(&self) -> &mut [u8] {
77 unsafe { std::slice::from_raw_parts_mut(self.lock() as *mut u8, self.len()) }
78 }
79
80 fn lock(&self) -> *mut c_void {
81 use winapi::um::libloaderapi::LockResource;
82 unsafe { LockResource(self.data_handle) }
83 }
84}
85
86pub struct EmbedResource {
107 pub hinst: HINSTANCE,
108}
109
110impl EmbedResource {
111 pub fn load(name: Option<&str>) -> Result<EmbedResource, NwgError> {
113 let mut embed = EmbedResource::default();
114 EmbedResource::builder().module(name).build(&mut embed)?;
115
116 Ok(embed)
117 }
118
119 pub fn builder() -> EmbedResourceBuilder {
121 EmbedResourceBuilder { module: None }
122 }
123
124 pub fn string(&self, id: u32) -> Option<String> {
126 use winapi::um::libloaderapi::LoadStringW;
127 unsafe {
128 let mut str_ptr = ptr::null_mut();
129 let ccount = LoadStringW(self.hinst, id, (&mut str_ptr) as *mut *mut u16 as _, 0);
130 match ccount {
131 0 => None,
132 count => {
133 let str_slice = slice::from_raw_parts(str_ptr, count as usize);
134 Some(from_utf16(str_slice))
135 }
136 }
137 }
138 }
139
140 pub fn icon(&self, id: usize, size: Option<(u32, u32)>) -> Option<Icon> {
143 use winapi::um::winuser::IMAGE_ICON;
144
145 unsafe {
146 let id_rc = id as _;
147 let icon = match size {
148 None => LoadImageW(self.hinst, id_rc, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE),
149 Some((w, h)) => LoadImageW(self.hinst, id_rc, IMAGE_ICON, w as _, h as _, 0),
150 };
151
152 if icon.is_null() {
153 None
154 } else {
155 Some(Icon {
156 handle: icon as _,
157 owned: true,
158 })
159 }
160 }
161 }
162
163 pub fn icon_str(&self, id: &str, size: Option<(u32, u32)>) -> Option<Icon> {
165 let name = to_utf16(id);
166 self.icon(name.as_ptr() as usize, size)
167 }
168
169 pub fn bitmap(&self, id: usize, size: Option<(u32, u32)>) -> Option<Bitmap> {
171 use winapi::um::winuser::IMAGE_BITMAP;
172
173 unsafe {
174 let id_rc = id as _;
175 let bitmap = match size {
176 None => LoadImageW(self.hinst, id_rc, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE),
177 Some((w, h)) => LoadImageW(
178 self.hinst,
179 id_rc,
180 IMAGE_BITMAP,
181 w as _,
182 h as _,
183 LR_CREATEDIBSECTION,
184 ),
185 };
186
187 if bitmap.is_null() {
188 None
189 } else {
190 Some(Bitmap {
191 handle: bitmap as _,
192 owned: true,
193 })
194 }
195 }
196 }
197
198 pub fn bitmap_str(&self, id: &str, size: Option<(u32, u32)>) -> Option<Bitmap> {
200 let name = to_utf16(id);
201 self.bitmap(name.as_ptr() as usize, size)
202 }
203
204 #[cfg(feature = "image-decoder")]
205 pub fn image(&self, id: usize, size: Option<(u32, u32)>) -> Option<Bitmap> {
208 use crate::win32::resources_helper as rh;
209
210 match self.raw(id, RawResourceType::Other("Image")) {
211 None => None,
212 Some(raw) => {
213 let src = raw.as_mut_slice();
214 let handle = unsafe { rh::build_image_decoder_from_memory(src, size) };
215 match handle {
216 Ok(handle) => Some(Bitmap {
217 handle,
218 owned: true,
219 }),
220 Err(e) => {
221 println!("{:?}", e);
222 None
223 }
224 }
225 }
226 }
227 }
228
229 #[cfg(feature = "image-decoder")]
230 pub fn image_str(&self, id: &str, size: Option<(u32, u32)>) -> Option<Bitmap> {
232 let name = to_utf16(id);
233 self.image(name.as_ptr() as usize, size)
234 }
235
236 pub fn cursor(&self, id: usize) -> Option<Cursor> {
238 use winapi::um::winuser::IMAGE_CURSOR;
239
240 unsafe {
241 let id_rc = id as _;
242 let cursor = LoadImageW(self.hinst, id_rc, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE);
243 if cursor.is_null() {
244 None
245 } else {
246 Some(Cursor {
247 handle: cursor as _,
248 owned: true,
249 })
250 }
251 }
252 }
253
254 pub fn cursor_str(&self, id: &str) -> Option<Cursor> {
256 let name = to_utf16(id);
257 self.cursor(name.as_ptr() as usize)
258 }
259
260 pub fn raw(&self, id: usize, ty: RawResourceType) -> Option<RawResource> {
262 use RawResourceType::*;
263 use winapi::um::libloaderapi::{FindResourceW, LoadResource};
264
265 unsafe {
266 let data_u16;
267 let ty_value = match ty {
268 Cursor => 1,
269 Bitmap => 2,
270 Icon => 3,
271 Menu => 4,
272 Dialog => 5,
273 String => 6,
274 FontDir => 7,
275 Font => 8,
276 Accelerator => 9,
277 RawData => 10,
278 MessageTable => 11,
279 Version => 16,
280 DlgInclude => 17,
281 PlugPlay => 19,
282 Vxd => 20,
283 AnimatedCursor => 21,
284 AnimatedIcon => 22,
285 Html => 23,
286 Manifest => 24,
287 Other(value) => {
288 data_u16 = Some(to_utf16(value));
289 data_u16.as_ref().map(|v| v.as_ptr() as usize).unwrap()
290 }
291 };
292
293 let handle = FindResourceW(self.hinst as _, id as _, ty_value as _);
294 if handle.is_null() {
295 return None;
296 }
297
298 let data_handle = LoadResource(self.hinst as _, handle);
299
300 Some(RawResource {
301 module: self.hinst,
302 handle,
303 data_handle,
304 ty,
305 })
306 }
307 }
308
309 pub fn raw_str(&self, id: &str, ty: RawResourceType) -> Option<RawResource> {
311 let name = to_utf16(id);
312 self.raw(name.as_ptr() as usize, ty)
313 }
314}
315
316impl Default for EmbedResource {
317 fn default() -> EmbedResource {
318 EmbedResource {
319 hinst: ptr::null_mut(),
320 }
321 }
322}
323
324pub struct EmbedResourceBuilder {
328 module: Option<String>,
329}
330
331impl EmbedResourceBuilder {
332 pub fn module(mut self, module: Option<&str>) -> EmbedResourceBuilder {
333 self.module = module.map(|s| s.to_string());
334 self
335 }
336
337 pub fn build(self, out: &mut EmbedResource) -> Result<(), NwgError> {
338 use winapi::um::libloaderapi::GetModuleHandleW;
339
340 let hinst = match self.module.as_ref() {
341 Some(name) => {
342 let name = to_utf16(name);
343 unsafe { GetModuleHandleW(name.as_ptr()) as HINSTANCE }
344 }
345 None => unsafe { GetModuleHandleW(ptr::null_mut()) as HINSTANCE },
346 };
347
348 if hinst.is_null() {
349 let name = self.module.as_ref().map(|name| name as &str).unwrap_or("");
350 return Err(NwgError::resource_create(format!(
351 "No module named \"{}\" in application",
352 name
353 )));
354 }
355
356 *out = EmbedResource { hinst };
357
358 Ok(())
359 }
360}