これを行う方法はすでに述べたように、既存のフォームの上に別のコントロール/フォームをオーバーレイし、これのグレースケールバージョンを上にレンダリングすることです。これは、元のフォームの上に正確に配置された追加のフォームを使用して行うことができます。 、またはPanel
他のすべてのコントロールの上に配置されたようなものを使用します。
これは、最初のクライアント領域の真上に別のフォームを配置するときにこれを行う方法の実例です。それの使い方
using (Grayscale(this))
{
MessageBox.Show("Test");
}
実装
public static Form Grayscale(Form tocover)
{
var frm = new Form
{
FormBorderStyle = FormBorderStyle.None,
ControlBox = false,
ShowInTaskbar = false,
StartPosition = FormStartPosition.Manual,
AutoScaleMode = AutoScaleMode.None,
Location = tocover.PointToScreen(tocover.ClientRectangle.Location),
Size = tocover.ClientSize
};
frm.Paint += (sender, args) =>
{
var bmp = GetFormImageWithoutBorders(tocover);
bmp = ConvertToGrayscale(bmp);
args.Graphics.DrawImage(bmp, args.ClipRectangle.Location);
};
frm.Show(tocover);
return frm;
}
private static Bitmap ConvertToGrayscale(Bitmap source)
{
var bm = new Bitmap(source.Width, source.Height);
for (int y = 0; y < bm.Height; y++)
{
for (int x = 0; x < bm.Width; x++)
{
Color c = source.GetPixel(x, y);
var luma = (int)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11);
bm.SetPixel(x, y, Color.FromArgb(luma, luma, luma));
}
}
return bm;
}
private static Bitmap GetControlImage(Control ctl)
{
var bm = new Bitmap(ctl.Width, ctl.Height);
ctl.DrawToBitmap(bm, new Rectangle(0, 0, ctl.Width, ctl.Height));
return bm;
}
private static Bitmap GetFormImageWithoutBorders(Form frm)
{
// Get the form's whole image.
using (Bitmap wholeForm = GetControlImage(frm))
{
// See how far the form's upper left corner is
// from the upper left corner of its client area.
Point origin = frm.PointToScreen(new Point(0, 0));
int dx = origin.X - frm.Left;
int dy = origin.Y - frm.Top;
// Copy the client area into a new Bitmap.
int wid = frm.ClientSize.Width;
int hgt = frm.ClientSize.Height;
var bm = new Bitmap(wid, hgt);
using (Graphics gr = Graphics.FromImage(bm))
{
gr.DrawImage(wholeForm, 0, 0,
new Rectangle(dx, dy, wid, hgt),
GraphicsUnit.Pixel);
}
return bm;
}
}
ご了承ください:
- の実装
Paint
はかなり貧弱です。実際には、ダブルバッファリングを使用して、グレースケール画像がバッファリングされたグラフィックスコンテキストに事前にレンダリングされるようにする必要があります。これにより、Paintメソッドは事前に描画されたバッファの内容をペイントするだけで済みます。C#のカスタム描画コントロール–手動ダブルバッファリングを参照してください
ConvertToGrayscale
遅い側では少しですが、おそらくスピードアップすることができます
- 誰かが何らかの理由で元のフォームを移動することに成功した場合、事態はうまくいきません
- 画像は静的です。ベースコントロールが再描画された場合、理想的にはトップフォームも再描画する必要があります。別のフォームの一部が無効になったことを検出する最善の方法がわかりません。
時間があれば、これらの問題のいくつかを修正しようとしますが、上記は少なくとも一般的な考え方を示しています。
WPFでは、これがはるかに簡単になることに注意してください。
出典: