SDL2 如何将窗口定位到第二个显示器?

10
我正在使用SDL_SetWindowPosition来定位我的窗口。我能用这个函数将我的窗口定位到另一个显示器上吗? 更新 在Windows 10中更改文本大小时,使用SDL_GetDisplayBounds将无法返回正确的监视器位置。有什么解决方法吗?

enter image description here


2
非常感谢您提出这个问题。我一直在想为什么在使用SDL时缩放完全错误,但原来是因为Windows设置了125%的缩放。这节省了我数小时的调试时间。 - julealgon
3个回答

17

SDL2使用全局屏幕空间坐标系统。每个显示设备在此坐标空间中具有自己的边界。以下示例将窗口放置在第二个显示设备上:

// enumerate displays
int displays = SDL_GetNumVideoDisplays();
assert( displays > 1 );  // assume we have secondary monitor

// get display bounds for all displays
vector< SDL_Rect > displayBounds;
for( int i = 0; i < displays; i++ ) {
    displayBounds.push_back( SDL_Rect() );
    SDL_GetDisplayBounds( i, &displayBounds.back() );
}

// window of dimensions 500 * 500 offset 100 pixels on secondary monitor
int x = displayBounds[ 1 ].x + 100;
int y = displayBounds[ 1 ].y + 100;
int w = 500;
int h = 500;

// so now x and y are on secondary display
SDL_Window * window = SDL_CreateWindow( "title", x, y, w, h, FLAGS... );

查看 SDL_video.hSDL_WINDOWPOS_CENTERED 的定义,我们可以看到它被定义为

#define SDL_WINDOWPOS_CENTERED         SDL_WINDOWPOS_CENTERED_DISPLAY(0)

因此,我们也可以使用宏SDL_WINDOWPOS_CENTERED_DISPLAY(n),其中n是显示器索引。

针对Windows 10的更新 - DPI缩放问题

似乎SDL2在Windows更改DPI比例(即文本缩放)时确实存在一个错误。

以下是两个与该问题相关的漏洞报告。它们似乎仍未得到解决。

https://bugzilla.libsdl.org/show_bug.cgi?id=3433

https://bugzilla.libsdl.org/show_bug.cgi?id=2713

潜在解决方案

我相信OP可以使用WIN32 api来确定dpi缩放,对于scale!= 100%,然后通过它来纠正边界。


我想评论原问题以回答你的问题,但我还没有这个特权。我的猜测是,在Windows 10中更改文本比例会以某种方式影响SDL的屏幕坐标。我曾经遇到过一个不同但相关的问题,直到我弄清楚如何在我的Mac的Retina显示器上使用SDL2。(Retina使用缩放)。我建议你尝试以下实验:输出显示边界,并检查当你在Windows 10下更改文本比例设置时它们是否会改变。 - Jacques Nel
这可能是SDL2的一个bug。你在Windows 10上搜索过其他人是否有相同的经历吗? - Jacques Nel
如果我的假设是正确的,那么所有屏幕位置都将乘以1.25,因为文本比例是125%。 - Jacques Nel
2
关于Win 10缩放问题,请参阅此优秀文章:https://nlguillemot.wordpress.com/2016/12/11/high-dpi-rendering/ 如果您的应用程序是dpi感知的(通过使用清单或winapi的SetProcessDpiAwareness),SDL_WINDOWPOS_CENTERED_DISPLAY将正常工作!;) - pergy

2

DPI缩放问题(“在更改文本大小时将不返回正确的监视器位置”)

这是SDL2已知的问题(我在这些版本中遇到过:2.0.6、2.0.7、2.0.8,可能旧版本也存在此问题)。

解决方案:

1)使用清单文件并在其中设置:

<dpiAware>True/PM</dpiAware>

你需要将清单文件包含到应用程序分发中。

2)尝试使用SetProcessDPIAware()。


0

是的,如果您知道第二个显示器的边界,您可以使用SetWindowPosition函数。 您可以使用函数SDL_GetDisplayBounds(int displayIndex,SDL_Rect* rect)来获取它们。


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