最終更新日 2025-03-26

「デスクトップの復元」と「自動起動マクロ(ファイルを開いた時)」の不具合の抑制

概要

秀丸の機能の1つである「デスクトップの復元」時に、「自動起動マクロ(ファイルを開いた時)」というタイミングとみなして、
自動実行することが出来ますが、
これを安易にすると、WebView2コンポーネントが描画されなくなる、という問題があります。

自動起動マクロで呼び出すマクロ

デスクトップ復元時の自動起動マクロは、本来は以下のようなクッションとでもいう役割を果たすマクロを間に挟むことで、正しく動作し、しかも、実は動作が軽くなります。

これは「どんどんファイルを開いていく時に、その場では自動起動マクロを実行せず、後で「ユーザーにとって意味のあるフォーカスを得たタイミング」で実行する、
といった、一種の遅延実行のスタイルを採用しているためです。

OnEventMacros.mac (このファイルを自動起動マクロとして呼び出す)

このソースは一種のテンプレートと考えてよく、そのまま利用することを検討してください。

このOnEventMacros.mac から 「同じフォルダにある、本来の自動起動マクロとも言える OnEventMacrosMain.mac」 を、
状況次第では「遅延」で呼び出します。
これにより普通に呼び出してしまうと、WebView2の描画がバグり、以後利用できなくなるバグの発生確率を限りなくゼロへと近づけます。

// ある意味、間のプロキシーとでもいう役目を担う
hidemaruversion "9.46.02";

// 「自動起動マクロでファイルを開いた時」、
// タブモード かつ 「安全にWebView2系コンポーネントをオープンできない状況」なら、自動マクロは(後で実行する)予約形式にする。
if (event == 1 && tabmode && (windowstate2 & 0x0004 || inputstates & 0x00080000)) {

    jsmode "JScript\\" + currentmacrofilename;

    js {
        var currentMacroDirectory = currentmacrodirectory(); // 非同期になると取れないため、取得

        function isSafeMakeConditionOfWebView2Pane() {

            // タブモードでアクティブではない非表示
            if( (windowstate2() & 0x0004)){
                return false;
            }

            // デスクトップ復元中
            if (inputstates() & 0x00080000) {
                return false;
            }

            return true;
        }

        var timerHandle; // 宣言だけ。初期化しないこと

        if (typeof("timerHandle") != "undefined") {
            hidemaru.clearTimeout(timerHandle);
        }

        // マクロ実行を予約する
        function reserveExecMacroFile(macroFileFullPath) {
            // ダメなタイミングなら、0.4秒後にまたチェック
            if (!isSafeMakeConditionOfWebView2Pane()) {
                timerHandle = hidemaru.setTimeout(reserveExecMacroFile, 400, macroFileFullPath);
                return;
            }
            // 大丈夫そうなので、マクロ実行を予約
            var isScheduled = hidemaru.postExecMacroFile(macroFileFullPath, 1);
            if (isScheduled) {
                hidemaru.clearTimeout(timerHandle);
            } else {
                // マクロ予約自体が失敗しているので、0.2秒後にまたチェック
                timerHandle = hidemaru.setTimeout(reserveExecMacroFile, 200, macroFileFullPath);
            }
        }

        reserveExecMacroFile(currentMacroDirectory + "\\OnEventMacrosMain.mac");

    } // js

// それ以外はこれまで通り
} else {

   execmacro currentmacrodirectory + "\\OnEventMacrosMain.mac";

}

OnEventMacrosMain.mac (このファイルに実際の分岐処理を記述していく)

こちらが、「本来の自動起動マクロを集めたもの」で、「各種のeventのタイミング」や「呼び出し」の「分岐」などを行うところです。

遅延実行になることがあるため、(実質的に自動起動ではなくなっており)eventでは取れなくなるため、
実質的にどのeventとして見なしてほしいのかを、引数 getarg(0) として OnEventMacros.mac から渡しています。
これを#eventIDとして受け取っています。

必要に応じて、この#eventIDは、execmacro 先 (さらなる呼び出しマクロ)にも伝搬していく必要があります。

/*
 * 自動起動マクロ
 */
hidemaruversion "9.35.99";

//===========================================================
// イベント番号に対応するラベルへと飛ぶ。
//-----------------------------------------------------------
disablebreak;
// 遅延呼び出しの時、引数にeventの値を伝搬する形を取るので受け取る。
if (argcount > 0) {
    #eventID = val(getarg(0));
} else {
    #eventID = event;
}
$event_label = "OnEvent_" + sprintf("%02d", #eventID);

call $event_label;
enablebreak;
endmacro;
//===========================================================


//===========================================================
// 自動起動マクロではない
//-----------------------------------------------------------
OnEvent_00:
    return;
//===========================================================

//===========================================================
// ファイルを開いた直後
//-----------------------------------------------------------
OnEvent_01:
    call OnPost_FileOpen;

    return;
//===========================================================

//===========================================================
// 新規作成直後
//-----------------------------------------------------------
OnEvent_02:
    call OnPost_NewDocumentMake;

    return;
//===========================================================

//===========================================================
// 保存直前と直後
//-----------------------------------------------------------
OnEvent_03:
    ##is_after_save = geteventparam(0);
    if (##is_after_save) {
        call OnPost_FileSave;
    } else {
        call OnPrev_FileSave;
    }

    return;
//===========================================================

//===========================================================
// 印刷直前と直後
//-----------------------------------------------------------
OnEvent_04:

    return;
//===========================================================

//===========================================================
// 編集後タイマー
//-----------------------------------------------------------
OnEvent_05:

    return;
//===========================================================

//===========================================================
// カーソル移動後タイマー
//-----------------------------------------------------------
OnEvent_06:

    return;
//===========================================================

//===========================================================
// ファイルを閉じる直前
//-----------------------------------------------------------
OnEvent_07:
    call OnPrev_FileClose;

    return;
//===========================================================

//===========================================================
// 秀丸の対象ウィンドウがアクティブになった直後
//-----------------------------------------------------------
OnEvent_08:
    call OnPost_WindowFocus;

    return;
//===========================================================


// 予備
OnEvent_09:
    return;

// 予備
OnEvent_10:
    return;

// 予備
OnEvent_11:
    return;

// 予備
OnEvent_12:
    return;

// 予備
OnEvent_13:
    return;


//===========================================================


//-----------------------------------------------------------
// 各実装
//-----------------------------------------------------------

//-----------------------------------------------------------
OnPost_FileOpen:

    call HmExcelFileLoader;

    call HmMacroEncodeNormalize;

    call HmCustomWebView2Mode;

    call HmGitWatcher;

    call HmWebView2BrowserMode;

    return;

//-----------------------------------------------------------
OnPost_NewDocumentMake:

    return;

//-----------------------------------------------------------
OnPost_WindowFocus:

    return;

//-----------------------------------------------------------
OnPrev_FileSave:

    return;

//-----------------------------------------------------------
OnPost_FileSave:
    call HmMacroEncodeNormalize;

    call HmGitWatcher;

    return;

//-----------------------------------------------------------
OnPrev_FileClose:

    return;





//===========================================================
// 以下、各イベントハンドラ
//-----------------------------------------------------------

HmExcelFileLoader:

    if(filetype == ".xls" || filetype == ".xlsx" ) {
        setencode 26, 0;
        // 閉じるので先にExcelファイルの名前をとっておく
        $$dummyXlsFileName = filename2;
        // 閉じる
        closenew;
        execmacro macrodir + @"\HmExcelFileLoader\HmExcelFileLoader.mac", $$dummyXlsFileName;
    }


HmMacroEncodeNormalize:

    if (filetype == ".mac") {
        execmacro macrodir + @"\HmMacroEncodeNormalize\HmMacroEncodeNormalize.mac";
    }

    return;


HmCustomWebView2Mode:

    if (filetype == ".md") {
        execmacro macrodir + @"\HmMarkdownSimpleServer\HmMarkdownSimpleServer.mac";
    }
    if (filetype == ".php" || filetype == ".html" || filetype == ".htm") {
        execmacro macrodir + @"\HmPHPSimpleServer\HmPHPSimpleServer.mac";
    }

    return;


HmWebView2BrowserMode:

    if (filetype==".jpg"  ||
        filetype==".jpeg" ||
        filetype==".bmp"  ||
        filetype==".png"  ||
        filetype==".gif"  ||
        filetype==".ico"  ||
        filetype==".webp" ||
        filetype==".pdf") {
        setencode 26, 0;
        showbrowserpane 1, 2;
        setbrowserpaneurl filename2, 2;
    }

    if (filetype==".svg") {
        showbrowserpane 1, 2;
        setbrowserpaneurl filename2, 2;
    }
    return;



HmGitWatcher:
    // このように必要に応じて、#eventIDをさらに伝搬していく必要があるだろう。
    execmacro macrodir + @"\HmGitWatcher\\HmGitWatcher.mac", str(#eventID);


AlertOutputPane:

    $$message = $$1;

    #OUT = loaddll( macrodir + @"\HmOutputPane.dll");
    #ret = dllfunc(#OUT, "Output",hidemaruhandle(0), $$message);
    freedll(#OUT);

    return;