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