Programmatically Screenshot | Swift 3, Macos

Programmatically Screenshot | Swift 3, macOS

Yes its possible. This function takes all connected monitors screenshots and writes to specified path as jpg file. Generates file name as unix time stamp.

 func TakeScreensShots(folderName: String){

var displayCount: UInt32 = 0;
var result = CGGetActiveDisplayList(0, nil, &displayCount)
if (result != CGError.success) {
print("error: \(result)")
return
}
let allocated = Int(displayCount)
let activeDisplays = UnsafeMutablePointer<CGDirectDisplayID>.allocate(capacity: allocated)
result = CGGetActiveDisplayList(displayCount, activeDisplays, &displayCount)

if (result != CGError.success) {
print("error: \(result)")
return
}

for i in 1...displayCount {
let unixTimestamp = CreateTimeStamp()
let fileUrl = URL(fileURLWithPath: folderName + "\(unixTimestamp)" + "_" + "\(i)" + ".jpg", isDirectory: true)
let screenShot:CGImage = CGDisplayCreateImage(activeDisplays[Int(i-1)])!
let bitmapRep = NSBitmapImageRep(cgImage: screenShot)
let jpegData = bitmapRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])!


do {
try jpegData.write(to: fileUrl, options: .atomic)
}
catch {print("error: \(error)")}
}
}

func CreateTimeStamp() -> Int32
{
return Int32(Date().timeIntervalSince1970)
}

How can I programmatically display a window on a specific screen (i.e., main display as opposed to external displays) in Swift 5? [MacOS; Xcode 15]

Thanks to the question asked by @Willeke, I was able to use the following code to display the window on the main screen (as opposed to external displays). I just needed to use DispatchQueue.main.async {}.

   override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {

//set up the main display as the display where window shows up
let screens = NSScreen.screens
var pos = NSPoint()
pos.x = screens[0].visibleFrame.midX
pos.y = screens[0].visibleFrame.midY
self.view.window?.setFrameOrigin(pos)

}
}

Swift open new window programmatically in macOS

The following demo creates a second window called by a method in a custom class. It may be run in Xcode by adding a 'swift.main' file and replacing AppDelegate with the following code:

import Cocoa

class Abc : NSObject {
var panel: NSPanel!

func buildWnd2() {
let _panelW : CGFloat = 200
let _panelH : CGFloat = 200

panel = NSPanel(contentRect:NSMakeRect(9300, 1300, _panelW, _panelH), styleMask:[.titled, .closable, .utilityWindow],
backing:.buffered, defer: false)
panel.isFloatingPanel = true
panel.title = "NSPanel"
panel.orderFront(nil)
}
}

let abc = Abc()

class AppDelegate: NSObject, NSApplicationDelegate {
var window:NSWindow!

@objc func myBtnAction(_ sender:AnyObject ) {
abc.buildWnd2()
}

func buildMenu() {
let mainMenu = NSMenu()
NSApp.mainMenu = mainMenu
// **** App menu **** //
let appMenuItem = NSMenuItem()
mainMenu.addItem(appMenuItem)
let appMenu = NSMenu()
appMenuItem.submenu = appMenu
appMenu.addItem(withTitle: "Quit", action:#selector(NSApplication.terminate), keyEquivalent: "q")
}

func buildWnd() {

let _wndW : CGFloat = 400
let _wndH : CGFloat = 300

window = NSWindow(contentRect:NSMakeRect(0,0,_wndW,_wndH),styleMask:[.titled, .closable, .miniaturizable, .resizable], backing:.buffered, defer:false)
window.center()
window.title = "Swift Test Window"
window.makeKeyAndOrderFront(window)

// **** Button **** //
let myBtn = NSButton (frame:NSMakeRect( 100, 100, 175, 30 ))
myBtn.bezelStyle = .rounded
myBtn.autoresizingMask = [.maxXMargin,.minYMargin]
myBtn.title = "Build Second Window"
myBtn.action = #selector(self.myBtnAction(_:))
window.contentView!.addSubview (myBtn)

// **** Quit btn **** //
let quitBtn = NSButton (frame:NSMakeRect( _wndW - 50, 10, 40, 40 ))
quitBtn.bezelStyle = .circular
quitBtn.autoresizingMask = [.minXMargin,.maxYMargin]
quitBtn.title = "Q"
quitBtn.action = #selector(NSApplication.terminate)
window.contentView!.addSubview(quitBtn)
}

func applicationDidFinishLaunching(_ notification: Notification) {
buildMenu()
buildWnd()
}

func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}

}
let appDelegate = AppDelegate()

// **** main.swift **** //
let app = NSApplication.shared
app.delegate = appDelegate
app.setActivationPolicy(.regular)
app.activate(ignoringOtherApps:true)
app.run()

How to take a screenshot of your entire screen

The error has to do with saving the file. You are constructing the URL badly.

First, expanding ~ to the home directory is generally a shell feature, not an OS feature. The underlying file path APIs (e.g. open()) just treat that as a normal character in a path. Foundation does support expanding ~ in path strings (not URLs), but you have to specifically request it with expandingTildeInPath. It's never automatic and it's never meaningful in URLs.

Next, I suspect you were trying to build a URL to a file within the Documents directory. However, you did not put a path separator (/) between the name of the directory and the name of the file. In other words, you constructed ~/Documents10989439875_1.jpg, not ~/Documents/10989439875_1.jpg.

You should use FileManager().urls(for:.downloadsDirectory, in:.userDomainMask)[0] to get the URL to the Downloads folder and then append a path component to that using appendingPathComponent(_:isDirectory:).

Swift 3/macOS: Open window on certain screen

Each screen from NSScreen.screens() has a visibleFrame property that tells you the global frame rectangle.

You can then set your window origin to fit inside the frame rect coordinates of whatever screen you want. Objective-C answers can be seen here and here.

This does mean you have to write some code to specify the preferred window. In my own app, I take the global frame rectangles for each screen and then scale them way down into a NSView to display something that looks like the Monitors pane from System Preferences:

Set Video Preferences

Mac - How to programmatically hide NSApplicationActivationPolicyAccessory or LSUIElement application?

Use NSApplication.sharedApplication().hide(nil). One would normally address the application object (instance of NSApplication) rather than an instance of NSRunningApplication to operate on the current app.



Related Topics



Leave a reply



Submit