菜鸟学ffmpeg音视频技术之7 mac枚举窗口

9 篇文章 0 订阅
9 篇文章 0 订阅

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;
  }

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值