分享一个可以跨平台的屏幕尺寸获取工具

159 阅读2分钟

分享一个可以跨平台的屏幕尺寸获取工具

描述

这是一个C++练手的项目,在linux端使用X11及其前端Xrandr来实现,在MacOS使用AppKit来实现,在Windows端...我没有Windows机器,所以目前没做Windows端兼容。 那我就先来讲讲Linux端和MacOS端是如何实现的吧。

CMakeLists.txt

首先我们来看CMakeLists.txt文件 首先我们要先声明好CMake的版本,C++的版本,这里要注意的是,MacOS上我们还需要专门声明ObjectC的版本,因为AppKit是基于ObjectC的

cmake_minimum_required(VERSION 3.10)
project(screen-tool)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")

if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
    set(CMAKE_SOURCE_LANGUAGE OBJCXX)
    set(CMAKE_OBJCXX_EXTENSIONS OFF)
endif()

之后配置一下链接库、头文件地址、生成可执行文件这些 这里要注意Linux和MacOS配置不相同的链接库

include_directories(
    ${PROJECT_SOURCE_DIR}/include
    ${PROJECT_SOURCE_DIR}/resources
    ${PROJECT_SOURCE_DIR}/lib
    $ENV{CMAKE_INCLUDE_PATH}
)

# 在 macOS 平台上查找 AppKit 框架
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
    find_library(APPKIT_LIBRARY AppKit)
endif()

# 在 linux 平台上查找 X11 库
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
    find_library(X11_LIBRARIES X11)
    find_library(XRANDR_LIBRARIES Xrandr)
    include_directories(/usr/include/X11)
    link_directories(/usr/lib/X11)
endif()

# 设置源文件目录
set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)

# 添加源文件路径
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
    file(GLOB_RECURSE SRC_FILES "${SRC_DIR}/*.cpp" "${SRC_DIR}/**/*.cpp" "${SRC_DIR}/**/*.mm")
else()
    file(GLOB_RECURSE SRC_FILES "${SRC_DIR}/*.cpp" "${SRC_DIR}/**/*.cpp")
endif()

# 生成可执行文件
# add_library(${PROJECT_NAME} ${SRC_FILES})
add_executable(${PROJECT_NAME} ${SRC_FILES})

# 链接 CoreGraphics 框架
if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
    target_link_libraries(${PROJECT_NAME} ${APPKIT_LIBRARY})
endif()

# 链接到X11库
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
    target_link_libraries(${PROJECT_NAME} ${X11_LIBRARIES} ${XRANDR_LIBRARIES})
endif()


# 拷贝资源文件
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/resources DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

代码

之后呢,我们需要把Linux和MacOS单独两个文件实现
screen_x11.h

#ifndef NATIVE_SCREEN_X11_H
#define NATIVE_SCREEN_X11_H

#ifdef __linux__

#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#include <iostream>
#include <vector>
#include <cstring>

#include "screen-tool/common/ScreenExtends.h"

namespace screen_tool {
    namespace native {
        namespace screen {
            int print_screen_info();

            std::vector<ScreenSimpleInfo> get_screen_list();

            int get_primary_screen_bounds(ScreenBounds *screenBounds);
        }
    }
}

#endif

#endif /* NATIVE_SCREEN_X11_H */

screen_mac.h

#ifndef NATIVE_SCREEN_MAC_H
#define NATIVE_SCREEN_MAC_H

#ifdef __APPLE__

#include <vector>
#include <iostream>
#include "screen-tool/common/ScreenExtends.h"

namespace screen_tool {
    namespace native {
        namespace screen {
            int print_screen_info();

            std::vector<ScreenSimpleInfo> get_screen_list();

            int get_primary_screen_bounds(ScreenBounds *screenBounds);
        }
    }
}

#endif

#endif /* NATIVE_SCREEN_MAC_H */

最后我们再使用一个头文件把具体的实现导出,在入口文件中调用
screen.h

#ifndef NATIVE_SCREEN_H
#define NATIVE_SCREEN_H

#ifdef __linux__
    #include "screen-tool/native/screen_x11.h"
#endif

#ifdef __APPLE__
    #include "screen-tool/native/screen_mac.h"
#endif

#endif

main.cpp

#include <iostream>

#include "screen-tool/native/screen.h"

int main() {
    screen_tool::native::screen::print_screen_info();

    std::vector<ScreenSimpleInfo> screens = screen_tool::native::screen::get_screen_list();  // 获取活动屏幕列表

    for (const auto& screen : screens) {
        std::cout << "Screen Name: " << screen.name << std::endl;  // 打印屏幕名称
        std::cout << "Screen ID: " << screen.id << std::endl;  // 打印屏幕 ID
        std::cout << "Screen Is Primary: " << screen.is_primary << std::endl;  // 打印屏幕是否为主屏幕
        std::cout << "Screen Bounds: x=" << screen.bounds.x << ", y=" << screen.bounds.y
                  << ", width=" << screen.bounds.width << ", height=" << screen.bounds.height << std::endl;  // 打印屏幕边界信息

        std::cout << "---------------------" << std::endl;
    }

    ScreenBounds primary_screen_bounds;
    screen_tool::native::screen::get_primary_screen_bounds(&primary_screen_bounds);  // 获取主屏幕边界信息

    std::cout << "Primary Screen Bounds: x=" << primary_screen_bounds.x << ", y=" << primary_screen_bounds.y
              << ", width=" << primary_screen_bounds.width << ", height=" << primary_screen_bounds.height << std::endl;  // 打印主屏幕边界信息
}

结果

最后编译输出

image.png

源码提交在了github.com/Methy42/scr…

有编译好的版本可以在github.com/Methy42/scr…获取