I’m trying to listen to display change events in windows, so I can resize my application. I’m using a hidden window for this, since it needs to be a top level window. I’m able to send the message, and the result is ok, but the main application never receives the event. Any ideas what could be causing it? The websocket example works correctly for me. I’m using version 12 :
main.rs
#[derive(Debug, Clone)]
enum Message {
Init(window::Id),
Hide(window::Id),
Show(window::Id),
DisplayChanged(monitor::Event),
}
impl Application for Banner {
type Executor = executor::Default;
type Flags = config::Settings;
type Message = Message;
type Theme = Theme;
...
fn update(&mut self, message: Message) -> iced::Command<Message> {
match message {
...
Message::DisplayChanged(_) => {
println!("display changed");
Command::none()
},
}
}
fn subscription(&self) -> Subscription<Message> { monitor::monitor().map(Message::DisplayChanged) }
monitor.rs
use futures::{channel::mpsc::Sender, sink::SinkExt};
use iced::subscription::{self, Subscription};
use std::sync::{Mutex, OnceLock};
use windows::{
core::*,
Win32::{Foundation::*, System::LibraryLoader::GetModuleHandleA, UI::WindowsAndMessaging::*},
};
static SENDER: OnceLock<Mutex<Sender<Event>>> = OnceLock::new();
pub fn monitor() -> Subscription<Event> {
struct Connect;
subscription::channel(std::any::TypeId::of::<Connect>(), 100, |output| async move {
unsafe {
let instance = GetModuleHandleA(None).unwrap();
debug_assert!(instance.0 != 0);
let window_class = s!("window");
let wc = WNDCLASSA {
hCursor: LoadCursorW(None, IDC_ARROW).unwrap(),
hInstance: instance.into(),
lpszClassName: window_class,
style: CS_HREDRAW | CS_VREDRAW,
lpfnWndProc: Some(wndproc),
..Default::default()
};
let atom = RegisterClassA(&wc);
debug_assert!(atom != 0);
SENDER.set(Mutex::new(output)).expect("failed to set monitor sender");
CreateWindowExA(
WINDOW_EX_STYLE(0),
window_class,
s!("resize_monitor"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
HWND_DESKTOP,
None,
instance,
None,
);
let mut message = MSG::default();
loop {
while GetMessageA(&mut message, None, 0, 0).into() {
DispatchMessageA(&message);
}
}
}
})
}
extern "system" fn wndproc(window: HWND, message: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
unsafe {
match message {
WM_DESTROY => {
PostQuitMessage(0);
LRESULT(0)
},
WM_DISPLAYCHANGE => {
iced::futures::executor::block_on(async {
let mut sender = SENDER.get().unwrap().lock().unwrap();
let result = sender.send(Event::DisplayChanged).await;
println!("message sent: {result:#?}");
});
LRESULT(0)
},
_ => DefWindowProcA(window, message, wparam, lparam),
}
}
}
#[derive(Debug, Clone)]
pub enum Event {
DisplayChanged,
}