Буфер не соответствует задаваемым параметрам.Проблемы с Dpi

277
05 мая 2022, 20:20

Делаю программу которая поверх целевого окна будет рисовать то что мне нужно,но когда я рисую,отрисовка идет не на те координаты,которые я указал.Более того,размер буфера почему то не соответствует тем параметрам которые я задаю.Так я инициализирую d2d:

ID2D1Factory* pFactory;
ID2D1HwndRenderTarget* pRenderTarget;
ID2D1SolidColorBrush* ColorBrush;
bool init_render()
{
    D2D1_FACTORY_OPTIONS CreateOpt = { D2D1_DEBUG_LEVEL_NONE };
    if (S_OK != D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), &CreateOpt, (void**)&pFactory))
    {
        MessageBox(0, "D2D1CreateFactory", "ERROR", MB_OK | MB_ICONERROR);
        return 0;
    }
    create_canvas();
    return 1;
}
void create_canvas()
{
    RECT rc;
    GetClientRect(targetHWND, &rc);
    //std::cout<< rc.right - rc.left <<" "<< rc.bottom - rc.top<<std::endl;
    pFactory->CreateHwndRenderTarget(
        D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_HARDWARE, D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED)),//D2D1_RENDER_TARGET_TYPE_DEFAULT
        D2D1::HwndRenderTargetProperties(myHWND, D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)),
        &pRenderTarget);
    pRenderTarget->CreateSolidColorBrush(color_brush, &ColorBrush);
}

Размер своего окна я подстраиваю в цикле под размер окна над которым мы будем рисовать. Так же в обработчике сообщений своего окна меняю размер буфера при смене размера целевого окна:

LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_SIZE:
        if (pRenderTarget != NULL)pRenderTarget->Resize(D2D1::SizeU((UINT)LOWORD(lParam), (UINT)HIWORD(lParam)));
        return 0;
    case WM_SYSCOMMAND:
        if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
            return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
}

Но если получить размер буфера,то он не равен размерам которые я ему задавал,точнее не равен размеру целевого окна в пикселях:

void rect(float x,float y,float h,float w) {
    D2D1_SIZE_F rtSize= pRenderTarget->GetSize();//получаем размер буфера 
    int width = static_cast<int>(rtSize.width);
    int height = static_cast<int>(rtSize.height);
    std::cout <<"Render target: "<< width<<" " << height << std::endl;//выводим размер буфера
    ColorBrush->SetColor({0.0f,1.0f,0.0f,1.0f});
    pRenderTarget->DrawRectangle(D2D1::RectF(x, y, x+h, y+w), ColorBrush,1.0f);//пробуем рисовать по заданным координатам
}

Как результат,буфер не того размера,и отрисовка происходит не туда куда я задал.Эффект получается,как будто бы координаты(в пикселях),куда я говорю рисовать в полтора раза(примерно) больше.

Answer 1

Покопался и нашел ответ.Как оказалось,windows использует масштабирование и когда пользователь устанавливает значение больше 100%,меняется системный DPI.Когда мы создаем контекст directx,он по умолчанию использует системный dpi.Чтобы задать dpi вручную(в моем случае нужно 100% -это 96dpi по горизонтали и вертикали,так как у меня квадратные пиксели),надо задать в интерфейс ID2D1RenderTarget dpi вручную:

pRenderTarget->SetDpi(96, 96);

Либо же при инициализации:

pFactory->CreateHwndRenderTarget(
        D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_HARDWARE, D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),96,96),//D2D1_RENDER_TARGET_TYPE_DEFAULT
        D2D1::HwndRenderTargetProperties(cheatEspHWND, D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)),
        &pRenderTarget);

Спасибо @Qwertiy за наводящий ответ.

READ ALSO
error: no match for &#39;operator[]

error: no match for 'operator[]

Ошибка возникла на первом cout, полный текст ошибки:

128
Создать иерархию

Создать иерархию

Тема наследованиеЗадача -Разработать иерархическую структуру классов для обработки данных

240
Qt, потоки и объекты. Как правильно?

Qt, потоки и объекты. Как правильно?

Я много читал о том, как работать с потоками в QtКто-то наследуется от QThread и переопределяет void run();, кто-то наследует класс worker от QObject, связывает...

255