GDI + мерцание

Способ иметь отдельную реализацию выглядит следующим образом.

//inner_foo.h

template <typename T>
struct Foo
{
    void doSomething(T param);
};


//foo.tpp
#include "inner_foo.h"
template <typename T>
void Foo<T>::doSomething(T param)
{
    //implementation
}


//foo.h
#include <foo.tpp>

//main.cpp
#include <foo.h>

inner_foo имеет форвардные объявления. foo.tpp имеет реализацию и включает inner_foo.h; и foo.h будет иметь только одну строку, чтобы включить foo.tpp.

Во время компиляции содержимое foo.h копируется в foo.tpp, а затем весь файл копируется в foo.h после который он компилирует. Таким образом, ограничений нет, и именование согласовано в обмен на один дополнительный файл.

Я делаю это, потому что статические анализаторы для кода разбиваются, когда он не видит передовые объявления класса в * .tpp. Это раздражает при написании кода в любой среде IDE или с помощью YouCompleteMe или других.

0
задан genpfault 13 July 2018 в 17:26
поделиться

1 ответ

Вам нужно использовать буфер для рисования. Вы можете создать память dc или использовать BeginBufferedPaint:

#include <uxtheme.h>
#pragma comment (lib, "uxtheme.lib")
...

case WM_PAINT:
{
    hdc = BeginPaint(hwnd, &ps);
    RECT rc;
    GetClientRect(hwnd, &rc);
    HDC memdc;
    auto hbuff = BeginBufferedPaint(hdc, &rc, BPBF_COMPATIBLEBITMAP, NULL, &memdc);
    Paint(memdc);
    EndBufferedPaint(hbuff, TRUE);
    EndPaint(hwnd, &ps);
    break;
}

Это должно исправить мерцание. Я бы предложил удалить таймер и обновить краску в перемещении мыши:

case WM_MOUSEMOVE:
    InvalidateRect(hwnd, NULL, NULL);
    break;

Вы также можете изучить флаг WS_EX_LAYERED с помощью SetLayeredWindowAttributes, это создаст прозрачное окно, которое отобразит рабочий стол под этим. Для простого рисования текста на самом деле не потребуется GDI +.

Кроме того, для большинства его классов Gdiplus имеет разные конструкторы, что позволяет избежать использования new / delete. Пример:

void DrawCursorCoords(Gdiplus::Graphics &graphics, Gdiplus::Bitmap&, Gdiplus::Color c)
{
    POINT cursorPos;
    GetCursorPos(&cursorPos);

    std::wstring x = std::to_wstring(cursorPos.x);
    std::wstring y = std::to_wstring(cursorPos.y);

    Gdiplus::Font font(L"Consolas", (Gdiplus::REAL)16);
    Gdiplus::SolidBrush brush(c);

    graphics.DrawString(x.c_str(), (int)x.length(), &font,
        Gdiplus::PointF((Gdiplus::REAL)cursorPos.x, (Gdiplus::REAL)cursorPos.y),
        &brush);

    graphics.DrawString(y.c_str(), (int)y.length(), &font,
        Gdiplus::PointF((Gdiplus::REAL)cursorPos.x, (Gdiplus::REAL)(cursorPos.y + 16)),
        &brush);
}

void Paint(HDC &hdc)
{
    Gdiplus::Graphics gfx(hdc);
    Gdiplus::Bitmap bmap(hbm, (HPALETTE)0);

    gfx.DrawImage(&bmap, 0, 0,
        GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));

    if(GetAsyncKeyState(VK_LBUTTON))
        DrawCursorCoords(gfx, bmap, (Gdiplus::Color)Gdiplus::Color::Red);
    else
        DrawCursorCoords(gfx, bmap, (Gdiplus::Color)Gdiplus::Color::Green);
}

Или вы можете объявить Gdiplus::Bitmap *bmap = new Gdiplus::Bitmap(hbm, NULL);, это делает копию hbm, поэтому вы можете сделать это более эффективным, объявив bmap глобальным и создав / уничтожьте его только один раз .

ReleaseDC(hwndDesktop, hdcDesktop);
DeleteDC(hdcDesktop); //<- not required

DeleteDC(hdcDesktop) не требуется. hdcDesktop был из GetDC, он очищен ReleaseDC

hbm = CreateCompatibleBitmap(...)
SelectObject(hdcCapture, hbm);
...
DeleteObject(hbm);

Вы также должны восстановить старое растровое изображение следующим образом:

 hbm = CreateCompatibleBitmap(...)
 auto oldbitmap = SelectObject(hdcCapture, hbm);
 ...
 //cleanup
 SelectObject(hdcCapture, oldbitmap);
 DeleteObject(hbm);

Хотя если вы не восстановите старое растровое изображение, окна будут пытаться исправить ошибку в любом случае, поэтому в большинстве случаев не будет никакой проблемы.

6
ответ дан Barmak Shemirani 17 August 2018 в 12:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: