native_windows_gui2/controls/
button.rs1use super::{ControlBase, ControlHandle};
2use crate::win32::{base_helper::check_hwnd, resources_helper as rh, window_helper as wh};
3use crate::{Bitmap, Font, Icon, NwgError};
4use winapi::um::winuser::{
5 BS_BITMAP, BS_ICON, BS_NOTIFY, WS_CHILD, WS_DISABLED, WS_TABSTOP, WS_VISIBLE,
6};
7
8const NOT_BOUND: &'static str = "Button is not yet bound to a winapi object";
9const BAD_HANDLE: &'static str = "INTERNAL ERROR: Button handle is not HWND!";
10
11bitflags! {
12 pub struct ButtonFlags: u32 {
24 const NONE = 0;
25 const VISIBLE = WS_VISIBLE;
26 const DISABLED = WS_DISABLED;
27 const ICON = BS_ICON;
28 const BITMAP = BS_BITMAP;
29 const NOTIFY = BS_NOTIFY;
30 const TAB_STOP = WS_TABSTOP;
31 }
32}
33
34#[derive(Default, Eq, PartialEq)]
74pub struct Button {
75 pub handle: ControlHandle,
76}
77
78impl Button {
79 pub fn builder<'a>() -> ButtonBuilder<'a> {
80 ButtonBuilder {
81 text: "Button",
82 size: (100, 25),
83 position: (0, 0),
84 enabled: true,
85 flags: None,
86 ex_flags: 0,
87 font: None,
88 parent: None,
89 bitmap: None,
90 icon: None,
91 focus: false,
92 }
93 }
94
95 pub fn click(&self) {
97 use winapi::um::winuser::BM_CLICK;
98 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
99 wh::send_message(handle, BM_CLICK, 0, 0);
100 }
101
102 pub fn set_bitmap<'a>(&self, image: Option<&'a Bitmap>) {
105 use winapi::shared::minwindef::{LPARAM, WPARAM};
106 use winapi::um::winuser::{BM_SETIMAGE, IMAGE_BITMAP};
107
108 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
109
110 let image_handle = image.map(|i| i.handle as LPARAM).unwrap_or(0);
111 wh::send_message(handle, BM_SETIMAGE, IMAGE_BITMAP as WPARAM, image_handle);
112 }
113
114 pub fn set_icon<'a>(&self, image: Option<&'a Icon>) {
117 use winapi::shared::minwindef::{LPARAM, WPARAM};
118 use winapi::um::winuser::{BM_SETIMAGE, IMAGE_ICON};
119
120 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
121
122 let image_handle = image.map(|i| i.handle as LPARAM).unwrap_or(0);
123 wh::send_message(handle, BM_SETIMAGE, IMAGE_ICON as WPARAM, image_handle);
124 }
125
126 pub fn image<'a>(&self, bitmap: &mut Option<Bitmap>, icon: &mut Option<Icon>) {
130 use winapi::shared::minwindef::WPARAM;
131 use winapi::shared::windef::HBITMAP;
132 use winapi::um::winnt::HANDLE;
133 use winapi::um::winuser::{BM_GETIMAGE, IMAGE_BITMAP, IMAGE_ICON};
134
135 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
136
137 let bitmap_handle = wh::send_message(handle, BM_GETIMAGE, IMAGE_BITMAP as WPARAM, 0);
138 let icon_handle = wh::send_message(handle, BM_GETIMAGE, IMAGE_ICON as WPARAM, 0);
139
140 *bitmap = None;
141 *icon = None;
142
143 if bitmap_handle != 0 && rh::is_bitmap(bitmap_handle as HBITMAP) {
144 *bitmap = Some(Bitmap {
145 handle: bitmap_handle as HANDLE,
146 owned: false,
147 });
148 } else if icon_handle != 0 {
149 *icon = Some(Icon {
150 handle: icon_handle as HANDLE,
151 owned: false,
152 });
153 }
154 }
155
156 pub fn font(&self) -> Option<Font> {
158 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
159
160 let font_handle = wh::get_window_font(handle);
161 if font_handle.is_null() {
162 None
163 } else {
164 Some(Font {
165 handle: font_handle,
166 })
167 }
168 }
169
170 pub fn set_font(&self, font: Option<&Font>) {
172 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
173
174 wh::set_window_font(handle, font.map(|f| f.handle), true);
175 }
176
177 pub fn focus(&self) -> bool {
179 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
180 wh::get_focus(handle)
181 }
182
183 pub fn set_focus(&self) {
185 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
186
187 wh::set_focus(handle);
188 }
189
190 pub fn enabled(&self) -> bool {
192 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
193 wh::get_window_enabled(handle)
194 }
195
196 pub fn set_enabled(&self, v: bool) {
198 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
199 wh::set_window_enabled(handle, v)
200 }
201
202 pub fn visible(&self) -> bool {
205 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
206 wh::get_window_visibility(handle)
207 }
208
209 pub fn set_visible(&self, v: bool) {
211 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
212 wh::set_window_visibility(handle, v)
213 }
214
215 pub fn size(&self) -> (u32, u32) {
217 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
218 wh::get_window_size(handle)
219 }
220
221 pub fn set_size(&self, x: u32, y: u32) {
223 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
224 wh::set_window_size(handle, x, y, false)
225 }
226
227 pub fn position(&self) -> (i32, i32) {
229 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
230 wh::get_window_position(handle)
231 }
232
233 pub fn set_position(&self, x: i32, y: i32) {
235 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
236 wh::set_window_position(handle, x, y)
237 }
238
239 pub fn text(&self) -> String {
241 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
242 wh::get_window_text(handle)
243 }
244
245 pub fn set_text<'a>(&self, v: &'a str) {
247 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
248 wh::set_window_text(handle, v)
249 }
250
251 pub fn class_name(&self) -> &'static str {
253 "BUTTON"
254 }
255
256 pub fn flags(&self) -> u32 {
258 WS_VISIBLE | WS_TABSTOP | BS_NOTIFY
259 }
260
261 pub fn forced_flags(&self) -> u32 {
263 WS_CHILD
264 }
265}
266
267impl Drop for Button {
268 fn drop(&mut self) {
269 self.handle.destroy();
270 }
271}
272
273pub struct ButtonBuilder<'a> {
274 text: &'a str,
275 size: (i32, i32),
276 position: (i32, i32),
277 enabled: bool,
278 flags: Option<ButtonFlags>,
279 ex_flags: u32,
280 font: Option<&'a Font>,
281 bitmap: Option<&'a Bitmap>,
282 icon: Option<&'a Icon>,
283 parent: Option<ControlHandle>,
284 focus: bool,
285}
286
287impl<'a> ButtonBuilder<'a> {
288 pub fn flags(mut self, flags: ButtonFlags) -> ButtonBuilder<'a> {
289 self.flags = Some(flags);
290 self
291 }
292
293 pub fn ex_flags(mut self, flags: u32) -> ButtonBuilder<'a> {
294 self.ex_flags = flags;
295 self
296 }
297
298 pub fn text(mut self, text: &'a str) -> ButtonBuilder<'a> {
299 self.text = text;
300 self
301 }
302
303 pub fn size(mut self, size: (i32, i32)) -> ButtonBuilder<'a> {
304 self.size = size;
305 self
306 }
307
308 pub fn position(mut self, pos: (i32, i32)) -> ButtonBuilder<'a> {
309 self.position = pos;
310 self
311 }
312
313 pub fn enabled(mut self, e: bool) -> ButtonBuilder<'a> {
314 self.enabled = e;
315 self
316 }
317
318 pub fn font(mut self, font: Option<&'a Font>) -> ButtonBuilder<'a> {
319 self.font = font;
320 self
321 }
322
323 pub fn bitmap(mut self, bit: Option<&'a Bitmap>) -> ButtonBuilder<'a> {
324 self.bitmap = bit;
325 self
326 }
327
328 pub fn icon(mut self, ico: Option<&'a Icon>) -> ButtonBuilder<'a> {
329 self.icon = ico;
330 self
331 }
332
333 pub fn focus(mut self, focus: bool) -> ButtonBuilder<'a> {
334 self.focus = focus;
335 self
336 }
337
338 pub fn parent<C: Into<ControlHandle>>(mut self, p: C) -> ButtonBuilder<'a> {
339 self.parent = Some(p.into());
340 self
341 }
342
343 pub fn build(self, out: &mut Button) -> Result<(), NwgError> {
344 let flags = self.flags.map(|f| f.bits()).unwrap_or(out.flags());
345
346 let parent = match self.parent {
347 Some(p) => Ok(p),
348 None => Err(NwgError::no_parent("Button")),
349 }?;
350
351 *out = Button::default();
353
354 out.handle = ControlBase::build_hwnd()
355 .class_name(out.class_name())
356 .forced_flags(out.forced_flags())
357 .flags(flags)
358 .ex_flags(self.ex_flags)
359 .size(self.size)
360 .position(self.position)
361 .text(self.text)
362 .parent(Some(parent))
363 .build()?;
364
365 if self.font.is_some() {
366 out.set_font(self.font);
367 } else {
368 out.set_font(Font::global_default().as_ref());
369 }
370
371 out.set_enabled(self.enabled);
372
373 if self.bitmap.is_some() {
374 out.set_bitmap(self.bitmap);
375 } else if self.icon.is_some() {
376 out.set_icon(self.icon);
377 }
378
379 if self.focus {
380 out.set_focus();
381 }
382
383 Ok(())
384 }
385}