2016-09-04 3 views
-5

Каждый пример кода, который я видел, - это GetDC и releaseDC снова и снова. (или BeginPaint/EndPaint) Но я думаю, что рисование экрана происходит очень часто (особенно в игре), хранить их в памяти лучше, чем получать и отпускать все время.Win32API) Зачем мне снова и снова получать GetDC и ReleaseDC?

Так что я действительно хотел бы сохранить mainDC как глобальный и просто использовать его, только отпустите его, когда программа закончится. Но почему люди этого не делают? (возможно, затраты на прием/выпуск DC очень малы?)

case WM_CREATE: 
    hdc = GetDC(hWnd); //hdc is declared as global HDC 
    MyBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1)); 
    return 0; 
case WM_PAINT: 
    MemDC = CreateCompatibleDC(hdc); 
    OldBitmap = (HBITMAP)SelectObject(MemDC, MyBitmap); 
    BitBlt(hdc, 0, 0, 300, 300, MemDC, 0, 0, SRCCOPY); 
    SelectObject(MemDC, OldBitmap); 
    DeleteDC(MemDC); 
    return 0; 
+4

* «Но почему люди этого не делают?» * - Потому что это все неправильно , Таким образом, вы сохранили дешевую операцию «GetDC» только для того, чтобы назвать дорогостоящую на каждом перерисовке («CreateCompatibleDC»). И так как вы никогда не называете 'BeginPaint' /' EndPaint', недопустимая область никогда не проверяется, вызывая непрерывные сообщения 'WM_PAINT', даже если нет ничего, чтобы рисовать. Вам нужно научиться тому, как это работает, прежде чем пытаться оптимизировать. – IInspectable

+0

Люди не делают этого так, потому что в документации говорится, что вы не можете. DC не следует кэшировать, как это, если вы не проявляете особой осторожности, чтобы создать свой класс окна с соответствующими флагами, которые вы не должны делать. DC должны быть временными объектами, создаваемыми только тогда, когда это необходимо, и располагаются сразу же после этого. Получение DC с 'GetDC' достаточно дешево, что это хорошо отразилось на 286 процессорах. Это гарантировано *, чтобы быть достаточно быстрым на любом кремнии, который вы используете сейчас. –

+0

@CodyGray Ничего себе, мое любопытство просто сдулось! Спасибо всем за ответ. – JokyDandy

ответ

0

Код, представленный здесь, неверен. Прежде всего, вам нужно прочитать немного больше документации. Вот полезная ссылка: Painting and Drawing. В основном есть два способа обновить окно:

  • В ответ на сообщение WM_PAINT. Используйте функции BeginPaint()/EndPaint(), чтобы правильно рисовать область клиента. Это сообщение отправляется системой, когда часть клиентской области «недействительна» (в результате изменения размера, восстановления из минимизированного состояния, перемещения окна, ранее затеняющего его, или его программной недействительности). WM_PAINT - это сообщение с низким приоритетом, полученным непосредственно перед отправкой очереди сообщений
  • В частности, для рисования части или всей клиентской области без наличия на ней недействительной области. Используйте GetDC()/ReleaseDC() для этого. Полезно, если вы хотите сразу же увидеть изменения , когда приложение (CPU) занято.

Дать код для обработки сообщения WM_PAINT, как правило, почти обязательные, а конкретно рисунка, а также не является обязательным, в зависимости от требований приложения.

Никогда не отправляйте или не отправляйте сообщение WM_PAINT самостоятельно, вместо этого недействительным части или всей клиентской области - приложение получит сообщение WM_PAINT перед прохождением. Если вы хотите, чтобы живопись происходила сразу, вызовите UpdateWindow() - это обходит очередь сообщений.

0

Последнее обновление (август 2016 г.) в Windows 10 предотвращает повторное использование контекстов устройства принтера. После печати одного документа Windows 10 откажется печатать снова с тем же DC. Всегда было предпочтительной практикой создавать новый DC для каждого документа, но теперь это похоже на требование в Windows 10.