博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SDL获得屏幕属性及实现分析
阅读量:5840 次
发布时间:2019-06-18

本文共 3120 字,大约阅读时间需要 10 分钟。

[时间:2017-05] [状态:Open]

[关键词:sdl2,屏幕分辨率,显示区域,多媒体渲染,窗口,sdl2源码分析]

0 引言

本文的主要目标在于使用SDL2获得屏幕相关的属性,比如分辨率、屏幕个数以及屏幕可用区域的范围。

通常情况下,有过图形界面编程经验的人都知道桌面系统的构成,屏幕分辨率是指的整个屏幕区域的宽高,而通常屏幕区域有一些系统的任务栏或者菜单栏;举个例子,windows下的任务栏一般位于下面,并且通常非全屏窗口是不能占用任务栏的。

1 获得屏幕个数

SDL2中提供了获得屏幕个数的接口SDL_GetNumVideoDisplays,具体建议参考。

当然屏幕还有其他属性,比如显示模式等,可以通过SDL_GetNumDisplayModesSDL_GetDisplayMode获得SDL_DisplayMode的结构,其中包括显示格式(YUV、RGB等)、宽高、刷新率等。

2 每个屏幕的分辨率

SDL_GetDisplayBounds可以获得指定屏幕的显示区域,可以通过显示区域获取屏幕分辨率。

3 获取实际显示区域的大小

SDL_GetDisplayUsableBounds返回的是实际可用显示区域的大小,这个通常比屏幕分辨率小。

4 SDL2内部实现的原理分析

这里以SDL_GetDisplayBounds为例说明,如果读者对其他函数感兴趣,可以查看sdl2代码。

int SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect){    CHECK_DISPLAY_INDEX(displayIndex, -1);    if (rect) {        SDL_VideoDisplay *display = &_this->displays[displayIndex];        if (_this->GetDisplayBounds) {            if (_this->GetDisplayBounds(_this, display, rect) == 0) {                return 0;            }        }        /* Assume that the displays are left to right */        if (displayIndex == 0) {            rect->x = 0;            rect->y = 0;        } else {            SDL_GetDisplayBounds(displayIndex-1, rect);            rect->x += rect->w;        }        rect->w = display->current_mode.w;        rect->h = display->current_mode.h;    }    return 0;  /* !!! FIXME: should this be an error if (rect==NULL) ? */}

很明显这个函数直接调用了SDL_VideoDevice->GetDisplayBounds函数,那么我们找一个实现版本看看,比如windows下的,代码如下:

static SDL_VideoDevice * WIN_CreateDevice(int devindex){    // ...    device->GetDisplayBounds = WIN_GetDisplayBounds;    // ...}

这个实现被重定向到WIN_GetDisplayBounds函数中,代码如下:

intWIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect){    SDL_DisplayModeData *data = (SDL_DisplayModeData *) display->current_mode.driverdata;    rect->x = (int)SDL_ceil(data->DeviceMode.dmPosition.x * data->ScaleX);    rect->y = (int)SDL_ceil(data->DeviceMode.dmPosition.y * data->ScaleY);    rect->w = (int)SDL_ceil(data->DeviceMode.dmPelsWidth * data->ScaleX);    rect->h = (int)SDL_ceil(data->DeviceMode.dmPelsHeight * data->ScaleY);    return 0;}

实现比较简单,直接从display->current_mode中获得数据。那么这个mode在哪里赋值的呢?

在SDL_windowsvideo.c中查找下,发下如下调用:

static SDL_bool WIN_AddDisplay(_THIS, LPTSTR DeviceName){    SDL_VideoDisplay display;    SDL_DisplayData *displaydata;    SDL_DisplayMode mode;    DISPLAY_DEVICE device;    if (!WIN_GetDisplayMode(_this, DeviceName, ENUM_CURRENT_SETTINGS, &mode)) {        return SDL_FALSE;    }    displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));    if (!displaydata) {        return SDL_FALSE;    }    SDL_memcpy(displaydata->DeviceName, DeviceName,               sizeof(displaydata->DeviceName));    SDL_zero(display);    device.cb = sizeof(device);    if (EnumDisplayDevices(DeviceName, 0, &device, 0)) {        display.name = WIN_StringToUTF8(device.DeviceString);    }    display.desktop_mode = mode;    display.current_mode = mode;    display.driverdata = displaydata;    SDL_AddVideoDisplay(&display);    SDL_free(display.name);    return SDL_TRUE;}

明显这是从中获取。

至此所有实现逻辑基本理清。

5 小结

本文主要整理我近期遇到的SDL2关于窗口和屏幕属性获取的逻辑,同时分析了SDL_GetDisplayBounds在windows上的实现逻辑。

转载地址:http://owtcx.baihongyu.com/

你可能感兴趣的文章
Maven修改全局和局部JDK版本
查看>>
设计模式——组合模式(Composite Pattern)
查看>>
java设计模式之——代理模式
查看>>
每天学习2小时的故事
查看>>
asa-url-filter
查看>>
iOS入门培训还要钱?看博客,看视频都拿下
查看>>
mysql:error: 'Access denied for user 'root'@'localhost' (using password: YES)
查看>>
rsync 不能复制数据
查看>>
Workspace in use or cannot be created, choose a different one.
查看>>
linux下mongodb的安装
查看>>
分页查询
查看>>
安卓网络编程
查看>>
我的个人博客地址
查看>>
java 的HashMap和HashTable的区别?
查看>>
php页面防止重复提交
查看>>
Perl DBI模块的例子
查看>>
python中str和repr区别
查看>>
升级win10后无法使用桥接网络解决方法
查看>>
如何进行跨网段的远程唤醒
查看>>
数据挖掘-同比与环比
查看>>