さて、Googleは今夜私の友達ではありません...
スクリーンセーバー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));
そして、スタイルは最後の3つのトレースで同じであり、そのうちの2つはフォーム自体から値を取得する必要があります。私のネイティブ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;
}
}