簡體   English   中英

用 WINAPI 創建的窗口不是繪圖對象。 有什么問題?

[英]Window created with WINAPI is not drawing objects. What's the problem?

我有我的窗口文件( Window.h ):

LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);

class Window
{
private:
    HWND hWnd;
    HINSTANCE hInstance;
    bool running = true;
    const char* ID = "WINAPI_JVM64";
public:
    Window()
    {
        init();
    }

    virtual void draw(Gdiplus::Graphics*) = 0;

    void init()
    {
        hInstance = (HINSTANCE)GetModuleHandle(NULL);
        WNDCLASS wc;

        wc = {};
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = MessageHandler;
        wc.hInstance = hInstance;
        wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
        wc.hCursor = LoadCursor(NULL, IDC_HAND);
        wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
        wc.lpszClassName = ID;

        assert(RegisterClass(&wc));

        hWnd = CreateWindow(ID, "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                       200, 200, 400, 400, NULL, NULL, hInstance, NULL);

        ShowCursor(true);
        SetForegroundWindow(hWnd);
        SetFocus(hWnd);
    }
    void run()
    {
        MSG msg;
        PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE);
        while(running)
        {
            if(PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
            {
                if(msg.message == WM_QUIT)
                    running = false;

                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            else
            {
                // Here, the draw function is called.
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hWnd, &ps);
                Gdiplus::Graphics* g = Gdiplus::Graphics::FromHDC(hdc);
                draw(g);
                EndPaint(hWnd, &ps);
            }
        }
        UnregisterClass(ID, hInstance);
    }
};

和主文件( main.cpp ):

#include "Window.h"

LRESULT CALLBACK MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_CLOSE:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

class AppWindow : public Window
{
public:
    void draw(Gdiplus::Graphics* g) override
    {
        Gdiplus::SolidBrush brown_brush(Gdiplus::Color(255, 128, 57, 0));
        g->FillRectangle(&brown_brush, 0, 0, 200, 200);
    }
};

int main()
{
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);

    AppWindow w;
    w.run();

    Gdiplus::GdiplusShutdown(gdiplusToken);
    return 0;
}

我的問題是它不會畫!

它處理每條消息,一切都很好,但它不繪制。 甚至發送了WM_PAINT類型的消息,但沒有任何反應。

你能發現問題嗎?

我只想要一個窗口類,它有一個可覆蓋的draw()函數和一個處理所有事件的run()函數,例如WM_LBUTTONDOWN 所有這些工作正常,屏幕只是保持空白。

另外,我無法關閉窗口,當按下右上角的X按鈕時,窗口只是停留; 只有在調整大小並快速按下X ,它才會關閉。

正如你所看到的,我有一些非常奇怪的行為,我不知道問題是什么。

你的繪圖邏輯在錯誤的地方。 處理WM_PAINT消息時,它需要在MessageHandler內部。 如果需要繪制窗口並且沒有其他消息待處理, PeekMessage()將生成WM_PAINT消息。 您不能從WM_PAINT處理程序的外部在窗口上繪圖。

此外,您在init()wc.hbrBackground分配了錯誤的值。 如果您使用像COLOR_WINDOW這樣的顏色常量,則需要向其添加1 WNDCLASS文檔中對此進行了詳細說明

此外,在run() ,您創建消息隊列的第一個PeekMessage()會丟棄初始消息(如果有待處理的消息),則您的調度循環不會處理該消息。 第一次調用應該使用PM_NOREMOVE標志。

另外,請注意在消息循環中過濾窗口消息的危險

話雖如此,請試試這個:

LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);

class Window
{
private:
    HWND hWnd;
    HINSTANCE hInstance;
    const char* ID = "WINAPI_JVM64";

public:
    Window()
    {
        init();
    }

    ~Window()
    {
        cleanup();
    }

    virtual void draw(Gdiplus::Graphics*) = 0;

    void init()
    {
        hInstance = (HINSTANCE)GetModuleHandle(NULL);

        WNDCLASS wc{};
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = &MessageHandler;
        wc.hInstance = hInstance;
        wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
        wc.hCursor = LoadCursor(NULL, IDC_HAND);
        wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
        wc.lpszClassName = ID;

        assert(RegisterClass(&wc));

        hWnd = CreateWindow(ID, "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                       200, 200, 400, 400, NULL, NULL, hInstance, this);
        assert(hWnd != NULL);

        ShowCursor(true);
        SetForegroundWindow(hWnd);
        SetFocus(hWnd);
    }

    void cleanup()
    {
        UnregisterClass(ID, hInstance);
    }

    void run()
    {
        MSG msg;
        PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);

        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
};
#include "Window.h"

LRESULT CALLBACK MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_NCCREATE:
        {
            Window *pThis = static_cast<Window*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams);
            SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pThis));
            break;
        }

        // DefWindowProc(WM_CLOSE) calls DestroyWindow(),
        // WM_CLOSE is not the right place to call PostQuitMessage()...
        //case WM_CLOSE:
        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        case WM_PAINT:
        {
            Window *pThis = reinterpret_cast<Window*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            if (pThis)
            {
                Gdiplus::Graphics* g = Gdiplus::Graphics::FromHDC(hdc);
                pThis->draw(g);
                delete g;
            }
            EndPaint(hWnd, &ps);
            return 0;
        }
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

class AppWindow : public Window
{
public:
    void draw(Gdiplus::Graphics* g) override
    {
        Gdiplus::SolidBrush brown_brush(Gdiplus::Color(255, 128, 57, 0));
        g->FillRectangle(&brown_brush, 0, 0, 200, 200);
    }
};

int main()
{
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);

    AppWindow w;
    w.run();

    Gdiplus::GdiplusShutdown(gdiplusToken);
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM