分享一个可以跨平台的屏幕尺寸获取工具
描述
这是一个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; // 打印主屏幕边界信息
}
结果
最后编译输出
源码提交在了github.com/Methy42/scr…
有编译好的版本可以在github.com/Methy42/scr…获取