2015-11-02 14 views
1

Я работаю над программой, которая будет иметь много растровых изображений DIB (созданных CreateDIBSection), и им придется рисовать много текста на них с помощью Win API.Насколько дешево/дорого стоит DC в Win API?

Чтобы рисовать на растровом изображении, Windows требует контекста устройства, созданного CreateCompatibleDC.

И вот теперь два подхода:

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

  2. Или я могу создать постоянный ток только тогда, когда мне нужно нарисовать растровое изображение, вызвать функции рисования и удалить DC.

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

Но разве это не слишком дорого провести длинный живой DC для каждого растрового изображения?

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

+0

Распространенной практикой является вызов "' GetDC() '" (или GetDCEx()), рисовать, а затем "' ReleaseDC() '". – paulsm4

+0

Мне не нужно рисовать на окне, поэтому GetDC не вариант. CreateCompatibleDC - это то, что нужно использовать. Это DC, который не связан с окном. – johnfound

+0

@selbie Хм, может быть, вы имеете в виду №2? И я все еще не чувствую, что знаю ответ на вопрос. – johnfound

ответ

3

GDI objects ограничены как для каждого процесса, так и для сеанса. Вы конкурируете за ресурсы со всеми другими процессами, запущенными в одном сеансе. Имея это в виду, вы должны потреблять ресурсы GDI только тогда, когда это необходимо (вариант 2 в вашем вопросе).

Запись блога Марка Руссиновича Pushing the Limits of Windows: USER and GDI Objects – Part 2 идет в большом количестве деталей. Подводя итог сути, вот список ограничений, что оконный менеджер место на GDI ресурсах:

  • 10000 объектов GDI в процесс (значение по умолчанию, настраиваемого с помощью ключа реестра HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Windows \ GDIProcessHandleQuota).
  • 65.535 Объекты GDI для сеанса пользователя.
  • Предел памяти объекта GDI является пределом выгружаемого пула (см. Pushing the Limits of Windows: Paged and Nonpaged Pool).
2

Вот тест, чтобы узнать, сколько времени потребуется, чтобы позвонить по телефону CreateCompatibleDC. Я считаю, что для каждого вызова требуется в среднем от 10 до 15 микросекунд. Это относительно быстро по сравнению с BitBlt, специально для больших изображений. Поэтому нет большого преимущества в хранении памяти DC.

case WM_PAINT: 
{ 
    static HBITMAP hbitmap = (HBITMAP)LoadImage(0, L"path.bmp", 
     IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); 
    std::wostringstream oss; 

    PAINTSTRUCT ps; 
    HDC hdc = BeginPaint(hwnd, &ps); 

    auto start = std::chrono::system_clock::now(); 
    auto memdc = CreateCompatibleDC(hdc); 
    oss << L"CreateCompatibleDC: " 
     << (std::chrono::system_clock::now() - start).count()/10 << "\n"; 

    auto oldbitmap = SelectObject(memdc, hbitmap); 

    start = std::chrono::system_clock::now(); 
    BitBlt(hdc, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, memdc, 0, 0, SRCCOPY); 
    oss << L"BitBlt: " 
     << (std::chrono::system_clock::now() - start).count()/10 << "\n"; 

    SelectObject(memdc, oldbitmap); 
    DeleteDC(memdc); 

    EndPaint(hwnd, &ps); 

    OutputDebugString(oss.str().c_str()); 
    break; 
} 

Результат на Windows 10:

Результат для 24bit 5MB растрового изображения:

CreateCompatibleDC: 17 микросекунд
BitBlt: 2500 микросекунд

Результат для 8bit 275kb:

CreateCompatibleDC: 12 микросекунд
BitBlt: 500 микросекунд

 Смежные вопросы

  • Нет связанных вопросов^_^