C++ 如何在C++;使用GDI(而不是创建图像)将Cairo连接到窗口?

C++ 如何在C++;使用GDI(而不是创建图像)将Cairo连接到窗口?,c++,c,cairo,C++,C,Cairo,我设法找到了这个代码片段,并用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_F

我设法找到了这个代码片段,并用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;
}
#定义LIBCAIRO#u导出
#包括
#包括
int main(int argc,字符**argv)
{
开罗曲面;
开罗*cr;
surface=cairo\u image\u surface\u create(cairo\u格式\u ARGB32,240,80);
cr=cairo_创建(曲面);
cairo\u选择字体\u面(cr,“衬线”,cairo\u字体\u倾斜\u法线,
开罗(字体、重量、粗体);
cairo_set_font_size(cr,32.0);
cairo_set_source_rgb(cr,0.0,0.0,1.0);
开罗(cr,10.0,50.0);
开罗秀(cr,“你好,世界”);
开罗大学(cr);
cairo_surface_write___png(surface,“hello.png”);
开罗·表面·破坏(表面);
返回0;
}
如您所见,它创建了一个带有文本“Hello World”的图像,并将其保存在驱动器上。 如何创建win32曲面并绘制到窗口

我无法使用:
cairo\u win32\u surface\u create

它需要一个
hdc
,我不知道那是什么。我试着阅读了一些教程,但似乎没有一本能帮助您完成打印到新窗口的过程

我找到了这个链接:


它有一个工作演示,但它使用
int-WINAPI-WinMain
。我不想使用它。

有几种方法可以在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);
还有其他调用可用于获取或创建设备上下文。您可以找到这些函数和相关函数的列表

创建和使用窗口要复杂一些,所以我将向您提供一些基本步骤和一些示例代码,您可以使用这些代码进行操作。要创建和使用窗口

  • 使用注册表类注册窗口类
  • 使用
    CreateWindow
    CreateWindowEx
  • 通过调用
    GetMessage
    TranslateMessage
    DispatchMessage
此外,您还必须实现一个函数来处理窗口消息的处理,例如
WM\u 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;
}

我发现初学者打开一个窗口并在其中画一些线的最简单方法是下载并设置gtk+和使用ZetCode的教程

您可能需要从以下位置下载GTK:

设置Gtk+:

开罗教程:


请记住将所有GTK的dll文件包含在编译的可执行文件所在的目录中。

HDC是设备上下文的句柄,它基本上是一个虚拟画布,其状态包括选定的画笔、选定的画笔和选定的位图。我希望这至少有一点帮助。如果你不熟悉Windows GDI开发,你可能想看看。您可能最感兴趣的是,我发现了这个链接,它展示了如何使用除win32 gdi之外的所有东西:我也发现了这个链接,它似乎部分地回答了我的问题:但它使用了我希望避免的winmain。甚至可能吗?您可以从控制台程序创建窗口,但必须运行消息循环才能正确操作它。从一个使用winmain.+1的示例开始比较容易,但是在WM_PAINT之外进行绘制通常是个坏主意。如果仔细看这个问题,你会发现它是一个没有消息循环的控制台程序
WM_PAINT
是正确的,但完整的答案要复杂得多。什么是窗口句柄?我已经看到“hwnd”提到很多次了。如何获取?@MarkRansom控制台应用程序不会阻止您使用消息泵,也不会阻止您创建窗口。我正在编辑它以包含窗口创建和消息循环。