Comments (5)
Many years ago, when I was still writing WinLamb, I looked into MFC headers and I found that it allowed the Resource Editor to auto-generate user IDs up to 19,999. So WinSafe auto-generated IDs start at 20,000, giving the user the same range given by MFC, as you can see here.
This behavior should be documented though, I'll write it down now.
from winsafe.
Ideally, all native controls should be supported by WinSafe. I plan to implement them all, the next one being this one you suggested (hard stuff, but it will be fun to implement).
As for third-party DLL controls, I never worked with one of those, so I have no idea how they interact with the window message loop, which is the heart of the window and all its child controls. I imagine those third-party controls expose some C functions, and have some hooks (possibly callbacks) to process messages and return whether they processed them or not. Anyway, I'd like to see one of those, and learn how they work.
Indeed, all 4 points you consider refer to the very same problem I cited in the paragraph above: how to expose the window message loop. Currently, it is exposed through the on()
method, which adds entries to the core message loop. These entries are then executed when the internal WndProc is called by the OS.
The WindowControl abstraction is the most flexible control I could conceive. Basically, it's a blank canvas which you can paint and treat input the way you want, and handle the messages any way you want. For exotic/specific controls, it should suffice. However, for controls already written in C, that's a whole new world I never dealt with, as I said before.
What are you trying to do, specifically?
from winsafe.
What I’m actually trying to accomplish right now is using a tab control. I totally agree that the ideal case is that all the Microsoft common controls have wrappers in the gui
module, and I’ll be happy to use that in future once it’s available. I just figured there would be a reasonable option available before that time, namely a way to handle arbitrary controls.
I don’t actually know for sure how third-party controls tend to work in practice; I’ve never used one. I just figured they would work somewhat similarly to the Microsoft common controls:
- The application calls some kind of magic initialization function provided by the library (akin to
InitCommonControlsEx
), which callsRegisterClassEx
for all the kinds of controls available in the library. This might have to be done via C FFI or whatever, but it is a single straightforward function call. - The application instantiates the control with
CreateWindowEx
by specifying the relevant class. - The application asks the control to do things by sending it messages.
- The control handles e.g. keyboard input while it has focus and mouse events over its rectangle by having its own window proc registered in its class, which
DispatchMessage
sends messages to (so Winsafe would never see them or need to worry about them). - The application gets notified of the control doing things by receiving
WM_COMMAND
orWM_NOTIFY
messages to the parent window.
So, if this is actually realistic, then to handle such things in Winsafe, what one would want is basically exactly the same as WindowControl
, except don’t register a class when creating it, just create it using a class that already exists.
from winsafe.
Turns out, you can.
Taking this example as the baseline, I created a dynamic, arbitrary button with CreateWindowEx:
use std::cell::RefCell;
use std::rc::Rc;
use winsafe::{prelude::*, self as w, co, gui};
#[derive(Clone)]
pub struct MyWindow {
wnd: gui::WindowMain,
hbtn: Rc<RefCell<w::HWND>>,
}
const ID_BTN: u16 = 2000;
impl MyWindow {
pub fn new() -> Self {
let wnd = gui::WindowMain::new(
gui::WindowMainOpts {
title: "My window title".to_owned(),
class_icon: gui::Icon::Id(101),
size: w::SIZE::new(300, 150),
..Default::default()
},
);
let new_self = Self { wnd, hbtn: Rc::new(RefCell::new(w::HWND::NULL)) };
new_self.events(); // attach our events
new_self
}
pub fn run(&self) -> gui::MsgResult<i32> {
self.wnd.run_main(None) // simply let the window manager do the hard work
}
fn events(&self) {
let self2 = self.clone();
self.wnd.on().wm_create(move |_| {
*self2.hbtn.borrow_mut() = unsafe {
w::HWND::CreateWindowEx(
co::WS_EX::NoValue,
w::AtomStr::Str(w::WString::from_str("BUTTON")),
Some("&Click me"),
co::WS::CHILD | co::WS::VISIBLE | co::WS::TABSTOP
| co::WS::GROUP | co::BS::PUSHBUTTON.into(),
w::POINT::new(20, 20),
w::SIZE::new(90, 30),
Some(self2.wnd.hwnd()),
w::IdMenu::Id(ID_BTN),
&self2.wnd.hwnd().hinstance(),
None,
)
}?;
Ok(0)
});
let self2 = self.clone();
self.wnd.on().wm_command(co::BN::CLICKED, ID_BTN, move || {
self2.wnd.hwnd().MessageBox("Clicked!", "Clicking", co::MB::ICONINFORMATION)?;
Ok(())
});
}
}
Notice I used the raw on().wm_command()
event to handle the button click. Since you want a tab control, you'll have to handle all its messages properly. I used a tab control once, and I remember it was very tricky.
I plan to implement the tab control in the library, but if you need it now, you can crack it up after this example.
from winsafe.
const ID_BTN: u16 = 2000;
How did you know to choose 2000? How did you know that 2000 wouldn’t collide with winsafe
’s internal ID number allocation?
from winsafe.
Related Issues (20)
- validate_retrieved_reg_val always fails
- [Question] - Calling windows APIs twice best practice HOT 3
- RegQueryValueEx returning TRANSACTION_REQUEST_NOT_VALID for valid data HOT 6
- nm_custom_draw should provide a mutable reference? HOT 6
- How do you envision WM_USER being used? HOT 1
- `WC::NoValue`? HOT 1
- Wrong GetAsyncKeyState return type. HOT 4
- SetLayeredWindowAttributes HOT 3
- GetTokenInformation missing HOT 2
- Panic when add empty strings in listview HOT 2
- How to display rich text such as superscript/subscript? HOT 3
- [Feature Request] Message only window support HOT 3
- [Feature Request] Implement Ord, PartialOrd, Eq and PartialEq for WString
- Public access ot LocalFreeGuard::new or LocalFree HOT 2
- [BUG?QUESTION?]SendInput example not working HOT 1
- [Question] How can I set the pszText into NMLVDISPINFO correctly when handling lvn_get_disp_info event? HOT 19
- [Question] Using MutFn as WinApi callback
- WString pointers cause issues on stack for certain API calls HOT 5
- Build fails for the i686-pc-windows-(msvc/gnu) targets HOT 8
- winsvc.h HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from winsafe.