Ok so Google is not my friend tonight...
I have a screen saver, CC.Votd (Full source on Codeplex), and I've just started to implement the preview mode (/p argument) which is working ok. When it's in preview mode I make my form a child to the little computer monitor window and it draws in there.
This works fine and my application exits if the display properties dialog goes away.
The issue is that if I select my screen saver from the list and then select a different screen saver mine continues to run and draws over the newly selected screen saver's preview.
So how do I know when a different screen saver is selected and mine should close?
Edit: For Anon, here's the code I'm using to make my form a child of the preview window:
P/invokes:
[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);
The code:
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);
Complete form code: http://ccvotd.codeplex.com/SourceControl/changeset/view/40085#862458
Forgot to mention that I tried using IsWindowVisible()
and that didn't work since the preview window is still visible and has the same handle as when my screen saver was selected.
Edit: Before I added the SetParent()
and associated calls my application would continue to run after the display dialog was closed so I think that part is working and something different happens when the user selects a different screen saver.
As John K suggested I've been looking at my form with Spy++. I never see the WS_CHILD style applied. However all my debugging suggests it should be. I modified the code to:
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));
And the style is the same on the last three traces, two of which should be getting the value from the form itself. Going to research my native API calls and clean up their declarations to see what I can figure out.
Thanks for all the help so far!
Solution: The problem ended up being that I was setting several properties of the form that resulted in the underlying .NET control overwriting my new styles. So changing:
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;
To:
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);
}
Fixed the problem. Simple mistake :-)
The correct way to solve it... override CreateParams:
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
if (!DesignMode && _IsPreview)
{
createParams.Style |= 0x40000000;
}
return createParams;
}
}