メッセージボックスを表示する - Rustで作るWindowsアプリ
- 作成日: 2023-05-02
- 更新日: 2023-12-24
- カテゴリ: windows-rs
RustでWindowsアプリを作る
Rustはメモリ安全な言語として最近話題の言語です。
Linuxの開発にも導入されるなど徐々にその活躍の場を広げています。
しかしRustはまだ歴史の浅い言語だけあって、周辺ライブラリなどはそれほど充実しているとは言えません。
特にGUIライブラリはまだ発展途上で、Rustでウィンドウを出すプログラムを作ろうとすると選択肢も限られてきます。
しかしRustのモダンな機能を使ってウィンドウを表示できるアプリを作れればそれは素晴らしいことです。
特にRustの機能でWindowsアプリを作れればなかなか楽しそうです。
この本ではRustでWindowsアプリを作る方法を解説していきます。
具体的にはWindows APIを使ってウィンドウを表示するアプリを作ります。
Rustのインストール、windows-rs
の導入から解説していきます。
この書籍では紹介するソースコードの動作確認は以下の環境で行っています。
- Windows10(64ビット)
- cargo 1.69.0
- rustc 1.69.0
- windows-rs 0.48
WindowsでRustを使うには?
Windows環境でRustを使うには https://rust-lang.org からrustup-init.exe
をダウンロードしてパソコンにRustをセットアップします。
rustup-init.exeのダウンロードとインストール
rustup-init.exe
のダウンロードは https://www.rust-lang.org/tools/install のページから行えます。
使っているWindowsが64ビットの場合は 64-BIT のrustup-init.exe
をダウンロードしてください。
ダウンロードしたrustup-init.exe
をダブルクリックして実行すると以下のような黒い画面(コマンドプロンプト)が出ます。
The Cargo home directory is located at:
C:\Users\myname\.cargo
This can be modified with the CARGO_HOME environment variable.
The cargo, rustc, rustup and other commands will be added to
Cargo's bin directory, located at:
C:\Users\myname\.cargo\bin
This path will then be added to your PATH environment variable by
modifying the HKEY_CURRENT_USER/Environment/PATH registry key.
You can uninstall at any time with rustup self uninstall and
these changes will be reverted.
Current installation options:
default host triple: x86_64-pc-windows-msvc
default toolchain: stable (default)
profile: default
modify PATH variable: yes
1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
「1) Proceed with installation (default)
」と表示されているところに注目してください。
これはデフォルトではエンターキーを押せばインストールが開始するという意味です。
エンターキーを押してRustの周辺実行ファイルをインストールしてください。
このインストールが完了するとWindowsのコマンドプロンプトやPowerShellからcargo
が使えるようになります。
> cargo --help
インストールが完了してからコマンドプロンプトを開き上記のコマンドを実行するとcargo
の使い方が表示されます。
cargo
というのはRustの公式のパッケージ管理ツールのことです。
パッケージ管理ツールとはRustのパッケージの作成、ビルド、外部ライブラリのインストールと管理などをまとめて行ってくれるツールのことです。
実際のRustの開発ではこのcargo
を使って開発していきます。
ちなみにこの本で使っているcargo
は以下のバージョンになります。
> cargo -V
cargo 1.69.0 (6e9a83356 2023-04-12)
Windows APIとは?
Windows APIとはWindowsアプリケーションの作成やWindowsの機能を使うためのインターフェースです。
このWindows APIを使うとGUIアプリケーションやWindowsの機能を使ったアプリケーションが作れるようになります。
Windows 95/NTのころからある32ビット環境のAPIは特にWin32 APIと呼ばれます。
最近では64ビットへの移行が進んでいるのでWindows APIと言えば64ビットのAPIを含んでいます。
古(いにしえ)の時代よりWindowsプログラマはこのWindows APIを使ってWindowsアプリを開発してきた歴史があります。
つまりRustでWindows APIを使うということはRustという最新の言語を使ってその歴史に飛び込むということになります。
当然、Windows APIにはモダンとは言えないインターフェースも含まれています。
Windows APIはC言語が開発のメインだった時代から使われていますので、インターフェースもC言語から扱えるものになっています。
RustでWindows APIを利用するには?
マイクロソフト社がRustでWindows APIを使うためのライブラリを公開しています。
その名もwindows-rs
というのがそうです。
これはオープンソースでソースコードはGitHubに公開されています。
microsoft/windows-rs: Rust for Windows
https://github.com/microsoft/windows-rs
このwindows-rs
を使えばRustからWindows APIを使うことが可能になります。
またwindows-rs
のドキュメントは以下にあります。
windows - Rust
https://microsoft.github.io/windows-docs-rs/doc/windows/index.html
windows-rsのクレートの種類
windows-rs
にはwindows
クレートとwindows-sys
クレートがあります。windows-sys
クレートはオーバヘッドを無くしたフォールバックな定義です。
この2つのクレートにはそれぞれWindows APIのラッパーなどが定義されていますが、両者の定義はそれぞれ違っています。
たとえばwindows
クレートのw!
マクロはPCWSTR
構造体を返しますが、windows-sys
クレートのw!
マクロはu16
の配列のポインタを返すなど、仕様が違っています。
windows-sys
を探検するときはこの両者のクレートが共存していることを意識して探検する必要があります。
この本ではおもにwindows
クレートの処理について取り上げています。つまりこの本で話すw!
マクロの返り値はPCWSTR
構造体になります。
windows-rsでHello, World!
ではさっそくwindows-rs
で「Hello, World!」するところまでやってみます。
まずcargo
で適当なフォルダに新規パッケージを作成します。
ここではコマンドプロンプトから以下のコマンドを打ちます。
> cargo new hello_world
Created binary (application) `hello_world` package
cargo new
はRustの新規パッケージを作成するコマンドになります。
これでhello_world
というパッケージを作ります。
パッケージを作ったらcd
コマンドでパッケージフォルダの中に移動します。
> cd hello_world
> dir
Cargo.toml
src
dir
コマンドでパッケージの中身を見ると上記のようにCargo.toml
とsrc
フォルダがあります。
Cargo.toml
はパッケージの設定や外部ライブラリの依存関係などを記述するファイルです。
> type Cargo.toml
[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
type
コマンドでファイルの中身を見ると上記のようになっていると思います。
[package]
にはパッケージの名前やバージョンなどを書きます。
[dependencies]
には外部ライブラリの依存関係を書きます。
src
フォルダ以下には実際のソースコードを配置します。
デフォルトではmain.rs
というRsutのソースファイルが配置されています。
> dir src
main.rs
Cargo.tomlの編集
ではCargo.toml
ファイルを以下のように編集します。
[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"
[dependencies.windows]
version = "0.48"
features = [
"Win32_Foundation",
"Win32_UI_WindowsAndMessaging",
]
features
に書かれているのがwindows-rs
の外部ライブラリです。
基本となるパッケージとしてWin32_Foundation
, それからMessageBoxW()
を使うためのWin32_UI_WindowsAndMessaging
を取り込んでいます。
続いてsrc\main.rs
を以下のように編集します。
use windows::{
core::*,
Win32::UI::WindowsAndMessaging::*,
};
fn main() {
unsafe {
MessageBoxW(None, w!("Hello, World!"), w!("日本から"), MB_OK);
}
}
このソースコードは簡単なメッセージボックスを表示するためのコードです。
use
しているのはwindows
以下のcore::w
とWin32::UI::WindowsAndMessaging::{MessageBoxW, MB_OK}
になります。ここではアスタリスク(*
)で省略しています。
unsafe { }
はRustで安全じゃないコードを書くときに使います。
多くのGUIアプリケーションは本質的には安全なアプリではないので、windows-rs
を使った開発では全般的にこのunsafe
を使います。
このunsafe
を使うとメモリ安全じゃなくなり未定義の動作を起こすこともあるので注意してください。
MessageBoxW()
はワイド文字列に対応したメッセージボックスです。
Function windows::Win32::UI::WindowsAndMessaging::MessageBoxW
pub unsafe fn MessageBoxW<P0, P1, P2>(
hwnd: P0, // ウィンドウのハンドル(HWND型)
lptext: P1, // 表示するメッセージ(PCWSTR型)
lpcaption: P2, // メッセージボックスのタイトル(PCWSTR型)
utype: MESSAGEBOX_STYLE // メッセージボックスのスタイル(MESSAGEBOX_STYLE構造体)
) -> MESSAGEBOX_RESULT
where
P0: IntoParam<HWND>,
P1: IntoParam<PCWSTR>,
P2: IntoParam<PCWSTR>,
w!()
はマクロでnullターミネートされたUTF-16のワイド文字列の定義に使います。windows
クレートではPCWSTR
構造体を返し、windows-sys
クレートではu16
の配列のポインタを返します。
Macro windows::w
macro_rules! w {
($s:literal) => { ... };
}
nullターミネートというのは文字列の末尾に0
が番兵として配置されている状態を言います。
C言語などでは文字列を表現するために文字列の末尾にナル文字(\0
)を配置します。
このナル文字は数値で言うと0
になります。
Windows APIはC言語由来のものなのでこのように文字列にもナル文字が必要です。
コマンドプロンプトでCargo.toml
があるフォルダに移動して以下のコマンドを実行します。
> cargo run
Compiling hello_world v0.1.0 (C:\src\windows-rs-hello-world\hello_world)
Finished dev [unoptimized + debuginfo] target(s) in 0.43s
Running `target\debug\hello_world.exe`
すると以下のようなメッセージボックスが表示されると思います。