如何知道何时在显示属性对话框中选择了不同的屏幕保护程序?

时间:2010-02-08 02:11:08

标签: c# .net windows screensaver

好的,所以Google今晚不是我的朋友......

我有一个屏幕保护程序,CC.Votd (Full source on 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;
    }
}

1 个答案:

答案 0 :(得分:1)

一旦尝试在窗口创建后改变窗口的WS_CHILD样式,就会悄然失败。我认为他们在当前版本的Windows中改变了这一点,但可以肯定的是,您应该从一开始就将您的预览表单创建为子窗口。

我预感到你的窗口没有结束预览的子窗口。 你可以试试这个。

SetParent(Handle, _PreviewHandle);
SetWindowLong(Handle, -16, new IntPtr(GetWindowLong(Handle, -16) | 0x40000000));
SetParent(Handle, _PreviewHandle);
在之后

SetParent 将窗口样式更改为WS_CHILD。

此外,您的表单上可能没有WS_POPUP样式,但如果这样,则要删除它。

int style = GetWindowLong(Handle, -16);
style &= ~0x800000000;
style |= 0x40000000;
SetWindowLong(Handle, -16, new IntPtr(style));

这里发生的事情是SetParent设置子窗口的父窗口,但它设置了WS_POPUP和WS_OVERLAPPED窗口的所有者