TransparencyKey를 통해서 편리한 도우미 유틸리티를 하나 만들어볼까 합니다. 바로 자동 클리핑 윈도우입니다. Window Region API를 이용하여 계산하고 자르는 작업을 하지 않고서도 간단하고 깔끔하게 이런 작업을 해낼 수 있습니다.

[Flags]
[Serializable]
public enum TransformOptions : int
{
    None = 0,
    HideAllControls = None + 1,
    RemoveWindowText = HideAllControls * 2,
    HideFromTaskbar = RemoveWindowText * 2,
    All = (HideAllControls | RemoveWindowText | HideFromTaskbar)
}

public static void TransformToCustomRegion(Form targetForm, Color transparentColor, TransformOptions options)
{
    if (targetForm == null)
        throw new ArgumentNullException("targetForm");

    if (targetForm.IsDisposed)
        throw new ObjectDisposedException("targetForm");

    if (targetForm.Visible)
        targetForm.Visible = false;

    targetForm.FormBorderStyle = FormBorderStyle.None;
    targetForm.BackColor = transparentColor;
    targetForm.TransparencyKey = targetForm.BackColor;

    if (((int)options & (int)TransformOptions.HideAllControls) != 0)
        foreach (Control c in targetForm.Controls)
            c.Visible = false;

    if (((int)options & (int)TransformOptions.RemoveWindowText) != 0)
        targetForm.Text = String.Empty;

    if (((int)options & (int)TransformOptions.HideFromTaskbar) != 0)
        targetForm.ShowInTaskbar = false;

    if (!targetForm.Visible)
        targetForm.Visible = true;
}

public static void TransformToCustomRegion(Form targetForm, Color transparentColor)
{
    TransformToCustomRegion(targetForm, transparentColor, TransformOptions.None);
}

// 실제 적용

private void Form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.FillPie(Brushes.Aqua, 140, 0, 400, 400, 30, 80);
}

private void Form1_Load(object sender, EventArgs e)
{
    TransformToCustomRegion(this, Color.Empty);
}

여기서 TransformToCustomRegion 메서드가 동작하는 원리를 살펴보면, BackColor와 TransparencyKey의 값을 일치시켜주는 것과 함께, 창의 구성요소들을 제거하는 것입니다. 이로서, 창의 다른 구성 요소가 제거된 상태에서 순수한 컨텐츠만 Paint 이벤트를 통해서 그려지게 되는데, 이 중 색이 겹치지 않는 내용만이 남아서 창으로 존재하게 되고 나머지는 잘립니다.

이와 같은 원리를 이용하여 가운데에 구멍이 뚫려있는 창도 만들 수 있고, 예전 노턴 크래쉬가드 같은 프로그램처럼 방패모양 창도 구현할 수 있습니다. Hit-Test 구현만 정확히 되어주면 기존 제목 표시줄도 대체가 가능합니다. :-)

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)