Как нарисовать в C ++ с Cairo в окно, используя GDI (вместо создания изображения)?

Мне удалось найти этот фрагмент кода и скомпилировать его с помощью Cairo:

#define LIBCAIRO_EXPORTS
#include <cairo/cairo.h>
#include <cairo/cairo-win32.h>

int main(int argc, char** argv)
{
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 240, 80);
cr = cairo_create (surface);

cairo_select_font_face (cr, "serif", CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (cr, 32.0);
cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
cairo_move_to (cr, 10.0, 50.0);
cairo_show_text (cr, "Hello, World");
cairo_destroy (cr);
cairo_surface_write_to_png (surface, "hello.png");
cairo_surface_destroy (surface);

return 0;
}

Как видите, он создает изображение с текстом «Hello World» и сохраняет его на диске.
Как мне создать поверхность win32 и нарисовать вместо нее окно?

Я не могу использовать: cairo_win32_surface_create

Требуется hdc и я не знаю что это. Я попытался прочитать несколько учебных пособий, но ни один из них не помог вам распечатать в новом окне.

Я нашел эту ссылку:
http://windrealm.org/cairo-gdi/

У него есть рабочая демонстрация, но она использует int WINAPI WinMain, Я не хочу этим пользоваться.

4

Решение

Есть несколько способов получить дескриптор контекста устройства в Windows. Например, типично, что WM_PAINT обработчик позвонит BeginPaint чтобы получить контекст устройства, обновите содержимое окна и затем вызовите EndPaint, В случаях, когда BeginPaint а также EndPaint не может использоваться (например, вне сообщения WM_PAINT), которое вы можете использовать GetDC обновить окно и затем вызвать ReleaseDC,

Контекст устройства, возвращаемый BeginPaint а также GetDC позволяют рисовать прямо в окне. Иногда, однако, вы хотите нарисовать прямо в растровое изображение. В этом случае вы бы позвонили CreateCompatibleDCвыберите растровое изображение, к которому хотите рисовать, сделайте свой рисунок и затем вызовите DeleteDC,

В вашем случае вы ищете что-то вроде следующего:

HDC dc = GetDC(windowHandle);
cairo_win32_surface_create(dc);
ReleaseDC(windowHandle, dc);

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

HWND windowHandle = GetDesktopWindow();
HDC dc = GetDC(windowHandle);
cairo_win32_surface_create(dc);
ReleaseDC(windowHandle, dc);

Существуют и другие вызовы, которые можно использовать для получения или создания контекста устройства. Вы можете найти список этих и связанных функций Вот

Создание и использование окна немного сложнее, поэтому я собираюсь предоставить вам основные шаги и пример кода, с которым вы можете поиграть. Чтобы создать и использовать окно …

  • Зарегистрировать класс окна с RegisterClass
  • Создать окно с CreateWindow или же CreateWindowEx
  • Обрабатывать сообщения с помощью рассылки сообщений, вызывая GetMessage, TranslateMessage а также DispatchMessage

Кроме того, вам нужно будет реализовать функцию для обработки сообщений окна, таких как WM_PAINT,

ПРИМЕЧАНИЕ. Следующий код является НЕПРОВЕРЕННЫМ, но должно быть правильным.

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if(message == WM_PAINT)
{
HDC dc;
PAINTSTRUCT ps;
dc = BeginPaint(hwnd, &ps);

// do your drawing here

EndPaint(hwnd, &ps);
}

return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szClassName[] = TEXT("DrawSurfaceClass");
HWND         hwnd;
MSG          msg;
WNDCLASS     wndclass;

///////////////////////////////////////////////////////////
//  Register a window "class"///////////////////////////////////////////////////////////
wndclass.style         = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc   = WndProc;
wndclass.cbClsExtra    = 0;
wndclass.cbWndExtra    = 0;
wndclass.hInstance     = hInstance;
wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground =(HBRUSH)COLOR_WINDOW;
wndclass.lpszMenuName  = NULL;
wndclass.lpszClassName = szClassName;

if(!RegisterClass(&wndclass))
{
//  error
return 1;
}

///////////////////////////////////////////////////////////
//  Create the window and display it (if iCmdShow says so)
///////////////////////////////////////////////////////////
hwnd = CreateWindow(
szAppName,
TEXT("Draw Surface"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);

ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);///////////////////////////////////////////////////////////
//  Run the message pump so the window proc recieves events
///////////////////////////////////////////////////////////
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
5

Другие решения

Я нашел самый простой способ для новичков открыть окно и нарисовать в нем несколько линий, это загрузить и настроить gtk + и использовать учебные пособия ZetCode.

Вам, вероятно, нужно скачать GTK отсюда:
http://gtk.hexchat.org/

Настройка Gtk +:
Использование GTK + в Visual C ++

Каирские уроки:
http://zetcode.com/gfx/cairo/

Не забудьте включить все DLL-файлы GTK в каталог, где находится ваш скомпилированный исполняемый файл.

0