Dxライブラリを使ってスクリーンセーバを作ってみた
Dxライブラリを使って、スクリーンセーバを作ってみました。
C/C++自体あまり触る機会がないので、良い書き方がどんなものかよくわかりませんが・・・
機能としては背景1枚のみを表示するスクリーンセーバ
ゲーム用ライブラリを使っているのでモッサリ・・・
アニメーション、画像多用のスクリーンセーバを作る予定なのでDxライブラリを使ったんですけど
失敗だったかな・・・
ブログ書いてる途中に見つけた参考になりようなサイト
ブログを書いてる時になぜか見つけてしまうなー
このソースはプロジェクトのプロパティを変更する必要あり
※構成プロパティ−全般−文字セットを「マルチ バイト文字セットを使用する」
/// --------------------------------------------------------------- /// 概 要: /// 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も中々面白いですねー