今日はc# Windowsフォームでオーバーレイを表示する方法。
よくWebで見る警告や確認のメッセージが最前面にくるやつです。
WPFだと簡単に実装できるのですが、Windowsフォームだと少し面倒です。
実装のイメージとしては、現在表示中のフォームの上に透過したフォームを被せるイメージです。
何が面倒かというと、FormのOpacityプロパティを透過に設定したフォームを被せると、
他のコントロールまで透過されてしまいます。
こんな感じで
ちょっと見るに堪えないですね。
ではちょっと小細工してみます。
どうでしょう?見るに堪えるレベルになりました。
小細工の内容はこうです。
まず透過率(Opacity)と背景色(BackColor)のみ設定したフォームを被せます。
次にコントロールを配置し、透明キー(TransparencyKey)を設定したフォームを被せます。
2個のフォームを重ねるわけですね。こんな順で。
まず1つ目のフォーム(OverlayBase.cs)
using System;
using System.Windows.Forms;
namespace OverlaySample
{
/// <summary>
/// <para>透過率のみ設定するForm</para>
/// <para>※コントロールを配置するとコントロールまで透過されるため、コントロールを配置するFormは上に被せる</para>
/// </summary>
internal partial class OverlayBase : Form
{
public OverlayBase()
{
InitializeComponent();
}
public OverlayBase(Form owner) : this()
{
// 表示位置は親フォームにあわせる
this.StartPosition = FormStartPosition.CenterParent;
// Formの枠なし
this.FormBorderStyle = FormBorderStyle.None;
// 透過率60%
this.Opacity = 0.6;
// 親フォームの情報を引き継ぐ
this.Location = owner.Location;
this.Size = owner.Size;
this.Font = owner.Font;
}
/// <summary>
/// Shownで2つ目のフォームを呼んでまう
/// </summary>
/// <param name="buttons"></param>
private void OverlayBase_Shown(object sender, EventArgs e)
{
OverlayParts parts = new OverlayParts(this);
this.DialogResult = parts.ShowDialog();
this.Close();
}
}
}
そして2つ目のフォーム(OverlayParts.cs)
using System.Drawing;
using System.Windows.Forms;
namespace OverlaySample
{
/// <summary>
/// 背景のみ透過させ、部品を配置するForm
/// </summary>
internal partial class OverlayParts : Form
{
public OverlayParts()
{
InitializeComponent();
}
public OverlayParts(Form owner) : this()
{
// 表示位置は親フォームにあわせる
this.StartPosition = FormStartPosition.CenterParent;
// Formの枠なし
this.FormBorderStyle = FormBorderStyle.None;
// 背景色を透明化するキーに指定
this.TransparencyKey = this.BackColor;
// ラベルの書式設定
lblMessage.Anchor = AnchorStyles.None;
lblMessage.Text = "実行します。\r\nよろしいですか?";
lblMessage.Font = new Font(owner.Font.FontFamily, 14f);
lblMessage.ForeColor = Color.White;
// ラベルを中央に配置する
lblMessage.Left = (this.Width / 2) - (lblMessage.Width / 2);
// ボタンの配置
LocateButton();
// 親フォームの情報を引き継ぐ
this.Location = owner.Location;
this.Size = owner.Size;
this.Font = owner.Font;
}
/// <summary>
/// ボタンの配置
/// </summary>
/// <param name="buttons"<</param>
private void LocateButton()
{
Button btn = new Button();
btn.Anchor = AnchorStyles.None;
btn.Location = new Point(130, 186);
btn.Size = new Size(80, 32);
btn.TabIndex = 51;
btn.Text = "OK";
btn.UseVisualStyleBackColor = true;
btn.Click += (sender, e) =< { this.DialogResult = DialogResult.OK; this.Close(); };
this.Controls.Add(btn);
btn = new Button();
btn.Anchor = AnchorStyles.None;
btn.Location = new Point(230, 186);
btn.Size = new Size(80, 32);
btn.TabIndex = 52;
btn.Text = "キャンセル";
btn.UseVisualStyleBackColor = true;
btn.Click += (sender, e) =< { this.DialogResult = DialogResult.Cancel; this.Close(); };
this.Controls.Add(btn);
}
}
}
あとは実際に使用する画面で下記のように書けばOKです。
OverlayBase overlay = new OverlayBase(this);
overlay.ShowDialog();
このコードはイケてるか?と聞かれればイケてはないですね。
イケてない点ついでに言うと、テーマを
「Windows 7 ベーシック」
にしていると、Windowの左上と右上が丸まってると思うのですが、よく見るとそれをカバーできていません。
Windows 8や10だと大丈夫かもしれません。角ばっているので。
おしまい。