【问题标题】:C++ resizing issueC ++调整大小问题
【发布时间】:2021-01-06 00:14:34
【问题描述】:

我已经成功打开了一个 win32 窗口(没有 OpenGL 上下文)。打开窗口,然后调整它的大小会导致很多问题。我们如何正确处理 win32 api 中的大小调整?我用 WS_OVERLAPPEDWINDOW 创建了一个窗口并使窗口可调整大小。主要是,我尝试使用 WM_SIZE 事件处理程序来处理大小调整。

#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include <iostream>
using namespace std;
HINSTANCE hInstanceGlobal;
LRESULT CALLBACK wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    PAINTSTRUCT ps;
    switch (message) {
    default:
        return DefWindowProcA(hWnd, message, wParam, lParam);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_PAINT:
        BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        return 0;

    case WM_SIZE:
        SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
        PostMessage(hWnd, WM_PAINT, 0, 0);
        return 0;
    case WM_KEYDOWN:
        
        break;
    case WM_SETCURSOR:
        if (LOWORD(lParam) == HTCLIENT) {
            SetCursor(LoadCursor(NULL, IDC_ARROW));
            return TRUE;
        }
        break;
    }

    return DefWindowProcA(hWnd, message, wParam, lParam);
    
}
int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR     lpCmdLine,
    int       nShowCmd) {

#ifdef _DEBUG
    AllocConsole();
    //SetWindowPos(GetConsoleWindow(), 0, 1920, 200, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
    AttachConsole(GetCurrentProcessId());
    freopen("CON", "w", stdout);
    
#endif  
    hInstanceGlobal = hInstance;
    const char* CLASSNAME = "APIOPENGL";
    WNDCLASS cl = { };
    cl.lpfnWndProc = wndproc;
    cl.hCursor = LoadCursor(NULL, IDC_ARROW);
    cl.hInstance = hInstance;
    cl.lpszClassName = CLASSNAME;
    
    RegisterClass(&cl);

    HWND hWnd = CreateWindowEx(
        WS_EX_APPWINDOW|WS_EX_CLIENTEDGE,
        CLASSNAME,
        "Opengl Window",
        WS_OVERLAPPEDWINDOW |WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL
    );
    if (hWnd == NULL)
    {
        return 0;
    }
    ShowWindow(hWnd, nShowCmd);

    MSG msg;
    MessageBox(NULL, (char*)GetLastError(), "Hello", NULL);
    bool bRet;
    while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
        
        if (GetKeyState(VK_RMENU) & 0x8000)
        {
            cout << "Pressed" << endl;
        }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        
    }
}

【问题讨论】:

  • 对于WM_SIZE 上的SetWindowPos ?这是错误的。并且不需要WM_PAINT 帖子。请致电InvalidateRect。但通常我们需要句柄WM_SIZE,如果我们需要移动子窗口(我们是“框架”)或重新创建位图等。在你的情况下,你根本不需要句柄WM_SIZE。评论您的case WM_SIZE: 并查看
  • 您可以在网上找到许多示例:developer.microsoft.com/en-us/windows/samples。 Win32 API 是低级的,所以从一本书或一个示例开始都会给你一个巨大的开始。 您还应该能够找到特定于 OpenGL 的示例,这些示例已经具备基本...

标签: c++ winapi


【解决方案1】:

看看这个:Resize window with Win32 API

在您的 WM_PAINT 处理程序中,您可能会得到奇怪的结果,因为您没有调用 FillRect 函数。

    case WM_PAINT:
       PAINTSTRUCT ps;
       HDC hdc = BeginPaint(m_hwnd, &ps);
       FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 6));
       EndPaint(m_hwnd, &ps);

【讨论】:

  • 如果您能告诉我们您将如何正确调整窗口大小并更新窗口内的内容,将会非常有帮助。
  • @dudewritecode 这是 Windows 101。Windows 已经存在 30 年了,这些基本技术没有改变。我建议您查阅有关该主题的众多书籍中的一本。
【解决方案2】:

截图中的问题(黑色背景)是因为你没有设置窗口类的hbrBackground成员。根据document

当此成员为 NULL 时,应用程序必须绘制自己的 每当请求在其客户区域中绘制背景时。到 确定是否必须绘制背景,应用程序可以 处理WM_ERASEBKGND 消息或测试fErase PAINTSTRUCT 结构的成员,由 BeginPaint 函数。

和@Stra 的回答一样,用FillRect 填充背景。

或者初始化hbrBackground:

hInstanceGlobal = hInstance;
const char CLASSNAME[] = "APIOPENGL";
WNDCLASS cl = { };
cl.lpfnWndProc = wndproc;
cl.hCursor = LoadCursor(NULL, IDC_ARROW);
cl.hInstance = hInstance;
cl.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
cl.lpszClassName = CLASSNAME;

RegisterClass(&cl);

那么你就不需要处理WM_SIZE这个消息了。

另外,你不需要调用GetKeyState来获取VK_RMENU key Presse事件,只需处理WM_SYSKEYDOWN消息并指明该键是否为扩展键:

/*case WM_SIZE:
    SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
    PostMessage(hWnd, WM_PAINT, 0, 0);
    return 0;*/
case WM_SYSKEYDOWN:
    if (VK_MENU == wParam)
    {
        BOOL bit = (lParam >> 24) & 1;
        if (bit)
            cout << "Pressed" << endl;
    }
    return 0;

【讨论】:

  • 嗨,@dudewritecode,这能回答你的问题吗?如果您有任何问题,请随时与我联系,如果这对您有帮助,也请随时accept此答案。
猜你喜欢
  • 1970-01-01
  • 2021-09-20
  • 2011-07-05
  • 2013-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多