我正在尝试使用SDL2中的无边框窗口创建应用程序。
我通过拖动实现了移动和调整大小。移动工作非常好。通过拖动底部和右边框来调整大小也很正常。
通过拖动顶部和左侧边框功能来调整大小,但它有一个装饰性的错误。
基本上,如果我从左边框拖动,窗口的右侧在移动时会产生很小的跳跃(可能是1-2个像素)。从顶部边框拖动会导致底部跳跃。当我停止拖动窗口总是在正确的位置,但这个错误使它看起来非常不优雅。
Linux(多个WM / DE)和Windows上存在该错误。我没有在OS X上测试过。
我正在使用SDL_SetWindowPosition
和SDL_SetWindowSize
。我试过绕过SDL并使用XMoveResizeWindow
,但它会导致同样的错误。
虽然我强烈不想绕过SDL,但如果需要,我愿意使用Xlib和/或WinAPI。
以下是我的代码片段:
// mousePos is initialized to current mouse pos
// newWindowSize initilized to current window size
// newWindowPos initialized to current window position
// mWindowResizeOffset variable is where the mouse grabbed the window
// omitted code for right and bottom borders because the bug doesn't exist there
// Logic for the top border is the same
if (mLeftBorderGrabbed)
{
newWindowPos.x = mousePos.x - mWindowResizeOffset.x;
newWindowSize.x += windowPos.x - newWindowPos.x;
}
SDL_SetWindowPosition(mInternalWindow, newWindowPos.x, newWindowPos.y);
SDL_SetWindowSize(mInternalWindow, newWindowSize.x, newWindowSize.y);
答案 0 :(得分:5)
我选择了SDL2并花了最后几个小时尝试不同的窗口移动/大小调整/重绘API:
SDL_SetWindowPosition(window, newWindowPos.x, newWindowPos.y);
SDL_SetWindowSize(window, newWindowSize.x, newWindowSize.y);
SetWindowPos(windowHandle, nullptr, newWindowPos.x, newWindowPos.y, newWindowSize.x, newWindowSize.y, SWP_SHOWWINDOW);
MoveWindow(windowHandle, newWindowPos.x, newWindowPos.y, newWindowSize.x, newWindowSize.y, TRUE);
和
MoveWindow(windowHandle, newWindowPos.x, newWindowPos.y, newWindowSize.x, newWindowSize.y, TRUE);
InvalidateRect(windowHandle, &windowRect, TRUE);
我已经了解到SDL API可以通过缓慢的小拖动来实现,但更大,更快的拖动会触发您描述的视觉故障。
SetWindowPos
和MoveWindow
似乎几乎完全相同 - 在我的系统上都能正常工作。在拖动过程中窗口的左边缘会出现一些毛刺,但这与我系统上其他窗口的行为一致。右边缘在视觉上固定在原位,没有毛刺。我可能会选择MoveWindow
调用永久解决方案,尽管这主要是基于不同API设置如何运行的直觉。 YMMV。
InvalidateRect
似乎没有对事物的绘制方式产生任何影响。它不会加剧我提到的左边界故障,也不会减轻它。我猜这是因为我为MoveWindow
调用指定了重绘标记。
供参考,这是我用于测试的代码。我只是评论/取消评论相关API并根据需要重建项目。对于混乱感到抱歉 - 我更感兴趣的是获得一些东西,而不是让代码看起来更完美。如果您想要我清理它,请告诉我。
//Using SDL and standard IO
#include <windows.h>
#include <SDL.h>
#include <SDL_syswm.h>
#include <stdio.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
struct Point
{
int x;
int y;
};
int main(int argc, char* args[])
{
bool quit = false, dragging = false;
//The window we'll be rendering to
SDL_Window* window = NULL;
//The surface contained by the window
SDL_Surface* screenSurface = NULL;
SDL_Event e;
SDL_SysWMinfo windowInfo;
HWND windowHandle;
Point mousePos, windowPos, newWindowPos, newWindowSize, mWindowResizeOffset;
//Initialize SDL
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
}
else
{
//Create window
window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS); // | SDL_WINDOW_RESIZABLE
if(window == NULL)
{
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
}
else
{
//Get window surface
screenSurface = SDL_GetWindowSurface(window);
SDL_VERSION(&windowInfo.version);
SDL_GetWindowWMInfo(window, &windowInfo);
windowHandle = windowInfo.info.win.window;
//While application is running
while(!quit)
{
//Handle events on queue
while(SDL_PollEvent(&e) != 0)
{
//process events
switch(e.type)
{
case SDL_QUIT:
quit = true;
break;
case SDL_WINDOWEVENT:
if(e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
screenSurface = SDL_GetWindowSurface(window);
}
//Fill the surface blue
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0x00, 0xA2, 0xE8));
//Update the surface
SDL_UpdateWindowSurface(window);
break;
case SDL_MOUSEBUTTONDOWN:
SDL_GetMouseState(&mWindowResizeOffset.x, &mWindowResizeOffset.y);
SDL_GetWindowPosition(window, &windowPos.x, &windowPos.y);
dragging = true;
break;
case SDL_MOUSEBUTTONUP:
dragging = false;
break;
case SDL_MOUSEMOTION:
if(dragging)
{
SDL_GetMouseState(&mousePos.x, &mousePos.y);
SDL_GetWindowPosition(window, &newWindowPos.x, &newWindowPos.y);
SDL_GetWindowSize(window, &newWindowSize.x, &newWindowSize.y);
newWindowPos.x = newWindowPos.x + mousePos.x - mWindowResizeOffset.x;
newWindowSize.x += windowPos.x - newWindowPos.x;
//SDL_SetWindowPosition(window, newWindowPos.x, newWindowPos.y);
//SDL_SetWindowSize(window, newWindowSize.x, newWindowSize.y);
//SetWindowPos(windowHandle, nullptr, newWindowPos.x, newWindowPos.y, newWindowSize.x, newWindowSize.y, SWP_SHOWWINDOW);
MoveWindow(windowHandle, newWindowPos.x, newWindowPos.y, newWindowSize.x, newWindowSize.y, TRUE);
/*RECT drawRect;
drawRect.left = windowPos.x;
drawRect.top = windowPos.y;
drawRect.right = windowPos.x + newWindowSize.x;
drawRect.bottom = windowPos.y + newWindowSize.y;
InvalidateRect(windowHandle, &drawRect, TRUE);*/
windowPos = newWindowPos;
}
break;
}
}
SDL_Delay(1);
}
}
}
//Destroy window
SDL_DestroyWindow(window);
//Quit SDL subsystems
SDL_Quit();
return 0;
}