Изменение размера окна вызывает черные полосы - PullRequest
3 голосов
/ 10 апреля 2010

У меня есть форма, которая устанавливает эти стили в конструкторе:

this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

И я рисую несколько прямоугольников в событии Paint. В форме нет элементов управления. Однако, когда я изменяю размер формы, в правой и нижней части формы появляются черные полосы. Есть ли способ избавиться от них? Я перепробовал все, слушая WM_ERASEBKGND в WndProc, вручную рисуя форму на WM_PAINT, реализуя пользовательский двойной буфер и т. Д. Могу ли я попробовать еще что-нибудь?

Я нашел это: https://connect.microsoft.com/VisualStudio/feedback/details/522441/custom-resizing-of-system-windows-window-flickers и похоже, что это ошибка в DWM, но я просто надеюсь, что смогу обойти это.

Обратите внимание, что я должен использовать двойную буферизацию, так как я хочу нарисовать довольно интенсивное графическое представление в событии Paint. Я разрабатываю в C # .NET 2.0, Win7.

Обновление статуса 1

Мне удалось избавиться от большинства черных полос, самостоятельно реализовав функцию изменения размера. Но есть еще небольшие глюки. Есть ли способ сделать операции resize и paint одновременно? Вот псевдокод того, что мне нужно сделать:

IntPtr hDC;
var size = new Size(250, 200);
IntPtr handle = API.PaintAndResizeBegin(this.Handle /* Form.Handle */,
                                        size.Width, size.Height, out hDC);
using (var g = Graphics.FromHdc(hDC)) {
    this.backBuffer.Render(g, size);
}
API.PaintAndResizeCommit(handle);

Есть ли способ реализовать приведенный выше код?

Вторым решением может быть резервное копирование всей формы, включая не клиентскую область. Но как это сделать? Я не хочу рисовать не клиентскую область, так как хочу сохранить хороший аэроэффект на Vista / 7. Любая помощь будет высоко оценена.

Обновление статуса 2

Похоже, что эта проблема неразрешима, поскольку она присутствует в Windows в каждом приложении. Мы можем только надеяться, что MS получит вдохновение в Mac OS X и предоставит соответствующие API в новой Windows.

Ответы [ 2 ]

1 голос
/ 21 июня 2010

Я нашел функцию, которая может рисовать и изменять размер окна одновременно - UpdateLayeredWindow.

Так что теперь можно создавать окна с изменяемым размером, которые не имеют полос при изменении размера. Тем не менее, вы должны нарисовать содержимое окна самостоятельно, так что это немного неудобно. Но я думаю, что при использовании WPF и UpdateLayeredWindow проблем быть не должно.


Обновление

Найдены проблемы. :-) При использовании UpdateLayeredWindow вы должны нарисовать границу окна самостоятельно. Итак, если вы хотите, чтобы стандартное окно было окрашено с помощью UpdateLayeredWindow с хорошим стеклянным эффектом в win7, вы прикручены.

Вкл. Microsft Connect - даже поток об этой проблеме, где Microsoft говорит, что это ошибка по конструкции, и если она когда-нибудь будет исправлена, то, вероятно, в Win8 или какой-либо более новой системе. Так что мы мало что можем с этим поделать.

0 голосов
/ 26 апреля 2010

Я обнаружил, что лучше не делать какой-либо пользовательский рендеринг непосредственно на поверхности формы. Вместо этого поместите закрепленный PictureBox в форму, создайте объект Bitmap, который будет отображаться в PictureBox, нарисуйте все на нем, используя метод System.Drawing.Graphics.FromImage(Image).

Я использовал этот метод с игровым циклом для создания простой игры-шутера (в стиле Crimsonland) и получил довольно хорошую производительность (с сглаженными линиями), выше 100 FPS.

...