在SDL 2中获取连续的窗口缩放事件

24

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

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

如何才能连续获取新数据,也就是在我拖动窗口的同时获取?


2
尝试使用SDL_WINDOWEVENT_SIZE_CHANGED - Ivan Aksamentov - Drop
4
SDL_WINDOWEVENT_SIZE_CHANGED并没有记录为可提供持续的大小调整更新。在我的实验中(在Mac OS X上),它也没有实现。我还想知道如何在用户操作期间获取连续的调整大小的事件! - david van brink
4
因为这个漏洞(https://bugzilla.libsdl.org/show_bug.cgi?id=2077),实际上是不可能的。 - LB--
SDL_SetWindowsMessageHook 函数,它会在每个 Windows 消息之前调用提供的函数,包括 TranslateMessage - Xeverous
3个回答

18
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可以解决这个问题。


@pergy 在这种情况下,没有太多的区别...但我认为这是因为它会创建一个始终执行的线程。 - manudicri
1
@pergy 抱歉回复晚了,刚好看到这个问题。区别在于事件观察是由发出事件的线程(可能是系统/操作系统线程)调用的。在这种情况下,事件泵被阻塞在调整大小操作上,直到调整大小完成才返回。同时,尺寸更改事件正在排队等待处理,但它们被排队在当前调整大小操作之后。添加事件观察以侦听这些事件可以在不同的线程上有效地处理它们,从而为您提供重新绘制的机会。但要注意线程安全! - jeremyong

0
如果您正在使用单个线程,仅仅使用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)。


-9

如果你在使用Windows系统,你尝试过使用Windows API吗?

我知道这不是一个真正的解决方案,但如果你不需要跨平台应用程序,你应该试一试。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接