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

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
sisi

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

#1

投稿記事 by sisi » 15年前

ゲームではないので場違いな質問なら申し訳ありません
タイトルの通りなのですがデスクトップアクセサリはどうやって作ればいいのでしょうか?
デスクトップ上にウインドウを表示させずにキャラだけを描写
といったことは出来ないのでしょうか?
デスクトップでキー操作を受け付けるようにしてゲームを作ってみても面白いと思ったので
質問させていただきました。
キー操作を受け付けなくてもデスクトップをランダムに動き敵と会えば戦闘していく
成長系など

出来れば常に前面に表示されるものを作るにはどうしたらいいのでしょうか?

YuO

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

#2

投稿記事 by YuO » 15年前

キャラクタの形のリージョンを作って,
ウィンドウにリージョンを設定すれば,ウィンドウがキャラクタの形に切り抜かれます。
MSDN: CreateRectRgn Function (Windows)
http://msdn.microsoft.com/en-us/library/dd183514.aspx
MSDN: CombineRgn Function (Windows)
http://msdn.microsoft.com/en-us/library/dd183465.aspx
MSDN: SetWindowRgn Function (Windows)
http://msdn.microsoft.com/en-us/library/dd145102.aspx

あとは,普通に最前面表示をするだけです。
MSDN: CreateWindowEx Function ()
http://msdn.microsoft.com/en-us/library/ms632680.aspx
MSDN: SetWindowPos Function ()
http://msdn.microsoft.com/en-us/library/ms633545.aspx

Ma

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

#3

投稿記事 by Ma » 15年前

横槍失礼。
前から私も自力でできるようになればいいなーと思っていたので、ちらっとやってみました。
(初めてですが^^;)
YuOさんの方法でとりあえずウィンドウを部分的に表示できました。
問題は、リージョンの形をいかにキャラクターの形に指定するか、ってところでしょうか・・?

CreatePolygonRgn

で、大量の点を使って指定するのがてっとりばやいのかな?
となると、先にデータを作っておくか、使用するビットマップ画像を起動時に毎回解析して頂点データをたくさん取り出すかでしょうか?

頂点を保存するプログラムを作って(もしくはどっかからDLして)、それから頂点情報を読み込ませる方が得策?

YuO

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

#4

投稿記事 by YuO » 15年前

VS2008/C#2.0 Sample: http://pub.idisk-just.com/fview/olN5vuU ... VnaW9u.zip


> 問題は、リージョンの形をいかにキャラクターの形に指定するか、ってところでしょうか・・?

結局はそうなります。

サンプルはVisual Studio 2008 / C# 2.0によるコードですが,
α値を条件に,画像と同じ大きさのリージョンから非表示部分を削除していく (APIでは第4引数にRGN_DIFFを指定したCombineRgnに相当) 方法で作成しています。
# BitmapDataからデータを引っこ抜くのは,結局unsafe使うことになるのがちょっと悔しい。

ここの部分を,ツールとして別途用意してしまえばいいわけです。

一度リージョンを作ったならば,
MSDN: GetRegionData Function (Windows)
http://msdn.microsoft.com/en-us/library/dd144920.aspx
で取り出したリージョン情報を保存できるので,次回からは
MSDN: ExtCreateRegion Function (Windows)
http://msdn.microsoft.com/en-us/library/dd162706.aspx
でリージョンを再生成することになると思います。


なお,サンプルの画像は龍神録プログラミングの館にある,
project.zip/project/dat/img/char/body.png
を使わさせていただきました。
body.pngを置き換えれば,別の画像でも動くと思います (要ビルド)。
# あまりに大きいと処理できないかもしれませんが。

Ma

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

#5

投稿記事 by Ma » 15年前

>YuOさま
C#分からないんです。。。orz

大体やり方は把握しました。

ところで、DXライブラリを使いながら無理やりデスクトップアクセサリを作ってみたのですが、
リージョンをセーブロードの部分でうまくいかないので、よろしければどなたかお助けください。


問題点
1.DXライブラリ使うと起動時にウィンドウが表示されてしまう。
2.初回起動時にはリージョンが正しいが、リージョンデータをロードしてから表示しようとすると途中でリージョンが切れる。
(おそらく保存方法がおかしくてデータが途中から破損。)
3.ウィンドウのふちのサイズによって、リージョンの座標軸とDXライブラリの描画の座標軸がずれる。


以上です、以下にコードをそのまんまはりつけましたので、よろしければお試しください。


#追記
ソース長すぎておこられたので続きます・・・。

Ma

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

#6

投稿記事 by Ma » 15年前

#include "DxLib.h"
#include <fstream>                        //ファイル読み書き用

#define FILENAME "myAcce.acce"    //リージョンを保存するファイル名
#define IMG_FILE "body.png"            //画像ファイル名
#define ALPHA_S (200)                    //アルファ値(これ以下の値はリージョンから除外。)
#define DELETE_ALLTIME (false)        //true にすると、毎回起動時にリージョンを作成。false なら FILENAME のファイルが存在しないときのみリージョンを新規作成。



/*--- 名前がfilenameであるファイルが存在するかどうかを調査 ---*/
int fexist(const char *filename)
{
    FILE  *fp;

    if ((fp = fopen(filename, "r")) == NULL)
        return (0);
    fclose(fp);
    return (1);
}

 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){

    //DX ライブラリ初期化
    if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1;

    //画像ロード
    int softIHandle = LoadSoftImage(IMG_FILE) ;

    //画像のサイズ取得
    int width, height;
    GetSoftImageSize( softIHandle, &width, &height ) ;
    //画像のサイズにウィンドウの形を合わせる。
    SetGraphMode( width , height , 32 ) ;


    //リージョン
    HRGN myRegion;
    
    //リージョンを新規作成か、データからロードかの分岐
    if(!fexist(FILENAME) || DELETE_ALLTIME){
        //新規作成する。

        //とりあえず、リージョンを画像のサイズに合わせる。
        myRegion = CreateRectRgn(0,0,width,height);
        //画像のすべてのピクセルを調べる。
        for(int x = 0; x < width;x++){
            for(int y = 0; y < height;y++){
                int r,g,b,a;
                GetPixelSoftImage( softIHandle, x , y, &r, &g, &b, &a ) ;
                //(x,y)のピクセルのアルファ値が、ALPHA_S未満のとき、リージョンの範囲外とする。
                if(a < ALPHA_S){
                    //1ピクセル四方のリージョン作成。
                    HRGN dotRegion = CreateRectRgn(x ,y,x+1,y+1);
                    //これまでの領域からこのリージョンを排除。
                    CombineRgn(myRegion, myRegion, dotRegion, RGN_DIFF);
                    DeleteObject(dotRegion);//後処理
                }
            }
        }
        RGNDATA *data;    //リージョンデータ
        //保存に必要なバッファサイズ取得
        DWORD bufferSize = GetRegionData( myRegion, 0,NULL);
        //バッファに応じて確保
        data = (RGNDATA*)HeapAlloc( GetProcessHeap(), 0,  bufferSize );
        //data にリージョンのデータを格納。
        GetRegionData( myRegion, bufferSize,data);

        //指定されたファイルに、バッファサイズとdataを書き込む。
        std::ofstream ofs( FILENAME );
        ofs.write(( char * )&bufferSize, sizeof(bufferSize));
        ofs.write(( char * ) data, bufferSize);
        ofs.close();

        //HRGN testWin = ExtCreateRegion(NULL, bufferSize, data);
        HeapFree(GetProcessHeap(), 0, data);
    }
続く。。。。

Ma

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

#7

投稿記事 by Ma » 15年前

else{
        DWORD bufferSize;    //バッファサイズ
        RGNDATA *data;    //リージョンデータ

        //指定されたファイルから、バッファサイズとdataを読み込む。
        std::ifstream ifs(FILENAME);
        //バッファサイズ読み込み。
        ifs.read((char*)&bufferSize,sizeof(bufferSize));
        //バッファサイズ分だけヒープ確保。
        data = (RGNDATA*)HeapAlloc( GetProcessHeap(), 0,  bufferSize );
        //バッファサイズ分、dataにリージョンデータをファイルから読み込み。
        ifs.read((char*)data,bufferSize);
        ifs.close();
        //得たリージョンデータより、リージョンハンドル生成。
        myRegion = ExtCreateRegion(NULL, bufferSize, data);
        HeapFree(GetProcessHeap(), 0, data);//後処理
    }

    //リージョンを適応。
    SetWindowRgn( GetMainWindowHandle() ,myRegion,TRUE);
    DeleteObject(myRegion);//後処理

    //描画するために、画像ハンドル生成
    int ghandle = CreateGraphFromSoftImage( softIHandle) ;

    //TO DO: ウィンドウのふちによってずれる誤差だが、環境によって大きさが変わるので要改善
    DrawGraph(-5,-28,ghandle,TRUE);
    
    //待機。
    WaitKey();

    DxLib_End();
    return 0;
}

閉鎖

“C言語何でも質問掲示板” へ戻る