2020年4月30日に, Microsoft から Rust/WinRT のプレビュー版が発表されました!これまでもサードパーティによる winrt クレートはありましたが, 今後は Microsoft が WinRT の Rust 言語プロジェクションをサポートしていくことになります (issue76).
興味があったので早速試してみました. お題はトースト通知を表示することです (参考資料が豊富にありとっつきやすかったので).
2020-06-09追記 crates.io に winrt 0.7.0 が公開されたのに伴いコード修正.
2021-03-20追記 Rust for Windows (windows-rs) に改名されたのに伴いコード修正. Win10 v20H2, windows="0.5.0" で動作確認しました.
環境
本記事では Rust/WinRT の動作確認に Win10 Pro v1909 build 18363.778 を用いました.
- Visual Studio Build Tools 2019 (16.5.4)
- Rust 1.43.0 stable-x86_64-pc-windows-msvc
これだけで動きました. あたかも WinRT が pure Rust クレートかのような簡単さです. ただコンパイルが毎回5秒程度かかるのが若干気になります. あとドキュメントがまだオンラインで見られないため, cargo doc
して自分で生成する必要があります.
2021-03-20追記 このあたりの問題は解決しましたが説明すると長くなるのでいつか別記事にします. さしあたりチュートリアルを読むことを強くお勧めします.
コード
参考文献の最初に挙げた C++/WinRT のコードを翻訳しただけですが, いろいろと苦労しました.
fn main() {
windows::build!(
windows::ui::*,
windows::data::xml::dom::{XmlDocument, XmlText, XmlNodeList},
windows::ui::notifications::*,
);
}
mod bindings {
::windows::include_bindings!();
}
use bindings::windows::ui::notifications::{
ToastNotificationManager, ToastTemplateType, ToastNotification,
};
fn main() -> windows::Result<()> {
let notification_manager = ToastNotificationManager::get_default()?;
let toast_xml = ToastNotificationManager::get_template_content(ToastTemplateType::ToastText01)?;
// 通知の内容を設定する
let text_node = toast_xml.get_elements_by_tag_name("text")?.item(0)?;
let text = toast_xml.create_text_node(r"Hello from Rust/WinRT!")?;
text_node.append_child(text)?;
// トースト通知を表示する.
// v1709 以降は AppId が必要なので, Powershell のものを使う
let toast = ToastNotification::create_toast_notification(toast_xml)?;
notification_manager
.create_toast_notifier_with_id("{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\\WindowsPowerShell\\v1.0\\powershell.exe")?
.show(toast)?;
std::thread::sleep(std::time::Duration::from_millis(10)); // <- この行を消すとなぜかトースト通知が表示されない
Ok(())
}
よくわからなかった点
- シングルバイナリでは AppId を発行することができない?
-
参考文献その1では
ExpirationTime
をセットしているが,windows::foundation::DateTime
型の取得まわりがうまくいかなかった. - 最後にスリープさせないと通知が出ずにプログラムが終了してしまう.