c# - Windows 窗体屏幕保护程序预览窗口句柄

标签 c# windows winforms

我已经构建了一个 Windows 窗体屏幕保护程序,但我似乎无法弄清楚为什么预览功能不起作用。

enter image description here

用于预览的构造函数重载

public ScreenSaverForm(IntPtr PreviewWndHandle)
{
  InitializeComponent();

  //set the preview window as the parent of this window
  SetParent(this.Handle, PreviewWndHandle);

  //make this a child window, so when the select screensaver 
  //dialog closes, this will also close
  SetWindowLong(this.Handle, -16,
        new IntPtr(GetWindowLong(this.Handle, -16) | 0x40000000));

  //set our window's size to the size of our window's new parent
  Rectangle ParentRect;
  GetClientRect(PreviewWndHandle, out ParentRect);
  this.Size = ParentRect.Size;

  //set our location at (0, 0)
  this.Location = new Point(0, 0);

  previewMode = true;
}

Program.cs 或采用命令参数的主要入口点

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
 if (args.Length > 0)
        {
            if (args[0].ToLower().Trim().Substring(0,2) == "/s") //show
            {
                //show the screen saver
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                ShowScreenSaver(); //this is the good stuff
                Application.Run();
            }
            else if (args[0].ToLower().Trim().Substring(0,2) == "/p") //preview
            {
              //show the screen saver preview
              Application.EnableVisualStyles();
              Application.SetCompatibleTextRenderingDefault(false);
              //args[1] is the handle to the preview window
              Application.Run(new ScreenSaverForm(new IntPtr(long.Parse(args[1]))));
            }
            else if (args[0].ToLower().Trim().Substring(0,2) == "/c") //configure
            {
              //nothing to configure
              MessageBox.Show(
              "This screensaver has no options that you can set",
              "Dancing Polygons",
              MessageBoxButtons.OK,
              MessageBoxIcon.Information);
            }
        }
        else
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            ShowScreenSaver(); //this is the good stuff
            Application.Run();
        }
}

屏幕保护程序加载事件

 private void ScreenSaver_Load(object sender, EventArgs e)
{
  Cursor.Hide();
  TopMost = false;
  MouseDown += new MouseEventHandler(MouseDownEvent);
  timer.Tick += new EventHandler(Run);
  timer.Interval = 30;
  watch.Start();
  timer.Start();
  //loopThread = new Thread(() => RunThread(this.CreateGraphics(), this, timer));
  //loopThread.Start();
}

所以我不明白为什么我会得到一个空引用。我相信它的命令参数。我在 Windows 8.1 中运行此屏幕保护程序。

最佳答案

   SetParent(this.Handle, PreviewWndHandle);

不要在构造函数中使用 Handle 属性。这迫使窗口过早创建。您的 Load 事件在构造函数完成运行之前触发。这是非常不健康的,当您的 Load 事件处理程序使用尚未设置的类的字段时,当然很容易导致 NullReferenceException。

您没有发布炸弹 (ScreenSaver_Load) 的代码,因此我们无法猜测具体是什么语句失败了。使用 Debug > Exceptions > CLR Exceptions > 勾选 Thrown 复选框以确保在引发异常时调试器停止,以便您可以看到失败的语句。

此外,当 Winforms 被迫重新创建窗口时,Handle 属性值可能会发生变化。此代码的适当位置是 OnHandleCreated() 方法的覆盖。此时 Handle 属性保证有效且不会产生副作用。

   this.Size = ParentRect.Size;

在构造函数中更改 Size 属性也是错误的,窗体的 AutoScaleMode 属性稍后会更改它以调整视频适配器的 DPI 设置。您必须延迟分配 Size 直到 Load 事件,当它以正常方式触发时,所有自动缩放都已完成。

关于c# - Windows 窗体屏幕保护程序预览窗口句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31552379/

相关文章:

c# - ASP.NET MVC + LINQ 异常

c# - RDotNet.dll 中发生类型为 'System.StackOverflowException' 的未处理异常

Windows如何创建启动应用程序?

c - GENERIC_ALL 和文件夹/文件 ACL? GENERIC_ALL 到底做了什么?

c# - 线程启动期间的竞争条件?

c# - wpf 中 OnPaintBackground 的替代方案。

c# - 如何将查询字符串传递给 Ajax WebService

c# - 类不继承自对象?

c# - 64 位 Windows 上的气球工具提示

c# - 从另一个 WPF 窗体打开一个新的 WPF 窗体