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

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

在这里输入图像说明

构造函数重载预览

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设置。 您必须延迟分配大小,直到Load事件发生,当它以正常方式触发,然后所有自动缩放都已完成。