-
Notifications
You must be signed in to change notification settings - Fork 919
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SendMessage Question #1052
Comments
cc @Osspial |
The low-level Windows event loop should be receiving your event, but Winit doesn't have any logic to translate your custom Windows message to a Winit message, so the high-level Winit event loop isn't dispatching it to the event handler closure. If you want to translate your message into a Winit message, you should be able to use the Windows subclassing API to catch your custom message, than use |
Thanks for the information so far. I've done some messing around and was able to register a subclass and successfully send a custom message, but I'm not quite sure how I should translate that back to the event loop proxy. This is a basic example of what I've come up with so far.
At first I tried casting my app like this to send it in.
and then once inside the subclass_proc, I tried to access it like this, but I kept getting access violations.
@Osspial Do you have any advice, or possibly an example of the proper way to pass in my event_loop_proxy to the subclass_proc so that I can trigger my event in the main event loop? Any additional help would be greatly appreciated. |
@RKennedy9064 Your original attempt to cast We use that technique internally in Winit to pass custom data into the window callback, and if you'd like reference code I've linked the places we use it below (specifically, check out the winit/src/platform_impl/windows/event_loop.rs Lines 827 to 911 in 39e668f
|
@Osspial I took your advice and put my struct in a box. I was able to pass it to the subclass_proc, but now I'm getting an Err(EventLoopClosed) when I try to use event_loop_proxy to send an event. This is the updated code I have so far.
The part I'm confused about is why I'm getting an Err(EventLoopClosed). My main event loop is still responding to messages. I also tried to use the actual event_loop before using send_event and the output of primary_monitor returned this.
Is there any reason why the event_loop_proxy would think the event_loop is closed? I feel like I'm missing something obvious here. |
@RKennedy9064 can you post your full source code? It's hard to thoroughly understand your problem with just the snippet you posted. |
@Osspial Sure, here's a gist of my code. I haven't really used winit much, so it's possible I'm just doing things incorrectly. https://gist.github.com/RKennedy9064/d6d78ab3b30ee6c667c25f25ab304b61 Edit: I'm sending my message Event::NewEvents(StartCause::Init) for now, but the end goal is to send the message from a different application, then fire my user event to the event loop for processing. |
@RKennedy9064 I think you're still invoking undefined behavior there, actually. Since I've modified the code to only pass the proxy, which should work: #[derive(Debug)]
pub struct App {
event_loop: EventLoop<NsEvent>,
window: Window,
}
type SubclassInput = EventLoopProxy<NsEvent>;
impl App {
pub fn new() -> Result<App, Box<dyn Error>> {
let (event_loop, window) = init()?;
let mut app = App {
event_loop,
window,
};
app.set_window_subclass();
Ok(app)
}
pub fn run(self) {
let hwnd = self.window.hwnd() as HWND;
self.event_loop.run(move |event, _, control_flow| {
match event {
Event::NewEvents(StartCause::Init) => {
unsafe {
winuser::SendMessageW(
hwnd,
WM_NS_LAUNCH,
0,
0
);
}
},
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit
},
Event::UserEvent(event) => {
println!("{:?}", event);
},
_ => *control_flow = ControlFlow::Wait,
}
});
}
fn set_window_subclass(&mut self) {
unsafe {
let sender_box: Box<SubclassInput> = Box::new(self.event_loop.create_proxy());
commctrl::SetWindowSubclass(
self.window.hwnd() as HWND,
Some(App::subclass_proc),
0,
Box::into_raw(sender_box) as DWORD_PTR,
);
}
}
unsafe extern "system" fn subclass_proc(
hwnd: HWND,
msg: UINT,
wparam: WPARAM,
lparam: LPARAM,
_id: UINT_PTR,
data: DWORD_PTR,
) -> LRESULT {
match msg {
WM_NS_LAUNCH => {
let proxy = &mut *(data as *mut SubclassInput);
println!("{:?}", proxy.send_event(NsEvent::Launch));
0
},
winuser::WM_DESTROY => {
// Clean up our allocated data.
Box::from_raw(data as *mut SubclassInput);
0
}
_ => commctrl::DefSubclassProc(hwnd, msg, wparam, lparam),
}
}
} |
@Osspial That worked perfectly. I just tested it out and received the event. I'm guessing I don't need to keep a reference of the proxy in the struct since it's being created by the event loop? I had issues with my window closing if I only stored the event_loop in my struct, so I figured I would store the proxy there also to be safe. Thanks for taking the time to look into this and showing me how to properly pass in a pointer to a win32 proc from Rust. I'm still used to the C/C++ way of only needing to cast the reference to the pointer type and then recast it back into the struct in the callback. |
So I've been looking at the alpha version and saw that you can send UserEvents to the event_loop by using an event_loop_proxy. Is it also possible to send a custom message to the event_loop from another application. I've tried using FindWindowA to get the hwnd for my application, then send a custom message to it by using SendMessageA, but it doesn't seem like the event_loop receives the message. Is this something that isn't currently possible using winit?
The text was updated successfully, but these errors were encountered: