[BlueLeaf1336]> PROBLEMS> PasteIt>

PasteIt > デスクトップの壁紙を変更する

historyTOP

2007/02/08:作成
2007/02/21:その前に、デスクトップのダブルクリック検出をこましに

はじめにTOP

デスクトップのダブルクリックは、途中でほっぽり出した形になってしまいましたが、仕事じゃないので全然オッケー。次に進むことにします。まずは、About Delphi でずっと前にダウンロードしてきた、Delphi-ML で「壁紙」を検索してみます。オフラインなので。

その前に、デスクトップのダブルクリック検出をこましに(2007/02/21)TOP

壁紙のことを、Delphi-ML で調べてみましたが、調べながら思いついたことがあって試してみたところ少しばかりいい感じになりました。

目的語がありませんでしたが、「デスクトップのダブルクリック検出」のことです。

時間がかかるアプリを起動するときってマウスのカーソルが時計になるやん500ミリ秒待ってなおウィンドウができひんからアイコンのダブルクリックとデスクトップのダブルクリックを見まがうんやからそれはそれでおいといてそれとは別にカーソルの変化を監視しとけばどうよスレッドかなんかでひたすらよぅ。やってみよう。

そんなこんなでそれなりにましな感じになりました。でも完璧ではなさそうですけど。

20070221PasteIt.zip(223,250bytes) 実行ファイルとソースコード。

実行結果。各行末の日本語は手で書き加えています。TMemoなので。

「カーソルの監視の変化」なんて大げさに書いてますが、やってることは単純で、GetCursorInfo を使ってカーソルのハンドル(HCURSOR つまるところ HICON)をひたすら取得し比較しているだけです。で、変化がおきたら、前回説明した(はず)、「実行予約」をキャンセルします。

//-----------------------------------------------------------------------------
//  カーソルハンドルを取得
function GetCursorHandle(): HCURSOR;
var
    LCursorInfo: TCursorInfo;
begin
    FillChar(LCursorInfo, SizeOf(LCursorInfo), 0);
    LCursorInfo.cbSize := SizeOf(LCursorInfo);
    GetCursorInfo(LCursorInfo);
    Result := LCursorInfo.hCursor;
end;

ちなみに、その実行予約とキャンセルを処理しているのはこんなスレッドです。

(略)
//-----------------------------------------------------------------------------
//  時間差で処理を実行するクラス
type
    TExecuteProc = procedure() of object;

    TTimeLagExecuter = class(TThread)
    private
        FTick: Cardinal;
        procedure ExecProc();
    public
        TimeLag: Cardinal;
        ExecuteProc: TExecuteProc;
    protected
        procedure Execute(); override;
        procedure Reserve();
        procedure Cancel();
    public
        constructor Create();
    end;
(略)
implementation
(略)
//=============================================================================
//  時間差で処理を実行するクラス

//-----------------------------------------------------------------------------
//  コンストラクタ
constructor TTimeLagExecuter.Create();
begin
    inherited Create(True);

    //  待ち時間初期値
    TimeLag := 500;
    FTick := 0;

    //  実行関数初期化
    ExecuteProc := nil;
end;

//-----------------------------------------------------------------------------
//  処理実行
procedure TTimeLagExecuter.ExecProc();
begin
    if Assigned(ExecuteProc) then
    begin
        ExecuteProc();
    end;
end;

//-----------------------------------------------------------------------------
//  処理を予約
procedure TTimeLagExecuter.Reserve();
begin
    FTick := GetTickCount();
end;

//-----------------------------------------------------------------------------
//  キャンセル
procedure TTimeLagExecuter.Cancel();
begin
    FTick := 0;
end;

//-----------------------------------------------------------------------------
//  メインループ
procedure TTimeLagExecuter.Execute();
var
    LPrevCursor: HCURSOR;
    LCurrCursor: HCURSOR;
begin
    inherited;

    LPrevCursor := GetCursorHandle();

    while not Terminated do
    begin
        Sleep(1);

        //  カーソルが変更されたら有無を言わさずキャンセル
        LCurrCursor := GetCursorHandle();
        if (LPrevCursor <> LCurrCursor) then
        begin
            Cancel();
            LPrevCursor := LCurrCursor;
        end;

        if (FTick > 0) and (GetTickCount() - FTick > TimeLag) then
        begin
            //  処理実行
            Synchronize(ExecProc);
            Cancel();
        end;
    end;
end;
(略)
end.

アプリ起動時にこのスレッドクラスのインスタンスを作成して、ExecuteProc に実行したい procedure を代入しておきます(いわゆる関数ポインタです)。で、ダブルクリックを検出したら Reserve() を呼び出し、ウィンドウが作成されたら Cancel() を呼び出す。それとは別に、このスレッド自身が、マウスカーソルのハンドルを取得・比較し続けていて、変化したら Cancel() を呼び出しています。

で、Reserve() されてから 500ミリ秒 Cancel() されなければ、ExecuteProc を実行します。ヌルポとガッの関係です。

話は変わって、壁紙に何か自前の画像を組み合わせて書き戻すのって邪魔くさそう...タイル表示とかされてたりしたらどうしよう。

EOFTOP