Как узнать, когда в диалоговом окне свойств экрана была выбрана другая заставка? - PullRequest
1 голос
/ 08 февраля 2010

Хорошо, сегодня Google не мой друг ...

У меня есть заставка, CC.Votd (Полный исходный код в Codeplex) , и я только начал реализовывать режим предварительного просмотра (аргумент / p), который работает нормально. Когда он находится в режиме предварительного просмотра, я превращаю свою форму ребенка в маленькое окно монитора компьютера, и оно рисует там.

Это работает нормально, и мое приложение закрывается, если диалоговое окно свойств экрана исчезает.

Проблема заключается в том, что если я выберу заставку из списка, а затем выберу другую заставку, шахта продолжит работу и будет отображать предварительный просмотр только что выбранной заставки.

Итак, как мне узнать, когда выбрана другая заставка, и моя должна закрыться?


Редактировать: Для Анона, вот код, который я использую, чтобы сделать мою форму дочерней по отношению к окну предварительного просмотра:

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() и связанные вызовы, мое приложение продолжало бы работать после закрытия диалогового окна, поэтому я думаю, что часть работает, и что-то другое происходит, когда пользователь выбирает другой заставка.


Как предположил Джон К, я просматривал свою форму в 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 Ответ

1 голос
/ 08 февраля 2010

Однажды попытка изменить стиль окна WS_CHILD после того, как оно уже было создано, просто потерпит неудачу. Я думаю, что они изменили это в текущих версиях окон, но чтобы быть уверенным, вы должны действительно создать свою форму предварительного просмотра как дочернее окно с самого начала.

У меня есть догадка, что ваше окно не заканчивается дочерним окном предварительного просмотра. Вы можете попробовать это.

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.

...