Как исправить изменение размера формы WPF - отстающие элементы управления и черный фон?
У меня очень простое окно WPF - единственное, что в нем - кнопка, выровненная по правому краю. Когда я изменяю размер окна, перетаскивая левую границу, кнопка перепрыгивает - много. Попробуйте сами, перетащите левую границу назад и вперед.
Кроме того, черный фон временно экспонируется во время изменения размера.
В этом вопросе я задал похожий вопрос о Windows Forms. Единственный ответ, который я получил, заключается в том, что это исправлено в WPF, однако, как ни удивительно, оно не только не исправлено, но и в WPF добавлена вторая визуальная ошибка - временный черный фон.
Вот как выглядит задержка управления; это происходит, когда я изменяю размер окна по его верхней границе (записано камерой, потому что экранная крышка делала его менее заметным, делая все медленным):
Пример черной рамки: это было захвачено при изменении размера окна; это только так на долю секунды, но это очень заметно:
Я делаю что-то неправильно? Как сделать так, чтобы мои элементы управления визуально находились в одном месте при изменении размеров? Как я могу избежать черной границы?
Примечание: кнопка в конечном итоге оказывается в правильном месте - она только ненадолго прыгает во время изменения размера.
5 ответов
Это полный рабочий код, основанный на втором решении Wieser Software Ltd.
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
//ensure win32 handle is created
var handle = new WindowInteropHelper(this).EnsureHandle();
//set window background
var result = SetClassLong(handle, GCL_HBRBACKGROUND, GetSysColorBrush(COLOR_WINDOW));
}
public static IntPtr SetClassLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
{
//check for x64
if (IntPtr.Size > 4)
return SetClassLongPtr64(hWnd, nIndex, dwNewLong);
else
return new IntPtr(SetClassLongPtr32(hWnd, nIndex, unchecked((uint)dwNewLong.ToInt32())));
}
private const int GCL_HBRBACKGROUND = -10;
private const int COLOR_WINDOW = 5;
[DllImport("user32.dll", EntryPoint = "SetClassLong")]
public static extern uint SetClassLongPtr32(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetClassLongPtr")]
public static extern IntPtr SetClassLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll")]
static extern IntPtr GetSysColorBrush(int nIndex);
}
Есть два решения, описанные здесь: http://wieser-software.blogspot.co.uk/2012/06/wpf-window-rendering-woes.html
- Подключите WndProc, обработайте WM_ERASEBKGND и нарисуйте систему WINDOW_COLOR на фоне или в другом цвете в соответствии с темой вашего приложения.
Вызовите SetClassLong, чтобы установить фоновую кисть класса окна
SetClassLong(Handle, GCL_HBRBACKGROUND, GetSysColorBrush(COLOR_WINDOW));
Я считаю, что временный черный фон - это проблема WPF, связанная с тем фактом, что WPF использует DirectX в качестве механизма рендеринга, и при изменении размеров окон он должен синхронизировать рисование с системой управления окнами. Это также может объяснить, почему кнопка перемещается по отношению к окну при перетаскивании границы окна. Рисование не-клиентской области окна происходит намного медленнее, чем рисование того, что находится внутри окна, и если вы быстро перемещаете мышь на медленном компьютере, расхождения между границей и внутренними границами окна, вероятно, будут более заметными.
Предположительно, это происходит только в Vista с включенным Aero, и это должно быть исправлено в Vista SP1. Тем не менее, я только что проверил на SP2, и я все еще видел немного черного фона, но только когда Aero был включен. Моя видеокарта довольно быстрая, поэтому это было едва заметно.
Если мой анализ верен, единственный способ решить эту проблему - получить более быструю графическую карту или отключить Aero.
В других ответах рассказывалось, как залить другой цвет фона, чтобы попытаться смягчить эффект медленного рисования WPF.
Я не могу предложить никакой магии, чтобы ускорить WPF, но я могу дать некоторое представление о том, откуда берутся черные.
Визуальная ошибка на вашем первом снимке экрана связана с дополнительной проблемой изменения размера, добавленной Aero, и существует частичный обходной путь.
Я боролся с проблемой уродливого live-resize в нативных приложениях Win32 и создал сводку вопросов / ответов, в которой собраны 10-летние публикации о проблемах изменения размера и предложены некоторые новые идеи (слишком долго, чтобы вставить содержимое в этот вопрос). Посмотри пожалуйста: