好吧,谷歌今晚不是我的朋友......
我有一个屏幕保护程序CC.Votd(Codeplex 上的完整源代码),并且我刚刚开始实现运行正常的预览模式(/p 参数)。当它处于预览模式时,我将我的表单设置为小计算机监视器窗口的子窗口,然后它会在那里绘制。
这工作正常,如果显示属性对话框消失,我的应用程序将退出。
问题是,如果我从列表中选择我的屏幕保护程序,然后选择不同的屏幕保护程序,我的会继续运行并绘制新选择的屏幕保护程序的预览。
那么我怎么知道何时选择了不同的屏幕保护程序并且我的应该关闭?
编辑:对于 Anon,这是我用来使我的表单成为预览窗口的子窗体的代码:
P/调用:
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern bool GetClientRect(IntPtr hWnd, out Rectangle lpRect);
编码:
SetParent(Handle, _PreviewHandle);
SetWindowLong(Handle, -16, new IntPtr(GetWindowLong(Handle, -16) | 0x40000000));
Rectangle parentRectangle;
GetClientRect(_PreviewHandle, out parentRectangle);
Size = parentRectangle.Size;
Location = new Point(0, 0);
完整的表单代码:http ://ccvotd.codeplex.com/SourceControl/changeset/view/40085#862458
忘了提及我尝试使用IsWindowVisible()
但没有工作,因为预览窗口仍然可见并且与选择我的屏幕保护程序时具有相同的句柄。
编辑:在我添加SetParent()
和关联调用之前,我的应用程序将在显示对话框关闭后继续运行,所以我认为该部分正在工作,并且当用户选择不同的屏幕保护程序时会发生不同的事情。
正如 John K 建议的那样,我一直在使用 Spy++ 查看我的表单。我从来没有看到应用了 WS_CHILD 样式。然而,我所有的调试都表明它应该是。我将代码修改为:
long style = GetWindowLong(Handle, -16);
System.Diagnostics.Trace.WriteLine("Original Style: " + style);
style &= ~0x800000000;
style |= 0x40000000;
System.Diagnostics.Trace.WriteLine("Adjusted Style: " + style);
SetWindowLong(Handle, -16, new IntPtr(style));
System.Diagnostics.Trace.WriteLine("After Set Style: " + GetWindowLong(Handle, -16));
SetParent(Handle, _PreviewHandle);
System.Diagnostics.Trace.WriteLine("After Set Parent: " + GetWindowLong(Handle, -16));
最后三个跟踪的样式相同,其中两个应该是从表单本身获取值。去研究我的原生 API 调用并清理它们的声明,看看我能弄清楚什么。
感谢您迄今为止的所有帮助!
解决方案:问题最终是我设置了表单的几个属性,导致底层 .NET 控件覆盖了我的新样式。所以改变:
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
Capture = true;
if (!_IsPreview)
{
// Removed ...
}
else
{
SetWindowLong(Handle, -16, new IntPtr(GetWindowLong(Handle, -16) | 0x40000000));
SetParent(Handle, _PreviewHandle);
Rectangle parentRectangle;
GetClientRect(_PreviewHandle, out parentRectangle);
Size = parentRectangle.Size;
Location = new Point(0, 0);
}
ShowInTaskbar = false;
DoubleBuffered = true;
BackgroundImageLayout = ImageLayout.Stretch;
至:
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
BackgroundImageLayout = ImageLayout.Stretch;
Capture = true;
DoubleBuffered = true;
ShowInTaskbar = false;
if (!_IsPreview)
{
// Removed ...
}
else
{
SetWindowLong(Handle, -16, new IntPtr(GetWindowLong(Handle, -16) | 0x40000000));
SetParent(Handle, _PreviewHandle);
Rectangle parentRectangle;
GetClientRect(_PreviewHandle, out parentRectangle);
Size = parentRectangle.Size;
Location = new Point(0, 0);
}
修复了问题。简单的错误:-)
解决它的正确方法...覆盖 CreateParams:
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
if (!DesignMode && _IsPreview)
{
createParams.Style |= 0x40000000;
}
return createParams;
}
}