Xamarin - Как получить скриншот и сохранить его на диск с помощью Xamarin Mac?

Я пытаюсь получить скриншот и сохранить его на диске, используя Xamarin и C# на Mac. Я написал код ниже:

public static void TakeScreenshotAndSaveToDisk(string path)
    {
        var fullScreenBounds = NSScreen.MainScreen.Frame;
        IntPtr ptr = CGWindowListCreateImage(fullScreenBounds, CGWindowListOption.OnScreenAboveWindow, 0, CGWindowImageOption.Default);
        var cgImage = new CGImage(ptr);
        var fileURL = new NSUrl(path, false);
        var imageDestination = CGImageDestination.Create(new CGDataConsumer(fileURL), UTType.PNG, 1);
        imageDestination.AddImage(cgImage);
        imageDestination.Close();
        imageDestination.Dispose();
        fileURL.Dispose();
        cgImage.Dispose();
    }

Метод выполняется, и файл появляется в правильном месте. Если я попытаюсь открыть его, он покажет пустым. Если я нажму "Получить информацию" в файле, он не будет отображать предварительный просмотр. После того, как я закрываю свое приложение, изображение может быть открыто, и "Get Info" показывает предварительный просмотр.

Что я здесь не так делаю? Мне кажется, что ресурсы не освобождаются, хотя я вызываю Dispose() для объектов.

Благодарю.

2 ответа

Решение

CGImageDestination.Create Метод имеет 3 разных подписи, если вы используете ту, которая принимает NSUrl вместо CGDataConsumer тебе должно быть хорошо.

var imageDestination = CGImageDestination.Create(fileURL, UTType.PNG, 1);

С этим вам не нужно создавать CGDataConsumer но если вы действительно хотите / нужно

var dataConsumer = new CGDataConsumer(fileURL);
var imageDestination = CGImageDestination.Create(dataConsumer, UTType.PNG, 1);
imageDestination.AddImage(cgImage);
imageDestination.Close();
dataConsumer.Dispose();

Просто убедитесь, что утилизировали экземпляр, как только вы сохранили файл.

С using подход:

using (var dataConsumer = new CGDataConsumer(fileURL))
{
    var imageDestination = CGImageDestination.Create(dataConsumer, UTType.PNG, 1);
    imageDestination.AddImage(cgImage);
    imageDestination.Close();
}

Примечание: для CGImageDestination вам не нужно утилизировать вручную, Close Метод также выбрасывает объект (на основании документации).

public Boolean Close ()

Записывает изображения в пункт назначения и удаляет объект.

Надеюсь это поможет.-

Я могу опоздать, но только что реализовал этот алгоритм Swift с помощью Xamarin.Mac, и его можно использовать и в режиме без головы:

https://gist.github.com/MarcosCobena/b4768bacc1a112a4f38a9d11a19f1251

Он использует "новые" привязки CoreGraphics (некоторые уже присутствовали в Xamarin.Mac, но внутренние или частные) для обнаружения дисплеев и их перечисления. Наконец, он принимает один скриншот на экран, сохраняя его в формате PNG по заданному пути.

Другие вопросы по тегам