ホームページ>開発ツール>Xojo / Real Studio Trial and Error・CocoaのDeclareでリッチテキストを扱う・アンドゥの問題と対策 - 別稿
- NSTextViewCategoryのメソッドを以下の通り書き換え
メソッド名: insTextStrage 引数: kind As String, id as Ptr, obj As Ptr Dim enable As Boolean = true // UndoManagerを取得するウィンドウを指定していない場合はdisableに if myWindow = nil then enable = false end if // アンドゥが無効ならdisableに declare function allowsUndo lib "Cocoa" selector "allowsUndo" (receiver as Ptr) As Boolean Dim flg As Boolean = allowsUndo(id) if flg = false then enable = false end if // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。 Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr // NSTextStorageの取得 declare function textStorage lib "Cocoa" selector "textStorage" (obj_id as Ptr) As Ptr // Return NSTextStorage* Dim pnt2 As Ptr = textStorage(id) Declare Function alloc Lib "Cocoa" Selector "alloc" (receiver As Ptr) As Ptr Dim attachChar As Ptr if kind = "String" then attachChar = obj elseif kind = "Image" then Dim attachment As Ptr = NSClassFromString("NSTextAttachment") attachment = alloc(attachment) Declare Function wrapInit Lib "Cocoa" Selector "initWithFileWrapper:" (receiver As Ptr, wrapper As Ptr) As Ptr attachment = wrapInit(attachment, obj) Dim attachChar1 As Ptr = NSClassFromString("NSAttributedString") Declare Function attributedStringWithAttachment Lib "Cocoa" Selector "attributedStringWithAttachment:" (receiver As Ptr, attachment As Ptr) As Ptr attachChar = attributedStringWithAttachment(attachChar1, attachment) end if Dim attrString As Ptr = NSClassFromString("NSMutableAttributedString") attrString = alloc(attrString) Declare Function initWithString Lib "Cocoa" Selector "initWithAttributedString:" (receiver As Ptr, str As Ptr) As Ptr attrString = initWithString(attrString, pnt2) Declare Function mutableCopy Lib "Cocoa" Selector "mutableCopy" (receiver As Ptr) As Ptr Dim oldAttrString As Ptr = mutableCopy(attrString) // Undo登録用に現在の値を複製しておく Declare Sub beginEditing Lib "Cocoa" Selector "beginEditing" (receiver As Ptr) beginEditing(attrString) Declare Function selectedRange Lib "Cocoa" Selector "selectedRange" (receiver As Ptr) As NSRange Dim rng As NSRange = selectedRange(id) Declare Sub insertAttributedString Lib "Cocoa" Selector "insertAttributedString:atIndex:" (receiver As Ptr, attachChar As Ptr, index As Integer) insertAttributedString(attrString, attachChar, rng.location) // キャレット位置をNSTextViewから取得 Declare Sub endEditing Lib "Cocoa" Selector "endEditing" (receiver As Ptr) endEditing(attrString) if enable then // アンドゥが有効なら // NSUndoManagerの取得 declare function undoManager lib "Cocoa" selector "undoManager" (obj_id as Integer) as Ptr // Return NSUndoManager* Dim pnt11 As Ptr = undoManager(myWindow.Handle) // UndoManagerにUndo時に使うメソッドと値を登録 declare function prepareWithInvocationTarget lib "Cocoa" selector "prepareWithInvocationTarget:" (receiver as Ptr, target As Ptr) As Ptr Dim pnt12 As Ptr = prepareWithInvocationTarget(pnt11, stAttrStrInstance) Declare Sub tStragesetAttrString Lib "Cocoa" Selector "tStrage:setAttrString:" (receiver As Ptr, tStrage As Ptr, attrString As Ptr) tStragesetAttrString(pnt12, pnt2, oldAttrString) end if // 画像を追加したストレージを書き戻す mySetAttributedString(nil, nil, pnt2, attrString)
- NSTextViewCategoryのメソッドを以下の通り書き換え
注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)メソッド名: myDeleteBackward 引数: id As Ptr, SEL As CString Dim enable As Boolean = true // UndoManagerを取得するウィンドウを指定していない場合はdisableに if myWindow = nil then enable = false end if // アンドゥが無効ならdisableに declare function allowsUndo lib "Cocoa" selector "allowsUndo" (receiver as Ptr) As Boolean Dim flg As Boolean = allowsUndo(id) if flg = false then enable = false end if Dim pnt1 As Ptr if enable then // アンドゥが有効なら // NSUndoManagerの取得 declare function undoManager lib "Cocoa" selector "undoManager" (obj_id as Integer) as Ptr // Return NSUndoManager* pnt1 = undoManager(myWindow.Handle) // UndoGrouping開始 declare sub beginUndoGrouping lib "Cocoa" selector "beginUndoGrouping" (receiver as Ptr) beginUndoGrouping(pnt1) end if // 本来のdeleteBackwardを実行 declare sub myDeleteBackward lib "Cocoa" selector "myDeleteBackward" (receiver as Ptr) myDeleteBackward(id) if enable then // アンドゥが有効なら // UndoGrouping終了 declare sub endUndoGrouping lib "Cocoa" selector "endUndoGrouping" (receiver as Ptr) endUndoGrouping(pnt1) end if
- NSTextViewCategoryのメソッドを以下の通り書き換え
注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)メソッド名: myInsertText 引数: id As Ptr, SEL As CString, txt As Ptr Dim enable As Boolean = true // UndoManagerを取得するウィンドウを指定していない場合はdisableに if myWindow = nil then enable = false end if // アンドゥが無効ならdisableに declare function allowsUndo lib "Cocoa" selector "allowsUndo" (receiver as Ptr) As Boolean Dim flg As Boolean = allowsUndo(id) if flg = false then enable = false end if Dim pnt1 As Ptr if enable then // アンドゥが有効なら // NSUndoManagerの取得 declare function undoManager lib "Cocoa" selector "undoManager" (obj_id as Integer) as Ptr // Return NSUndoManager* pnt1 = undoManager(myWindow.Handle) // UndoGrouping開始 declare sub beginUndoGrouping lib "Cocoa" selector "beginUndoGrouping" (receiver as Ptr) beginUndoGrouping(pnt1) end if // 本来のinsertText:を実行 declare sub myInsertText lib "Cocoa" selector "myInsertText:" (receiver as Ptr, txt As Ptr) myInsertText(id, txt) if enable then // アンドゥが有効なら // UndoGrouping終了 declare sub endUndoGrouping lib "Cocoa" selector "endUndoGrouping" (receiver as Ptr) endUndoGrouping(pnt1) end if
- NSTextViewCategoryのメソッドを以下の通り書き換え
注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)メソッド名: mySetAttributedString 引数: id As Ptr, SEL As CString, tStrage As Ptr, attrString As Ptr Dim enable As Boolean = true // UndoManagerを取得するウィンドウを指定していない場合はdisableに if myWindow = nil then enable = false end if // アンドゥが無効ならdisableに declare function allowsUndo lib "Cocoa" selector "allowsUndo" (receiver as Ptr) As Boolean Dim flg As Boolean = allowsUndo(id) if flg = false then enable = false end if if enable then // アンドゥが有効なら // NSUndoManagerの取得 declare function undoManager lib "Cocoa" selector "undoManager" (obj_id as Integer) as Ptr // Return NSUndoManager* Dim pnt11 As Ptr = undoManager(myWindow.Handle) // Redo用 declare function prepareWithInvocationTarget lib "Cocoa" selector "prepareWithInvocationTarget:" (receiver as Ptr, target As Ptr) As Ptr Dim pnt12 As Ptr = prepareWithInvocationTarget(pnt11, stAttrStrInstance) Declare Sub tStragesetAttrString Lib "Cocoa" Selector "tStrage:setAttrString:" (receiver As Ptr, tStrage As Ptr, attrString As Ptr) tStragesetAttrString(pnt12, tStrage, attrString) end if // 画像を追加したストレージを書き戻す Declare Sub setAttributedString Lib "Cocoa" Selector "setAttributedString:" (receiver As Ptr, identifier As Ptr) setAttributedString(tStrage, attrString)
- NSTextViewCategoryのメソッドを以下の通り書き換え
注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)メソッド名: mySetMarkedTextSelectedRange 引数: id As Ptr, SEL As CString, txt As Ptr, range As NSRange Dim enable As Boolean = true // UndoManagerを取得するウィンドウを指定していない場合はdisableに if myWindow = nil then enable = false end if // アンドゥが無効ならdisableに declare function allowsUndo lib "Cocoa" selector "allowsUndo" (receiver as Ptr) As Boolean Dim flg As Boolean = allowsUndo(id) if flg = false then enable = false end if // txtをPtr型で受けているため、CFStringRef型に変換(macoslibによる) soft declare function CFRetain lib "Carbon" (cf as Ptr) as CFStringRef Dim st As CFStringRef = CFRetain(txt) if 0 < LenB(st) then Dim pnt1 As Ptr if enable then // アンドゥが有効なら // NSUndoManagerの取得 declare function undoManager lib "Cocoa" selector "undoManager" (obj_id as Integer) as Ptr // Return NSUndoManager* pnt1 = undoManager(myWindow.Handle) // UndoGrouping開始 declare sub beginUndoGrouping lib "Cocoa" selector "beginUndoGrouping" (receiver as Ptr) beginUndoGrouping(pnt1) end if // 本来のsetMarkedText:SelectedRange:を実行 declare sub mySetMarkedText lib "Cocoa" selector "mySetMarkedText:selectedRange:" (receiver as Ptr, txt As Ptr, range As NSRange) mySetMarkedText(id, txt, range) if enable then // アンドゥが有効なら // UndoGrouping終了 declare sub endUndoGrouping lib "Cocoa" selector "endUndoGrouping" (receiver as Ptr) endUndoGrouping(pnt1) end if end if
- NSTextViewCategoryのメソッドを以下の通り書き換え
注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)メソッド名: myShouldChangeTextInRangeReplacementString 引数: id As Ptr, SEL As CString, range As NSRange, txt As Ptr 戻り値型: Boolean Dim enable As Boolean = true // UndoManagerを取得するウィンドウを指定していない場合はdisableに if myWindow = nil then enable = false end if // アンドゥが無効ならdisableに declare function allowsUndo lib "Cocoa" selector "allowsUndo" (receiver as Ptr) As Boolean Dim flg As Boolean = allowsUndo(id) if flg = false then enable = false end if Dim pnt1 As Ptr if enable then // アンドゥが有効なら // NSUndoManagerの取得 declare function undoManager lib "Cocoa" selector "undoManager" (obj_id as Integer) as Ptr // Return NSUndoManager* pnt1 = undoManager(myWindow.Handle) // UndoGrouping開始 declare sub beginUndoGrouping lib "Cocoa" selector "beginUndoGrouping" (receiver as Ptr) beginUndoGrouping(pnt1) end if // 本来のshouldChangeTextInRange:replacementString:を実行 declare function myShouldChangeText lib "Cocoa" selector "myShouldChangeTextInRange:replacementString:" (receiver as Ptr, range As NSRange, txt As Ptr) As Boolean Dim ret As Boolean = myShouldChangeText(id, range, txt) if enable then // アンドゥが有効なら // UndoGrouping終了 declare sub endUndoGrouping lib "Cocoa" selector "endUndoGrouping" (receiver as Ptr) endUndoGrouping(pnt1) end if // 本来のshouldChangeTextInRange:replacementString:の結果を返す(trueでないと文字が入力されない?) return ret
[Home] [MacSoft] [Donation] [History] [Privacy Policy] [Affiliate Policy]