В своих экспериментах с ржавчиной я сейчас пробую следующее. Я хочу отобразить базовое пустое окно, используя ящик Windows и API Windows. Приведенный ниже код компилируется и выполняется. Единственное, чего он не делает, это отображает фактическое окно. Что я здесь делаю не так, поскольку код выглядит для меня и, например, Я полагаю, что эквивалент С++ покажет окно.
use windows::{
core::*, Win32::{Foundation::*, Graphics::Gdi::{CreateSolidBrush, UpdateWindow, ValidateRect, COLOR_WINDOW, HBRUSH}, System::LibraryLoader::{GetModuleHandleA, GetModuleHandleW}, UI::WindowsAndMessaging::*},
};
fn main() -> Result<()> {
unsafe{
let window_class = w!("the_window");
let window_name = w!("The Factory");
let instance = GetModuleHandleW(None)?;
let kleur = COLORREF{
0: 255,
};
let brush: HBRUSH = CreateSolidBrush(kleur);
debug_assert!(instance.0 != 0);
//define the window
let wc = WNDCLASSW {
hCursor: LoadCursorW(None, IDC_ARROW)?,
style: CS_HREDRAW | CS_VREDRAW,
lpszClassName: window_name,
hInstance: instance.into(),
hbrBackground: brush,
lpfnWndProc: Some(wndproc),
..Default::default()
};
//register the class
let atom = RegisterClassW(&wc);
debug_assert!(atom != 0);
let hwnd_desktop = GetDesktopWindow();
let hwnd = CreateWindowExW(WINDOW_EX_STYLE::default(), window_class, window_name, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 100, 100, hwnd_desktop, None, instance, None);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
let mut message = std::mem::zeroed();
println!("init the msg structure success.");
while GetMessageA(&mut message, None, 0, 0).into() {
TranslateMessage(&message);
DispatchMessageA(&message);
}
Ok(())
}
}
extern "system" fn wndproc(window: HWND, message: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
unsafe {
match message {
WM_PAINT => {
println!("WM_PAINT");
_ = ValidateRect(window, None);
LRESULT(0)
}
WM_DESTROY => {
println!("WM_DESTROY");
PostQuitMessage(0);
LRESULT(0)
}
_ => DefWindowProcA(window, message, wparam, lparam),
}
}
}





Эквивалентный код C++ терпит неудачу по той же причине, что и этот код: попытка создать окно незарегистрированного класса.
Конкретная проблема здесь:
let wc = WNDCLASSW {
// ...
lpszClassName: window_name,
// ...
..Default::default()
};
Это подготавливает структуру WNDCLASSW для регистрации под именем window_name. Последующий вызов CreateWindowExW() затем запрашивает создание окна класса window_class (которое не было зарегистрировано).
Прежде чем перейти к решению проблемы, давайте оценим тот факт, что CreateWindowExW() может выйти из строя, и добавим следующий код обработки ошибок:
let hwnd = CreateWindowExW(
// ...
);
if hwnd == HWND::default() {
return Err(Error::from_win32());
}
После этого программа завершает работу. Выдача cargo run дает (помимо прочего) следующий результат:
Error: Error { code: HRESULT(0x8007057F), message: "Cannot find window class." }
Это полезно и подтверждает подозрения о несоответствии зарегистрированных и запрошенных имен классов.
Решение простое: убедитесь, что имена зарегистрированных и запрошенных классов совпадают. Обновление инициализации WNDCLASSW для чтения
let wc = WNDCLASSW {
// ...
lpszClassName: window_class,
// ...
..Default::default()
};
достает тебя
Сделанный!
Пока вы не схватите правый край и не переместите его дальше вправо. Достаточно, чтобы не осталось сомнений в том, что что-то отображается не так, как задумано. Что-то вроде
В заголовке окна должно быть The Factory, но на дисплее отображается T. Это еще одно воплощение Программа «Г» не дает вам выключиться.
Вкратце: вариант кодировки, используемый для регистрации класса (RegisterClassA или RegisterClassW), ДОЛЖЕН совпадать с кодировкой, предполагаемой предоставленной оконной процедурой . Наиболее ярким примером является делегирование необработанных сообщений:
Оконная процедура класса, зарегистрированного в
RegisterClassA должен делегировать DefWindowProcARegisterClassW должен делегировать DefWindowProcWРассматриваемый код регистрирует класс окна с помощью RegisterClassW, но делегирует его DefWindowProcA, вызывая (помимо прочего) усечение отображаемого заголовка окна.
Исправить здесь так же просто:
_ => DefWindowProcW(window, message, wparam, lparam),
который создает это окно
не могу поверить, что не заметил этой ошибки (регистрация класса). Другая проблема осталась, поскольку я переключился с RegisterClassA на RegisterClassW, чтобы посмотреть, повлияет ли это на ситуацию. Во всяком случае, это работает. Большое спасибо!