C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: 小ウインドウを含む画面キャプチャーの方法


(過去ログ 178 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■101948 / inTopicNo.1)  小ウインドウを含む画面キャプチャーの方法
  
□投稿者/ まき (1回)-(2023/05/18(Thu) 14:57:48)

分類:[C#] 

Visual Studio/C#

Windowsのデスクトップもしくはウインドウを指定して画面をミラーリングするアプリケーションを作成しています。(TeamsやZoomの画面共有機能のようなイメージ)

ウインドウを指定する場合、ウインドウハンドルを取得してそこから画面を取得しているのですが、そうすると対象ウインドウ内でプルダウンメニュー等を開いた状態にしても
取得する画像にはプルダウンメニューが含まれていません。(例:Excelのフォント選択など)
どうやらプルダウンメニューは別ウィンドウになっているらしく、親ウインドウのハンドルから画面を取得してもプルダウンメニューを含む画像は取得できないようです。

プルダウンメニュー等も含んだウインドウ画像をキャプチャーする方法はないでしょうか?
現在はPrintWindowのAPIでキャプチャーしていますが、このAPIのオプション等でも対応できませんでした。
他のこのキャプチャー用APIならできるよとか、PrintWindowをこう使うとできるよとか、アドバイスいただけると助かります。

※デスクトップの全体画像からウインドウの矩形部分を切り抜くという方法はありますが、こうすると指定ウインドウに他ウインドウがかぶさっていた場合に他ウインドウを含んだ画像になってしまうためNGです。
引用返信 編集キー/
■101949 / inTopicNo.2)  Re[1]: 小ウインドウを含む画面キャプチャーの方法
□投稿者/ 魔界の仮面弁士 (3642回)-(2023/05/18(Thu) 15:20:40)
No101948 (まき さん) に返信
> どうやらプルダウンメニューは別ウィンドウになっているらしく、親ウインドウのハンドルから画面を取得してもプルダウンメニューを含む画像は取得できないようです。
プルダウンやポップアップは親ウィンドウに対する子ウィンドウにはなっていません。
それ自体が単独のトップレベルウィンドウです。

それ自体はウィンドウハンドルを持っているので、プルダウンのみをキャプチャーすることは可能ですが、
別ウィンドウがアクティブになると閉じられてしまうため、フォーカス制御にも気を使う必要があります。


> プルダウンメニュー等も含んだウインドウ画像をキャプチャーする方法はないでしょうか?
プルダウンを表示させたまま親ウィンドウをキャプチャーすれば撮影は出来ますが、
親よりも外側の座標にかかることもある点がネックになります。


> ※デスクトップの全体画像からウインドウの矩形部分を切り抜くという方法はありますが、
矩形とは限りませんよね。親ウィンドウの外側にはみ出して表示されることもあるので、
「親ウィンドウの矩形とプルダウン ウィンドウの矩形を結合した領域」を切り出す必要があるかと。
https://vb-user.net/junk/replySamples/2023.05.18.15.11/notepad.png


> こうすると指定ウインドウに他ウインドウがかぶさっていた場合に他ウインドウを含んだ画像になってしまうためNGです。
であれば、先にプルダウン部分だけを単独撮影し、その後に親ウィンドウのみを撮影して重ね合わせるとか。


WinSnap なども、アプリケーション ウィンドウに関連付けられたすべてのウィンドウ
(ドロップダウン メニューやポップアップ)を一緒にキャプチャし、
それらを同じスクリーンショットに結合するという実装になっていたかと。
引用返信 編集キー/
■101950 / inTopicNo.3)  Re[2]: 小ウインドウを含む画面キャプチャーの方法
□投稿者/ まき (2回)-(2023/05/18(Thu) 17:50:16)
No101949 (魔界の仮面弁士 さん) に返信
返信ありがとうございます!
こんなに早く返信いただけるとは思っていませんでした!

>>プルダウンメニュー等も含んだウインドウ画像をキャプチャーする方法はないでしょうか?
> プルダウンを表示させたまま親ウィンドウをキャプチャーすれば撮影は出来ますが、
> 親よりも外側の座標にかかることもある点がネックになります。
この「撮影出来る」というのはウインドウハンドルから直接画像を取得する方法ではなく、領域指定で切り抜けばということでしょうか?
だとすると他ウインドウが重なった場合の問題があるため厳しいです。。

他ウインドウが重なっていた場合でも自ウインドウのみの画像が取得でき、かつ自ウインドウが表示しているプルダウンも重畳された画像が取得できる、
そんな方法がないかと模索しております。。

自前で重ね合わせて画像を生成する方法をご提案いただいたのですが、一発スクリーンショットを取るだけではなく映像配信のため10fps程度でキャプチャーし続けるため、
なるべく画像編集はしない方向でやりたいのです。

こんな都合のよいAPIはないのかしら。。Zoomとかどうやってんだろう?
引用返信 編集キー/
■101951 / inTopicNo.4)  Re[3]: 小ウインドウを含む画面キャプチャーの方法
□投稿者/ 魔界の仮面弁士 (3643回)-(2023/05/18(Thu) 20:16:35)
No101950 (まき さん) に返信
> なるべく画像編集はしない方向でやりたいのです。
なるほど。


> この「撮影出来る」というのはウインドウハンドルから直接画像を取得する方法ではなく、領域指定で切り抜けばということでしょうか?
いえ。メイン 画面のウィンドウハンドルを指定して撮影するのではなく、
そこから呼ばれたドロップダウンメニューのウィンドウハンドルを指定して撮影するという意図でした。

とはいえ、ドロップダウンの大きさや Z-Order が得られないと現実的ではないか…。

private void timer1_Tick(object sender, EventArgs e)
{
  timer1.Stop();
  var hwnd = WindowFromPoint(Cursor.Position);

  //GetWindowRect(hwnd, out Rectangle rect);
  DwmGetWindowAttribute(hwnd, DwmWindowAttribute.DWMWA_EXTENDED_FRAME_BOUNDS, out Rectangle rect, Marshal.SizeOf<Rectangle>());

  textBox1.Text = $"{rect}";
  var bmp = new Bitmap(rect.Width, rect.Height);
  using (var g = Graphics.FromImage(bmp))
  {
    var hdc = g.GetHdc();
    PrintWindow(hwnd, hdc, PW_RENDERFULLCONTENT);
    g.ReleaseHdc(hdc);
  }
  pictureBox1.Image?.Dispose();
  pictureBox1.Image = bmp;
  Clipboard.Clear();
  Clipboard.SetImage(bmp);
}
引用返信 編集キー/
■101952 / inTopicNo.5)  Re[3]: 小ウインドウを含む画面キャプチャーの方法
□投稿者/ 魔界の仮面弁士 (3644回)-(2023/05/18(Thu) 20:29:51)
No101950 (まき さん) に返信
> かつ自ウインドウが表示しているプルダウンも重畳された画像が取得できる、
タスクバーのサムネイル表示機能でも、プルダウンは含まれないんですよね…。


> 映像配信のため10fps程度でキャプチャーし続ける
その手の目的だと、Windows.Graphics.Capture ってのもありますね。
でもこれのウィンドウ指定時にも、プルダウンメニューは含まれなかったかも。
https://learn.microsoft.com/ja-jp/windows/uwp/audio-video-camera/screen-capture
https://learn.microsoft.com/ja-jp/windows/uwp/audio-video-camera/screen-capture-video
引用返信 編集キー/
■101953 / inTopicNo.6)  Re[4]: 小ウインドウを含む画面キャプチャーの方法
□投稿者/ まき (3回)-(2023/05/19(Fri) 09:41:55)
No101952 (魔界の仮面弁士 さん) に返信
> ■No101950 (まき さん) に返信
>>かつ自ウインドウが表示しているプルダウンも重畳された画像が取得できる、
> タスクバーのサムネイル表示機能でも、プルダウンは含まれないんですよね…。
ホントだ!
ここは用途的にこれで問題ないってことなんですかね。

>>映像配信のため10fps程度でキャプチャーし続ける
> その手の目的だと、Windows.Graphics.Capture ってのもありますね。
> でもこれのウィンドウ指定時にも、プルダウンメニューは含まれなかったかも。
> https://learn.microsoft.com/ja-jp/windows/uwp/audio-video-camera/screen-capture
> https://learn.microsoft.com/ja-jp/windows/uwp/audio-video-camera/screen-capture-video
情報ありがとうございます!確認してみます!

指定ウインドウがアクティブなときは切り取り(アクティブなときは基本的に最前面なので切り取りでも問題ない)、非アクティブなときはハンドル経由(非アクティブのときはプルダウンは非表示になるからハンドル経由でも問題ない)、と
動的に切り替えることで実現はできそうなのですが、筋が良いとは言えないんですよね。。
引用返信 編集キー/
■101954 / inTopicNo.7)  Re[5]: 小ウインドウを含む画面キャプチャーの方法
□投稿者/ 魔界の仮面弁士 (3645回)-(2023/05/19(Fri) 11:43:39)
No101953 (まき さん) に返信
> 指定ウインドウがアクティブなときは切り取り(アクティブなときは基本的に最前面なので切り取りでも問題ない)、
> 非アクティブなときはハンドル経由(非アクティブのときはプルダウンは非表示になるからハンドル経由でも問題ない)、と

モニター全体のキャプチャーと違って、ウィンドウ指定で撮影する場合、
別ウィンドウに対する追跡が問題になりそうですね。
配信結果に被せる領域や背景をどのように扱うのか。

子ウィンドウが発生した場合、子ウィンドウだけを撮影するのか否か。
子ウィンドウの出現をどのように検出するか。
プルダウンやポップアップがクライアント領域外に出た場合、どうするのか。
(プルダウンを無視 or プルダウンのみ撮影 or プルダウンを含めた合成領域を撮影)
https://vb-user.net/junk/replySamples/2023.05.19.11.10/Image1.png

非矩形のウィンドウ(リージョン指定や透過ウィンドウ)や、
背景合成が必要なウィンドウ(半透明レイヤード ウィンドウ、Aero Glass 適用時など)はどうあるべきか。
(透過度アルファ値を維持して取得したい or 背景合成結果を見えているまま撮影するだけで良いなど)
https://vb-user.net/junk/replySamples/2023.05.19.11.10/Image2.png

(Zoom でアプリ指定の画面共有したときって、この辺の動作ってどのように表示される仕様だったっけ…)
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -