スクリーンショットを取得したい - Kaneko - 05-29-2013
Curlのアプリで、エラーが発生した際にスクリーンショットを送ってもらうことが、時々あるんですが、
これをCurlのアプリ側でハンドリングすることはできないでしょうか?
①スクリーンショットを取得する(クリップボードでも、メモリ上でも、ファイルでも)
②特定のフォルダに吐き出す
の処理ができれば嬉しいんですが、
ActiveXで出来るのか?とも思ったんですが、ActiveXの情報の集め方がよくわからず、
苦戦しています。
よろしくお願いします。
RE: スクリーンショットを取得したい - dyoshida - 05-31-2013
Curlアプリのエラー状況のスクリーンショットに使えるか怪しい感もありますが
試しにCurlで保存するコードを書いてみました。
Code: || CurlのグラフィックをPNG形式のファイルに保存するプロシージャ
{define-proc {save-root-graphic g:Graphic}:void
|| GraphicからPixmapを生成
def pm = {Graphic-to-Pixmap g}
|| ImageDataを生成してPixmapを格納
let img:ImageData = {ImageData}
{img.pixmaps.append pm}
|| ファイル保存先のダイアログを表示
{let file-url:#Url =
{choose-file
style = FileDialogStyle.save-as,
title="Save screen shot",
filters={{Array-of FileDialogFilter}
{FileDialogFilter
"PNG",
{new
{Array-of FileDialogTypeFilter},
{FileDialogTypeFilter "png"}
}
}
}
}
}
|| ImageDataをPNG形式で指定ファイルパスへ保存
{if-non-null file-url then
{img.save-to-url file-url, "image/png"}
{popup-message "保存しました"}
}
}
|| スクリーンショットを取る領域の名前定義
{def main-box-name = "main-box"}
|| 保存ボタン押下イベント
{def on-save-button-event:EventHandler =
{on Action at b:CommandButton do
|| ボタンから親をたどってスクリーンショットを取る領域のグラフィックを取得
let grp:Graphic = b
{while grp.parent != null do
set grp = grp.parent
{if grp.name == main-box-name then
{break}
}
}
|| グラフィックを保存
{save-root-graphic grp}
}
}
|| 画面表示
{value
{VBox name = main-box-name,
halign="center",
margin=2mm,
{bold このアプリのスクリーンショットを保存},
{Fill height = 2mm},
{CommandButton
label="スクリーンショット保存",
on-save-button-event
}
}
}
画面がリフレッシュされると直ってしまうエラーの場合は上記の方法だと駄目かもしれないので、
その場合はスクリーンショットを取るActiveXコンポーネントを使った方がよいかもしれないですね。
Windwos標準でもっているActiveX だと、WScript.Shell が使えそうなのですが、これで
OSにALT + PrintScreenキーイベントを送ればクリップボードにスクリーンショットをとれるかとも
思ったのですが、情報抜き取りの悪用を避けるためかPrintScreenキー送信は不可でした・・・
他の方法も探してみます
RE: スクリーンショットを取得したい - Kaneko - 05-31-2013
試してみました。
かなりいい!ですが、POPUPだったり、Viewだったりで複数のオブジェクトが表示されている場合があるので、
あと一歩!(勝手に、評価してすいません)という印象でした。
たしかにPrintScreenは渡せないみたいですね。
ちょっと調べた範囲では、Excelを使った方法があるみたいですが
http://d.hatena.ne.jp/language_and_engineering/20081121/1227203100
これと同等のことをCurlからやる方法がイマイチわからず。。。
CurlとActiveXを駆使すればなんでもできてしまいそうな反面、
ActiveXとかWindowsの知識がシッカリしていないので、実装が難しいです。。。
上のコードをCurlに変換して頂けませんか!
期待してます。。。
RE: スクリーンショットを取得したい - dyoshida - 05-31-2013
ご指摘の通り、エラーが発生したときの状況把握という目的だとイマイチなのですよね・・・
Curlだけで書いているのでプラットフォーム依存がないというメリットはあるのですが
>ちょっと調べた範囲では、Excelを使った方法があるみたいですが
Excelマクロの機能をつかってWin32APIのkeybd_event()でキーイベントを送信・・・
なにかいろいろとレガシーな機能やAPIを使った方法のようなので、OSやExcelの
バージョンによっては動かなくなりそうな裏技っぽい気もしますが、書いてみました。
とりあえず、Windows7 pro(32bit) +Excel2007の環境ではこれで動作しました。
Code: {import * from CURL.GRAPHICS.ACTIVEX}
{import * from CURL.DESKTOP.CLIPBOARD}
|| WindowsへALT+PrintScreenキー押下イベントを送るプロシージャ
{define-proc {send-alt-print-screen-key}:void
def obj-excel =
{ActiveXObject
ProgId = "Excel.Application"
}
{obj-excel.ExecuteExcel4Macro( "CALL(\"user32\",\"keybd_event\",\"JJJJJ\",18, 0, 1,0)" )} || ALT press
{obj-excel.ExecuteExcel4Macro( "CALL(\"user32\",\"keybd_event\",\"JJJJJ\",44, 0, 1,0)" )} || PrintScreen press
{obj-excel.ExecuteExcel4Macro( "CALL(\"user32\",\"keybd_event\",\"JJJJJ\",44, 0, 3,0)" )} || PrintScreen release
{obj-excel.ExecuteExcel4Macro( "CALL(\"user32\",\"keybd_event\",\"JJJJJ\",18, 0, 3,0)" )} || ALT release
}
|| クリップボードの画像をPNG形式のファイルに保存するプロシージャ
{define-proc {save-clip-board}:void
|| クリップボードを取得
let cb:Clipboard = {Clipboard.get-system-clipboard}
def cb-obj = {cb.get-object}
|| クリップボードから取得したPixmapをImageDataへ格納
|| Todo クリップボードから取得したオブジェクトがpixmapかチェックが必要
let img:ImageData = {ImageData}
{img.pixmaps.append (cb-obj asa Pixmap)}
|| ファイル保存先のダイアログを表示
{let file-url:#Url =
{choose-file
style = FileDialogStyle.save-as,
title="Save screen shot",
filters={{Array-of FileDialogFilter}
{FileDialogFilter
"PNG",
{new
{Array-of FileDialogTypeFilter},
{FileDialogTypeFilter "png"}
}
}
}
}
}
|| ImageDataをPNG形式で指定ファイルパスへ保存
{if-non-null file-url then
{img.save-to-url file-url, "image/png"}
{popup-message "保存しました"}
}
}
|| 保存ボタン押下イベント
{def on-save-button-event:EventHandler =
{on Action at b:CommandButton do
|| WindowsへALT+PrintScreenキー押下イベントを送る
{send-alt-print-screen-key}
|| クリップボードに貼られたスクリーンショットを保存する処理をイベントキューへ積む
|| Todo
|| PrintScreenキーによるスクリーンショットのクリップボードへの貼り付けの完了待ちが
|| イベントキューへ積むだけで取れるのか不明なので念のため1s待って処理
{after 1s do
{save-clip-board}
}
}
}
|| 画面表示
{value
{View
visibility = "normal",
{VBox
halign="center",
margin=2mm,
{bold このアプリのスクリーンショットを保存},
{Fill height = 2mm},
{CommandButton
label="スクリーンショット保存",
on-save-button-event
}
},
{on WindowClose do
{exit}
}
}
}
アクティブウィンドウをキャプチャするために、ALTキーのon/offを追加していますが、
ディスクトップ全体をキャプチャしたい場合は"ALT press"/ ”ALT release”の
コメントが付いている行を削ってください。
とりあえず動きますという程度のコードですが、Curlでもこの技つかえましたね、
ということでご参考まで。
|