代码之家  ›  专栏  ›  技术社区  ›  Cory Charlton

如何知道何时在“显示属性”对话框中选择了其他屏幕保护程序?

  •  1
  • Cory Charlton  · 技术社区  · 15 年前

    好吧,谷歌今晚不是我的朋友。。。

    我有一个屏幕保护程序, 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调用并清理它们的声明,看看我能找出什么。

    谢谢你到目前为止的帮助!


    解决方案:

    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 回复  |  直到 14 年前
        1
  •  1
  •   John Knoeller    15 年前

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

    你可以试试这个。

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

    SetParent

    此外,表单上可能没有WS_弹出式样式,但如果有,则希望将其删除。

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

    这里发生的是SetParent设置子窗口的父窗口,但它设置 WS_弹出窗口和WS_重叠窗口的数量。

    推荐文章