티스토리 뷰
SetWindowDisplayAffinity 함수는 화면 캡쳐(동영상 녹화, 스크린샷) 시 해당 창을 검은색으로 만들어버린다. (MSDN)
Windows 10 20H 버전 이상이 아닌 경우 총 2가지 속성을 사용할 수 있다. (None, Monitor 속성)
SetWindowDisplayAffinity 함수에서 요구하는 핸들은 캡쳐를 방지할 폼에 대한 핸들이다. (컨트롤에 대한 핸들 X)
캡쳐 방지 또한 DWM이 활성화 되어 있는 상태에서만 작동된다. (Window 8 부터 계속 활성화 됨)
DWM 활성화 여부 체크는 다음 글을 참고하자.
테스트 케이스
- 보호여부가 체크 상태에 따라 다음과 같은 상태 적용
- 체크: Monitor 속성 적용
- 체크 해제: None 속성 적용
아쉽게도 초록색 패널만 캡쳐 방지 효과를 줘보려고 했으나, 실패했다.
폼에 배치된 컨트롤(초록색 패널 영역)은 적용되지 않고 폼만 적용되는 것으로 확인되었다.
코드 (Form.cs)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SetWindowDisplayAffinityTest
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern bool SetWindowDisplayAffinity(IntPtr hwnd, DisplayAffinity affinity);
enum DisplayAffinity : uint
{
None = 0,
Monitor = 1
}
public Form1()
{
InitializeComponent();
this.checkBox1.CheckedChanged += CheckBox1_CheckedChanged;
}
private void CheckBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked)
{
// protect
label2.Text = "Protect";
SetWindowDisplayAffinity(this.Handle, DisplayAffinity.Monitor);
}
else
{
label2.Text = "Disable";
SetWindowDisplayAffinity(this.Handle, DisplayAffinity.None);
}
}
private void Form1_Load(object sender, EventArgs e)
{
this.ShowIcon = false;
this.MaximizeBox = false;
}
}
}
코드 (Designer.cs)
namespace SetWindowDisplayAffinityTest
{
partial class Form1
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form 디자이너에서 생성한 코드
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.checkBox1 = new System.Windows.Forms.CheckBox();
this.panel1 = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 38);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(44, 12);
this.label1.TabIndex = 1;
this.label1.Text = "Status:";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(62, 38);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(11, 12);
this.label2.TabIndex = 2;
this.label2.Text = "-";
//
// checkBox1
//
this.checkBox1.AutoSize = true;
this.checkBox1.Location = new System.Drawing.Point(12, 12);
this.checkBox1.Name = "checkBox1";
this.checkBox1.Size = new System.Drawing.Size(76, 16);
this.checkBox1.TabIndex = 3;
this.checkBox1.Text = "보호 여부";
this.checkBox1.UseVisualStyleBackColor = true;
//
// panel1
//
this.panel1.BackColor = System.Drawing.Color.Green;
this.panel1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.panel1.Location = new System.Drawing.Point(12, 66);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(402, 140);
this.panel1.TabIndex = 4;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(426, 218);
this.Controls.Add(this.panel1);
this.Controls.Add(this.checkBox1);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Name = "Form1";
this.Text = "특정 윈도우 보호";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.CheckBox checkBox1;
private System.Windows.Forms.Panel panel1;
}
}
결과
녹화가 진행 중인 경우 녹화된 영상에서 Monitor 속성을 매개변수로 호출하면 핸들을 준 창이 검은색 창으로만 보이게 된다.
녹화가 실시간으로 진행 중이더라도 사용자 화면에는 정상적인 윈도우의 모습을 볼 수 있었고, 동영상 녹화된 영상에서만 검은색 창으로 보여졌다.
SetWindowDisplayAffinity 함수가 호출되어 Monitor 속성이 적용된 창에 대해서 스크린샷도 캡쳐할 수 없었다.
아래는 Monitor 속성이 적용된 스크린샷으로 캡쳐한 창 모습이다.
댓글