ページ 11

ディスクトップアクセサリについて

Posted: 2014年7月11日(金) 19:50
by DELTA-Ⅲ
気になる物があったので質問させていただきます。
ディスクトップアクセサリーが欲しいと思い、検索をしたらそれらしきトピックを見つけました。
しかし、やってみるとウインドの端は消えていますが何も表示されていません。
一応見てくれますか?お願いします。

コード:

#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	ChangeWindowMode( TRUE );
	SetUseBackBufferTransColorFlag(TRUE);
	SetDrawScreen(DX_SCREEN_BACK);


	SetBackgroundColor(255, 255, 0) ;
	if ( DxLib_Init( ) == -1 ) return -1;
	SetTransColor(255,255,0);

	while ( ProcessMessage( ) == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0)
	{	SetWindowPos( GetMainWindowHandle() , HWND_TOPMOST, 0, 0, 300, 300, (SWP_SHOWWINDOW |SWP_NOSIZE) ); 
		ClearDrawScreen();

		DrawBox(0,0,640,480,GetColor(255,0,0),TRUE);
		DrawBox(100,100,200,200,GetColor(255,255,0),TRUE);

		ScreenFlip( );

		
	}

	DxLib_End( ); 
	return 0;
}

Re: ディスクトップアクセサリについて

Posted: 2014年7月14日(月) 13:05
by Ketty
ディスクトップ⇒デスクトップの間違いですよね?

DELTA-Ⅲさんのやりたいこととしては、
DXライブラリで透明なウィンドウを作ってそこに何かを描画したい、ということだと思いますが、
下記公式サイトにてDXライブラリの管理人様が見本を提示されています。
http://hpcgi2.nifty.com/natupaji/bbs/pa ... ew&no=3158

ポイントは、上記で明記されていますが、
SetUseBackBufferTransColorFlagを使うこと、
ScreenFlipの代わりに、UpdateLayerdWindowForPremultipliedAlphaSoftImageを使うことです。

私は、上記のやり方で実現できた経験がありますので、DELTA-Ⅲさんも同じようにやればできると思います。
(私の環境は、DXライブラリVer.3.12a、VC++2010、Winows7 64bitです)

質問投稿される場合は、
環境やDXライブラリのバージョン、今回の場合だと「それらしきトピック」とやらの出典(URL)などを
合わせてご提示されるとよいと思います。

Re: ディスクトップアクセサリについて

Posted: 2014年7月14日(月) 18:44
by DELTA-Ⅲ
>>Kettyさん、
場所はこちらです。http://dixq.net/board/log/bbslog_152.html
検索だけだったので公式を見ていません。
申し訳ありません。

しかし、画像が画面の右下に表示する方法を知りたいです。
画面は1600x900です。

コード:

#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
	int Screen ;
	int SoftImage ;
	ChangeWindowMode( TRUE );
	SetUseBackBufferTransColorFlag( TRUE ) ;
	if( DxLib_Init() < 0 ) return -1;
	Screen = MakeScreen( 640, 480, TRUE ) ;
	SoftImage = MakeARGB8ColorSoftImage( 640, 480 ) ; 
	SetUsePremulAlphaConvertLoad( TRUE ) ;
	SetDrawScreen( Screen );

	// 画像の読み込み
	int GrHandle = LoadGraph( "Test1.png" );

	while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
	{	SetWindowPos( GetMainWindowHandle() , HWND_TOPMOST, 0, 0, 1600,900, (SWP_SHOWWINDOW |SWP_NOSIZE) ); 

		// 画像を描画
		DrawGraph( 0, 480, GrHandle, TRUE ) ;

		// 描画先の画像をソフトイメージに取得する
		GetDrawScreenSoftImage( 0, 0, 640, 480, SoftImage );
		UpdateLayerdWindowForPremultipliedAlphaSoftImage( SoftImage );
		Sleep(1) ;
	}

	// DXライブラリの後始末
	DxLib_End() ;

	// ソフトの終了
	return 0 ;
}

Re: ディスクトップアクセサリについて

Posted: 2014年7月14日(月) 20:30
by softya(ソフト屋)
>しかし、画像が画面の右下に表示する方法を知りたいです。
>画面は1600x900です。

何が不明なのでしょう。ウィンドウサイズを1600x900にする方法でしょうか?
自分で実験できるレベルだと思うのですが、聞かないと分からない事を整理してみてください。

Re: ディスクトップアクセサリについて

Posted: 2014年7月14日(月) 20:41
by DELTA-Ⅲ
>>ソフト屋さん、
すみませんでした。解決しました。

Re: ディスクトップアクセサリについて

Posted: 2014年7月14日(月) 20:51
by softya(ソフト屋)
できれば解決したコードを貼って頂けると他の人に役立ちます。

Re: ディスクトップアクセサリについて

Posted: 2014年7月14日(月) 21:20
by DELTA-Ⅲ
softya(ソフト屋) さんが書きました:できれば解決したコードを貼って頂けると他の人に役立ちます。
コードを貼ります、色々すみません。

コード:

 //※間違っているとの指摘をされました。一応使わないように
#include "DxLib.h"
//1600x900がディスプレイのサイズ
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
	int Screen ;
	int SoftImage ;
	ChangeWindowMode( TRUE );
	SetUseBackBufferTransColorFlag( TRUE ) ;
	if( DxLib_Init() < 0 ) return -1;
	Screen = MakeScreen( 1600,900, TRUE ) ;
	SoftImage = MakeARGB8ColorSoftImage( 1600,900) ; 
	SetUsePremulAlphaConvertLoad( TRUE ) ;
	SetDrawScreen( Screen );
	SetGraphMode(1600,900,32);//ディスプレイのサイズで登録

	// 画像の読み込み
	int GrHandle = LoadGraph( "Test1.png" );

	while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
	{	SetWindowPos( GetMainWindowHandle() , HWND_TOPMOST, 0, 0, 1600,900, (SWP_SHOWWINDOW |SWP_NOSIZE) ); //前に出たまんま

		// 画像を描画
		DrawGraph( 0, 380, GrHandle, TRUE ) ;

		//
		GetDrawScreenSoftImage( 0, 0, 1600,900, SoftImage );
		UpdateLayerdWindowForPremultipliedAlphaSoftImage( SoftImage );
		Sleep(1) ;
	}DxLib_End() ;
	return 0 ;
}

Re: ディスクトップアクセサリについて

Posted: 2014年7月14日(月) 21:38
by Ketty
ご本人が解決されたとのことなのですが、
上記の提示していただいたソースコードにつきまして、私が気づいた点だけ指摘させていただきます。
(他の方がこのソースを参考に誤って覚えてしまうことを避けたいので・・・)

1.1600*900というサイズでMakeScreenし、かつウィンドウ自体もその大きさにされていますが、
  表示される画像がデスクトップ全体を覆い隠すような大きい画像なのでしょうか?(壁紙?)
  違うのでしたら、メモリの無駄だと思いますし、処理負荷も気になるように思います。
  小さい画像なら、デフォルトのウィンドウサイズ640*480で、その中に画像を描画し、ウィンドウの座標を右下にすればいいように思います。
2.SetWindowPosはメインループ外側ではだめなのですか?
  (私の環境ですと、メインループ直前で一度だけ指定すると最前面に居続けますので)
  今後の拡張によって透明ウィンドウを座標指定で無限に動きまくるデスクトップアクセサリを作られたいのでしょうか。
3.ClearDrawScreen() がないので、絵が無限に上書きされてしまうように思います。
4.UpdateLayerdWindowForPremultipliedAlphaSoftImageは、
  重い処理だと思う(※注)ので、FPSを極力下げた方がよいように思うのですが、上記ではSleep(1)なので心配です。

(※注)計測した結果ではなく、推論です。
以下URLにて、
http://hpcgi2.nifty.com/natupaji/bbs/pa ... st&no=1616
UpdateLayerdWindowForSoftImageが「非常に遅い」とDXライブラリ公式サイトの管理人様が記述されていますので、
上位版ともいえるUpdateLayerdWindowForPremultipliedAlphaSoftImageは、もっと遅いと思われる・・・
ので、使われる場合はスペックと相談しながらFPSを調整するのがよいと考えられます。

Re: ディスクトップアクセサリについて

Posted: 2014年7月14日(月) 23:21
by DELTA-Ⅲ
Ketty さんが書きました:ご本人が解決されたとのことなのですが、
上記の提示していただいたソースコードにつきまして、私が気づいた点だけ指摘させていただきます。
(他の方がこのソースを参考に誤って覚えてしまうことを避けたいので・・・)
申し訳ありません、ご指摘通りの物を出来るだけ再現できるようになりました。
回答もさせていただきます。
1.画像は小さいです。ただそこに居るだけといった物です。(吹き出し付き)
2.ただ勘で外側だとその後初期化されると思ったからです。
3.通常のプログラムと同様の処理も必要と思っていませんでした。
4.情報不足でした。申し訳ありません。

最初はとにかく「自分のPC上で動くもんだからいいや」と思っていただけなので・・・

コード:

//今は画像が出てこない・・・
#include "DxLib.h"

void fps_wait();
int Screen,SoftImage;

void set_nanntara(int x,int y,int fx,int fy){
    SetGraphMode(x,y,32);//ディスプレイのサイズで登録
	SoftImage = MakeARGB8ColorSoftImage(fx,fy); 
	Screen = MakeScreen(x,y, TRUE );
	SetWindowPos( GetMainWindowHandle() , HWND_TOPMOST,DX-WX, DY-WY, DX,DY, (SWP_SHOWWINDOW |SWP_NOSIZE) ); 
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
	ChangeWindowMode( TRUE );
	SetUseBackBufferTransColorFlag( TRUE ) ;
	if( DxLib_Init() < 0 ) return -1;
	SetUsePremulAlphaConvertLoad( TRUE ) ;
	SetDrawScreen( Screen );
	
	// 画像の読み込み
	
	int WX=525,WY=600;
	int DX=1600,DY=900;
	set_nanntara(WX,WY,DX,DY);
	int i=0;
	int GrHandle = LoadGraph( "Test1.png" );
	
	while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
	{	
		ClearDrawScreen();

		// 画像を描画
		DrawGraph(i,45, GrHandle, TRUE ) ;

		i=(i++)%100;

		//
		GetDrawScreenSoftImage(0,0,DX,DY,SoftImage);
		UpdateLayerdWindowForSoftImage( SoftImage );
		fps_wait();
	}DxLib_End() ;
	return 0 ;
}

Re: ディスクトップアクセサリについて

Posted: 2014年7月14日(月) 23:43
by Ketty
あ、いえ別に謝っていただく必要はありません。私が気になっただけですのでm(__)m

1行目にコメントで画像が出て来ないとありますが、
修正によって画像が表示されなくなっちゃった、という認識でよいですか?
(まだコードを読めておりませんので私の認識まちがいでしたらスルーされてかまいません)

もしかして、SetWindowPosの使い方を悩んでおられるのでしょうか?

Re: ディスクトップアクセサリについて

Posted: 2014年7月14日(月) 23:58
by Ketty
>また、SetWindowPosの使い方もわからないです。
なるほど。
SetWindowPosについて、私も正しい回答を用意できる自信がないため、
以下、ちょっと的外れな意見になってしまうのですが、
DXライブラリをお使いになるのであれば、
SetWindowPositionという関数を使われるのが、敷居が低くて理解しやすいと思います。

例)SetWindowPosition( 1200, 600 ) ;
このように書くと、透明ウィンドウの左上を1200, 600の位置に指定できます。

ただこれでは、最前面にしたい、という要件が満たされないと思いますので、
以下のように

コード:

// 最前面指定する
SetWindowPos( DxLib::GetMainWindowHandle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
// そのあとで座標指定する
DxLib::SetWindowPosition( 1200, 600 ) ; 
こんな風にすると、最前面指定してから、座標設定もできます。
どうでしょうか。

Re: ディスクトップアクセサリについて

Posted: 2014年7月15日(火) 00:06
by DELTA-Ⅲ
何とか解決できました。
編集後にサイトを見返すとふと思い書いたら出来ました。
すぐな返信ができなかったので遅れました。
>>Kettyさん、
色々迷惑をかけてしまったので・・・
よく見返すと分かりますね。
SetWindowPosは少々分かってきました・・・
別の方法があるとは知りませんでした。ありがとうございます。
一応出来たコードを置いていきます。

コード:

#include "DxLib.h"

//void fps_wait();
int Screen,SoftImage;

void set_nanntara(int x,int y,int fx,int fy){
    SetGraphMode(x-7,y-16,32);
	SoftImage = MakeARGB8ColorSoftImage(fx,fy); 
	Screen = MakeScreen(fx,fy,TRUE);
	SetDrawScreen( Screen );//使える、というか使う
	//SetDrawScreen( DX_SCREEN_BACK );//使えない
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
	ChangeWindowMode( TRUE );
	SetUseBackBufferTransColorFlag( TRUE ) ;
	if( DxLib_Init() < 0 ) return -1;
	SetUsePremulAlphaConvertLoad( TRUE ) ;
	
	int WX=525,WY=600;
	int DX=1600,DY=900;//ディスプレイのサイズで登録、出来れば自動で行いたい所。
	set_nanntara(WX,WY,DX,DY);

	// 画像の読み込み

	int GrHandle = LoadGraph( "Test1.png" );
	int i=0;
	while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
	{	SetWindowPos( GetMainWindowHandle() , HWND_TOPMOST,DX-WX, DY-WY, DX,DY, (SWP_SHOWWINDOW |SWP_NOSIZE) ); 
		ClearDrawScreen();

		// 画像を描画
		DrawGraph(i,45, GrHandle, TRUE ) ;

		i = (i++)%100;

		//
		GetDrawScreenSoftImage(0,0,DX,DY,SoftImage);
		UpdateLayerdWindowForSoftImage( SoftImage );
		Sleep(12) ;//ちょっと怖い
		//fps_wait();
	}DxLib_End() ;
	return 0 ;
}

Re: ディスクトップアクセサリについて

Posted: 2014年7月15日(火) 00:26
by Ketty
どうもお疲れ様です。
ですがあああ・・・またメインループにSetWindowPosが入っておりますよ・・・念のため(^^;
あと、インデントなどが崩れてゆきつつあるように思いますので、お気を付けください。

私も実験用に書いてみました。C++ですが。
決して最適解ではありませんが、今後の参考になればと思いますm(__)m
(FPS制御部分はDixqさんのものをそのまま流用させていただいております http://dixq.net/rp/43.html )

コード:

#include <vector>
#include "DxLib.h"

using namespace std ;

// 透明にしたいウィンドウのサイズ(とりあえずDXライブラリのデフォルトサイズです)
static const int WIN_W = 640 ;
static const int WIN_H = 480 ;

// 透明のウィンドウを表示したい位置(ウィンドウの左上座標)
static const int POS_X = 1200 ;
static const int POS_Y = 600 ;

// FPS
static const int FPS = 10 ; // UpdateLayerdWindowForPremultipliedAlphaSoftImageは重い処理なのでFPSを10程度にしてます

// FPS管理クラス
// Dixqさんのものを移植しただけです
class FpsManager
{
public:
	// コンストラクタ
	FpsManager()
	{
		// 初期化
		vecRecord_.resize( FPS, 0 ) ;
		frameCounter_ = 0 ;
		base0tCounter_ = 0 ;
		//average_ = 0 ;
	}
	// デストラクタ
	~FpsManager(){}

	// FPSを調整する
	void Adjust()
	{
		// この関数内部で使うタイミング変数
		static int timing_ = 0 ;

		// 待つべき時間を求める
		int waitMillisecond = 0 ;
		// 60フレーム中の1フレーム目のとき
		if( frameCounter_ == 0 )
		{
			// 完全に最初なら
			if( timing_ == 0 )
			{
				// 待つべき時間=なし
				waitMillisecond = 0 ;
			}
		
			else
			{
				// 待つべき時間=前回記録した時間を元に計算
				waitMillisecond = base0tCounter_ + 1000 - DxLib::GetNowCount() ;
			}
		}
		// 上記以外のとき
		else
		{
			// 待つべき時間=現在あるべき時刻-現在の時刻
			waitMillisecond = static_cast<int>( base0tCounter_ + frameCounter_ * ( 1000.0 / FPS ) ) - DxLib::GetNowCount() ;
		}

		// 待つべき時間だけ待つ
		if( waitMillisecond > 0 )
		{
			Sleep( waitMillisecond ) ;
		}

		// 現在時間を取得
		const int gnt = DxLib::GetNowCount() ;

		// 60フレームに1度基準を作る
		if( frameCounter_ == 0 )
		{
			base0tCounter_ = gnt ;
		}

		//1周した時間を記録
		vecRecord_[frameCounter_] = gnt - timing_ ;
		// タイミング更新
		timing_ = gnt ;

		// 60フレーム中の最終フレームのときのみ平均計算
		if( frameCounter_ == FPS - 1 )
		{
			average_ = 0;
			for( int i=0; i<FPS; ++i )
			{
				average_ += vecRecord_[i] ;
			}
			average_ /= FPS ;
		}

		// フレームカウンタ更新
		frameCounter_ = ( ++frameCounter_ ) % FPS ;
	}

	// FPS測定値を取得する
	double GetFps()
	{
		if( average_ > 0 )
		{
			return 1000.0 / average_ ;
		}
		else
		{
			return 0.0 ;
		}
	}
private :
	// 平均を計算するための記録用変数(60回の1周時間を記録)
	vector<int> vecRecord_ ;
	// フレームのカウンタ
	int frameCounter_ ;
	// 60フレームに1回基準となる時刻を記録する変数
	int base0tCounter_ ;
	// 平均fps
	double average_ ;
} ;

// Main関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	int GrHandle = -1 ;		// 画像のグラフィックハンドル
	int Screen = -1 ;		// 描画用スクリーンハンドル
	int SoftImage = -1 ;	// 透過描画用のソフトイメージハンドル

	// DXライブラリのログ出力をしない
	DxLib::SetOutApplicationLogValidFlag( FALSE ) ;
	// ウィンドウモードで起動
	DxLib::ChangeWindowMode( TRUE ) ;
	// 画面モード設定
	DxLib::SetGraphMode( WIN_W, WIN_H, 32 ) ;
	// ウィンドウの透明化
	DxLib::SetUseBackBufferTransColorFlag( TRUE ) ;
	DxLib::SetTransColor( 0, 0, 0 ) ;
	DxLib::SetBackgroundColor( 0, 0, 0 ) ;

	// DXライブラリ初期化処理
	if( DxLib::DxLib_Init() == -1 ){ return -1 ; }

	// 描画用スクリーンの作成
	Screen = DxLib::MakeScreen( WIN_W, WIN_H, TRUE ) ;
	// 透過描画用のソフトイメージの作成
	SoftImage = DxLib::MakeARGB8ColorSoftImage( WIN_W, WIN_H ) ;

	// 画像を読み込む際にアルファ値をRGB値に乗算するように設定する
	DxLib::SetUsePremulAlphaConvertLoad( TRUE ) ;
	// 画像を読み込み
	GrHandle = DxLib::LoadGraph( "Test1.png" ) ;

	// 描画先を描画対象にできるアルファチャンネル付き画面にする
	DxLib::SetDrawScreen( Screen );

	// FPS管理クラスのインスタンス生成
	FpsManager *fpsManager = new FpsManager() ;

	// WindowsのAPIで最前面表示を指定
	SetWindowPos( DxLib::GetMainWindowHandle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
	// ウインドウの位置を設定する(枠も含めた左上座標) 
	DxLib::SetWindowPosition( POS_X, POS_Y ) ; 

	// メインループ(ESCで終了)
	while( DxLib::ProcessMessage() == 0 && DxLib::CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
	{
		// 画面クリア
		DxLib::ClsDrawScreen();

		// 描画ブレンドモードを乗算済みアルファにセット
		DxLib::SetDrawBlendMode( DX_BLENDMODE_PMA_ALPHA, 255 ) ;

		// 画像を描画
		DxLib::DrawGraph( 0, 0, GrHandle, TRUE ) ;

		// 描画先の画像をソフトイメージに取得する
		DxLib::GetDrawScreenSoftImage( 0, 0, WIN_W, WIN_H, SoftImage ) ;
		
		// 取り込んだソフトイメージを使用して透過ウインドウの状態を更新する
		DxLib::UpdateLayerdWindowForPremultipliedAlphaSoftImage( SoftImage ) ;

		// FPS調整
		fpsManager->Adjust();
	}

	// FPS管理クラスのインスタンス破棄
	delete fpsManager ;

	// DXライブラリ終了処理
	DxLib::DxLib_End() ;

	// ソフトの終了 
	return 0 ;
}
また、ディスプレイサイズはWindowsのAPIで取得できます。よろしければお試しください。

コード:

int DisplayW = GetSystemMetrics( SM_CXSCREEN ) ;
int DisplayH = GetSystemMetrics( SM_CYSCREEN ) ;

Re: ディスクトップアクセサリについて

Posted: 2014年7月15日(火) 00:33
by DELTA-Ⅲ
>>Kettyさん、返信ありがとうございます。
ぉふぅ・・・また忘れていました・・・分かっているはずなのに・・・
しかしディスプレイサイズを習得する方法を教えていただきありがとうございました。
これで何とかデスクトップアクセサリーができます。色々とすみませんでした。