読者です 読者をやめる 読者になる 読者になる

もなかアイスの試食品

「とりあえずやってみたい」そんな気持ちが先走りすぎて挫折が多い私のメモ書きみたいなものです.

Dxライブラリを使ってスクリーンセーバを作ってみた

C/C++

Dxライブラリを使って、スクリーンセーバを作ってみました。

C/C++自体あまり触る機会がないので、良い書き方がどんなものかよくわかりませんが・・・

機能としては背景1枚のみを表示するスクリーンセーバ

ゲーム用ライブラリを使っているのでモッサリ・・・

アニメーション、画像多用のスクリーンセーバを作る予定なのでDxライブラリを使ったんですけど

失敗だったかな・・・

ブログ書いてる途中に見つけた参考になりようなサイト

スクリーンセーバー作成スクリーンセーバー作成

ブログを書いてる時になぜか見つけてしまうなー


このソースはプロジェクトのプロパティを変更する必要あり
※構成プロパティ−全般−文字セットを「マルチ バイト文字セットを使用する」

VC++6のソースを最新のVC++でコンパイル - インコのWindowsSDKVC++6のソースを最新のVC++でコンパイル - インコのWindowsSDK

/// ---------------------------------------------------------------
/// 概 要:
///        C/C++    スクリーンセーバ 表示処理部
/// ---------------------------------------------------------------
 
#ifndef ShowScreenSaver_H
#define ShowScreenSaver_H
 
extern    const    int    NomalCode;
extern    const    int    ErrorCode;
extern    const    int    FailureAllocateMemory;
extern    const    int    FailureLoadImage;
 
/// ---------------------------------------------------------------
/// 概 要:
///        スクリーンセーバを開始します.
/// 
/// 引 数:
///        なし
/// 
/// 戻り値:
///        int 終了コード
/// ---------------------------------------------------------------
int StartScreenSaver( void );
 
#endif


関数StartScreenSaverのみを外部公開したつもり

以下は実装部分です。

/// ---------------------------------------------------------------
/// 概 要:
///        C/C++    スクリーンセーバ 表示処理部
/// ---------------------------------------------------------------
 
#include "ShowScreenSaver.h"
#include "resource.h"
#include <stdlib.h>
#include <DxLib.h>
#include <math.h>
 
const    int        NomalCode               = 0;
const    int        ErrorCode               = -1;
const    int        FailureAllocateMemory   = -2;
const    int        FailureLoadImage        = -3;
 
static    int       backImageHandle;
static    int       startSaverMouseX;
static    int       startSaverMouseY;
 
static int InitializeScreenSaver( void );
    static void SetWindowSize( void );
    static void SetMyWindowMostTop( HWND );
    static void ChangeStyleToNonBorderWindow( HWND );
 
static void AnimationLoop( void );
    static bool ContinueScreenSaver( void );
 
static void EndProcessScreenSaver( void );
 
/// ---------------------------------------------------------------
/// 概 要:
///        スクリーンセーバを開始します.
/// 
/// 引 数:
///        なし
/// 
/// 戻り値:
///        なし
/// ---------------------------------------------------------------
int StartScreenSaver( void )
{
 
    int endCode = NomalCode;
    if ( ( endCode = InitializeScreenSaver() ) != NomalCode )
    {
        return endCode;
    }
 
    AnimationLoop();
 
    EndProcessScreenSaver();
 
    return NomalCode;
 
}
 
/// ---------------------------------------------------------------
/// 概 要:
///        スクリーンセーバの初期化処理を行います.
///            -Dxライブラリ初期化
///            -画面サイズ設定
///            -画像ハンドルの登録
///            -マウスカーソルの非表示
///            -描画対象をウラ画面に設定
///            -ウィンドウを最前面に設定
///            -ウィンドウスタイルを「境界線なし」に変更
///            -マウスの現在位置を登録する
///            -マウスを非表示にする
/// 
/// 引 数:
///        なし
/// 
/// 戻り値:
///        int    終了コード
///                正常                      : 0
///                Dxライブラリ初期化失敗    :-1
///                メモリ確保失敗            :-2    (現在未使用)
///                画像読み込み失敗          :-3
/// ---------------------------------------------------------------
static int InitializeScreenSaver( void )
{
 
    HWND    myWindowHandle = NULL;
 
    // これがないとフルスクリーンモードで起動する.
    // 他アプリのウィンドウサイズ・位置変更防止ためウィンドウモードで一度起動
    ChangeWindowMode( FALSE );
 
    if ( DxLib_Init() == ErrorCode ) { return ErrorCode; }
 
    SetWindowSize();    // Later:画面サイズを自動検知する予定
 
    backImageHandle = LoadGraphToResource( IDB_BITMAP1 );  // リソースからハンドル取得
    // ファイルからハンドルを取得する場合
    // backImageHandle = LoadGraph( FilePath );
 
    SetDrawScreen( DX_SCREEN_BACK );
 
    myWindowHandle = GetMainWindowHandle();
 
    SetMyWindowMostTop( myWindowHandle );
 
    ChangeStyleToNonBorderWindow( myWindowHandle );
 
    GetMousePoint( &startSaverMouseX, &startSaverMouseY );
 
    SetMouseDispFlag( FALSE );        // マウスカーソル非表示
 
    return NomalCode;
 
}
 
/// ---------------------------------------------------------------
/// 概 要:
///        画面サイズを設定します.
/// 
/// 引 数:
///        なし
/// 
/// 戻り値:
///        なし
///
/// 備 考:
///        Later:モニターより画面サイズを自動検知する予定
/// ---------------------------------------------------------------
static void SetWindowSize( void )
{
 
    // とりあえずのウィンドウサイズ
    static    const    int        WindowWidth  = 1920;
    static    const    int        WindowHeight = 1080;
    static    const    int        ColorDepth   = 32;
    
    SetGraphMode( WindowWidth, WindowHeight, ColorDepth );
 
    ChangeWindowMode( FALSE );        // ウィンドウモードで画面表示
 
}
 
/// ---------------------------------------------------------------
/// 概 要:
///        画面を最前面に設定します.
/// 
/// 引 数:
///        [i]        HWND    myWindowHandle    :自分自身のハンドル
/// 
/// 戻り値:
///        なし
/// ---------------------------------------------------------------
static void    SetMyWindowMostTop( HWND myWindowHandle )
{
 
    const    int    Ignore        =    0;
    // 第5, 4引数を無視、大きさを変更しない。ウィンドウを表示する
    const    int    PositionChangeOption = SWP_NOSIZE |
                                           SWP_SHOWWINDOW;
    int            positionX    =    0;
    int            positionY    =    0;
    
    SetWindowPos( myWindowHandle,
                  HWND_TOPMOST,
                  positionX,
                  positionY,
                  Ignore,
                  Ignore,
                  PositionChangeOption );
 
}
 
/// ---------------------------------------------------------------
/// 概 要:
///        ウィンドウスタイルを境界線なしのウィンドウに変更します.
/// 
/// 引 数:
///        [i]        HWND    myWindowHandle    :自分自身のハンドル
/// 
/// 戻り値:
///        なし
/// ---------------------------------------------------------------
static void ChangeStyleToNonBorderWindow( HWND myWindowHandle )
{
 
    const    int    NonBoderWindowStyle    = WS_POPUP | WS_VISIBLE;
 
    SetWindowLong( myWindowHandle,
                   GWL_STYLE,      // 現在のスタイルに別のものに変更
                   NonBoderWindowStyle );
 
}
 
/// ---------------------------------------------------------------
/// 概 要:
///        スクリーンセーバの終了処理を行います.
///            -マウスカーソルの表示
///            -Dxライブラリ終了処理
/// 
/// 引 数:
///        なし
/// 
/// 戻り値:
///        なし
/// ---------------------------------------------------------------
static void EndProcessScreenSaver( void )
{
 
    SetMouseDispFlag( TRUE );        // マウスカーソル表示
 
    DxLib_End();
 
}
 
/// ---------------------------------------------------------------
/// 概 要:
///        アニメーションループ処理
/// 
/// 引 数:
///        なし
/// 
/// 戻り値:
///        なし
/// ---------------------------------------------------------------
static void AnimationLoop( void )
{
 
    const    int    BackImagePositionX    = 0;
    const    int    BackImagePositionY    = 0;
    const    int    NotTrancemission      = FALSE;  // 描写時透過しない
 
    while( ContinueScreenSaver() )
    {
        ClsDrawScreen();
 
        DrawGraph( BackImagePositionX,
                   BackImagePositionY,
                   backImageHandle,
                   NotTrancemission );
 
        ScreenFlip();
    }
 
}
 
/// ---------------------------------------------------------------
/// 概 要:
///        アニメーションループ継続判定処理
///            終了条件
///                -ウィンドウメッセージ処理失敗&閉じる
///                -キーボード&マウス入力検知
///                -マウス移動
/// 
/// 引 数:
///        なし
/// 
/// 戻り値:
///        スクリーンセーバ継続時    :true
///        スクリーンセーバ中断時    :false
/// ---------------------------------------------------------------
static bool ContinueScreenSaver( void )
{
 
    const    int    NotError             = 0;
    const    int    NotHit               = 0;
    const    int    AllowMoveDistance    = 10;
    int             positionX            = 0;
    int             positionY            = 0;
    bool            isProcess            = false;
    bool            notHitKey            = false;
    bool            notMoveMouse         = false;
 
    GetMousePoint( &positionX, &positionY );
 
    isProcess = ProcessMessage()    == NotError;
 
    notHitKey = CheckHitKeyAll()    == NotHit;
 
    notMoveMouse = abs( positionX - startSaverMouseX ) < AllowMoveDistance ||
                   abs( positionY - startSaverMouseY ) < AllowMoveDistance;
 
    return isProcess && notHitKey && notMoveMouse;
 
}


作成したcpp・hファイルを使ってスクリーンセーバを実行

ちなみにスクリーンセーバは、コマンドより起動するウィンドウが異なります

/S・・・スクリーンセーバ開始コマンド
/C・・・設定用
/P・・・コントロールパネル−画面のプレビュー用

このソースは「/S」しか実装していません

/// ---------------------------------------------------------------
/// 概 要:
///        C/C++    スクリーンセーバ メイン処理
/// ---------------------------------------------------------------
 
#include<Windows.h>
#include"ShowScreenSaver.h"
 
/// 概 要:
///        コマンド 列挙
typedef enum show_type
{
    // サポートしていないコマンドライン
    NotSupport,
    // スクリーンセーバ表示
    ShowSaver,
    // プレビュー
    Preveiw,
    // 設定
    Config,
    // カウント用
    Max,
} EnumShowType;
 
EnumShowType DecideShowTypeFromCommand( const char* );
void ShowErrorMessageBox( const char*, const char* );
 
/// ---------------------------------------------------------------
/// 概 要:
///        エントリポイント
/// 
/// 引 数:
///        [i]     HINSTANCE    hInstance  :インスタンスハンドル
///        [i]     HINSTANCE    preInstance:以前のハンドル(常にNULL)
///        [i]     LPSTR        commandLine:コマンドライン
///        [i]     int          showCommand:ウィンドウの表示状態
///
/// 戻り値:
///        なし
/// ---------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE preInstance, LPSTR commandLine, int showCommand )
{
 
    const    char*    ErrorCaption          = "起動失敗";
    const    char*    NotSupportMessage     = "サポートしていないコマンドです.";
    const    char*    NotImplementedMessage = "未実装のコマンドを検出しました.";
 
    switch ( DecideShowTypeFromCommand( commandLine ) )
    {
        case NotSupport:
            ShowErrorMessageBox( ErrorCaption,
                                 NotSupportMessage );
            break;
 
        case Config:
            ShowErrorMessageBox( ErrorCaption,
                                 NotImplementedMessage );
            break;
 
        case Preveiw:
            ShowErrorMessageBox( ErrorCaption,
                                 NotImplementedMessage );
            break;
 
        case ShowSaver:
            StartScreenSaver();
            break;
 
        default:
            ShowErrorMessageBox( ErrorCaption,
                                 NotSupportMessage );
            break;
    }
 
    return 0;
 
}
 
/// ---------------------------------------------------------------
/// 概 要:
///        コマンドラインから,表示するウィンドウタイプを取得します.
/// 
/// 引 数:
///        [i]        char*    command    :コマンドライン
/// 
/// 戻り値:
///        表示するウィンドウタイプ
/// ---------------------------------------------------------------
EnumShowType DecideShowTypeFromCommand( const char* command )
{
 
    const    char*    SaverOption        = "/S";
    const    char*    ConfigOption       = "/C";
    const    char*    PreveiwOption      = "/P";
    const    int      Same = 0;
 
    // _stricmp関数 大文字,小文字区別なし比較(stricmpは警告が出る)
    // OSからは,大文字でオプションが渡される
    if ( _stricmp( command, SaverOption ) == Same )
    {
        return ShowSaver;
    }
    else if ( _stricmp( command, ConfigOption ) == Same )
    {
        return Config;
    }
    else if ( _stricmp( command, PreveiwOption ) == Same )
    {
        return Preveiw;
    }
    else
    {
        return NotSupport;
    }
 
}
 
/// ---------------------------------------------------------------
/// 概 要:
///        エラーメッセージボックスを表示します.
/// 
/// 引 数:
///        [i]        char*    title        :タイトルバー文字
///        [i]        char*    showMessage    :表示メッセージ
/// 
/// 戻り値:
///        なし
/// ---------------------------------------------------------------
void ShowErrorMessageBox( const char* title, const char* showMessage )
{
 
    // ボタン:OKのみ アイコン:エラー
    const int BoxType = MB_OK | MB_ICONERROR;
 
    MessageBox( NULL,
                showMessage,
                title,
                BoxType );
 
}


今後このソースには画面上を動くキャラやアニメーションを追加する予定

あと、マルチモニタにも対応するようにしなければ・・・

WinAPIも中々面白いですねー