ホームページ開発ツール>Xojo / Real Studio Trial and Error・CocoaのDeclareでツールバーを実装する・コントロールの追加

 Xojo / Real Studio Trial and Error

CocoaのDeclareでツールバーを実装する・コントロールの追加

目次
 はじめに

 以下は、Xojo Cocoaビルドについての話題です。

 前回のケースに、サーチフィールド/セグメンテッドコントロール/スライダーを追加してみました。

 なお検証には、Xojo 2015 Release 2.4を用いています。(Mac mini mid 2010 + OS X 10.11 El Capitan)


 コントロールを配置する上での留意点

 ツールバーには通常のアイテム(ボタン)の他に、サーチフィールド等のコントロールを配置できます。
 ただし、コントロールを直接配置することはできず、まずはコントロールのインスタンスを作り、それをアイテムのビューにセットする、という手順をとります。
 この時、Action発生時に渡されるsenderはアイテムではなく、コントロールになります。

 サーチフィールドはその使い方として、文字列を入力後、虫眼鏡ボタンを押すのではなく、リターンキーを押すこともある訳ですが、そのためにはリターンキーが押されたことを検知する必要があります。この操作はActionでは伝わってこないため、Delegateを設定することで対処します。
 DelegateはNSToolbarItemではなく、NSSearchFieldに対して設定します。
 また、TargetはNSSearchFieldではなく、NSSearchFieldCellのsearchButtonCellに対して設定します。
 サーチフィールドの動作は、文字を入力すると直ちにActionが発生するもの(アップル標準のアプリは、こちらがデフォ)と、リターンキーを押すとActionが発生するものを選択できます。
 また、直ちにActionが発生する方を選択した場合は、キーストローク毎にActionが発生するものと、ある程度文字入力が進んでからActionが発生するもの(その方が検索処理の負荷が軽減される、ということのようだ)を選択できます。
 なお、キーが押されたことの検知は、TargetをNSSearchFieldに設定することにより、Actionで拾うことができます。(Delegateの設定は不要です。)
 一方、虫眼鏡ボタンは、NSSearchFieldでもNSSearchFieldCellのsearchButtonCellでも、Actionを拾える(?)ようです。

 セグメンテッドコントロールでは、どのセグメントが押されたかの判定に、タグを用います。そのため、タグの値は同一セグメント内だけでなく、Actionメソッドを共有する全セグメント内で固有である必要があります。

 スライダーは、デフォルトではノブを動かした時にリアルタイムでActionが発生しますが、確定時のみ発生させたい場合はcontinuousプロパティをfalseに設定します。(どちらも取得したい場合については未調査です。)


 Xojoでの実装

 以下の実装では、Actionの受け口を全てToolbarItemClickedとしているため、senderのdescriptionで振り分け処理を行っています。必要なら、個別に受け口を設定して下さい。ただし、その場合は動的クラス生成(makeTarget)も個別化する必要があります。
 実装にあたっては、以下のサイトを参考にさせて頂きました。
 参考サイト(1):Introduction to Segmented Controls
 参考サイト(2):NSTextFieldでReturn等のkeyDownイベントを検知する - 日々精進
  1. 前回プロジェクトのWindow1にListBox(名前はListBox1)を追加(注:デバッグ用であり、必須ではない。)
  2. 以下のWindow1のメソッドを書き換え
    メソッド名: ToolbarItemClicked
    引数: sender As Ptr
    
    Declare Function description Lib "Cocoa" Selector "description" (receiver As Ptr) As CFStringRef
    Declare Function label Lib "Cocoa" Selector "label" (receiver As Ptr) As CFStringRef
    
    Dim name As String = description(sender)
    if InStrB(name,"NSToolbarItem")>0 then  // 通常のアイテム
    
        // アイテムの種別がSaveなら必要な処理を行う
        if label(sender) = "Save" then
            Listbox1.AddRow label(sender)+" Pushed."
        end if
        
    elseif InStrB(name,"NSSearchField")>0 then  // サーチフィールド
        
        Declare Function stringValue Lib "Cocoa" Selector "stringValue" (receiver As Ptr) As CFStringRef
        Listbox1.AddRow "Search Word = "+stringValue(sender)  // 検索文字列
        
    elseif InStrB(name,"NSSegmentedControl")>0 then  // セグメンテッドコントロール
        
        Declare Function selectedSegment Lib "Cocoa" Selector "selectedSegment" (receiver As Ptr) As Integer
        Declare Function cell Lib "Cocoa" Selector "cell" (receiver As Ptr) As Ptr
        Declare Function tagForSegment Lib "Cocoa" Selector "tagForSegment:" (receiver As Ptr, seg As Integer) As Integer
        Dim tagno As Integer = tagForSegment(cell(sender), selectedSegment(sender))
        if tagno = 500 then
           Listbox1.AddRow "Selected = Yes."
        elseif tagno = 501 then
            Listbox1.AddRow "Selected = No."
        elseif tagno = 502 then
            Listbox1.AddRow "Selected = Unknown."
        end if
        
    elseif InStrB(name,"NSSlider")>0 then  // スライダー
        
        Declare Function doubleValue Lib "Cocoa" Selector "doubleValue" (receiver As Ptr) As Double
        Listbox1.AddRow "Value = "+str(doubleValue(sender))
        
    else
        msgBox "No Define"
    end if
    
  3. 以下をWindow1の共有メソッド(Shared Methods)に追加(不要だったので、削除(2018.01.17))
    メソッド名: controlTextViewDoCommandBySelector
    引数: id As Ptr, sel As Ptr, control As Ptr, textView As Ptr, command As Ptr
    
    Dim mb As MemoryBlock
    mb = command
    if mb.CString(0) = "insertNewline:" then  // retunキーが押された
    
        // Sharedでないメソッドに渡す(control = myNSSearchField がsenderになる。)
        Window1Instance.ToolbarItemClicked(control)
    
    end if
    
  4. 以下をWindow1の共有メソッド(Shared Methods)に追加(不要だったので、削除(2018.01.17))
    メソッド名: makeDelegateTextView
    引数: name As String
    戻り値型: Ptr
    
    // 文字列を指定してクラスオブジェクト/セレクタを取得する。最初に一回宣言しておけばよい。
    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 SearchDelegateInstance <> nil then
        return SearchDelegateInstance
    end if
    
    // クラス名を引数のname(名前は任意だが、重複を避けるためにアイテムのIdentifierにしている。)、メタクラス名をNSObjectにして、生成
    Dim newClassId As Ptr = objc_allocateClassPair(NSClassFromString("NSObject"), name, 0)
    // ランタイムに登録(参照を可能とするため)
    objc_registerClassPair newClassId
    // Delegateの対象となるメソッドを追加(control:textView:doCommandBySelector:をXojo側で用意したcontrolTextViewDoCommandBySelectorメソッドで受け取る。)
    if not class_addMethod (newClassId, NSSelectorFromString("control:textView:doCommandBySelector:"), AddressOf controlTextViewDoCommandBySelector, "v@:@@@") then
        msgBox "error."
        return nil
    end if
    
    // 上記で生成したクラスのインスタンスを作成
    Declare Function alloc Lib "Cocoa" selector "alloc" (class_id As Ptr) As Ptr
    Declare Function init Lib "Cocoa" selector "init" (obj_id As Ptr) As Ptr
    Dim delegateId As Ptr = init(alloc(newClassId))
    
    // インスタンスを保持
    SearchDelegateInstance = delegateId
    
    // インスタンスを返す
    return delegateId
    
  5. 以下をWindow1の共有メソッド(Shared Methods)に追加
    メソッド名: setToolItemSave
    引数: itemIdentifier As String
    戻り値型: Ptr
    
    // 文字列を指定してクラスオブジェクト/セレクタを取得する。最初に一回宣言しておけばよい。
    Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
    Declare Function NSSelectorFromString Lib "Cocoa" (aSelName As CFStringRef) As Ptr
    
    Declare Function alloc Lib "Cocoa" Selector "alloc" (receiver As Ptr) As Ptr
    
    // アイコン取得
    Dim bundle1 As Ptr = NSClassFromString("NSBundle")
    Declare Function mainBundle Lib "Cocoa" Selector "mainBundle" (receiver As Ptr) As Ptr
    bundle1 = mainBundle(bundle1)
    Declare Function pathForResource Lib "Cocoa" Selector "pathForResource:ofType:" (receiver As Ptr, path As CFStringRef, type As CFStringRef) As CFStringRef
    Dim filepath As String = pathForResource(bundle1,"save","png")
    Dim image1 As Ptr = NSClassFromString("NSImage")
    image1 = alloc(image1)
    Declare Function initWithContentsOfFile Lib "Cocoa" Selector "initWithContentsOfFile:" (receiver As Ptr, path As CFStringRef) As Ptr
    image1 = initWithContentsOfFile(image1, filepath)
    
    // アイテム初期化
    Dim toolbarItem As Ptr = NSClassFromString("NSToolbarItem")
    toolbarItem = alloc(toolbarItem)
    Declare Function initWithItemIdentifier Lib "Cocoa" Selector "initWithItemIdentifier:" (receiver As Ptr, identifier As CFStringRef) As Ptr
    toolbarItem = initWithItemIdentifier(toolbarItem, itemIdentifier)
    
    // ラベル/ツールチップ設定
    Declare Sub setLabel Lib "Cocoa" Selector "setLabel:" (receiver As Ptr, label As CFStringRef)
    setLabel(toolbarItem, "Save")
    Declare Sub setPaletteLabel Lib "Cocoa" Selector "setPaletteLabel:" (receiver As Ptr, label As CFStringRef)
    setPaletteLabel(toolbarItem, "Save")
    Declare Sub setToolTip Lib "Cocoa" Selector "setToolTip:" (receiver As Ptr, text As CFStringRef)
    setToolTip(toolbarItem, "Save Your Document")
    
    // アイコン設定
    Declare Sub setImage Lib "Cocoa" Selector "setImage:" (receiver As Ptr, image As Ptr)
    setImage(toolbarItem, image1)
    
    // Target/Action設定
    Declare Sub setTarget Lib "Cocoa" Selector "setTarget:" (receiver As Ptr, actionTarget As Ptr)
    setTarget(toolbarItem, makeTarget(itemIdentifier))  // Actionの受け口となるメソッドを定義
    Declare Sub setAction Lib "Cocoa" Selector "setAction:" (receiver As Ptr, actionEvent As Ptr)
    setAction(toolbarItem, NSSelectorFromString("action:"))
    
    // 生成したアイテムを返す
    return toolbarItem
    
  6. 以下をWindow1の共有メソッド(Shared Methods)に追加(大幅に改訂(2018.01.17))
    メソッド名: setToolItemSearch
    引数: itemIdentifier As String
    戻り値型: Ptr
    
    // 文字列を指定してクラスオブジェクト/セレクタを取得する。最初に一回宣言しておけばよい。
    Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
    Declare Function NSSelectorFromString Lib "Cocoa" (aSelName As CFStringRef) As Ptr
    
    Declare Function alloc Lib "Cocoa" Selector "alloc" (receiver As Ptr) As Ptr
    
    // サーチフィールド初期化
    Dim search1 As Ptr = NSClassFromString("NSSearchField")
    search1 = alloc(search1)
    Declare Function initWithFrame Lib "Cocoa" Selector "initWithFrame:" (receiver As Ptr, identifier As NSRect) As Ptr
    search1 = initWithFrame(search1, NSMakeRect(0,0,150,24))
    
    // アイテム初期化
    Dim toolbarItem As Ptr = NSClassFromString("NSToolbarItem")
    toolbarItem = alloc(toolbarItem)
    Declare Function initWithItemIdentifier Lib "Cocoa" Selector "initWithItemIdentifier:" (receiver As Ptr, identifier As CFStringRef) As Ptr
    toolbarItem = initWithItemIdentifier(toolbarItem, itemIdentifier)
    
    // ラベル/ツールチップ設定
    Declare Sub setLabel Lib "Cocoa" Selector "setLabel:" (receiver As Ptr, label As CFStringRef)
    setLabel(toolbarItem, "Search")
    Declare Sub setPaletteLabel Lib "Cocoa" Selector "setPaletteLabel:" (receiver As Ptr, label As CFStringRef)
    setPaletteLabel(toolbarItem, "Search")
    Declare Sub setToolTip Lib "Cocoa" Selector "setToolTip:" (receiver As Ptr, text As CFStringRef)
    setToolTip(toolbarItem, "Search Your Document")
    
    // サーチフィールドクリック後、直ちに文字入力を可能とするための設定(2016.06.28追加)
    Declare Sub refusesFirstResponder Lib "Cocoa" Selector "setRefusesFirstResponder:" (receiver As Ptr, flg As Boolean)
    refusesFirstResponder(search1, true)
    
    // アイテムのビューにサーチフィールドを設定
    Declare Sub setView Lib "Cocoa" Selector "setView:" (receiver As Ptr, actionTarget As Ptr)
    setView(toolbarItem, search1)  // 初出時、変数名をsearchView1としていたが誤りで、search1に訂正(2016.03.28)
    
    // Target/Action設定
    Declare Sub setTarget Lib "Cocoa" Selector "setTarget:" (receiver As Ptr, actionTarget As Ptr)
    setTarget(search1, makeTarget(itemIdentifier))  // Actionの受け口となるメソッドを定義
    Declare Sub setAction Lib "Cocoa" Selector "setAction:" (receiver As Ptr, actionEvent As Ptr)
    setAction(search1, NSSelectorFromString("action:"))
    
    // 検索オプション設定(本サンプルでは、Retrnキーを押した時点でActionが発生、を選択)
    Declare Function cell Lib "Cocoa" Selector "cell" (receiver As Ptr) As Ptr
    Dim cell1 As Ptr = cell(search1)  // NSSearchFieldCellを取得
    Declare Sub setSendsWholeSearchString Lib "Cocoa" Selector "setSendsWholeSearchString:" (receiver As Ptr, flag As Boolean)
    setSendsWholeSearchString(cell1, true)  // false:キーストローク毎にActionが発生, true:Retrnキーを押した時点でActionが発生
    Declare Sub sendsSearchStringImmediately Lib "Cocoa" Selector "setSendsSearchStringImmediately:" (receiver As Ptr, flag As Boolean)
    sendsSearchStringImmediately(cell1, false)  // false:文字をある程度溜めてからActionが発生, true:文字を入力すると直ちにActionが発生
    
    // 生成したアイテムを返す
    return toolbarItem
    
  7. 以下をWindow1の共有メソッド(Shared Methods)に追加
    メソッド名: setToolItemSegment
    引数: itemIdentifier As String
    戻り値型: Ptr
    
    // 文字列を指定してクラスオブジェクト/セレクタを取得する。最初に一回宣言しておけばよい。
    Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
    Declare Function NSSelectorFromString Lib "Cocoa" (aSelName As CFStringRef) As Ptr
    
    Declare Function alloc Lib "Cocoa" Selector "alloc" (receiver As Ptr) As Ptr
    
    // セグメンテッドコントロール初期化
    Dim segment1 As Ptr = NSClassFromString("NSSegmentedControl")
    segment1 = alloc(segment1)
    Declare Function initWithFrame Lib "Cocoa" Selector "initWithFrame:" (receiver As Ptr, identifier As NSRect) As Ptr
    segment1 = initWithFrame(segment1, NSMakeRect(0,0,180,24))
    
    // セグメント数/ラベル/選択状態/タグ設定
    Declare Sub setSegmentCount Lib "Cocoa" Selector "setSegmentCount:" (receiver As Ptr, cnt As Integer)
    setSegmentCount(segment1, 3)
    Declare Sub setLabel Lib "Cocoa" Selector "setLabel:forSegment:" (receiver As Ptr, label As CFStringRef, no As Integer)
    setLabel(segment1, "Yes", 0)
    setLabel(segment1, "No", 1)
    setLabel(segment1, "Unknown", 2)
    Declare Sub setSelected Lib "Cocoa" Selector "setSelected:forSegment:" (receiver As Ptr, selected As Boolean, no As Integer)
    setSelected(segment1, true, 0)  // デフォルトの選択
    setSelected(segment1, false, 1)
    setSelected(segment1, false, 2)
    Declare Function cell Lib "Cocoa" Selector "cell" (receiver As Ptr) As Ptr
    Declare Sub setTag Lib "Cocoa" Selector "setTag:forSegment:" (receiver As Ptr, tag As Integer, no As Integer)
    setTag(cell(segment1), 500, 0)  // タグだけ判別するので、同じActionメソッドを使用するセグメント間で固有の数値にする
    setTag(cell(segment1), 501, 1)
    setTag(cell(segment1), 502, 2)
    
    // アイテム初期化
    Dim toolbarItem As Ptr = NSClassFromString("NSToolbarItem")
    toolbarItem = alloc(toolbarItem)
    Declare Function initWithItemIdentifier Lib "Cocoa" Selector "initWithItemIdentifier:" (receiver As Ptr, identifier As CFStringRef) As Ptr
    toolbarItem = initWithItemIdentifier(toolbarItem, itemIdentifier)
    
    // ラベル/ツールチップ設定
    Declare Sub setLabel Lib "Cocoa" Selector "setLabel:" (receiver As Ptr, label As CFStringRef)
    setLabel(toolbarItem, "Segmented Control")
    Declare Sub setPaletteLabel Lib "Cocoa" Selector "setPaletteLabel:" (receiver As Ptr, label As CFStringRef)
    setPaletteLabel(toolbarItem, "Segmented Control")
    Declare Sub setToolTip Lib "Cocoa" Selector "setToolTip:" (receiver As Ptr, text As CFStringRef)
    setToolTip(toolbarItem, "Segmented Control")
    
    // アイテムのビューにセグメンテッドコントロールを設定
    Declare Sub setView Lib "Cocoa" Selector "setView:" (receiver As Ptr, actionTarget As Ptr)
    setView(toolbarItem, segment1)
    
    // Target/Action設定
    Declare Sub setTarget Lib "Cocoa" Selector "setTarget:" (receiver As Ptr, actionTarget As Ptr)
    setTarget(toolbarItem, makeTarget(itemIdentifier))  // Actionの受け口となるメソッドを定義
    Declare Sub setAction Lib "Cocoa" Selector "setAction:" (receiver As Ptr, actionEvent As Ptr)
    setAction(toolbarItem, NSSelectorFromString("action:"))
    
    // 生成したアイテムを返す
    return toolbarItem
    
  8. 以下をWindow1の共有メソッド(Shared Methods)に追加
    メソッド名: setToolItemSlider
    引数: itemIdentifier As String
    戻り値型: Ptr
    
    // 文字列を指定してクラスオブジェクト/セレクタを取得する。最初に一回宣言しておけばよい。
    Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
    Declare Function NSSelectorFromString Lib "Cocoa" (aSelName As CFStringRef) As Ptr
    
    Declare Function alloc Lib "Cocoa" Selector "alloc" (receiver As Ptr) As Ptr
    
    // スライダー初期化
    Dim slider1 As Ptr = NSClassFromString("NSSlider")
    slider1 = alloc(slider1)
    Declare Function initWithFrame Lib "Cocoa" Selector "initWithFrame:" (receiver As Ptr, identifier As NSRect) As Ptr
    slider1 = initWithFrame(slider1, NSMakeRect(0,0,100,24))
    
    // 最小値/最大値/動作モード設定
    Declare Sub setMinValue Lib "Cocoa" Selector "setMinValue:" (receiver As Ptr, value As Double)
    setMinValue(slider1, 0.0)
    Declare Sub setMaxValue Lib "Cocoa" Selector "setMaxValue:" (receiver As Ptr, value As Double)
    setMaxValue(slider1, 100.0)
    Declare Sub setContinuous Lib "Cocoa" Selector "setContinuous:" (receiver As Ptr, flag As Boolean)
    setContinuous(slider1, true)  // false:確定時のみAction発生, true:リアルタイムにAction発生
    
    // アイテム初期化
    Dim toolbarItem As Ptr = NSClassFromString("NSToolbarItem")
    toolbarItem = alloc(toolbarItem)
    Declare Function initWithItemIdentifier Lib "Cocoa" Selector "initWithItemIdentifier:" (receiver As Ptr, identifier As CFStringRef) As Ptr
    toolbarItem = initWithItemIdentifier(toolbarItem, itemIdentifier)
    
    // ラベル/ツールチップ設定
    Declare Sub setLabel Lib "Cocoa" Selector "setLabel:" (receiver As Ptr, label As CFStringRef)
    setLabel(toolbarItem, "Slider")
    Declare Sub setPaletteLabel Lib "Cocoa" Selector "setPaletteLabel:" (receiver As Ptr, label As CFStringRef)
    setPaletteLabel(toolbarItem, "Slider")
    Declare Sub setToolTip Lib "Cocoa" Selector "setToolTip:" (receiver As Ptr, text As CFStringRef)
    setToolTip(toolbarItem, "Slider")
    
    // アイテムのビューにスライダーを設定
    Declare Sub setView Lib "Cocoa" Selector "setView:" (receiver As Ptr, actionTarget As Ptr)
    setView(toolbarItem, slider1)
    
    // Target/Action設定
    Declare Sub setTarget Lib "Cocoa" Selector "setTarget:" (receiver As Ptr, actionTarget As Ptr)
    setTarget(toolbarItem, makeTarget(itemIdentifier))  // Actionの受け口となるメソッドを定義
    Declare Sub setAction Lib "Cocoa" Selector "setAction:" (receiver As Ptr, actionEvent As Ptr)
    setAction(toolbarItem, NSSelectorFromString("action:"))
    
    // 生成したアイテムを返す
    return toolbarItem
    
  9. 以下のWindow1共有メソッド(Shared Methods)を書き換え
    メソッド名: toolbarAllowedItemIdentifiers
    引数: id As Ptr, SEL As CString, toolbar As Ptr
    戻り値型: Ptr
    
    // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。
    Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
    
    Dim arr As Ptr = NSClassFromString("NSMutableArray")  // クラスメソッドなので、まずNSMutableArrayクラスを取得
    Declare Function getArray Lib "Cocoa" Selector "array" (receiver As Ptr) As Ptr  // Return Array*
    arr=getArray(arr)
    
    Declare Sub addObject Lib "Cocoa" Selector "addObject:" (receiver As Ptr, obj As CFStringRef)
    addObject(arr, SaveToolbarItemIdentifier)  // ユーザ定義アイテム
    addObject(arr, SearchToolbarItemIdentifier)  // ユーザ定義アイテム
    addObject(arr, SegmentedControlToolbarItemIdentifier)  // ユーザ定義アイテム
    addObject(arr, SliderToolbarItemIdentifier)  // ユーザ定義アイテム
    addObject(arr, "NSToolbarShowColorsItem")
    addObject(arr, "NSToolbarShowFontsItem")
    addObject(arr, "NSToolbarPrintItem")
    addObject(arr, "NSToolbarSpaceItem")
    addObject(arr, "NSToolbarFlexibleSpaceItem")
      
    // リストを返す
    return arr
    
    注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)
  10. 以下のWindow1共有メソッド(Shared Methods)を書き換え
    メソッド名: toolbarDefaultItemIdentifiers
    引数: id As Ptr, SEL As CString, toolbar As Ptr
    戻り値型: Ptr
    
    // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。
    Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
    
    Dim arr As Ptr = NSClassFromString("NSMutableArray")  // クラスメソッドなので、まずNSMutableArrayクラスを取得
    Declare Function getArray Lib "Cocoa" Selector "array" (receiver As Ptr) As Ptr  // Return Array*
    arr=getArray(arr)
    
    Declare Sub addObject Lib "Cocoa" Selector "addObject:" (receiver As Ptr, obj As CFStringRef)
    addObject(arr, SaveToolbarItemIdentifier)  // ユーザ定義アイテム
    addObject(arr, "NSToolbarSpaceItem")
    addObject(arr, SegmentedControlToolbarItemIdentifier)  // ユーザ定義アイテム
    addObject(arr, SliderToolbarItemIdentifier)  // ユーザ定義アイテム
    addObject(arr, "NSToolbarFlexibleSpaceItem")
    addObject(arr, SearchToolbarItemIdentifier)  // ユーザ定義アイテム
      
    // リストを返す
    return arr
    
    注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)
  11. 以下のWindow1共有メソッド(Shared Methods)を書き換え
    メソッド名: toolbarItemForItemIdentifierWillBeInsertedIntoToolbar
    引数: id As Ptr, SEL As CString, toolbar As Ptr, itemIdentifier As CFStringRef, flag As Boolean
    戻り値型: Ptr
    
    if itemIdentifier = SaveToolbarItemIdentifier then
        return setToolItemSave(itemIdentifier)
    
    elseif itemIdentifier = SearchToolbarItemIdentifier then
        return setToolItemSearch(itemIdentifier)
    
    elseif itemIdentifier = SegmentedControlToolbarItemIdentifier then
        return setToolItemSegment(itemIdentifier)
    
    elseif itemIdentifier = SliderToolbarItemIdentifier then
        return setToolItemSlider(itemIdentifier)
    
    else
        return nil
    end if
    
    注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)
  12. 以下をWindow1の共有プロパティ(Shared Properties)に追加
    プロパティ名: SearchDelegateInstance
    データ型: Ptr
    
  13. 以下をWindow1の共有プロパティ(Shared Properties)に追加
    プロパティ名: SearchToolbarItemIdentifier
    データ型: String
    標準値: My Search Toolbar Item
    
  14. 以下をWindow1の共有プロパティ(Shared Properties)に追加
    プロパティ名: SegmentedControlToolbarItemIdentifier
    データ型: String
    標準値: My Segmented Control Toolbar Item
    
  15. 以下をWindow1の共有プロパティ(Shared Properties)に追加
    プロパティ名: SliderToolbarItemIdentifier
    データ型: String
    標準値: My Slider Toolbar Item
    
  16. 他に、NSMakeRect/NSMakeSize(共有メソッド)、NSRect/NSSize(構造体)が必要ですが、それらはmacoslibからコピーさせて頂きました。

  17. 以下をWindow1の共有メソッド(Shared Methods)に追加(初出時、抜けていたので追加(2016.03.28))
    メソッド名: toolbarSelectableItemIdentifiers
    引数: id As Ptr, SEL As CString, toolbar As Ptr
    戻り値型: Ptr
    
    // 選択(凹んだ)状態にしたいアイテムのリストを返す(今回は未実装)
    return nil
    
    注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)
 実行してみたところ、各コントロールが機能することを確認しました。
S Shot1

S Shot1


 おわりに

 今回も仕組みを理解するために、極力シンプルな書き方を心懸けました。
 なので、よりきめ細かな機能や外観を得るためには、各コントロールの設定にコードを追加する必要があります。
 また、今回(及び前回)はウィンドウが(従って、ツールバーも)一つしかないケースを想定しましたが、複数のウィンドウに配置したい場合は、(個別に全部実装することも考えられはしますが)クラス化する等した方が効率的です。

 実用目的であれば、macoslibをそのまま利用させて頂くことを考えた方がいいでしょう。


 お世話になったサイト

 貴重な情報をご提供頂いている皆様に、お礼申し上げます。(以下、順不同)

 参考サイト(1):Introduction to Segmented Controls
 参考サイト(2):NSTextFieldでReturn等のkeyDownイベントを検知する - 日々精進


 更新履歴

 2018.07.30 Xojoでの実装、の9,10,11,17項を改訂
 2018.01.17 Xojoでの実装、のソースのうち、controlTextViewDoCommandBySelector/makeDelegateTextViewを削除、setToolItemSearchを大幅改訂。
 2018.01.17 コントロールを配置する上での留意点、のサーチフィールドの項が理解不足だったので改訂。
 2016.06.28 Xojoでの実装、のソース(setToolItemSearch)に「サーチフィールドクリック後、直ちに文字入力を可能とするための設定」を追加。
 2016.03.29 Xojoでの実装、のソースを修正/追加。
 2015.10.12 新規作成


[Home]  [MacSoft]  [Donation]  [History]  [Privacy Policy]  [Affiliate Policy]