はじめに
Windows には、ウィンドウを画面キャプチャから外す API があります。これを使うと、本人の画面には普通に表示したまま、画面共有・録画・スクリーンショットには映らないようにできます。
WPF で試してみたので紹介します。
使う API
user32.dll の SetWindowDisplayAffinity です。ウィンドウハンドルと、次のどれかの値を渡します。
| 値 | 動き |
|---|---|
WDA_NONE(0x00) |
普通に映る |
WDA_MONITOR(0x01) |
キャプチャでは黒い四角で映る |
WDA_EXCLUDEFROMCAPTURE(0x11) |
キャプチャに映らない。ウィンドウが無いように見える |
WDA_EXCLUDEFROMCAPTURE は Windows 10 バージョン 2004(ビルド 19041)以降で使えます。
コード
P/Invoke で呼び出します。
using System;
using System.Runtime.InteropServices;
internal static class NativeMethods
{
public const uint WDA_NONE = 0x00000000;
public const uint WDA_EXCLUDEFROMCAPTURE = 0x00000011;
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowDisplayAffinity(IntPtr hWnd, uint dwAffinity);
}
WPF では、ウィンドウハンドルができた直後の SourceInitialized で設定します。表示してから設定すると、設定するまでの間はキャプチャに映ってしまうためです。
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
SourceInitialized += (_, _) =>
{
var handle = new WindowInteropHelper(this).Handle;
if (!NativeMethods.SetWindowDisplayAffinity(handle, NativeMethods.WDA_EXCLUDEFROMCAPTURE))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
};
}
}
これだけです。元に戻すときは WDA_NONE を渡します。
試した結果
Windows 11(ビルド 26200)で試しました。
会議ツールの画面共有
| ツール | 画面全体の共有 | ウィンドウ単位の共有 |
|---|---|---|
| Teams(新しい Teams) | 映らない | 映らない(共有の映像が止まる) |
| Zoom(デスクトップアプリ) | 映らない | 映らない(後ろにある画面が映る) |
| Google Meet(Chrome) | 映らない | 映らない(共有の映像が止まる) |
| Webex(デスクトップアプリ) | 映らない | 映らない(後ろにある画面が映る) |
画面全体の共有では、ウィンドウがあった場所に後ろのデスクトップや別のウィンドウが映ります。黒い四角も出ません。ウィンドウ単位の共有では、映らない点は同じですが、相手に見える画面はツールによって違いました。
録画・スクリーンショット
| ツール | 結果 |
|---|---|
| Snipping Tool(スクリーンショット・録画) | 映らない |
| Teams の会議の録画 | 映らない |
| OBS Studio の画面キャプチャ(DXGI デスクトップ複製 / Windows 10(1903 以降)) | 映らない |
| OBS Studio のウィンドウキャプチャ(BitBlt / Windows 10(1903 以降)) | 映らない(マウスカーソルだけ映る) |
| リモートデスクトップ(RDP) | 映る(接続した側から見える) |
リモートデスクトップだけは、設定に関係なく接続した側から見えました。
注意すること
- セキュリティ機能ではありません。 カメラで物理画面を撮れば映ります。Microsoft のドキュメントにも、セキュリティ機能や DRM ではないと書かれています
- 本人の画面には表示されます。 「相手に見せない」ことはできますが、「本人にも見せない」ことはできません
- 本人のスクリーンショットにも写りません。 問い合わせのために画面を撮ってもらいたいアプリでは、設定で外せるようにしておくと安心です
- リモートデスクトップでは隠せません。 接続した側からは普通に見えます
- 自分のプロセスのトップレベルウィンドウにしか設定できません。 ほかのアプリのウィンドウは隠せません
- Windows 10 バージョン 2004 より前では
WDA_MONITORと同じ動きになり、黒い四角で映ります
おわりに
API を1つ呼ぶだけで、画面共有・録画・スクリーンショットに映らないウィンドウが作れました。通知やパスワードの表示など、画面共有で相手に見せたくないものがあるときに使えそうです。
参考
本ブログに掲載している内容は、私個人の見解であり、所属する組織の立場や戦略、意見を代表するものではありません。
