はじめに
D言語のポピュラーなDUBパッケージの中にarsd-officialがあります。
この記事では、arsd-officialのサブパッケージsimpledisplayの使い方を紹介します。
開発環境
- Windows 10
- DMD v2.099.0
- DUB version 1.28.0
- arsd-official Version 10.7.0
その1-ウィンドウ画面作成
simpledisplayは、ウィンドウ画面の作成や表示処理が簡単に実装できるような機能が提供されています。
まずは、ウィンドウ作成に必要な最小限のソースコード実装例です。
この記事を参考にSingle-file packagesで実装しました。
/+ dub.sdl:
name "sample1"
dependency "arsd-official:simpledisplay" version="~>10.7.0"
+/
// dub run --single sample1.d
import arsd.simpledisplay;
void main() {
auto window = new SimpleWindow(500, 500, "Sample1");
window.eventLoop(0);
}
これだけのソースコードでウィンドウの作成とイベント処理ができます。
SimpleWindow
でウィンドウを作成します。ウィンドウの幅、高さ、タイトルを引数にセットしています。
eventLoop
はウィンドウのイベント処理を行います。
引数に0
のみをセットした場合、simpledisplay
が用意したデフォルトのイベント処理を行います。
以下はコンパイルと実行結果です。
D:\Dev> dub run --single sample1.d
parsePackageRecipe dub.sdl
Fetching arsd-official 10.7.0 (getting selected version)...
Performing "debug" build using D:\Dev\dmd2\windows\bin64\dmd.exe for x86_64.
arsd-official:color_base 10.7.0: building configuration "library"...
arsd-official:simpledisplay 10.7.0: building configuration "normal"...
sample1 ~master: building configuration "application"...
Linking...
Running sample1.exe
ウィンドウの最小化、最大化、サイズ変更、閉じるなどのイベントはsimpledisplay
が処理してくれています。
その2-イベント処理の実装
eventLoop
を使って、イベント処理を実装します。
simpledisplayのソースコード内のサンプルコードを参考に実装しました。
他にもサンプルコードが紹介されているので、興味がある方はソースコードを参照してください。
/+ dub.sdl:
name "sample2"
dependency "arsd-official:simpledisplay" version="~>10.7.0"
+/
// dub run --single sample2.d
import std.conv;
import arsd.simpledisplay;
void main() {
auto window = new SimpleWindow(Size(500, 500), "Event example - simpledisplay.d");
int y = 0;
void addLine(string text) {
auto painter = window.draw();
if(y + painter.fontHeight >= window.height) {
painter.scrollArea(Point(0, 0), window.width, window.height, 0, painter.fontHeight);
y -= painter.fontHeight;
}
painter.outlineColor = Color.green;
painter.fillColor = Color.black;
painter.drawRectangle(Point(0, y), window.width, painter.fontHeight);
painter.outlineColor = Color.white;
painter.drawText(Point(10, y), text);
y += painter.fontHeight;
}
window.eventLoop(1000,
(){
addLine("Timer went off!");
},
(KeyEvent event){
addLine(to!string(event));
},
(MouseEvent event){
addLine(to!string(event));
},
(dchar ch){
addLine(to!string(ch));
}
);
}
eventLoop
内の(){~}
は、タイマーイベント処理です。
eventLoop
の第1引数に正数をセットすると、その時間間隔ごとにタイマーイベントが発生します。単位はミリ秒です。
(KeyEvent event){~}
は、キーボード操作のイベント処理です。
キーを押した場合、キーを離した場合にイベントが発生します。
(MouseEvent event){~}
は、マウス操作のイベント処理です。
ウィンドウ上でマウスを動かした場合、クリックした場合にイベントが発生します。
(dchar ch){~}
では、キーボードから入力された文字ごとの処理を実装します。
以下はコンパイルと実行結果です。
D:\Dev> dub run --single sample2.d
parsePackageRecipe dub.sdl
Performing "debug" build using D:\Dev\dmd2\windows\bin64\dmd.exe for x86_64.
arsd-official:color_base 10.7.0: target for configuration "library" is up to date.
arsd-official:simpledisplay 10.7.0: target for configuration "normal" is up to date.
sample2 ~master: building configuration "application"...
Linking...
To force a rebuild of up-to-date targets, run again with --force.
Running sample2.exe
どのイベントでもaddLine
関数が呼び出されています。
addLine
関数内のwindow.draw()
で、ウィンドウの描画処理に必要なpainter
(struct ScreenPainter
)を取得しています。
ScreenPainter
のデストラクタが呼び出される際にウィンドウの表示を更新する仕組みとのことです。
以下の実行結果を補足します。
- 1000ミリ秒ごとに
Timer went off!
が出力されています。 - キーボードの
a
を押した際、離した際にKeyEvent
が発生しています。 -
(dchar ch){~}
で引数ch
に、押したキーであるa
がセットされて呼び出されています。 - マウス操作のイベント
MouseEvent
も発生しています。
マウス動かした際にMouseEvent(motion, ~
、クリックした際にMouseEvent(buttonPressed, ~
とMouseEvent(buttonReleased, ~
が発生しています。
その3-OS固有のイベント処理の実装
その2では、タイマー、キーボード、マウスイベントの処理方法を紹介しました。
その3では、その他のウィンドウイベントの処理実装例になります。
また、arsd-official
は汎用的なパッケージため、Windows
やX11
のいずれでも使用可能ですが、OS固有のイベントを処理できる仕組みも用意されています。
/+ dub.sdl:
name "sample3"
dependency "arsd-official:simpledisplay" version="~>10.7.0"
dependency "arsd-official:image_files" version="~>10.7.0"
+/
// dub run --single sample3.d
import core.sys.windows.windows;
import std.conv;
import arsd.image;
import arsd.simpledisplay;
void main()
{
auto window = new SimpleWindow(Size(500, 500), "Arsd Viewer");
MemoryImage image;
void draw(int width, int height){
auto painter = window.draw();
painter.clear();
if ( image !is null ){
if ( (cast(double)width) / image.width > (cast(double)height) / image.height ){
width = image.width * height / image.height;
} else {
height = image.height * width / image.width;
}
TrueColorImage winImage = image.imageResize(width, height);
painter.drawImage(Point(0, 0), Image.fromMemoryImage(winImage));
}
}
window.windowResized = (int width, int height){
draw(width, height);
};
window.handleNativeEvent =
delegate int(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, out int r){
switch ( msg ){
case WM_DROPFILES:
const MAX_SIZE = 256;
wchar[] fileName = new wchar[MAX_SIZE];
int nSize = DragQueryFile(cast(HDROP)wParam, 0, fileName.ptr, cast(int)(fileName.length));
try {
image = loadImageFromFile(fileName[0 .. nSize].to!string);
} catch (Exception e){
}
draw(window.width, window.height);
r = 1;
return ( 0 );
default:
}
return ( 1 );
};
draw(window.width, window.height);
window.eventLoop(0);
}
ウィンドウの描画イベントを処理するためにdraw
関数を用意しました。
draw
関数では、MemoryImage image
に格納された画像情報をウィンドウ画面に表示します。
window.windowResized
は、ウィンドウのサイズを変更した際に発生するイベントです。draw
関数を呼び出すように実装しました。
window.handleNativeEvent
で、OS固有イベントの処理方法を実装します。
今回は、ファイルをドラッグ&ドロップした際(Windows
のWM_DROPFILES
イベント)に、ファイルをMemoryImage
に読み込み、draw
関数を呼び出します。
handleNativeEvent
を実装する際の注意点として、自分で処理したイベントは戻り値0
、自分で処理しないイベントは戻り値1
を返すことです。
戻り値1
を返すことで、simpledisplay
が用意したデフォルトのイベント処理を行います。
戻り値0
を返すとイベント処理を何も行わないため、ご注意ください。
以下はコンパイルと実行結果です。
D:\Dev> dub run --single sample3.d
parsePackageRecipe dub.sdl
Performing "debug" build using D:\Dev\dmd2\windows\bin64\dmd.exe for x86_64.
arsd-official:color_base 10.7.0: target for configuration "library" is up to date.
arsd-official:bmp 10.7.0: target for configuration "library" is up to date.
arsd-official:imageresize 10.7.0: target for configuration "library" is up to date.
arsd-official:jpeg 10.7.0: target for configuration "library" is up to date.
arsd-official:png 10.7.0: target for configuration "library" is up to date.
arsd-official:svg 10.7.0: target for configuration "library" is up to date.
arsd-official:image_files 10.7.0: target for configuration "library" is up to date.
arsd-official:simpledisplay 10.7.0: target for configuration "normal" is up to date.
sample3 ~master: building configuration "application"...
Linking...
To force a rebuild of up-to-date targets, run again with --force.
Running sample3.exe
以下は、ファイル(Qiitaのロゴ画像)をウィンドウにドラッグ&ドロップした際の結果です。
ウィンドウサイズを変えると、ロゴマークが拡大縮小表示されます。
ウィンドウイベント一覧(Windows用)
用意されているWindowS
用のウィンドウイベントをまとめました。
X11
用のウィンドウイベントなど、さらに詳細を知りたい方は、ソースコードを参照してください。
イベント関数 | 説明 |
---|---|
void delegate(KeyEvent ke) handleKeyEvent | キーボード操作イベント |
void delegate(dchar c) handleCharEvent | キーボードで押した文字処理イベント |
void delegate() handlePulse | タイマーイベント |
void delegate(bool) onFocusChange | ウィンドウのフォーカス有効無効イベント |
void delegate() onClosing | ウィンドウを閉じるイベント |
void delegate() onDestroyed | ウィンドウのリソース開放イベント |
void delegate(MouseEvent) handleMouseEvent | マウス操作イベント |
void delegate() paintingFinished | ウィンドウ描画終了時イベント |
void delegate(int width, int height) windowResized | ウィンドウサイズ変更イベント |
更新履歴
- 2021.1.9 初回投稿
- 2022.3.26 開発環境のバージョンを更新。ソースコードを更新。