在 SDL 2 中获取连续窗口大小调整事件

问题描述 投票:0回答:4

我使用以下结构来获取调整大小的 SDL 窗口的新宽度和高度:

if (sdl_set->GetMainEvent()->type == SDL_WINDOWEVENT)
{
  if (sdl_set->GetMainEvent()->window.event == SDL_WINDOWEVENT_RESIZED)
  {
    ScreenWidth = sdl_set->GetMainEvent()->window.data1;
    ScreenHeight = sdl_set->GetMainEvent()->window.data2;
    cout << "Window Resized!" << endl;
  }
}

但是使用这种结构,我只能在调整大小完成后(即完成拖动并释放鼠标按钮时)获取新数据。

如何在拖动窗口时持续获取新数据?

c++ sdl-2
4个回答
20
投票
static int resizingEventWatcher(void* data, SDL_Event* event) {
  if (event->type == SDL_WINDOWEVENT &&
      event->window.event == SDL_WINDOWEVENT_RESIZED) {
    SDL_Window* win = SDL_GetWindowFromID(event->window.windowID);
    if (win == (SDL_Window*)data) {
      printf("resizing.....\n");
    }
  }
  return 0;
}

int main() {
    SDL_Window* win = ...
    ...
    SDL_AddEventWatch(resizingEventWatcher, win);
    ...
}

使用SDL的EventWatch可以解决。


2
投票

如果您使用单线程,则使用

SDL_AddEventWatch
设置事件观察器是不够的。这是因为
SDL_PumpEvents
(由 sdl 直接或间接调用)在调整大小完成之前不会返回,从而有效地阻塞了您的线程。

要解决此问题,您可以在事件观察器中设置回调:

    void Window::HandleWindowEvent(const SDL_WindowEvent e)
    {
        switch(e.event)
        {
        ...
        case SDL_WINDOWEVENT_MOVED:
            if (_lastWindowMetrics.left != e.data1 || _lastWindowMetrics.top != e.data2)
            {
                _lastWindowMetrics.left = e.data1;
                _lastWindowMetrics.top = e.data2;
                _windowEvents.emplace_back(_lastWindowMetrics);

                _refresh(); // user callback that may be used to repaint the window
            }
            break;
        case SDL_WINDOWEVENT_RESIZED:
        case SDL_WINDOWEVENT_SIZE_CHANGED:
            if (_lastWindowMetrics.width != e.data1 || _lastWindowMetrics.height != e.data2)
            {
                _lastWindowMetrics.width = e.data1;
                _lastWindowMetrics.height = e.data2;
                _windowEvents.emplace_back(_lastWindowMetrics);

                _refresh(); // user callback that may be used to repaint the window
            }
            break;
         ...
        }

    }

我使用观察者机制来处理所有窗口事件,并且只使用

SDL_PumpEvents
而不使用
SDL_PollEvents

这与

glfwSetWindowRefreshCallback
提供的机制非常相似(如果你习惯了 glfw)。


0
投票

使用 SDL3:

_Bool event_watch(void *userdata, SDL_Event *event) {
    if (event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) {
        do_something();
    }
    return true;
}

int main() {

    SDL_AddEventWatch(event_watch, NULL);

    ...
}

-11
投票

如果您使用的是 Windows,您是否尝试过使用 Windows api?

我知道这不是一个真正的解决方案,但如果您没有制作跨平台应用程序,您应该尝试一下。

使用HWND查找SDL的窗口并返回窗口大小。

© www.soinside.com 2019 - 2024. All rights reserved.