Xamarin.Mac/ウインドウの一覧を取得する

提供: MonoBook
ナビゲーションに移動 検索に移動

概要

Mac OS X上で開いている全てのウインドウの情報を取得したい。

実装

Mac上で開いているウインドウの一覧を取得するにはCore GraphicsのCGWindowListCopyWindowInfoメソッドを呼び出してやることで実現できる。

このメソッドをラッピングしたと思わしきクラスは2015年10月時点でのXamarin.Macには見当たらない。 一方でこのメソッドの引数に渡すCGWindowListOption列挙体だけは標準で存在している。 仕方がないのでP/Invokeで直叩きしてみた。

using System;
using System.Linq;
using System.Runtime.InteropServices;
using MonoMac.Foundation;
using MonoMac.AppKit;
using MonoMac.CoreGraphics;

public static class CoreGraphicsEx
{
    public const string DllName = "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics";

    [DllImport(DllName)]
    extern static IntPtr CGWindowListCopyWindowInfo(CGWindowListOption option, UInt32 relativeToWindow);

    [DllImport(DllName)]
    extern static void CFRelease(IntPtr cf);

    public static NSDictionary[] GetWindowList(CGWindowListOption option, UInt32 relativeToWindow = 0)
    {
        IntPtr handle = IntPtr.Zero;

        try
        {
            handle = CoreGraphicsEx.CGWindowListCopyWindowInfo(option, relativeToWindow);
            return NSArray.ArrayFromHandle<NSDictionary>(handle);
        }
        finally
        {
            if (handle != IntPtr.Zero)
            {
                CFRelease(handle);
            }
        }
    }
}

class MainClass
{
    static void Main(string[] args)
    {
        NSApplication.Init();

        var windows = CoreGraphicsEx.GetWindowList(CGWindowListOption.All, 0);
        foreach (var window in windows)
        {
            Console.WriteLine(window.);
        }
    }
}

上記の実装では以下のような構造(NSDictionary)の配列が得られる。

{
    kCGWindowAlpha = 1;
    kCGWindowBounds =     {
        Height = 291;
        Width = 1465;
        X = 1072;
        Y = 1126;
    };
    kCGWindowLayer = 0;
    kCGWindowMemoryUsage = 1717392;
    kCGWindowName = XamarinStudio;
    kCGWindowNumber = 1483;
    kCGWindowOwnerName = "Xamarin Studio";
    kCGWindowOwnerPID = 28997;
    kCGWindowSharingState = 1;
    kCGWindowStoreType = 2;
}

これは配列連想配列が入っているような状態であり、各項目はアクセサメソッドで取得できる。

    var windows = CoreGraphicsEx.GetWindowList(CGWindowListOption.All, 0);
    foreach (var window in windows)
    {
        Console.WriteLine(window["kCGWindowOwnerPID"]);
    }

関連項目

参考文献