はじめに
お約束をお読みになった上で、イカよろしくおねがいいたします。IkaLogさんのja_FAQで、
ユーザからの報告によるとアマレコTVのウインドウ枠表示モード/非表示モード(画像のみ)でメッセージを送信すべきウインドウハンドルが異なるとのことです。現状、同梱している AutoIT スクリプトはそのあたりをうまくハンドルしていません。どちらでも動くように修正できたら是非 Pull Request をお願いします。
とあって、AutoITの関数表を見てる時に見つけたサンプルコードで出来るんじゃないかと思ったのでアプローチしてみました。
結局は、知識不足による勘違いで特定の条件では動作しないロジックでした。
最後にコードを掲載しておりますが、参考程度にご覧になってください。
何かありましたらご指摘いただけると本当にありがたいです。
作成者はコンピュータ関係の職業ではないので、用語の使い方、コードの書き方に変な所が沢山あるかもしれませんが許してください。
結論から
IkaLogに同梱されているControlAmarecTV.au3で対応出来ていない点は
AmarecTVがフレーム無しウインドの時はハンドルが変わるけど、その変わった値が取れていないの1点だけです。
それ以外は問題無いので、フレーム無しの時だけハンドルをすり替えるという手法を試しました。
そのロジックはサンプルコードのコピペ改変なのですが、表示されているウインド名の中から AmaRecTVに関係するものを探して、その値を取るという方法でした。
なので、こんなのも AmaRecTVと認識してしまいます。
普通の使い方ではこんなこと無いかも知れませんが、このままで既存の処理に組み込むのは落とし穴がぽっかり空いた害がある変更のように思います。
その辺りを含めて、イカよろしくお願い致します。
(ここから公開時の記事になります)
録画開始/終了のホットキーのグローバルフックを外した設定のAmaRecTV 3.10を準備
これに対して、コマンドプロンプトから動作テストを行いました。
(画像はクリックで拡大されます)
恥ずかしい勘違いで無ければ、AmaRecTVのフレーム無し/標準両方のウインドウハンドルを取得してアクティブにしてキーを送る事に成功したっぽいです。
対応してみた結果、AmaRecTV+IkaLogで自動録画を行うのなら、
・AmaRecTVは標準のウインドウの状態で使う
・AmaRecTVのホットキーでグローバルフックを有効にする
その上で、IkaLog同梱のControlAmarecTV.au3を使うのが一番良いような気がしています。
※他の使い方があまり想像出来ないので、あくまでじぶんが今現在使っている環境での印象です。
IkaLogに同梱されているControlAmarecTV.au3で対応出来ていない点は
AmarecTVがフレーム無しウインドの時はハンドルが変わるけど、その変わった値が取れていないの1点だけです。
それ以外は問題無いので、フレーム無しの時だけハンドルをすり替えるという手法を試しました。
そのロジックはサンプルコードのコピペ改変なのですが、表示されているウインド名の中から AmaRecTVに関係するものを探して、その値を取るという方法でした。
なので、こんなのも AmaRecTVと認識してしまいます。
普通の使い方ではこんなこと無いかも知れませんが、このままで既存の処理に組み込むのは落とし穴がぽっかり空いた害がある変更のように思います。
その辺りを含めて、イカよろしくお願い致します。
(ここから公開時の記事になります)
録画開始/終了のホットキーのグローバルフックを外した設定のAmaRecTV 3.10を準備
AmarecTVがフレーム無しウインドの時はハンドルが変わるけど、その変わった値が取れていないの1点だけです。
それ以外は問題無いので、フレーム無しの時だけハンドルをすり替えるという手法を試しました。
そのロジックはサンプルコードのコピペ改変なのですが、表示されているウインド名の中から AmaRecTVに関係するものを探して、その値を取るという方法でした。
なので、こんなのも AmaRecTVと認識してしまいます。
普通の使い方ではこんなこと無いかも知れませんが、このままで既存の処理に組み込むのは落とし穴がぽっかり空いた害がある変更のように思います。
その辺りを含めて、イカよろしくお願い致します。
(ここから公開時の記事になります)
録画開始/終了のホットキーのグローバルフックを外した設定のAmaRecTV 3.10を準備
これに対して、コマンドプロンプトから動作テストを行いました。
(画像はクリックで拡大されます)
恥ずかしい勘違いで無ければ、AmaRecTVのフレーム無し/標準両方のウインドウハンドルを取得してアクティブにしてキーを送る事に成功したっぽいです。
対応してみた結果、AmaRecTV+IkaLogで自動録画を行うのなら、
・AmaRecTVは標準のウインドウの状態で使う
・AmaRecTVのホットキーでグローバルフックを有効にする
その上で、IkaLog同梱のControlAmarecTV.au3を使うのが一番良いような気がしています。
※他の使い方があまり想像出来ないので、あくまでじぶんが今現在使っている環境での印象です。それは何故か
テスト用に、AmaRecTVのハンドル情報を表示する処理を追加してみました。AmaRecTV標準のウインドウで取得できる情報
(画像はクリックで拡大されます)
AmaRecTVフレーム無しウインドウで取得できる情報
(画像はクリックで拡大されます)
フレーム無しウインドウだと、(取得方法を変えないといけないのかもしれませんが…)画面下部の現在の状態を表す文字列が取得できません。
ControlAmarecTV.au3 の内部で、この情報を判別して録画中以外にならstopを無視するというロジックが入っています。
(録画停止のつもりなのに録画が開始されるといった事を防ぐためだと思います。)
Local $text = ControlGetText($hWnd, "", "[CLASS:msctls_statusbar32]")
Local $inRecording = StringInStr($text, '録画中...') > 0
既存の処理+追加した処理でハンドル値を比較して、違えばすり替えるという方法にしてみたのですが、追加したロジックに不具合が出る可能性があったので、結局ボツになります。
実験に使用したコードの使い方
1.AmaRecTVを起動してください。2.スクリプトを、オプション無しで起動してください。
3.現在の設定内容の確認メッセージが表示されるので、「いいえ」を選択してください。
すると AmaRecTVのウインドウハンドル情報のメッセージボックスが表示されると思います。
録画動作のテスト方法
1.スクリプトの内容を自分の環境や好みに合わせる
2.コマンドプロンプトを開いて、スクリプトをドラッグドロップ
オプションに start を付けて実行すれば、録画開始のテスト
オプションに stop を付けて実行すれば、録画停止のテストになります。
実験に使用したコード
コードを表示するパーツのせいか、コードが変に化けているみたいなので、テキストファイルを用意しました。
(こちらをクリックしてください。)
※コードを表示するパーツをコピペで導入してるから、取り方が分からないのです…
; ; ; IkaLog ; ====== ; Copyright (C) 2015 Takeshi HASEGAWA ; ; Licensed under the Apache License, Version 2.0 (the 'License'); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an 'AS IS' BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; ; Start and stop recording using Open Broadcaster Software(OBS). ; ; To Start Recording: ; ControlAmarecTV.au3 start ; ; To Stop Recording: ; ControlAmarecTV.au3 stop ; ; To Reanem the recording: ; If you want to rename the recording to a specific filename, ; Specifcy the filename as environment variables ; IKALOG_MP4_DESTDIR and IKALOG_MP4_DESTNAME. ; ; Though this script will sleep seconds so that work on ; a specific environment. The behavior is subject to change. ; #include#include ; ;注意! ;コマンドプロンプトからの動作確認は行っていますが、IkaLogと連動させての確認はまだ行っていません。 ;もし利用される場合は、事前に動作確認を行ってタイミングの調整を行ってください。 ;自分の好みに合わせて値を設定してください。 ;Sendキーの詳しい書き方については https://www.autoitscript.com/autoit3/docs/appendix/SendKeys.htm Global $SendStartkeyValue = "^z" ;送信する録画開始キー ファンクションキーは、 "{F8} "みたいに書きます。 Global $SendStopkeyValue = "^x" ;送信する録画終了キー Global $StartSleepSec = 0 ;録画開始待機時間(秒) Global $StopSleepSec = 0 ;録画終了待機時間(秒) Global $RenameSleepSec = 10 ;リネーム処理待機時間(秒) リネーム機能は使ってないので、値が正しいかわかりません。 Global $IniFileName = "ControlAmarecTV.exe" ;無視してください。 ;ウインドハンドル取得のサンプル動作用 Global $AmaCheckStr1 = "AmaRecTV" ;AmaRecTVハンドル取得用文字列(多分変更しないほうがいいです) Global $AmaCheckStr2 = ".avi" ;AmaRecTVハンドル取得用文字列(多分変更しないほうがいいです) Global $AmaCheckStr3 = "3.10" ;Ver 4.01出ましたが、SSE4.2が無いので動かず…4.01になる? Func RenameFile($source) Local $dest = EnvGet('IKALOG_MP4_DESTNAME') $dest = StringReplace($dest, "/", "\") If $dest = '' Then Return False EndIf ; IkaLog assumes mp4 as video file extension, but AmarecTV uses avi. If StringRight($dest, 4) = ".mp4" Then $dest = StringReplace($dest, ".mp4", ".avi", -1) EndIf FileMove($source, $dest, $FC_OVERWRITE) EndFunc Func FindRecentRecording() ; Replace all slashes to backslashes. ; $directory also needs a backslash at its end. $directory = StringReplace($directory, "/", "\") If StringRight($directory, 1) <> "\" Then $directory = $directory & "\" EndIf Local $hSearch = FileFindFirstFile($directory & "*.avi*") If $hSearch = -1 Then MsgBox(0, "Error", "Could not find any candinates in " & $directory & " (path 1)", 10) Return False EndIf Local $latest_file = '' Local $latest_timestamp = '' While True Local $file = FileFindNextFile($hSearch) If @error Then ExitLoop Local $timestamp = FileGetTime($directory & $file, $FT_MODIFIED, $FT_STRING) If StringCompare($timestamp, $latest_timestamp) > 0 Then $latest_file = $directory & $file $latest_timestamp = $timestamp EndIf WEnd FileClose($hSearch) If $latest_file = '' Then MsgBox(0, "Error", "Could not find any candinates in " & $directory & " (path 2)", 10) Return False EndIf Return $latest_file EndFunc Func ControlAmarecTV($stop) Local $hWnd = WinWait('[CLASS:AmaRecTV; INSTANCE:2]', '', 1) If $hWnd = 0 Then MsgBox(0, "Error", "Could not find AmarecTV") Return False EndIf Local $text = ControlGetText($hWnd, "", "[CLASS:msctls_statusbar32]") Local $inRecording = StringInStr($text, '録画中...') > 0 ;問題は、フレーム無し時のウインドウハンドル値が異なる事だけだと気付く Local $hWndDsp = $hWnd ;テスト表示用 処理的には不要 Local $var = AmarecTVWinHandleValue() If ($var[0] <> "") And ($hWnd <> $var[1]) Then $hWnd = $var[1] EndIf Local $click = False If $inRecording and $stop Then ;Stop Recording. $click = True ElseIf (Not $inRecording) and (Not $stop) Then ; Start Recording. $click = True EndIf If $click Then If $stop Then ; 録画終了待ち時間 Sleep(1000 * $StopSleepSec) Else ; 録画開始待ち時間 Sleep(1000 * $StartSleepSec) EndIf WinActivate($hWnd) WinWaitActive($hWnd, "", 1) If $stop Then ; 録画停止キー送る Send($SendStopkeyValue) Else ; 録画開始キー送る Send($SendStartkeyValue) EndIf If $stop Then Local $directory = EnvGet('IKALOG_MP4_DESTDIR') If (StringLen($directory) <> 0) Then Sleep(1000 * $RenameSleepSec) Local $file = FindRecentRecording() RenameFile($file) EndIf EndIf EndIf MsgBox(0, $var[0] , $hWndDsp & @CRLF & $hWnd & @CRLF & $var[1] , 5) ;テスト表示 EndFunc ;AmarecTVのハンドルとウインドタイトルを取得する(サンプルコードをそのまま流用) ;タイトル文字列に依存しているので、対象に含まれる文字を使ったファイル名を開いたメモ帳なんかがひっかかる ;http://open-shelf.appspot.com/AutoIt3.3.6.1j/html/functions/WinList.htm Func AmarecTVWinHandleValue() Local $var = WinList() Local $retValue[2] $retValue[0] = "" ;ウインドウタイトル $retValue[1] = 0 ;ウインドウハンドル For $i = 1 to $var[0][0] ; 可視で名前のあるウィンドウのみ If $var[$i][0] <> "" AND IsVisible($var[$i][1]) Then ;MsgBox(64, "Details", "Title=" & $var[$i][0] & @LF & "Handle=" & $var[$i][1], 10) ;起動直後 If ($var[$i][0] = $AmaCheckStr1) Then ;取れるのは、AmaRecTVのみ $retValue[0] = $var[$i][0] $retValue[1] = $var[$i][1] Return $retValue EndIf ;AmaRecTVを探す If (StringInStr($var[$i][0], $AmaCheckStr1)) Then ;AmaRecTVが含まれる If (StringInStr($var[$i][0], $AmaCheckStr2)) Then ;一度でも録画した後の状態だと.aviが含まれる $retValue[0] = $var[$i][0] $retValue[1] = $var[$i][1] Return $retValue EndIf If (StringInStr($var[$i][0], $AmaCheckStr3)) Then ;録画直後~一度も録画していない状態だと3.10が含まれる $retValue[0] = $var[$i][0] $retValue[1] = $var[$i][1] Return $retValue EndIf EndIf EndIf Next Return $retValue EndFunc Func IsVisible($handle) If BitAnd( WinGetState($handle), 2 ) Then Return 1 Else Return 0 EndIf EndFunc ;AmarecTVの枠表示の状態を確認 Func AmarecTVHandleMonitor() Local $var = AmarecTVWinHandleValue() Local $title = $var[0] Local $hWnd = $var[1] If $hWnd = 0 Then MsgBox(0, "取得できた情報", "AmarecTV いないっぽい。") Return False EndIf Local $text = ControlGetText($hWnd, "", "[CLASS:msctls_statusbar32]") If ($text = "") Then Local $ident = "枠なしっぽい?" Else $ident = "□枠ありっぽい!□" EndIf Local $hCnd = ControlGetHandle($hWnd, "", "[CLASS:msctls_statusbar32]") Local $hWndIka = WinWait('[CLASS:AmaRecTV; INSTANCE:2]', '', 1) ;オリジナルのハンドル取得 Local $textIka = ControlGetText($hWnd, "", "[CLASS:msctls_statusbar32]") ;オリジナルの文字列取得 $msg = StringFormat("ウインドウタイトル: %s%s", $title, @CRLF) $msg = StringFormat("%sオリジナルのハンドル: %s%s", $msg, $hWndIka, @CRLF) $msg = StringFormat("%sサンプルのハンドル : %s%s", $msg, $hWnd, @CRLF) $msg = StringFormat("%sオリジナルで取れる値: %s%s", $msg, $textIka, @CRLF) $msg = StringFormat("%sウインド下部の文字列: %s%s", $msg, $text, @CRLF) $msg = StringFormat("%sウインド下部の文字列を表示しているコントロールのハンドル: %s%s", $msg, $hCnd, @CRLF) $msg = StringFormat("%s枠の判定: %s", $msg, $ident) MsgBox(0, "取得できた情報", $msg) EndFunc ;main ;スクリプトの設置先を取得(無視してください) $IniFileName = StringFormat("%s", @ScriptFullPath) ;オプション無しで起動した時は、使い方と現在のiniの値を表示する。 if ($CmdLine[0] = 0) Then Local $title = "起動オプションが必要です" Local $msg = StringFormat("%s%s", "--- 使い方---", @CRLF) $msg = StringFormat("%s%s%s%s%s",$msg, "録画開始:", @ScriptFullPath, " start", @CRLF) $msg = StringFormat("%s%s%s%s", $msg, "録画終了:", @ScriptFullPath, " stop" & @CRLF & @CRLF) $msg = StringFormat("%s%s%s", $msg, "--- 現在の設定 --- ", @CRLF) $msg = StringFormat("%s%s%s%s", $msg, "スクリプトの設置パス: ", $IniFileName, @CRLF) $msg = StringFormat("%s%s%s%s", $msg, "録画開始キー: ", $SendStartkeyValue, @CRLF) $msg = StringFormat("%s%s%s%s", $msg, "録画終了キー: ", $SendStopkeyValue, @CRLF) $msg = StringFormat("%s%s%s%s", $msg, "録画開始待ち秒: ", $StartSleepSec, @CRLF) $msg = StringFormat("%s%s%s%s", $msg, "録画終了待ち秒: ", $StopSleepSec, @CRLF) $msg = StringFormat("%s%s%s%s", $msg, "リネーム待ち秒: ", $RenameSleepSec, @CRLF) $msg = StringFormat("%s%s", $msg, @CRLF) $msg = StringFormat("%s%s%s", $msg, "[はい]を押すと何もせずこのまま終了します。", @CRLF) $msg = StringFormat("%s%s%s", $msg, "[いいえ]を押すと表示中のウインドからAmaRecTVを探す処理を実行します。", @CRLF) If (MsgBox(4+64, $title, $msg, 60) = 7) Then AmarecTVHandleMonitor() EndIf Else $stop = StringCompare($CmdLine[1], 'stop') == 0 ControlAmarecTV($stop) EndIf
最後になりましたが
IkaLog CUI版を動かすのに調べてる時に、ja_FAQで紹介して頂いているのに気が付きました。
稚拙な文章でお恥ずかしいですが、ありがとうございます。
0 件のコメント:
コメントを投稿