https://blog.csdn.net/xpg4321/article/details/112357480 介绍了如何截屏
因为录制可能需要录制窗口,这里介绍如何枚举mac屏幕的窗口。
1.定义保存窗口信息的结构
struct WindowPoint {
int x;
int y;
};
struct MousePoint {
WindowPoint Position;
WindowPoint HotSpot;
};
struct Window {
uint32_t Handle{0};
WindowPoint Position;
WindowPoint Size;
// Name will always be lower case. It is converted to lower case internally by the library for comparisons
char Name[256] = {0};
};
uint32_t Handle{0} 窗口句柄类似windows的HWND,
WindowPoint Position; 窗口的位置
WindowPoint Size; 窗口的大小
2.获取显示区域个数
CGDisplayCount count=0;
CGGetActiveDisplayList(0, 0, &count);
std::vector<CGDirectDisplayID> displays;
displays.resize(count);
CGGetActiveDisplayList(count, displays.data(), &count);
主要考虑扩展屏平
3.遍历显示区域获取缩放因子
auto xscale=1.0f;
auto yscale = 1.0f;
for(auto i = 0; i < count; i++) {
//only include non-mirrored displays
if(CGDisplayMirrorsDisplay(displays[i]) == kCGNullDirectDisplay){
auto dismode =CGDisplayCopyDisplayMode(displays[i]);
auto scaledsize = CGDisplayBounds(displays[i]);
auto pixelwidth = CGDisplayModeGetPixelWidth(dismode);
auto pixelheight = CGDisplayModeGetPixelHeight(dismode);
CGDisplayModeRelease(dismode);
if(scaledsize.size.width !=pixelwidth){//scaling going on!
xscale = static_cast<float>(pixelwidth)/static_cast<float>(scaledsize.size.width);
}
if(scaledsize.size.height !=pixelheight){//scaling going on!
yscale = static_cast<float>(pixelheight)/static_cast<float>(scaledsize.size.height);
}
break;
}
}
缩放因子用于计算窗口的实际大小。
4.获取窗口个数
auto windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
Window ret;
CFIndex numWindows = CFArrayGetCount(windowList );
5. 遍历窗口获取窗口信息
for( int i = 0; i < (int)numWindows; i++ ) {
Window w = {};
uint32_t windowid=0;
auto dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(windowList, i));
auto cfwindowname = static_cast<CFStringRef>(CFDictionaryGetValue(dict, kCGWindowName));
if(cfwindowname == nullptr)
continue;
CFStringGetCString(cfwindowname, w.Name, sizeof(w.Name), kCFStringEncodingUTF8);
w.Name[sizeof(w.Name)-1] = '\n';
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kCGWindowNumber)), kCFNumberIntType, &windowid);
w.Handle = static_cast<size_t>(windowid);
auto dims =static_cast<CFDictionaryRef>(CFDictionaryGetValue(dict,kCGWindowBounds));
CGRect rect;
CGRectMakeWithDictionaryRepresentation(dims, &rect);
w.Position.x = static_cast<int>(rect.origin.x);
w.Position.y = static_cast<int>(rect.origin.y);
w.Size.x = static_cast<int>(rect.size.width * xscale);
w.Size.y = static_cast<int>(rect.size.height* yscale);
std::string strName = w.Name;
if(strName == name)
{
ret = w;
break;
}
}
CFRelease(windowList);
6.最终代码
根据窗口名字获取窗口信息:
Window MacScreenCaputre::getWindow(const std::string &name)
{
CGDisplayCount count=0;
CGGetActiveDisplayList(0, 0, &count);
std::vector<CGDirectDisplayID> displays;
displays.resize(count);
CGGetActiveDisplayList(count, displays.data(), &count);
auto xscale=1.0f;
auto yscale = 1.0f;
for(auto i = 0; i < count; i++) {
//only include non-mirrored displays
if(CGDisplayMirrorsDisplay(displays[i]) == kCGNullDirectDisplay){
auto dismode =CGDisplayCopyDisplayMode(displays[i]);
auto scaledsize = CGDisplayBounds(displays[i]);
auto pixelwidth = CGDisplayModeGetPixelWidth(dismode);
auto pixelheight = CGDisplayModeGetPixelHeight(dismode);
CGDisplayModeRelease(dismode);
if(scaledsize.size.width !=pixelwidth){//scaling going on!
xscale = static_cast<float>(pixelwidth)/static_cast<float>(scaledsize.size.width);
}
if(scaledsize.size.height !=pixelheight){//scaling going on!
yscale = static_cast<float>(pixelheight)/static_cast<float>(scaledsize.size.height);
}
break;
}
}
auto windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
Window ret;
CFIndex numWindows = CFArrayGetCount(windowList );
for( int i = 0; i < (int)numWindows; i++ ) {
Window w = {};
uint32_t windowid=0;
auto dict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(windowList, i));
auto cfwindowname = static_cast<CFStringRef>(CFDictionaryGetValue(dict, kCGWindowName));
if(cfwindowname == nullptr)
continue;
CFStringGetCString(cfwindowname, w.Name, sizeof(w.Name), kCFStringEncodingUTF8);
w.Name[sizeof(w.Name)-1] = '\n';
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kCGWindowNumber)), kCFNumberIntType, &windowid);
w.Handle = static_cast<size_t>(windowid);
auto dims =static_cast<CFDictionaryRef>(CFDictionaryGetValue(dict,kCGWindowBounds));
CGRect rect;
CGRectMakeWithDictionaryRepresentation(dims, &rect);
w.Position.x = static_cast<int>(rect.origin.x);
w.Position.y = static_cast<int>(rect.origin.y);
w.Size.x = static_cast<int>(rect.size.width * xscale);
w.Size.y = static_cast<int>(rect.size.height* yscale);
std::string strName = w.Name;
if(strName == name)
{
ret = w;
break;
}
}
CFRelease(windowList);
return ret;
}