65.9K
CodeProject 正在变化。 阅读更多。
Home

一个模态对话框,可将背景灰度化,模仿 XP 关机屏幕

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.49/5 (26投票s)

2006 年 2 月 23 日

CDDL

2分钟阅读

viewsIcon

197834

downloadIcon

2465

DimmerDialog 是一个 .NET 类,它显示一个模态对话框,该对话框将背景的其余部分灰显,就像 Windows XP 关机对话框一样。当您的应用程序需要显示一个非常重要的消息框或窗体,需要立即引起用户的注意时,可以使用此方法。

引言

DimmerDialog 是一个 .NET 类,它显示一个模态对话框,该对话框将背景的其余部分灰显,就像 Windows XP 关机对话框一样。当您的应用程序需要显示一个非常重要的消息框或窗体,需要立即引起用户的注意时,可以使用此方法。该类允许您显示消息框(您可以在其中设置文本、标题和图标)或 Form 实例。

此类的工作原理

XP 关机对话框显示一个模态窗体,而背景渐变为灰度。我试图模拟这一点,但我的渐变效果并不那么流畅或令人印象深刻(我使用了常规的 GDI 素材,而 XP 关机对话框可能使用了更强大的技术,例如 DirectX)。我创建一个新的桌面(以 GUID 命名),切换到此桌面,显示背景,使用计时器使其渐变,并且所有这些都在模态窗体或消息框保持在最顶层时进行。这是一个动画 gif,显示了渐变效果(由于 GIF 颜色深度限制,质量较差)。

使用该类

这里有一些示例代码,展示了如何显示消息框。

private void button2_Click(object sender, EventArgs e)
{
    DimmerDialog dimmer = new DimmerDialog();
    dimmer.ShowMessageBox(
        "You can show either a Form or a MessageBox here.", 
        "Fatal Error has occurred", MessageBoxIcon.Stop);
}

这是展示如何显示表单的一些代码。

private void button1_Click(object sender, EventArgs e)
{
    DimmerDialog dimmer = new DimmerDialog();
    dimmer.ShowForm(new Form2());
}

当您显示表单时,请确保您的表单没有启动任何进程(例如作为按钮单击操作),因为该进程将在您的主桌面而不是在此桌面上运行。最好保持简单(就像 XP 关机对话框一样),并且仅使用该表单来收集一些数据。

类实现

该类是用混合模式 C++/CLI 编写的,但这是 C# 中公共接口的样子(模拟 - 实际代码不在 C# 中)。

public class DimmerDialog
{
    public DimmerDialog();
    public void ShowForm(Form form);
    public void ShowMessageBox(string text, string title,
        MessageBoxIcon icon);
}

这是我编写的淡化函数(它是 C++),其中最终的灰度代码是从 Christian 的一篇 GDI+ 文章中提取的。 淡化算法是我经过一些反复试验后最终确定的算法。它远非完美,但我认为考虑到我们从淡化效果中获得的效用,这样做是可以的。

Bitmap^ DimBitmap()
{
  if(m_ColorReductionStep == 0)
    return m_Image;
  Bitmap^ imagecopy = (Bitmap^)m_Image->Clone();
  BitmapData^ bmData = imagecopy->LockBits(
    System::Drawing::Rectangle(0, 0, 
    imagecopy->Width, imagecopy->Height), 
    ImageLockMode::ReadWrite, PixelFormat::Format24bppRgb); 
  BYTE* p = (BYTE*)bmData->Scan0.ToPointer();
  int nOffset = bmData->Stride - imagecopy->Width * 3; 
  BYTE red, green, blue;
  for(int y=0; y < imagecopy->Height; y++)
  {
    for(int x=0; x < imagecopy->Width; x++)
    {
      blue = p[0];
      green = p[1];
      red = p[2];

      switch(m_ColorReductionStep)
      {
      case 1:
        p[0]  = (BYTE)(.001 * red + .286 * green + .713 * blue);
        p[1]  = (BYTE)(.001 * red + .986 * green + .013 * blue);
        p[2]  = (BYTE)(.899 * red + .087 * green + .013 * blue);
        break;
      case 2:
        p[0]  = (BYTE)(.099 * red + .387 * green + .514 * blue);
        p[1]  = (BYTE)(.099 * red + .887 * green + .014 * blue);
        p[2]  = (BYTE)(.699 * red + .287 * green + .013 * blue);
        break;
      case 3:
        p[0]  = (BYTE)(.199 * red + .487 * green + .314 * blue);
        p[1]  = (BYTE)(.199 * red + .787 * green + .014 * blue);
        p[2]  = (BYTE)(.499 * red + .487 * green + .014 * blue);
        break;
      case 4:
        p[0] = p[1] = p[2] = (BYTE)(.299 * red + .587 * green + .114 * blue);
        break;
      }         
      p += 3;
    }
    p += nOffset;
  }
  imagecopy->UnlockBits(bmData);
  return imagecopy;
}

甚至不要问我为什么使用这些分数,我只是在经过多次尝试后才得到的。 也许通过修改它们,并通过添加更多步骤(目前我使用 4 步淡化),我们可以获得更平滑的效果,但我认为这不值得付出努力。

历史

  • 2006 年 2 月 23 日 - 首次发布文章。
© . All rights reserved.