ホームページ>開発ツール>Xojo / Real Studio Trial and Error・CocoaのDeclareでドラッグ&ドロップを置き換える
Xojo / Real Studio Trial and Error
目次
CocoaのDeclareでドラッグ&ドロップを置き換える
はじめに
以下は、Xojo Cocoaビルドについての話題です。
ドラッグ&ドロップを、Xojoの機能を使わずに実現できるか試してみました。
なお検証には、Xojo 2016 Release 3を用いています。(Mac mini mid 2010 + OS X 10.13.6 High Sierra)
方針
Xojoはドラッグ&ドロップに対応していて、本Trial and Errorでも、こちらとこちらで利用しています。
ですが、(その時は敢えて深入りしませんでしたが、)どうも意図した通りには動いていないようです。
Xojo言語リファレンスの、ImageWellの項にあるサンプルをその通り再現しても、AcceptFileDropを記述すると、
1. 指定したファイルタイプだけでなく、全てのファイル/フォルダが対象になる。(そもそも、ファイルタイプグループがなくても機能してしまう。)
2. ピクチャークリッピングがファイルとしても読み込めてしまう。(AcceptPictureDropは機能しているので、obj.PictureAvailableをobj.FolderItemAvailableより前で判定すれば処理は可能。)
となってしまいます。
同じことをReal Studio 2011 Release 3で試すと、期待通りの動作をすることから、おそらくXojoがCocoa対応した辺りで変わったものと思われます(詳細未調査)。
この問題を解決しようとすると、純正コントロールのカスタマイズは難しそうなので、代替法はといえば、NSViewを使うことが考えられます。
NSViewにおけるドラッグ&ドロップは、例えば以下のサイトが参考になります。(他にも沢山あります。)
参考サイト(1):MacアプリTunacan開発の技術的メモ - Qiita
情報を基に、前述のXojoサンプル相当機能を実装してみることにします。
まずはXojoのAcceptFileDropに相当する(?)registerForDraggedTypes:ですが、public.file-url(注1)を指定して、全フォルダアイテムを対象とします。
注1)ググると、NSFilenamesPboardTypeを用いる例が多くヒットするが、既にDeprecatedになっている(とはいえ、10.14迄はOKなので暫くは大丈夫?)ので、代わりに用いることとした。ただしそうすると、propertyListForType:の戻り値はNSArrayではなく、(先頭の)NSStringになるようだ。次にデリゲートメソッドですが、concludeDragOperation、draggingEntered、performDragOperation、prepareForDragOperationをオーバーライドします。
参考サイト(2):SSFlight: Swift 4に移行したらファイルのドラッグ時にパスが取り出せない?
prepareForDragOperationは、全てのインスタンスで常にtrueを返せばよさそうだったので、クラス側(共有メソッド)で処理することとしました。
インスタンス側では、draggingEnteredでドラッグの可否判定(可の場合、カーソルに+印がつく)、performDragOperationでドロップの可否判定(否の場合、アイコンが元の場所に戻る)、concludeDragOperationでデータ処理を行います。
NSViewは、Xojoのコントロールを完全に置き換えることも可能ですが、ここではドラッグ&ドロップのみをNSViewに任せ、残りはXojoのコントロール側で処理することとしました。
NSViewをXojoのコントロールと同じ位置/サイズで置き、コントロール領域にドラッグされたものが処理対象となるようにします。
以上を踏まえ、(残りの)仕様は以下の通りとしました。
- ドロップ出来るファイルは1個とする。(複数ファイルのドロップには未対応。)
- Xojoのコントロールは、サンプルが記されたImageWellではなく、Canvasを用いる。
- Canvasは2個置き、一つ(Canvas1)はpng、もう一つ(Canvas2)はjpegのみを受け付ける。
- ファイル種別は、拡張子で判定する。(pngは「png」、jpegは「jpg」)
- Canvas2は、ウィンドウサイズに追随してリサイズする。
- Canvasへの描画は実寸とする。(画像をフィットさせる等、必要に応じてカスタマイズして下さい。)
- NSViewの作成とドラッグ&ドロップ関連の処理は、Canvasのサブクラスを作って、そこで行う。
- Canvas1、Canvas2のスーパークラスは上記サブクラスとする。
- クラス側にインスタンス情報をスタックして、振り分け処理を行う。
- インスタンス側への受け渡しには、イベントを用いる。
- コントロールのインスタンスをIDE上で配置すると、Constructorの引数でパラメータを渡すことができない(?)ようで、初期化メソッドを別途用意する。
- NSViewへの描画は積極的には行わないが、デバッグ用にDrawRectもオーバーライドしておく。
Xojoでの実装
【ソースコードのコピー&ペーストについて】
ソースコード(グレー背景部分の全文)をコピーし、指定のウィンドウ/クラスにペーストすると、(新規作成して名前等を個別にコピー&ペーストしなくても)復元されます。
ただし、この方法は、メソッドでは問題ないようですが、イベント/アクション/プロパティでは不安定?なので、ペーストできない場合は、各項目のカッコ内を適用して下さい。
実行してみたところ、ドラッグ&ドロップが機能することを確認しました。
- Xojoで新規プロジェクトを作成
- 新規クラス(名前は、ここでは「NSViewCanvas」)を作成し、Superを「Canvas」にする。
- 以下をNSViewCanvasにペースト(できなければ移譲に、デリゲート名:ActionDelegateC、引数:id As Ptr, SEL as CString, sender As Ptr、を追加)
Private Sub ActionDelegateC(id As Ptr, SEL as CString, sender As Ptr)
- 以下をNSViewCanvasにペースト(できなければ移譲に、デリゲート名:ActionDelegateD、引数:id As Ptr, SEL as CString, sender As Ptr、戻り値型:Integer、を追加)
Private Function ActionDelegateD(id As Ptr, SEL as CString, sender As Ptr) as Integer
- 以下をNSViewCanvasにペースト(できなければ移譲に、デリゲート名:ActionDelegateP、引数:id As Ptr, SEL as CString, sender As Ptr、戻り値型:Boolean、を追加)
Private Function ActionDelegateP(id As Ptr, SEL as CString, sender As Ptr) as Boolean
- 以下をNSViewCanvasにペースト(できなければイベント定義に、イベント名:ConcludeDragOperation、引数:id As Ptr, SEL as CString, sender As Ptr、を追加)
Event ConcludeDragOperation(id As Ptr, SEL as CString, sender As Ptr)
- 以下をNSViewCanvasにペースト(できなければイベント定義に、イベント名:DraggingEntered、引数:id As Ptr, SEL as CString, sender As Ptr、戻り値型:Integer、を追加)
Event DraggingEntered(id As Ptr, SEL as CString, sender As Ptr) As Integer
- 以下をNSViewCanvasにペースト(できなければイベント定義に、イベント名:PerformDragOperation、引数:id As Ptr, SEL as CString, sender As Ptr、戻り値型:Boolean、を追加)
Event PerformDragOperation(id As Ptr, SEL as CString, sender As Ptr) As Boolean
- 以下をNSViewCanvasにペースト
Private Sub EventConcludeDrag(id As Ptr, SEL as CString, sender As Ptr) // イベントをレイズ RaiseEvent ConcludeDragOperation(id,SEL,sender) End Sub
- 以下をNSViewCanvasにペースト
Private Function EventDragEntered(id As Ptr, SEL as CString, sender As Ptr) as Integer // イベントをレイズ return RaiseEvent DraggingEntered(id,SEL,sender) End Function
- 以下をNSViewCanvasにペースト
Private Function EventPerformDrag(id As Ptr, SEL as CString, sender As Ptr) as Boolean // イベントをレイズ return RaiseEvent PerformDragOperation(id,SEL,sender) End Function
- 以下をNSViewCanvasにペースト
Public Sub InitNSView(byRef inst As Ptr, win As Window, cnvs As Canvas) // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。 Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr // NSViewを継承したカスタムクラスを作成。初回のみ makeClass() // インスタンスを作成 Dim rect As NSRect = NSMakeRect(cnvs.Left, cnvs.Top, cnvs.Width, cnvs.Height) // Canvasの位置/サイズに合わせる Declare Function alloc Lib "Cocoa" selector "alloc" (class_id As Ptr) As Ptr Declare Function initWithFrame Lib "Cocoa" selector "initWithFrame:" (obj_id As Ptr, frame As NSRect) As Ptr Dim subclassId As Ptr = initWithFrame(alloc(NSVewClass), rect) // ドラッグ可能なタイプを指定 Dim ary As Ptr = NSClassFromString("NSMutableArray") Declare Function getArray Lib "Cocoa" Selector "array" (receiver As Ptr) As Ptr ary = getArray(ary) Declare Sub addObjectStr Lib "Cocoa" Selector "addObject:" (receiver As Ptr, obj As CFStringRef) addObjectStr(ary, "public.file-url") // フォルダアイテム // ドラッグ可能なタイプをViewにセット Declare Sub registerForDraggedTypes Lib "Cocoa" Selector "registerForDraggedTypes:" (receiver As Ptr, obj As Ptr) registerForDraggedTypes(subclassId, ary) // ウィンドウのビューを取得 Declare Function contentView Lib "Cocoa" selector "contentView" (class_id As Integer) As Ptr Dim pnt2 As Ptr = contentView(win.handle) // 生成したコントロールをビューに追加 Declare Sub addSubview Lib "Cocoa" selector "addSubview:" (class_id As Ptr, view As Ptr) addSubview(pnt2, subclassId) // Canvasごとにイベントをレイズするメソッドを登録 ActionHandlerC.Append AddressOf EventConcludeDrag ActionHandlerD.Append AddressOf EventDragEntered ActionHandlerP.Append AddressOf EventPerformDrag // インスタンスを保持 inst = subclassId InstancePtr.Append subclassId End Sub
- 以下をNSViewCanvasにペースト(できなければプロパティに、名前:Inst、データ型:Ptr、を追加)
Public Property Inst as Ptr
- 以下をNSViewCanvasにペースト
Private Shared Function GetInstIdx(id As Ptr) as Integer // 登録したインスタンス数だけチェック for i As Integer = 0 to InstancePtr.Ubound // ポインタが一致したら if id=InstancePtr(i) then return i end if next End Function
- 以下をNSViewCanvasにペースト
Private Shared Sub makeClass() // 文字列を指定してクラスオブジェクト/セレクタを取得する。最初に一回宣言しておけばよい。 Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr Declare Function NSSelectorFromString Lib "Cocoa" (aSelName As CFStringRef) As Ptr // Declare宣言 Declare Function objc_allocateClassPair Lib "Cocoa" (superclass As Ptr, name As CString, extraBytes As Integer) as Ptr Declare Sub objc_registerClassPair Lib "Cocoa" (cls As Ptr) Declare Function class_addMethod Lib "Cocoa" (cls As Ptr, name As Ptr, imp As Ptr, types As CString) As Boolean // 既にクラス作成済なら戻る if NSVewClass <> nil then return end if // クラス名をmyNSView、メタクラス名をNSViewにして、生成 Dim newClassId As Ptr = objc_allocateClassPair(NSClassFromString("NSView"), "myNSView", 0) // ランタイムに登録(参照を可能とするため) objc_registerClassPair newClassId // Delegateの対象となるメソッドを追加(drawRect:をXojo側で用意したmyDrawRectメソッドで受け取る。) if not class_addMethod (newClassId, NSSelectorFromString("drawRect:"), AddressOf myDrawRect, "v24@0:8@16") then msgBox "error6." return end if // Delegateの対象となるメソッドを追加(draggingEntered:をXojo側で用意したmyDraggingEnteredメソッドで受け取る。) if not class_addMethod (newClassId, NSSelectorFromString("draggingEntered:"), AddressOf myDraggingEntered, "v@0:@") then msgBox "error7." return end if // Delegateの対象となるメソッドを追加(prepareForDragOperation:をXojo側で用意したmyPrepareForDragOperationメソッドで受け取る。) if not class_addMethod (newClassId, NSSelectorFromString("prepareForDragOperation:"), AddressOf myPrepareForDragOperation, "v@0:@") then msgBox "error7." return end if // Delegateの対象となるメソッドを追加(performDragOperation:をXojo側で用意したmyPerformDragOperationtメソッドで受け取る。) if not class_addMethod (newClassId, NSSelectorFromString("performDragOperation:"), AddressOf myPerformDragOperation, "v@0:@") then msgBox "error7." return end if // Delegateの対象となるメソッドを追加(concludeDragOperation:をXojo側で用意したmyConcludeDragOperationメソッドで受け取る。) if not class_addMethod (newClassId, NSSelectorFromString("concludeDragOperation:"), AddressOf myConcludeDragOperation, "v@0:@") then msgBox "error7." return end if // クラスを保持 NSVewClass = newClassId End Sub
- 以下をNSViewCanvasにペースト
Private Shared Sub myConcludeDragOperation(id as Ptr, SEL as CString, sender As Ptr) // ドロップされたファイルを受け取って、処理する // idから、登録したインスタンスのインデックスを取得 Dim idx As Integer = GetInstIdx(id) // 当該インスタンスの、Actionを受け取るメソッドを呼び出す ActionHandlerC(idx).Invoke(id,SEL,sender) End Sub
- 以下をNSViewCanvasにペースト
Private Shared Function myDraggingEntered(id as Ptr, SEL as CString, sender As Ptr) as Integer // フォルダアイテムがビュー上にドラッグされた // idから、登録したインスタンスのインデックスを取得 Dim idx As Integer = GetInstIdx(id) // 当該インスタンスの、Actionを受け取るメソッドを呼び出す return ActionHandlerD(idx).Invoke(id,SEL,sender) // return = 0 : None , return = 1 : Copy End Function
- 以下をNSViewCanvasにペースト
Private Shared Sub myDrawRect(id as Ptr, sel as CString, rect As NSRect) // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。 Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr // 以下、デバッグ用。不要ならコメントアウトする -------------------- // カラーの取得 Dim clr As Ptr = NSClassFromString("NSColor") Declare Function colorWithRGBA Lib "Cocoa" Selector "colorWithRed:green:blue:alpha:" (receiver As Ptr, r As CGFloat, g As CGFloat, b As CGFloat, a As CGFloat) As Ptr clr = colorWithRGBA(clr, 1.0, 1.0, 1.0, 0.6) // 塗りつぶしカラーに指定 Declare Sub mySet Lib "Cocoa" selector "set" (class_id As Ptr) mySet(clr) // rectを半透明で塗りつぶす Declare Sub NSRectFillUsingOperation Lib "AppKit" (aRect As NSRect, parm As Integer) NSRectFillUsingOperation(rect, 2) // 2 = NSCompositeSourceOver // 以上、デバッグ用。不要ならコメントアウトする -------------------- // superの取得 dim sup As objc_super sup.receiver = id sup.pClass = NSClassFromString("NSView") // superに処理を渡す declare sub objc_msgSendSuper lib "Cocoa" (byref sup As objc_super, op As CString, rect As NSRect) objc_msgSendSuper(sup, sel, rect) End Sub
- 以下をNSViewCanvasにペースト
Private Shared Function myPerformDragOperation(id as Ptr, SEL as CString, sender As Ptr) as Boolean // ドロップ処理を受け付けるかを返す // idから、登録したインスタンスのインデックスを取得 Dim idx As Integer = GetInstIdx(id) // 当該インスタンスの、Actionを受け取るメソッドを呼び出す return ActionHandlerP(idx).Invoke(id,SEL,sender) End Function
- 以下をNSViewCanvasにペースト
Private Shared Function myPrepareForDragOperation(id as Ptr, SEL as CString, sender As Ptr) as Boolean // ドロップの前処理 return true // 常にtrueを返せばよさそう End Function
- 以下をNSViewCanvasにペースト(できなければ共有プロパティに、名前:ActionHandlerC(-1)、データ型:ActionDelegateC、を追加)
Private Shared Property ActionHandlerC(-1) as ActionDelegateC
- 以下をNSViewCanvasにペースト(できなければ共有プロパティに、名前:ActionHandlerD(-1)、データ型:ActionDelegateD、を追加)
Private Shared Property ActionHandlerD(-1) as ActionDelegateD
- 以下をNSViewCanvasにペースト(できなければ共有プロパティに、名前:ActionHandlerP(-1)、データ型:ActionDelegateP、を追加)
Private Shared Property ActionHandlerP(-1) as ActionDelegateP
- 以下をNSViewCanvasにペースト(できなければ共有プロパティに、名前:InstancePtr(-1)、データ型:Ptr、を追加)
Private Shared Property InstancePtr(-1) as Ptr
- 以下をNSViewCanvasにペースト(できなければ共有プロパティに、名前:NSVewClass、データ型:Ptr、を追加)
Private Shared Property NSVewClass as Ptr
- 以下をNSViewCanvasにペースト(できなければ構造体に、receiver As Ptr、pClass As Ptr、を追加)
Private Structure objc_super receiver As Ptr pClass As Ptr End Structure
- Window1に、Canvas2個(Name:Canvas1, Super:NSViewCanvas、Name:Canvas2, Super:NSViewCanvas, Locking:右と下もロック)を追加
- 以下をCanvas1にペースト(できなければ、Sub - Endの間をConcludeDragOperationイベントに記述)
Sub ConcludeDragOperation(id As Ptr, SEL as CString, sender As Ptr) Handles ConcludeDragOperation pic1 = GetPicture(id,SEL,sender,me.Inst) me.Refresh // 描画 End Sub
- 以下をCanvas1にペースト(できなければ、Sub - Endの間をDraggingEnteredイベントに記述)
Function DraggingEntered(id As Ptr, SEL as CString, sender As Ptr) Handles DraggingEntered as Integer if ValidateDragCanvas(id,SEL,sender,"png") then return 1 // Copy else return 0 // None end if End Function
- 以下をCanvas1にペースト(できなければ、Sub - Endの間をOpenイベントに記述)
Sub Open() Handles Open // NSView初期化。引数は順に、生成したインスタンス、配置するウィンドウ、自分自身 Dim inst As Ptr me.InitNSView(inst,self,me) me.Inst=inst // NSViewのLockingの設定(8 = 下辺が可変(即ち、上辺を固定)) Declare Sub setAutoresizingMask Lib "Cocoa" selector "setAutoresizingMask:" (class_id As Ptr, flg As Integer) setAutoresizingMask(inst, 8) End Sub
- 以下をCanvas1にペースト(できなければ、Sub - Endの間をPaintイベントに記述)
Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint g.ForeColor=RGB(0,255,255) g.FillRect 0,0,me.Width,me.Height if pic1<>nil then g.DrawPicture pic1,0,0 end if End Sub
- 以下をCanvas1にペースト(できなければ、Sub - Endの間をPerformDragOperationイベントに記述)
Function PerformDragOperation(id As Ptr, SEL as CString, sender As Ptr) Handles PerformDragOperation as Boolean return ValidateDragCanvas(id,SEL,sender,"png") End Function
- 以下をCanvas2にペースト(できなければ、Sub - Endの間をConcludeDragOperationイベントに記述)
Sub ConcludeDragOperation(id As Ptr, SEL as CString, sender As Ptr) Handles ConcludeDragOperation pic2 = GetPicture(id,SEL,sender,me.Inst) me.Refresh // 描画 End Sub
- 以下をCanvas2にペースト(できなければ、Sub - Endの間をDraggingEnteredイベントに記述)
Function DraggingEntered(id As Ptr, SEL as CString, sender As Ptr) Handles DraggingEntered as Integer if ValidateDragCanvas(id,SEL,sender,"jpg") then return 1 // Copy else return 0 // None end if End Function
- 以下をCanvas2にペースト(できなければ、Sub - Endの間をOpenイベントに記述)
Sub Open() Handles Open // NSView初期化。引数は順に、生成したインスタンス、配置するウィンドウ、自分自身 Dim inst As Ptr me.InitNSView(inst,self,me) me.Inst=inst // NSViewのLockingの設定(2 = 幅が可変、16 = 高さが可変) Declare Sub setAutoresizingMask Lib "Cocoa" selector "setAutoresizingMask:" (class_id As Ptr, flg As Integer) setAutoresizingMask(inst, 2+16) End Sub
- 以下をCanvas2にペースト(できなければ、Sub - Endの間をPaintイベントに記述)
Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint g.ForeColor=RGB(255,255,0) g.FillRect 0,0,me.Width,me.Height if pic2<>nil then g.DrawPicture pic2,0,0 end if End Sub
- 以下をCanvas2にペースト(できなければ、Sub - Endの間をPerformDragOperationイベントに記述)
Function PerformDragOperation(id As Ptr, SEL as CString, sender As Ptr) Handles PerformDragOperation as Boolean return ValidateDragCanvas(id,SEL,sender,"jpg") End Function
- 以下をWindow1にペースト
Protected Function GetPicture(id As Ptr, SEL As Cstring, sender As Ptr, viewInst As Ptr) as Picture // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。 Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr // ドラッグアイテムの取得 Declare Function draggingPasteboard Lib "Cocoa" selector "draggingPasteboard" (class_id As Ptr) As Ptr Dim pBoard As Ptr = draggingPasteboard(sender) // zoneの取得 Declare Function zone Lib "Cocoa" selector "zone" (class_id As Ptr) As Ptr Dim zn As Ptr = zone(viewInst) // ドラッグアイテムから画像の取得 Dim img As Ptr = NSClassFromString("NSImage") Declare Function allocWithZone Lib "Cocoa" selector "allocWithZone:" (class_id As Ptr, zone As Ptr) As Ptr Declare Function initWithPasteboard Lib "Cocoa" selector "initWithPasteboard:" (class_id As Ptr, board As Ptr) As Ptr img = initWithPasteboard(allocWithZone(img, zn), pBoard) // NSImageをNSDataに変換する Declare Function TIFFRepresentation Lib "Cocoa" Selector "TIFFRepresentation" (receiver As Ptr) As Ptr Dim data As Ptr = TIFFRepresentation(img) // clean up Declare Sub release Lib "Cocoa" Selector "release" (receiver As Ptr) release(img) // NSDataのデータ長を取得 Declare Function length Lib "Cocoa" Selector "length" (receiver As Ptr) As Integer Dim lng As Integer = length(data) // NSDataからバイト列を抽出 Declare Function bytes Lib "Cocoa" Selector "bytes" (receiver As Ptr) As Ptr Dim bstream As Ptr = bytes(data) // バイト列をXojo.Core.MemoryBlockに格納後、MemoryBlockに変換 Dim xmb As new Xojo.Core.MemoryBlock(bstream, lng) Dim temp As MemoryBlock = xmb.Data Dim mb As New MemoryBlock(xmb.Size) mb.StringValue(0, mb.Size) = temp.StringValue(0, mb.Size) // MemoryBlockからPictureを生成して返す return Picture.FromData(mb) End Function
- 以下をWindow1にペースト
Protected Function ValidateDragCanvas(id As Ptr, SEL As Cstring, sender As Ptr, extnRef As String) as Boolean // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。 Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr // ドラッグされたオブジェクトの取得 Declare Function draggingPasteboard Lib "Cocoa" selector "draggingPasteboard" (class_id As Ptr) As Ptr Dim pnt1 As Ptr = draggingPasteboard(sender) // ファイルパス(URL)の取得 Declare Function propertyListForType Lib "Cocoa" selector "propertyListForType:" (class_id As Ptr, sender As CFStringRef) As CFStringRef Dim url As CFStringRef = propertyListForType(pnt1, "public.file-url") // 拡張子の取得 Dim nsstr As Ptr = NSClassFromString("NSString") Declare Function stringWithString Lib "Cocoa" Selector "stringWithString:" (receiver As Ptr, string As CFStringRef) As Ptr Declare Function pathExtension Lib "Cocoa" Selector "pathExtension" (receiver As Ptr) As CFStringRef Dim extnF As String = pathExtension(stringWithString(nsstr, url)) // ファイルの拡張子が指定されたものならtrue、それ以外はfalse if extnF=extnRef then return true else return false end if End Function
- 以下をWindow1にペースト(できなければプロパティに、名前:pic1、データ型:Picture、を追加)
Protected Property pic1 as Picture
- 以下をWindow1にペースト(できなければプロパティに、名前:pic2、データ型:Picture、を追加)
Protected Property pic2 as Picture
- 他に、NSMakeRect(メソッド)、NSRect(構造体)が必要ですが、それらはmacoslibからコピーさせて頂きました。(上記NSViewCanvasまたは別途モジュールを用意してコピーする。)
おわりに
複数ファイルのドロップ対応とか、ファイル種別判定周りをもう少しきめ細かくする(注2)とか、手を加える箇所はありそうです。
注2)例えば「file」コマンドを使うと、ファイルの中身をチェックして種別を判定できるとのこと。とはいえ、純正のままでも、ドロップ受付後に判定して対象外はメッセージを出して受付ない、とかすれば実用上は問題ない(かもしれない)ので、置き換え自体、有用性が薄いかも。
参考サイト(3):拡張子を偽るPNGファイルを見破るfileコマンド - Qiita
お世話になったサイト
貴重な情報をご提供頂いている皆様に、お礼申し上げます。(以下、順不同)
参考サイト(1):MacアプリTunacan開発の技術的メモ - Qiita
参考サイト(2):SSFlight: Swift 4に移行したらファイルのドラッグ時にパスが取り出せない?
参考サイト(3):拡張子を偽るPNGファイルを見破るfileコマンド - Qiita
更新履歴
2019.05.07 新規作成
[Home] [MacSoft] [Donation] [History] [Privacy Policy] [Affiliate Policy]