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

Getting Continuous Window Resize Event in SDL 2

本文关键字:窗口大小 调整 事件 连续 SDL      更新时间:2023-10-16

我使用以下结构来获得调整大小的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;
  }
}

但是使用这个结构,我只能在调整大小完成后获得新数据,也就是当我完成拖动并释放鼠标按钮时。

我怎么能得到新的数据连续,也就是说,当我拖动窗口?

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可以解决它

如果您使用的是单个线程,那么使用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)。

如果你是在windows上,你试过使用windows api吗?

我知道这不是一个真正的解决方案,但如果你不做一个跨平台的应用程序,你应该给它一个机会。

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