Menu

Skip to content
AppleScriptの穴
  • Home
  • Products
  • Books
  • Docs
  • Events
  • Forum
  • About This Blog
  • License
  • 仕事依頼

AppleScriptの穴

Useful & Practical AppleScript archive. Click '★Click Here to Open This Script' Link to download each AppleScript

ディスプレイ選択ダイアログ

Posted on 7月 21 by Takaaki Naganoya

現時点でMacに接続されているディスプレイ情報を取得して、座標値からその位置関係や大きさを計算して画像にレンダリングし、ポップアップメニューから処理対象のディスプレイを選択してNSRectを返すAppleScriptです。

まだ試作品レベルですが、macOS 27 beta上で動作しています。ただ、NSAlertによるダイアログを表示させた場合に、アイコンもタイトルもサブタイトルもすべて左寄せになってしまうところがいまひとつです。

なんでこんなものを作ったかといえば、複数ディスプレイがつながっているMac上で任意のディスプレイ上に表示されているウィンドウ(に含まれるdocument)だけを処理対象とし、他のディスプレイ上のウィンドウを無視するといった処理をしたいと考えたからです。

少々AIにお願いしてコードを書いてもらっていますが、そのためにやや不要な処理までやっているような気もします。

AppleScript名:ディスプレイ情報を取得して、位置関係を画像化_take2_1b.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2026/07/19
—
–  Copyright © 2026 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.8"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property K_MAX_WIDTH : 600.0
property K_MAX_HEIGHT : 300.0
property selectedDispRes : missing value

set {aInfoList, aIMG, aSizeList} to drawDisplayLayout() of me
–return aIMG

set aInfoList to aInfoList as list
if length of aInfoList = 1 then return

set aParamRec to {myDispInfo:aInfoList, myImgView:aIMG, mySizeList:aSizeList, mymainTitle:"ディスプレイ選択", mySubTitle:"メイン画面が「1」、その他は左上から「2, 3…」となります。"}

–my dispLayoutAndPopup:aParamRec–for debugging on Script Editor
my performSelectorOnMainThread:"dispLayoutAndPopup:" withObject:(aParamRec) waitUntilDone:true
return (visibleFrame of selectedDispRes)’s |description|() as string –For Debugging

–Macに接続されているディスプレイ一覧から処理対象を選択するダイアログを表示
on dispLayoutAndPopup:aParam
  set dList to (myDispInfo of aParam) as list
  
set aIMG to myImgView of aParam
  
set aMainTitle to (mymainTitle of aParam) as string
  
set aSubTitle to (mySubTitle of aParam) as string
  
set {imgWidth, imgHeight} to (mySizeList of aParam) as list
  
set dNum to length of dList
  
set numStrList to makeNumberStringList(dNum) of me
  
  
set currentAlert to current application’s NSAlert’s alloc()’s init()
  
currentAlert’s setMessageText:aMainTitle
  
currentAlert’s setInformativeText:aSubTitle
  
  
set imageView to current application’s NSImageView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, imgWidth, imgHeight))
  
imageView’s setImage:aIMG
  
  
set a1Button to (current application’s NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, imgWidth – 100, 30)) pullsDown:false)
  
a1Button’s removeAllItems()
  (
a1Button’s addItemsWithTitles:(numStrList))
  
  
  
— 画像ビュー
  
set imageView to current application’s NSImageView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, imgWidth, imgHeight))
  
imageView’s setImage:aIMG
  
imageView’s setImageScaling:(current application’s NSImageScaleProportionallyUpOrDown)
  
  
— ポップアップ
  
set popupWidth to imgWidth – 80
  
set a1Button to (current application’s NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, popupWidth, 30)) pullsDown:false)
  
a1Button’s removeAllItems()
  (
a1Button’s addItemsWithTitles:(numStrList))
  
  
— OKボタン幅に合わせると見た目がよい
  
a1Button’s setControlSize:(current application’s NSControlSizeRegular)
  
  
————————————————–
  
— 中央寄せコンテナ
  
————————————————–
  
set containerWidth to imgWidth
  
set containerHeight to imgHeight + 60
  
  
set containerView to current application’s NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, containerWidth, containerHeight))
  
  
— StackView
  
set stackView to current application’s NSStackView’s alloc()’s initWithFrame:(containerView’s |bounds|())
  
  
stackView’s setOrientation:(current application’s NSUserInterfaceLayoutOrientationVertical)
  
stackView’s setAlignment:(current application’s NSLayoutAttributeCenterX)
  
stackView’s setDistribution:(current application’s NSStackViewDistributionGravityAreas)
  
stackView’s setSpacing:16.0
  
  
— Auto Layout
  
stackView’s setTranslatesAutoresizingMaskIntoConstraints:false
  
  
— 追加
  
stackView’s addArrangedSubview:imageView
  
stackView’s addArrangedSubview:a1Button
  
  
containerView’s addSubview:stackView
  
  
————————————————–
  
— StackViewをコンテナ中央へ固定
  
————————————————–
  
set centerX to (stackView’s centerXAnchor())
  (
centerX’s constraintEqualToAnchor:(containerView’s centerXAnchor()))’s setActive:true
  
  
set centerY to (stackView’s centerYAnchor())
  (
centerY’s constraintEqualToAnchor:(containerView’s centerYAnchor()))’s setActive:true
  
  
————————————————–
  
— accessoryView設定
  
————————————————–
  
currentAlert’s setAccessoryView:containerView
  
currentAlert’s runModal()
  
  
–popup buttonの選択肢を取得する
  
set tmpSegSel to (a1Button’s indexOfSelectedItem()) as number
  
set tRes to (tmpSegSel + 1)
  
  
set selectedDispRes to (contents of item tRes of dList)
end dispLayoutAndPopup:

on makeNumberStringList(aMax)
  set aList to {}
  
set aCount to 1
  
repeat aMax times
    set the end of aList to (aCount as string)
    
set aCount to aCount + 1
  end repeat
  
return aList
end makeNumberStringList

on drawDisplayLayout()
  set allScreens to current application’s NSScreen’s screens()
  
if allScreens is missing value or allScreens’s |count|() = 0 then return
  
  
— 1. メイン画面(配列の先頭)を取得
  
set mainScreen to allScreens’s firstObject()
  
  
— 2. サブ画面たちをリストとして抽出
  
set otherScreensList to {}
  
repeat with i from 1 to (allScreens’s |count|()) – 1
    copy (allScreens’s objectAtIndex:i) to end of otherScreensList
  end repeat
  
  
— 3. サブ画面を「左上から順(Y座標の降順 > X座標の昇順)」に手動ソート
  
— ※AppleScript側でハンドリングした方がCocoaの構造体ネスト問題を回避できて確実です
  
repeat with i from 1 to (count otherScreensList)
    repeat with j from i + 1 to (count otherScreensList)
      set scrI to item i of otherScreensList
      
set scrJ to item j of otherScreensList
      
set frameI to scrI’s frame()
      
set frameJ to scrJ’s frame()
      
      
set yI to current application’s NSMinY(frameI)
      
set yJ to current application’s NSMinY(frameJ)
      
set xI to current application’s NSMinX(frameI)
      
set xJ to current application’s NSMinX(frameJ)
      
      
— Yが小さい(下にある)か、Yが同じでXが大きい(右にある)場合は入れ替え
      
if (yI < yJ) or (yI = yJ and xI > xX) then
        set item i of otherScreensList to scrJ
        
set item j of otherScreensList to scrI
      end if
    end repeat
  end repeat
  
  
— 4. 最終的な順序の配列を作成(1番目がメイン、2番目以降がサブ)
  
set sortedScreens to current application’s NSMutableArray’s array()
  (
sortedScreens’s addObject:mainScreen)
  
repeat with aScr in otherScreensList
    (sortedScreens’s addObject:aScr)
  end repeat
  
  
— 5. 全体を含むバウンディングボックスの計算
  
set minX to 9.9999E+4
  
set maxX to -9.9999E+4
  
set minY to 9.9999E+4
  
set maxY to -9.9999E+4
  
  
repeat with aScreen in sortedScreens
    set f to aScreen’s frame()
    
set sx to current application’s NSMinX(f)
    
set sy to current application’s NSMinY(f)
    
set sw to current application’s NSWidth(f)
    
set sh to current application’s NSHeight(f)
    
    
if sx < minX then set minX to sx
    
if sy < minY then set minY to sy
    
if (sx + sw) > maxX then set maxX to (sx + sw)
    
if (sy + sh) > maxY then set maxY to (sy + sh)
  end repeat
  
  
set totalWidth to maxX – minX
  
set totalHeight to maxY – minY
  
  
— 6. スケール比率の計算
  
set scaleX to K_MAX_WIDTH / totalWidth
  
set scaleY to K_MAX_HEIGHT / totalHeight
  
set theScale to scaleX
  
if scaleY < theScale then set theScale to scaleY
  
  
set imgWidth to totalWidth * theScale
  
set imgHeight to totalHeight * theScale
  
set canvasSize to current application’s NSMakeSize(imgWidth, imgHeight)
  
set displayImage to current application’s NSImage’s alloc()’s initWithSize:canvasSize
  
  
— 7. 描画処理
  
displayImage’s lockFocus()
  
  
current application’s NSColor’s clearColor()’s |set|()
  
current application’s NSRectFill(current application’s NSMakeRect(0, 0, imgWidth, imgHeight))
  
  
set screenCount to sortedScreens’s |count|()
  
repeat with idx from 0 to screenCount – 1
    set aScreen to (sortedScreens’s objectAtIndex:idx)
    
set f to aScreen’s frame()
    
    
set rx to ((current application’s NSMinX(f)) – minX) * theScale
    
set ry to ((current application’s NSMinY(f)) – minY) * theScale
    
set rw to (current application’s NSWidth(f)) * theScale
    
set rh to (current application’s NSHeight(f)) * theScale
    
set drawRect to current application’s NSMakeRect(rx, ry, rw, rh)
    
    
— 枠と背景
    
current application’s NSColor’s windowBackgroundColor()’s |set|()
    
current application’s NSRectFill(drawRect)
    
current application’s NSColor’s textColor()’s |set|()
    
current application’s NSFrameRectWithWidth(drawRect, 1.5)
    
    
— ★【修正】数字の文字列生成方法をNSNumber経由に修正
    
set numObj to (current application’s NSNumber’s numberWithInteger:(idx + 1))
    
set numStr to numObj’s stringValue()
    
    
set fontHeight to rh * 0.4
    
if fontHeight > 24.0 then set fontHeight to 24.0
    
if fontHeight < 12.0 then set fontHeight to 12.0
    
    
set numFont to (current application’s NSFont’s systemFontOfSize:fontHeight weight:(current application’s NSFontWeightBold))
    
set paraStyle to current application’s NSMutableParagraphStyle’s alloc()’s init()
    (
paraStyle’s setAlignment:(current application’s NSTextAlignmentCenter))
    
    
set attrDict to current application’s NSMutableDictionary’s dictionary()
    (
attrDict’s setObject:numFont forKey:(current application’s NSFontAttributeName))
    (
attrDict’s setObject:paraStyle forKey:(current application’s NSParagraphStyleAttributeName))
    (
attrDict’s setObject:(current application’s NSColor’s textColor()) forKey:(current application’s NSForegroundColorAttributeName))
    
    
set strSize to (numStr’s sizeWithAttributes:attrDict)
    
set textY to ry + ((rh – (strSize’s height)) / 2.0)
    
set textRect to current application’s NSMakeRect(rx, textY, rw, strSize’s height)
    
    (
numStr’s drawInRect:textRect withAttributes:attrDict)
  end repeat
  
  
displayImage’s unlockFocus()
  
  
return {sortedScreens, displayImage, {imgWidth, imgHeight}}
end drawDisplayLayout

★Click Here to Open This Script 

(Visited 4 times, 3 visits today)
Posted in dialog System | Tagged 10.15savvy 26.0savvy 27.0savvy | Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

電子書籍(PDF)をオンラインストアで販売中!

Google Search

Popular posts

  • シンプルな文字置換
  • macOS(Mac OS X/OS X)上のAppleScriptの歴史
  • Appleに買収されたPixelmator ProがAppleとしての初アップデート
  • Apple Creator Studioに含まれるKeynote/Pages/Numbersは新バージョン?
  • 最初期に書かれた書籍「AppleScript道入門」の序文をいま振り返る
  • Claris FileMaker Pro 2025(v22)がリリースされた
  • 指定フォルダ内から指定拡張子のファイルを取得し、エイリアスだったらオリジナルのパスをPOSIX pathで取得
  • MacBook Air/MacBook Proのディスプレイ開閉角度を取得
  • macOS 15.7.2 スクリプトメニューから実行できなくなった地図系ライブラリ?
  • Adobe InDesignのAppleScript実行エンジンがCarbonからCocoaベースに書き換えられる
  • 暗黙のuseコマンド
  • ASCII ART QR Encoder
  • 「AppleScriptセキュリティ実践ガイド」を発売
  • 開始時刻から終了時刻までhh:mm形式の文字列を15分単位でリスト出力
  • 各種GUIアプリ書類のオープン速度を向上するためにUIアニメーションの一時停止を
  • Finder上で選択中のHEIC画像から位置情報を削除_v5
  • ASCII ARTで円を線で描く
  • Keynote->Keynote Creator Studio(以下同様)
  • FSFindFolder failed with error=-43
  • 2025年に書いた価値あるAppleScript

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1391) 10.14savvy (587) 10.15savvy (440) 11.0savvy (283) 12.0savvy (212) 13.0savvy (204) 14.0savvy (159) 15.0savvy (172) 26.0savvy (50) CotEditor (68) Finder (53) Keynote (123) NSAlert (61) NSArray (51) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (53) NSDictionary (28) NSFileManager (23) NSFont (21) NSImage (41) NSJSONSerialization (21) NSMutableArray (63) NSMutableDictionary (22) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (119) NSURL (98) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (80) Pages (58) Safari (45) Script Editor (27) WKUserContentController (21) WKUserScript (20) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • Beginner
  • Benchmark
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • check sum
  • Clipboard
  • Cocoa-AppleScript Applet
  • Code Sign
  • Color
  • Custom Class
  • date
  • dialog
  • diff
  • drive
  • Droplet
  • exif
  • file
  • File path
  • filter
  • folder
  • Font
  • Font
  • GAME
  • geolocation
  • GUI
  • GUI Scripting
  • Hex
  • History
  • How To
  • iCloud
  • Icon
  • Image
  • Input Method
  • Internet
  • iOS App
  • JavaScript
  • JSON
  • JXA
  • Keychain
  • Keychain
  • Language
  • Library
  • list
  • Locale
  • Localize
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Newt On Project
  • NFC
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • parallel processing
  • PDF
  • Peripheral
  • process
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • rectangle
  • recursive call
  • regexp
  • Release
  • Remote Control
  • Require Control-Command-R to run
  • REST API
  • Review
  • RTF
  • Sandbox
  • Screen Saver
  • Script Libraries
  • Scripting Additions
  • sdef
  • search
  • Security
  • selection
  • shell script
  • Shortcuts Workflow
  • Sort
  • Sound
  • Spaces
  • Spellchecker
  • Spotlight
  • SVG
  • Swift
  • System
  • Tag
  • Telephony
  • Text
  • Text to Speech
  • timezone
  • Tools
  • Update
  • URL
  • UTI
  • Web Contents Control
  • WiFi
  • XML
  • XML-RPC
  • イベント(Event)
  • 未分類

アーカイブ

  • 2026年7月
  • 2026年6月
  • 2026年5月
  • 2026年3月
  • 2026年2月
  • 2026年1月
  • 2025年12月
  • 2025年11月
  • 2025年10月
  • 2025年9月
  • 2025年8月
  • 2025年7月
  • 2025年6月
  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年12月
  • 2019年11月
  • 2019年10月
  • 2019年9月
  • 2019年8月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年11月
  • 2018年10月
  • 2018年9月
  • 2018年8月
  • 2018年7月
  • 2018年6月
  • 2018年5月
  • 2018年4月
  • 2018年3月
  • 2018年2月

https://piyomarusoft.booth.pm/items/301502

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org

Forum Posts

  • 人気のトピック
  • 返信がないトピック

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org
Proudly powered by WordPress
Theme: Flint by Star Verte LLC