Способ иметь отдельную реализацию выглядит следующим образом.
//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 или других.
Вам нужно использовать буфер для рисования. Вы можете создать память 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
глобальным и создав / уничтожьте его только один раз .
blockquote>ReleaseDC(hwndDesktop, hdcDesktop); DeleteDC(hdcDesktop); //<- not required
DeleteDC(hdcDesktop)
не требуется.hdcDesktop
был изGetDC
, он очищенReleaseDC
blockquote>hbm = CreateCompatibleBitmap(...) SelectObject(hdcCapture, hbm); ... DeleteObject(hbm);
Вы также должны восстановить старое растровое изображение следующим образом:
hbm = CreateCompatibleBitmap(...) auto oldbitmap = SelectObject(hdcCapture, hbm); ... //cleanup SelectObject(hdcCapture, oldbitmap); DeleteObject(hbm);
Хотя если вы не восстановите старое растровое изображение, окна будут пытаться исправить ошибку в любом случае, поэтому в большинстве случаев не будет никакой проблемы.