简体   繁体   English

如何使用GDI在Ca ++中使用GDI绘制窗口(而不是创建图像)?

[英]How to draw in C++ with Cairo to a window using GDI (instead of creating an image)?

I managed to find this code snippet and compile it with 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_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;
}

As you can see, it create an image with the text "Hello World" and saved it on the drive. 如您所见,它创建一个带有“Hello World”文本的图像并将其保存在驱动器上。 How do I go about creating a win32 surface and draw to a window instead? 如何创建win32曲面并绘制到窗口?

I am failing to use: cairo_win32_surface_create 我没有使用: cairo_win32_surface_create

It requires a hdc and I don't know what that is. 它需要一个hdc ,我不知道那是什么。 I tried to read a few tutorials but none seems to walk you through printing to a new window. 我试着阅读一些教程,但似乎没有人会引导您打印到新窗口。

I found this link: http://windrealm.org/cairo-gdi/ 我找到了这个链接: http//windrealm.org/cairo-gdi/

It has a working demo but it uses int WINAPI WinMain . 它有一个工作演示,但它使用int WINAPI WinMain I don't wish to use that. 我不想用它。

There are several ways to get a handle to a device context in Windows. 有几种方法可以在Windows中获取设备上下文的句柄。 For instance it is typical that the WM_PAINT handler will call BeginPaint to acquire a device context, update the contents to the window and then call EndPaint . 例如,通常WM_PAINT处理程序将调用BeginPaint来获取设备上下文,将内容更新到窗口然后调用EndPaint In cases where BeginPaint and EndPaint cannot be used (eg outside of a WM_PAINT message) you can use GetDC update the window and then call ReleaseDC . 如果无法使用BeginPaintEndPaint (例如,在WM_PAINT消息之外),您可以使用GetDC更新窗口,然后调用ReleaseDC

The device contexts returned by BeginPaint and GetDC allow you to draw directly to a window. BeginPaintGetDC返回的设备上下文允许您直接绘制到窗口。 Sometimes however you want to draw directly to a bitmap. 但有时您想直接绘制位图。 In this case you would call CreateCompatibleDC , select the bitmap you want to draw to, do your drawing and then call DeleteDC . 在这种情况下,您将调用CreateCompatibleDC ,选择要绘制的位图,执行绘图,然后调用DeleteDC

In your case what you're looking for is something like the following: 在您的情况下,您正在寻找的是类似以下内容:

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

If you do not want to create a window at this stage (since you are simply saving an image) you can probably get away with using the desktop window to acquire a device context. 如果您不想在此阶段创建窗口(因为您只是保存图像),您可以使用桌面窗口获取设备上下文。

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

There are other calls that can be used to acquire or create a device context. 还有其他调用可用于获取或创建设备上下文。 You can find a list of these and related functions here 您可以在此处找到这些功能和相关功能的列表

Creating and using a window is a bit more involved so I'm going to provide you with the basic steps and some sample code that you can use to play around with. 创建和使用窗口有点复杂,所以我将为您提供基本步骤和一些可用于解决的示例代码。 To create and use a window... 创建和使用窗口......

  • Register a window class with RegisterClass 注册窗口类RegisterClass
  • Create the window with CreateWindow or CreateWindowEx 使用CreateWindowCreateWindowEx创建窗口
  • Process messages with a message pump by calling GetMessage , TranslateMessage and DispatchMessage 通过调用GetMessageTranslateMessageDispatchMessage处理带消息泵的消息

Additionally you will have to implement a function to handle processing of window messages such as WM_PAINT . 此外,您还必须实现一个函数来处理窗口消息的处理,例如WM_PAINT

NOTE: The following code is UNTESTED but should be correct. 注意:以下代码是UNTESTED但应该是正确的。

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;
}

I found the easiest way for beginners to open a window and draw some lines into it, is downloading and setting up the gtk+ and using ZetCode's tutorials. 我找到了初学者打开窗口并在其中绘制一些线条的最简单方法,即下载并设置gtk +并使用ZetCode的教程。

You will probably need to download GTK from here: http://gtk.hexchat.org/ 您可能需要从这里下载GTK: http//gtk.hexchat.org/

Setting up Gtk+: Using GTK+ in Visual C++ 设置Gtk +: 在Visual C ++中使用GTK +

Cairo tutorials: http://zetcode.com/gfx/cairo/ 开罗教程:http: //zetcode.com/gfx/cairo/

Remember to include all the GTK's dll files in the directory where your compiled executable is. 请记住将所有GTK的dll文件包含在已编译的可执行文件所在的目录中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM