秀丸本体からのexport関数の追加要望No.09485
vscode-life さん 17/07/03 12:36
 
いつもお世話になっております、vscode-lifeです。

秀丸本体に備わっている関数 Hideamru_*** の追加の要望となります。

現在のところ、
Hidemaru_CheckQueueStatus
Hidemaru_GetCursorPosUnicode
Hidemaru_GetCursorPosUnicodeFromMousePos
Hidemaru_GetDllFuncCalledType
Hidemaru_GetLineTextUnicode
Hidemaru_GetSelectedTextUnicode
Hidemaru_GetTotalTextUnicode
Hidemaru_EvalMacro  (すでにマクロ実行中に文字列をマクロとして実行する)
があります。

これに加えて、現ウィンドウに新しいマクロファイルを発動するための関数をいくつ
か追加していただきたいです。


さて、現段階でも、「hidemaruプロセスに 引数付きでマクロを指定して起動すれ
ば」そのようなことはある程度可能ではありますが、
いくつか問題があります。

A) まだファイル名がついていない状態だと、とてもやりにくい
 (無題状態だと、どれが実行したいプロセスか判断が付かないため
    多分hidemaruを起動した後、ぐるぐるマクロ内でハンドル比較することになる、
考え方としてオカシイ)

B)マクロが今、新たに実行可能かどうか、事前に情報が取れていないので問題が多い
 (マクロが1つしか実行できない制限がある以上ここが重要です)

C)新たな秀丸プロセスを生成し、問い合わせしているようでは遅い。

といろいろ問題があります。


そこで以下のような関数を加えることを検討していただきたいと思います。

@ABはマクロ内実行中に実行するものではなく、
その逆でマクロ実行中ではない時にマクロを実行することを中心に据えるための関数
です。
(逆にいえば、マクロ実行中なら@はfalseを返し、AもBも必ず失敗する)


@その瞬間新たな秀丸マクロが発動可能な秀丸ステータスなのかを判定するための関
数となる、

 bool Hidemaru_IsExecutableNewMacro()

 のような関数。(boolではなく、LRESULTとかでもよし ⇐ 実行出来ない種別
など)
 
 マクロがすでに実行中なら、false, マクロが実行中でなかったとしても他の要因
で発動不可能だったとしてもfalse、
  Aの関数を実行するのに、極めて高確率で実行できるようにするため、


A現行の秀丸のメニュー「マクロ」→「マクロ実行」(をダイアログを出さずにおこ
なうよう)な関数となる、

 LRESULT Hidemaru_TryExecNewMacro(wchar_t* macfilename)

 (LRESULTには成功や失敗値。-1がマクロ実行中だったとか、-2がマクロコンパイル
エラーとか)

 @の関数で概ね弾いて、実行確率を高めて、直後に Aの関数を実行し、Aの関数
の結果をみて、
   プログラム内部で少し時間をずらしてから再度トライを試みるパターン。


B あるとファイルがとっちらからないという点で応用力が高い

 LRESULT Hidemaru_TryExecNewMacroFromString(wchar_t* macstring, wchar_t* vi
rtual_file_fullpath)

 秀丸マクロのファイルが実在しない状態で、秀丸マクロ内容を文字列で渡して新た
に実行する。
 秀丸は、まるで「macstringの内容が、virtual_file_fullpath というファイルに
秀丸マクロとして記述してあり、
 virtual_file_fullpathから実際にロードし、マクロを実行した」かのように振る
舞う。



これらがあると、
□小さなところでは
・「秀丸マクロからでしかえられないシンボルの情報や関数実行」がしたい時、
 C層dll等が「マクロが実行出来そう」というスキを見て、「一瞬だけマクロ実行」
して必要な情報の取得や処理を裏でする。
 「失敗しても失敗したということを認識出来、トライアル」可能になる。

□大きなところでは
・マクロとは、「マクロを発動させた瞬間処理するための単発時間の処理内容」が記
載されたもの、
 といったオールドタイプマクロになっていますが、
これを、いわゆる最新型エディタにあるような
 「1つのマクロは、ファイル1つの中に複数(通常3つ程度以上)のイベントハン
ドラを持ち、
  ふさわしいタイミングになればマクロ内の該当のイベントハンドラ部分実行される」
 という形にもっていけます。
 (特別なモジュールを実行している間は、ユーザー自身が定義した秀丸マクロには
ない新たなイベントハンドラをマクロと絡めることができます)



以上となります、ぜひ検討ください。

[ ]
RE:09485 秀丸本体からのexport関数の追加No.09486
秀丸担当 さん 17/07/03 16:04
 

外部からマクロを実行する場合、確かに現状で不可能ではないですが、言われて
いるような問題点があると思います。
弊社の秀丸リーダーというソフトでも似たようなことをしているのですが、マク
ロ実行は特定のマクロ登録をしているという前提にして、そのコマンド値を
WM_COMMANDで呼び出すということをしています。

あと、マクロ実行中かどうかを知るために、秀丸リーダー用にユーザーメッセー
ジがあります。(外側の枠ではなく内側のHM32CLIENTのウィンドウに送る)
#define WM_ISMACROEXECUTING (WM_USER + 167)
マクロヘルプには無いですが、将来も変わることは無いです。

イベントハンドラまで発展するかどうかはともかく、そういったことがマクロ登
録の前提などがなくても一般的にできたらいいと思います。
V8.73はそろそろ落ち着かせたいところもあるのですが、今後検討したいと思い
ます。

[ ]
RE:09486 秀丸本体からのexport関数の追加No.09487
vscode-life さん 17/07/04 11:39
 
了解しました。

ご検討のほどよろしくお願いします。


そういえば、HM32CLIENTで思い出しましたが、
(HM32CLIENTの方ではなく) hidemaruhandle(0) 相当をC層で得るのが
実はちょっと得にくいように思っているのですが、

今は以下のようにしているのですが、普通もっとサクッと
行きそうな気もするのですが何か手立てはありますか?
(マクロから渡すとかではなく)

//--------------------------------------------------- hidemaruexe_handle.h

#pragma once
#include <windows.h>
#include <string>

using namespace std;

extern HWND GetCurWndHidemaru();

// ストアアプリ版も考慮して鋳型にしておく
class HidemaruWindowHandleSearcher {

public:
 HidemaruWindowHandleSearcher(wstring strClassName);

private:
 // これはスタティックではない。デスクトップ版とアプリ版があるので
 wstring m_strClassName;
 // 秀丸ハンドル
 HWND hCurWndHidemaru;

public:
 HWND GetCurWndHidemaru();


private:
 bool IsWndHidemaru32ClassType(HWND hWnd);
 void SearchCurWndHidemaru(HWND hWnd);
};



//--------------------------------------------------- hidemaruexe_handle.cpp



#include <windows.h>

#include "hidemaruexe_handle.h"


HidemaruWindowHandleSearcher::HidemaruWindowHandleSearcher(wstring strClassN
ame) {
 this->m_strClassName = strClassName;
 this->hCurWndHidemaru = NULL;
}

HWND HidemaruWindowHandleSearcher::GetCurWndHidemaru() {
 if (!hCurWndHidemaru) {
  SearchCurWndHidemaru(GetDesktopWindow());
 }
 return this->hCurWndHidemaru;
}



bool HidemaruWindowHandleSearcher::IsWndHidemaru32ClassType(HWND hWnd) {
 wchar_t strTargetClassName[MAX_CLASS_NAME];
 ::GetClassName(hWnd, strTargetClassName, _countof(strTargetClassName));

 if (m_strClassName == strTargetClassName) {
  return true;
 }
 return false;
}

void HidemaruWindowHandleSearcher::SearchCurWndHidemaru(HWND hWnd)
{
 if (hCurWndHidemaru) { return; }

 HWND hWndParent = GetParent(hWnd);
 // 自分自身の親も指定のクラス名
 if (IsWndHidemaru32ClassType(hWndParent))
 {
  // 自分のプロセスIDと、サーチ対象のプロセスID
  DWORD pID1 = GetCurrentProcessId();
  DWORD pID2 = 0;
  GetWindowThreadProcessId(hWnd, &pID2);
  // 同じならこれだこれ
  if (pID1 == pID2) {
   hCurWndHidemaru = hWnd;
  }
 }

 // 子クラスをなめていく。子クラスはあくまでも「Hidemaru32Class系」。
 // ストア版はちょっと違うのでインスタンス変数になっている。
 HWND hWndChild = FindWindowEx(hWnd, NULL, m_strClassName.c_str(), NULL);
 while (hWndChild != NULL)
 {
  SearchCurWndHidemaru(hWndChild);
  if (hCurWndHidemaru) { break; }

  hWndChild = ::FindWindowEx(hWnd, hWndChild, m_strClassName.c_str(), NULL);
 }
}


// ★この関数でhidemarunandle(0)相当を得る。
static HWND hWnd = NULL;
HWND GetCurWndHidemaru() {
 if (!hWnd) {
  // 普通の秀丸
  HidemaruWindowHandleSearcher s1(L"Hidemaru32Class");
  hWnd = s1.GetCurWndHidemaru();
 }
 if (!hWnd) {
  // ストアアプリ版
  HidemaruWindowHandleSearcher s2(L"Hidemaru32Class_Appx");
  hWnd = s2.GetCurWndHidemaru();
 }

 return hWnd;
}


「なぜ自分でサーチする羽目になっているのだろう…」と
疑問には思っているのですが…



[ ]
RE:09487 秀丸本体からのexport関数の追加No.09488
秀丸担当 さん 17/07/04 14:00
 

マクロでは一般的にはhidemaruhandle(0)でウィンドウハンドルが得られますが、
接点が無いところから取得しようとすると、既にやられているようなことが必要
になってくると思います。
あるいは、フォーカスが秀丸エディタにあるときに実行されることがわかってい
る場合は、GetFocusやGetParentでしたほうが近道かもしれないです。

[ ]
RE:09488 秀丸本体からのexport関数の追加No.09489
vscode-life さん 17/07/05 03:29
 
何か微妙に上手くいかないことがあると思って調査してみると、
「タブモード」と「非タブモード」を切り替えた時に、

・「プロセスIDはそのままな」
・にもかかわらず、「idemaruhandle(0)」の値が変わる

ということになっているんじゃないでしょうか。

このタブモード変化等でhidemarunandle(0)の値が変わってしまうのだとすると、
C層からhidemaruhandle(0)を使うSendMessageを使うのは
結構厳しいように思えます。

hidemaruhandle(0)の値を取得する関数がhidemaru.exeにexportされている必要性が
実は高いように思えます。

[ ]
RE:09489 秀丸本体からのexport関数の追加No.09490
秀丸担当 さん 17/07/05 08:23
 

hidemaruhandle(0)の値を取得する関数はあってもいいと思います。
検討したいと思います。

タブモードの切り替えでは確かにウィンドウハンドルは変化すると思います。現
状でなんとかするとしたら、Win32 APIのIsWindow()でウィンドウハンドルが有
効かどうかを判断してから再取得などをするといいと思います。

[ ]
RE:09490 秀丸本体からのexport関数の追加No.09491
vscode-life さん 17/07/05 12:42
 
>
>hidemaruhandle(0)の値を取得する関数はあってもいいと思います。
>検討したいと思います。
>
>タブモードの切り替えでは確かにウィンドウハンドルは変化すると思います。現
>状でなんとかするとしたら、Win32 APIのIsWindow()でウィンドウハンドルが有
>効かどうかを判断してから再取得などをするといいと思います。

はい、私もそれしかないだろうなぁ…と思い、
呼ばれた際にIsWindow()がFALSEであることをきっかけに再取得するようにしました。

「秀丸エディタマクロヘルプ」の「情報取得のメッセージ」にhwndHidemaruの
取得の仕方を追記しておいたほうがよいのではなないでしょうか。

「情報取得のメッセージ」に記載している内容は、
hwndHidemaru が自然と渡ってくる「秀丸変換モジュール」利用用途が発祥なので、

それ以外の普通のdllから利用しようとすると「hwndHidemaru」の取得の仕方に躓く
可能性が高いと思います。

・非フォーカス時まで正確に考慮
・デスクトップ版とストア版を考慮

して、hwndHidemaru を取得するサンプルソースを
記載しておいた方が良いように思えます。


[ ]
RE:09491 秀丸本体からのexport関数の追加No.09492
秀丸担当 さん 17/07/05 13:52
 

「情報取得のメッセージ」はもともと確かに変換モジュールから呼ばれるための
もので、ウィンドウハンドルは事前に知っているという前提でした。
マクロからdllfuncの場合もhidemaruhandle(0)で渡すことが可能ということもあ
ります。
ほぼ接点が無いDLLから呼ばれることはあまり想定していないです。
ずっと以前はタブモードは無かったですし、最近もストアアプリ版があったりし
て、今後も変化があるとも限らないと思います。
Hidemaru_GetCurrentWindowHandleのような関数の追加を検討していますが、こ
れを追加して、これでやってもらうということでいいと思います。
外部からのマクロ実行の関数は慎重に考えたいところですが、
Hidemaru_GetCurrentWindowHandleであれば、すぐ次のβ版でできると思います。

[ ]
RE:09492 秀丸本体からのexport関数の追加No.09493
vscode-life さん 17/07/05 15:40
 
Hidemaru_GetCurrentWindowHandle の追加、ぜひお願いします。



「全く関係がないDLL」からというよりも、

http://hide.maruo.co.jp/lib/macro/hmhtmlpreview_v136.html

とかがわかりやすい一例と思うのですが、

実行時に「.macからdllにhidemaruhandle(0)を渡している」のですが、

マクロが終わっても .dll自体は実行を続けるタイプなので、
「タブモード」の切り替えをされると、
マクロ起動時に渡していた hidemaruhandle(0) は機能しないので
ファイル名の取得が出来なくなる。

といった感じが、バグがあることに気づきにくいパターンだと思います。

(逆に一瞬で実行が終わるようなdllなら、hidemaruhandle(0) 渡さなくても
 filename2 自体を渡せばいいだけなので)

[ ]
RE:09493 秀丸本体からのexport関数の追加No.09513
秀丸担当 さん 17/08/03 10:05
 

V8.73正式等で遅くなりましたが、マクロを外部から実行する方法をV8.75で検討
しています。
エクスポート関数をやろう思ったのですが、やっぱりSendMessage等で処理する
メッセージの方式にしようと思います。
メインスレッドでマクロ実行中以外でも関数を呼べるような状態では何でもあり
なので、結局のところどちらでもいいのですが、メインスレッドで実行できる状
態というのはかなり限定的だと思います。
呼ばれる側タイミングとしては、コマンド実行と同じようにメッセージが処理さ
れる段階のほうが都合がいいです。
メッセージであれば別スレッドか別プロセス(この場合VirtualAllocExが必要か
も)でもできるようになると思います。

[ ]
RE:09513 秀丸本体からのexport関数の追加No.09514
vscode-life さん 17/08/03 12:29
 
秀丸担当さん、ご検討のほどありがとうございます。

「登録済みマクロ」では、以前よりSendMessageで実行出来ていたので、
この既存の「@登録番号→Aマクロファイル名→B実行」
という流れの、
Aと合流するような形で実装して頂くのが、
エラーも出にくく手堅いと思います。

(おそらくは、秀丸担当さんの投稿も、そのような旨に近いのかな?)

[ ]
RE:09514 秀丸本体からのexport関数の追加No.09515
vscode-life さん 17/08/03 14:11
 
VirtualAllocEx必要ありますか?

送信側からの有意な情報が、マクロファイル名ぐらいしかないのであれば、
COPYDATASTRUCT にファイルのポインタとサイズ名乗せて送るぐらいで
いけたりしませんか?

[ ]
RE:09515 秀丸本体からのexport関数の追加No.09516
秀丸担当 さん 17/08/03 14:53
 

他のプロセスから呼び出されることを主眼にするならば、WM_COPYDATAのほうが
簡潔でいいと思います。

一応自身のプロセスからが主な目的のつもりで、lParamで単なるポインタ渡しが
簡潔でいいと思いました。
その場合、もし他のプロセスから呼ぶとしても、煩雑ではあるものの、
VirtualAllocExで不可能ではないことになると思います。

あと、wParamも使って、endmacroのパラメータで結果の文字列を受け取ることが
できるようにしようとしています。双方向となると、WM_COPYDATAでは不足とい
うこともあります。
もし必要であれば双方向ではないもののWM_COPYDATAでもどちらでもできるよう
にしてもいいと思います。

[ ]