D言語で作るスクリーンセーバー


はじめに

D言語で、スクリーンセーバーを作成することができます。
以下の環境があれば、とても簡単です。

環境

ひな形(その1)

まずは、ひな形のスクリーンセーバーを作成します。
スクリーンセーバー実行時に黒い画面を表示するだけです。設定画面はありません。

base1.d
import core.sys.windows.windows;

pragma(lib, "ScrnSave.Lib");
pragma(lib, "Gdi32.lib");
pragma(lib, "Kernel32.lib");
pragma(lib, "User32.lib");
pragma(lib, "Advapi32.lib");
pragma(lib, "Comctl32.lib");
pragma(lib, "libcmt.lib");

extern (Windows) nothrow @nogc {
    LRESULT DefScreenSaverProc(HWND, UINT, WPARAM, LPARAM);
}

extern(Windows) nothrow
BOOL RegisterDialogClasses(HANDLE hInst)
{
    return ( true );
}

extern(Windows) nothrow
BOOL ScreenSaverConfigureDialog(HWND hDlg, UINT message, UINT wParam,LONG lParam)
{
    return ( false );
}

extern(Windows) nothrow
LRESULT ScreenSaverProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch ( message ){
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            break;
    }
    return ( DefScreenSaverProc(hWnd, message, wParam, lParam) );
}

ソースコード補足説明1

pragma(lib, "ScrnSave.Lib")で、スクリーンセーバー作成に必要なライブラリを指定します。
pragma(lib, "Gdi32.lib")以下は、ScrnSave.Libがリンク時に必要とするライブラリです。

ScrnSave.Lib を使う場合、以下の3つの関数を開発者が作成する必要があります。

ScreenSaverProc

ScreenSaverProc は、スクリーンセーバー実行時やプレビュー時に呼び出される関数で、描画などの必要なイベントの処理を記述します。
ひな形では、スクリーンセーバー終了時に発生するWM_DESTROYイベントでPostQuitMessageを、それ以外のイベントではDefScreenSaverProcを呼び出すだけです。
DefScreenSaverProcは、core.sys.windows.windowsimportでは定義されないため、以下を記述します。

extern (Windows) nothrow @nogc {
    LRESULT DefScreenSaverProc(HWND, UINT, WPARAM, LPARAM);
}

ScreenSaverConfigureDialog

ScreenSaverConfigureDialog は、スクリーンセーバー設定時に表示されるダイアログボックスを処理する関数です。
ひな形では、ダイアログボックスを作成しないので、falseを返すだけです。

RegisterDialogClasses

RegisterDialogClasses は、スクリーンセーバー設定用ダイアログボックスの作成前に呼び出される関数です。
開発者が作成したコントロールをダイアログボックスで使う場合に、必要なコントロールの登録処理を記述します。
ひな形では、trueを返すだけです。

コンパイル、実行

D:\Dev> dmd -m64 -L/SUBSYSTEM:WINDOWS -of=base.scr base1.d
D:\Dev> copy base.scr C:\Windows\System32

作成されたbase.scrC:\Windows\System32にコピーします。管理者権限が必要です。
スクリーンセーバーの設定画面でbaseが選択可能になります。
設定画面はありませんが、プレビューは実行可能です。

ひな形(その2)

スクリーンセーバーの設定画面を実装します。

base2.d
import core.sys.windows.windows;

pragma(lib, "ScrnSave.Lib");
pragma(lib, "Gdi32.lib");
pragma(lib, "Kernel32.lib");
pragma(lib, "User32.lib");
pragma(lib, "Advapi32.lib");
pragma(lib, "Comctl32.lib");
pragma(lib, "libcmt.lib");

extern (Windows) nothrow @nogc {
    LRESULT DefScreenSaverProc(HWND, UINT, WPARAM, LPARAM);
}

extern(Windows) nothrow
BOOL RegisterDialogClasses(HANDLE hInst)
{
    return ( true );
}

extern(Windows) nothrow
BOOL ScreenSaverConfigureDialog(HWND hDlg, UINT message, UINT wParam,LONG lParam)
{
    switch ( message ){
        case WM_INITDIALOG:
            return ( true );
        case WM_COMMAND:
            switch ( LOWORD(wParam) ){
                case IDOK:
                case IDCANCEL:
                    EndDialog(hDlg,wParam);
                    return ( true );
                default:
                    break;
            }
            break;
        default:
            break;
    }
    return ( false );
}

extern(Windows) nothrow
LRESULT ScreenSaverProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch ( message ){
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            break;
    }
    return ( DefScreenSaverProc(hWnd, message, wParam, lParam) );
}
basedlg.rc
#include <windows.h>
#include <scrnsave.h>

DLG_SCRNSAVECONFIGURE DIALOG DISCARDABLE  50,50,200,150
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "スクリーンセーバー設定画面"
FONT 10, "system"
BEGIN
    CTEXT           "設定項目",-1,10,15,180,10
    DEFPUSHBUTTON   "OK",IDOK,40,130,50,14,WS_GROUP
    PUSHBUTTON      "キャンセル",IDCANCEL,110,130,50,14,WS_GROUP
END

ソースコード補足説明2

スクリーンセーバー設定画面では、DLG_SCRNSAVECONFIGUREのリソースが使用されるため、
リソースファイルbasedlg.rcを用意しました。

また、ScreenSaverConfigureDialogにダイアログボックス内のボタンを押した場合の処理を記述しました。
といっても、EndDialogを呼び出してダイアログボックスを終了させるだけです。

コンパイル、実行

d:\Dev> rc basedlg.rc
Microsoft (R) Windows (R) Resource Compiler Version 10.0.10011.16384
Copyright (C) Microsoft Corporation.  All rights reserved.

d:\Dev> dmd -m64 -L/SUBSYSTEM:WINDOWS -of=base.scr base2.d basedlg.res

D:\Dev> copy base.scr C:\Windows\System32
C:\Windows\System32\base.scr を上書きしますか? (Yes/No/All): y
        1 個のファイルをコピーしました。

「VS2019用 x64 Native Tools コマンドプロンプト」を起動します
作成されたbase.scrC:\Windows\System32にコピーします。管理者権限が必要です。
スクリーンセーバーの設定画面でbaseが選択可能になります。
「設定(T)...」ボタンを押すと作成した設定画面が開きます。

参考情報

ScreenSaverProc
ScreenSaverConfigureDialog
RegisterDialogClasses

DefScreenSaverProc