我已经构建了一个Windows窗体屏幕保护程序,我似乎无法弄清楚预览功能无法正常工作的原因。
构建器重载预览
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中运行此屏幕保护程序。
答案 0 :(得分:3)
SetParent(this.Handle, PreviewWndHandle);
不要在构造函数中使用Handle属性。这迫使窗口过早创建。您的Load事件在构造函数完成运行之前触发。这非常不健康,当你的Load事件处理程序使用尚未设置的类的字段时,当然很容易导致NullReferenceException。
您没有发布炸弹的代码(ScreenSaver_Load),因此我们无法猜出具体的声明失败了。使用Debug&gt;例外&gt; CLR例外&gt;勾选Thrown复选框以确保在引发异常时调试器停止,以便您可以看到失败的语句。
此外,当强制Winforms重新创建窗口时,Handle属性值可能会更改。此代码的适当位置是OnHandleCreated()方法的覆盖。此时,Handle属性保证有效,不会造成副作用。
this.Size = ParentRect.Size;
更改构造函数中的Size属性也是错误的,表单的AutoScaleMode属性稍后会更改它以调整视频适配器的DPI设置。您必须延迟分配大小,直到Load事件,当它以正常方式触发,然后所有自动缩放都已完成。