ホームページ>開発ツール>Xojo / Real Studio Trial and Error・CocoaのDeclareでツールバーを実装する・OS標準っぽくしてみる
Xojo / Real Studio Trial and Error
目次
CocoaのDeclareでツールバーを実装する・OS標準っぽくしてみる
はじめに
以下は、Xojo Cocoaビルドについての話題です。
OS標準添付のアプリやFinderのツールバーっぽくできるのか、試してみました。
なお検証には、Xojo 2016 Release 3を用いています。(Mac mini mid 2010 + OS X 10.11.6 El Capitan)
方針
例えばFinderのツールバーは、以下の通りです。
(離れてはいますが)左の二つはセグメンテッドコントロールだろうなぁ、と想像できますが、(サーチフィールドを除いた)残りは何なのかが判然としません。
特にメニューを表示するものは、メニューがあることを示す「下向きの山型」があることから、ポップアップメニューの可能性もあります。
ということで、試しに通常のボタン(NSButton)とポップアップメニュー(NSPopupButton)をツールバーに配置してみました。
が、ちょっと違います。
各コントロールの高さは全て24 pixelに統一してありますが、Finderのようには揃いません。
(ちなみに、5 pixel足してやるとコントロールの高さは一致するものの、今度はツールバーの高さが2 pixel増えてしまいます。)
何かパラメータをいじればいいのかもしれませんが、見つけられませんでした。
一方、セグメンテッドコントロールはセグメントを1個にすると、通常のボタンのように見えます。また、メニューを付加することもできます。
なので、(サーチフィールド以外を)全てセグメンテッドコントロールで実装してみたところ、以下の通りとなりました。
注:「アイコンのみ」の表示にしてあります。「並び順序」と「タグ」は当該アイコンが見つからなかったので、別アイコンを割り当てています。
したがって、今回はボタン類を全てセグメンテッドコントロールで実装することにしました。
ただし、セグメンテッドコントロールは、(デフォルトでは)ボタンを押すと押しっぱなしの状態になるため、そうならないようにしてやる必要が生じます。
何かパラメータがあるかと思って探したのですが、見当たらなかったので、今回は、ボタンが押された後に自分で戻すようにしました。
ボタンの有効/無効は、通常のツールバーボタンであればデリゲートメソッドで対応できるのですが、コントロール類の場合は対象外(注1)のため、今回は直接Enabledをいじることとしました。
注1)validateVisibleItemsを使う方法はあるようですが、今回は試していません。また、メニュー選択時のアクションは、ボタンと同じアクションで拾うことにし、メニューの判別は、こちらもタグを使うこととしました。(コントロール種別が異なるので、タグの数値は同じアクションを使うメニュー内で固有であればよい。)
参考サイト(1):cocoa - How to force NSToolBar validation? - Stack Overflow
メニューの有効/無効は、デリゲートメソッドでの対応となります(この辺は、通常のメニューと同様)。
次にアイコンですが、今回はOS標準アイコンを利用することにしました。
利用にあたっては、参考サイト(2)を参考にさせて頂きました。
また、アイコンは名前がTemplateで終わっているものを使いましたが、理由は参考サイト(3)に記されています。
参考サイト(2):Fucking NSImage Syntax
参考サイト(3):OS Xステータスバーアプリケーションの作り方 — Genji App Blog(ステータス項目を表示する、の5.項)
残りの(主な)方針は、以下の通りとしました。
メニューを示す山型を標準で表示する方法が(あるのかどうかも含めて)分からなかったので、画像を合成する。
メニューを示す山型は、標準の機能であるsetShowsMenuIndicator:forSegment:を用いる。- メニューのサブメニューは1階層までとする。(複数階層化するには再帰呼び出しが有効になるが、今回はそこまではしない。)
- ツールバーはクラス化する。ただし、個別にカスタマイズするベースという位置付けで、汎用クラスにすることまでは考えない。
(汎用クラスとしてのツールバーが必要なら、macoslibを使わせて頂く等した方が確実でしょう。)
Xojoでの実装
【ソースコードのコピー&ペーストについて】
ソースコード(グレー背景部分の全文)をコピーし、指定のウィンドウ/クラスにペーストすると、(新規作成して名前等を個別にコピー&ペーストしなくても)復元されます。
ただし、この方法は、メソッドでは問題ないようですが、イベント/アクション/プロパティでは不安定?なので、ペーストできない場合は、各項目のカッコ内を適用して下さい。
実行してみたところ、各コントロールが機能することを確認しました。
- Xojoで新規プロジェクトを作成
- Window1にListBox(名前はListBox1)、PushButton2個(名前はPushButton1とPushButton2)を追加(注:動作確認用であり、必須ではない。)
- 以下をPushButton1にペースト(できなければ、Sub - Endの間をActionイベントに記述)
Sub Action() Handles Action SetButtonEnable(601,not GetButtonEnable(601)) End Sub
- 以下をPushButton2にペースト(できなければ、Sub - Endの間をActionイベントに記述)
Sub Action() Handles Action EnableNewWin = not EnableNewWin End Sub
- 以下をWindow1にペースト(できなければ、Sub - Endの間をOpenイベントに記述)
Sub Open() Handles Open // ツールバー生成 Dim t As NSToolbar = new NSToolbar(self, AddressOf ToolbarItemClicked, AddressOf MenuItemClicked) End Sub
- 以下をWindow1にペースト
Protected Function GetButtonEnable(tagNo As Integer) as Boolean // 指定されたタグ番号を持つアイテムを取得 Dim pnt As Ptr = GetToolItem(tagNo) // 現在の有効/無効値を取得して返す Declare Function isEnabled Lib "Cocoa" Selector "isEnabled" (receiver As Ptr) As Boolean return isEnabled(pnt) End Function
- 以下をWindow1にペースト
Protected Function GetToolItem(tagNo As Integer) as Ptr // 文字列を指定してクラスオブジェクト/セレクタを取得する。最初に一回宣言しておけばよい。 Declare Function NSStringFromClass Lib "Cocoa" (aClass As Ptr) As CFStringRef Declare Function myClass Lib "Cocoa" Selector "class" (receiver As Ptr) As Ptr Declare Function objectAtIndex Lib "Cocoa" Selector "objectAtIndex:" (receiver As Ptr, info As Integer) As Ptr Declare Function view Lib "Cocoa" Selector "view" (receiver As Ptr) As Ptr Declare Function itemIdentifier Lib "Cocoa" Selector "itemIdentifier" (receiver As Ptr) As Ptr Declare Function tagForSegment Lib "Cocoa" Selector "tagForSegment:" (receiver As Ptr, seg As Integer) As Integer Declare Function cell Lib "Cocoa" Selector "cell" (receiver As Ptr) As Ptr // ツールバーの取得 declare function toolbar lib "Cocoa" selector "toolbar" (obj_id as Integer) as Ptr Dim pnt1 As Ptr = toolbar(Window1.Handle) // ツールバーアイテム(配列)の取得 declare function visibleItems lib "Cocoa" selector "visibleItems" (receiver As Ptr) as Ptr Dim pnt2 As Ptr = visibleItems(pnt1) // 配列の個数の取得 declare function count lib "Cocoa" selector "count" (receiver As Ptr) as Integer Dim cnt As Integer = count(pnt2) Dim i, tag As Integer Dim pnt3, ident, pnt4, cls1 As Ptr for i=0 to cnt-1 // ツールバーアイテムを順番に取得 pnt3 = objectAtIndex(pnt2, i) // 渡ってきたツールバーアイテムからアイデンティファイアを取得 ident = itemIdentifier(pnt3) // viewの取得(コントロール類はviewで取得できる) pnt4 = view(pnt3) // コントロールのクラス名を文字列で取得 cls1 = myClass(pnt4) if NSStringFromClass(cls1)="NSSegmentedControl" then // セグメンテッドコントロール tag = tagForSegment(cell(pnt4),0) if tag=tagNo then // 指定されたタグなら return pnt3 // 現在の値を取得 end if end if next End Function
- 以下をWindow1にペースト
Protected Function MenuItemClicked(sender As Ptr) as Boolean // このメソッドはメニューが表示される度に呼ばれる(?)ので、戻り値を指定すれば反映される。 // デフォルトはEnable Dim enable As Boolean = true // 渡ってきたメニューアイテムからタグを取得 Declare Function tag Lib "Cocoa" Selector "tag" (receiver As Ptr) As Integer Dim tagno As Integer = tag(sender) // メニューアイテム(タグ)ごとの処理 select case tagno case 101 // 名前 case 102 // 種類 case 201 // 新規フォルダ case 202 // 新規ウィンドウで開く // フラグが無効ならDisableに if EnableNewWin then enable = false end if end select return enable End Function
- 以下をWindow1にペースト
Protected Sub SetButtonEnable(tagNo As Integer, flg As Boolean) // 指定されたタグ番号を持つアイテムを取得 Dim pnt As Ptr = GetToolItem(tagNo) // 値をセット Declare Sub setEnabled Lib "Cocoa" Selector "setEnabled:" (receiver As Ptr, selected As Boolean) setEnabled(pnt, flg) End Sub
- 以下をWindow1にペースト
Protected Sub ToolbarItemClicked(sender As Ptr) Declare Function description Lib "Cocoa" Selector "description" (receiver As Ptr) As CFStringRef Dim name As String = description(sender) if InStrB(name,"NSSegmentedControl")>0 then // セグメンテッドコントロール(ボタン型やメニュー型を含む) 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 Declare Function selectedSegment Lib "Cocoa" Selector "selectedSegment" (receiver As Ptr) As Integer Declare Sub setSelected Lib "Cocoa" Selector "setSelected:forSegment:" (receiver As Ptr, selected As Boolean, no As Integer) Dim tagno As Integer = tagForSegment(cell(sender), selectedSegment(sender)) select case tagno case 501 Listbox1.AddRow "Selected Segment = Icon View" case 502 Listbox1.AddRow "Selected Segment = List View" case 503 Listbox1.AddRow "Selected Segment = Column View" case 504 Listbox1.AddRow "Selected Segment = Flow View" case 601 setSelected(sender, false, 0) Listbox1.AddRow "Selected Button = Share" case 611 setSelected(sender, false, 0) Listbox1.AddRow "Selected Button = Edit Tag" case 621 setSelected(sender, false, 0) Listbox1.AddRow "Selected Button = Quick Look" case 701 setSelected(sender, false, 0) Listbox1.AddRow "Selected Button = Go Left" case 702 setSelected(sender, false, 1) Listbox1.AddRow "Selected Button = Go Right" end select elseif InStrB(name,"NSMenuItem")>0 then // ボタンのメニュー Declare Function tag Lib "Cocoa" Selector "tag" (receiver As Ptr) As Integer Dim tagno As Integer = tag(sender) select case tagno case 101 // 名前 Listbox1.AddRow "Selected Menu = 名前" case 102 // 種類 Listbox1.AddRow "Selected Menu = 種類" case 104 // なし Listbox1.AddRow "Selected Menu = なし" case 201 // 新規フォルダ Listbox1.AddRow "Selected Menu = 新規フォルダ" case 202 // 新規ウィンドウで開く Listbox1.AddRow "Selected Menu = 新規ウィンドウで開く" case 901 // 開く 1 Listbox1.AddRow "Selected Menu = 開く 1" case 902 // 開く 2 Listbox1.AddRow "Selected Menu = 開く 2" end select elseif InStrB(name,"NSSearchField")>0 then // サーチフィールド Declare Function stringValue Lib "Cocoa" Selector "stringValue" (receiver As Ptr) As CFStringRef Listbox1.AddRow "Search Word = "+stringValue(sender) // 検索文字列 else msgBox "No Define :"+name end if End Sub
- 以下をWindow1にペースト(できなければプロパティに、名前:EnableNewWin、データ型:Boolean、を追加)
Private Property EnableNewWin as Boolean
- 新規クラスを作成(名前は、ここでは「NSToolbar」とした。)
- 以下をNSToolbarにペースト(できなければ移譲に、名前:ActionDelegate、引数:sender As Ptr、を追加)
Private Sub ActionDelegate(sender As Ptr)
- 以下をNSToolbarにペースト(できなければ移譲に、名前:ActionDelegate1、引数:sender As Ptr、戻り値型:Booleanを追加)
Private Function ActionDelegate1(sender As Ptr) as Boolean
- 以下をNSToolbarにペースト
Public Sub Constructor(win As Window, action As ActionDelegate, action1 As ActionDelegate1) // NSToolbarを継承したインスタンスを作成して、ウィンドウに貼り付ける makeToolbarInstance(win) // 外部指定されたパラメータを保持 ActionHandler = action // クラス生成元でActionを受け取るメソッドを登録 ActionHandler1 = action1 // クラス生成元でActionを受け取るメソッドを登録 End Sub
- 以下をNSToolbarにペースト
注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)Private Shared Sub actionEvent(id As Ptr, SEL As CString, sender As Ptr) // インスタンスメソッドに渡す ActionHandler.Invoke(sender) // クラス生成元でActionを受け取るメソッドを呼び出す End Sub
- 以下をNSToolbarにペースト
Private Shared Function makeDelegate() as 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 // クラス名をmyNSToolbarDelegate(名前は任意。少なくとも今回のケースでは参照されない。)、メタクラス名をNSObjectにして、生成 Dim newClassId As Ptr = objc_allocateClassPair(NSClassFromString("NSObject"), "myNSToolbarDelegate", 0) // ランタイムに登録(参照を可能とするため) objc_registerClassPair newClassId // Delegateの対象となるメソッドを追加(toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:をXojo側で用意したtoolbarItemForItemIdentifierWillBeInsertedIntoToolbarメソッドで受け取る。) if not class_addMethod (newClassId, NSSelectorFromString("toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:"), AddressOf toolbarItemForItemIdentifierWillBeInsertedIntoToolbar, "@@:@@c") then msgBox "error." return nil end if // Delegateの対象となるメソッドを追加(toolbarAllowedItemIdentifiers:をXojo側で用意したtoolbarAllowedItemIdentifiersメソッドで受け取る。) if not class_addMethod (newClassId, NSSelectorFromString("toolbarAllowedItemIdentifiers:"), AddressOf toolbarAllowedItemIdentifiers, "@@:@") then msgBox "error." return nil end if // Delegateの対象となるメソッドを追加(toolbarDefaultItemIdentifiers:をXojo側で用意したtoolbarDefaultItemIdentifiersメソッドで受け取る。) if not class_addMethod (newClassId, NSSelectorFromString("toolbarDefaultItemIdentifiers:"), AddressOf toolbarDefaultItemIdentifiers, "@@:@") then msgBox "error." return nil end if // Delegateの対象となるメソッドを追加(toolbarSelectableItemIdentifiers:をXojo側で用意したtoolbarSelectableItemIdentifiersメソッドで受け取る。) if not class_addMethod (newClassId, NSSelectorFromString("toolbarSelectableItemIdentifiers:"), AddressOf toolbarSelectableItemIdentifiers, "@@:@") 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)) // インスタンスを返す return delegateId End Function
- 以下をNSToolbarにペースト
Private Shared Function makeMenu(itemIdentifier As String, list() As String, tag0 As Integer) as 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 Declare Function init Lib "Cocoa" Selector "init" (receiver As Ptr) As Ptr Declare Function initWithTitleActKey Lib "Cocoa" Selector "initWithTitle:action:keyEquivalent:" (receiver As Ptr, title As CFStringRef, act As Ptr, key As CFStringRef) As Ptr Declare Sub setAction Lib "Cocoa" Selector "setAction:" (receiver As Ptr, actionEvent As Ptr) Declare Sub setTitle Lib "Cocoa" Selector "setTitle:" (receiver As Ptr, title As CFStringRef) Declare Sub setTarget Lib "Cocoa" Selector "setTarget:" (receiver As Ptr, actionTarget As Ptr) Declare Sub setTag Lib "Cocoa" Selector "setTag:" (receiver As Ptr, tag As Integer) Declare Sub setSubmenu Lib "Cocoa" Selector "setSubmenu:" (receiver As Ptr, item As Ptr) Declare Sub addItem Lib "Cocoa" Selector "addItem:" (receiver As Ptr, item As Ptr) Declare Function separatorItem Lib "Cocoa" Selector "separatorItem" (receiver As Ptr) As Ptr Declare Sub release Lib "Cocoa" Selector "release" (receiver As Ptr) // メニューの生成と初期化 Dim menu1 As Ptr = NSClassFromString("NSMenu") menu1 = alloc(menu1) menu1 = init(menu1) // メニュー項目 Dim menu2, menu20, menu21 As Ptr Dim pos, j, cnt As Integer pos=0 do // メニュー項目クラスの取得 menu2 = NSClassFromString("NSMenuItem") if list(pos)="---" then // セパレータ menu2 = separatorItem(menu2) elseif Left(list(pos),4)="sub:" then // サブメニューを持ったメニュー // メニュー項目の生成と初期化 menu2 = alloc(menu2) menu2 = init(menu2) setTitle(menu2, NthField(list(pos),":",3)) // Target/Actionを設定 setTarget(menu2, makeTarget(itemIdentifier)) setAction(menu2, NSSelectorFromString("action:")) // メニューの生成と初期化(サブメニューはメニューに付加する) menu20 = NSClassFromString("NSMenu") menu20 = alloc(menu20) menu20 = init(menu20) cnt=Val(NthField(list(pos),":",2)) for j=1 to cnt // サブメニューを生成 menu21 = NSClassFromString("NSMenuItem") menu21 = alloc(menu21) menu21 = initWithTitleActKey(menu21, list(pos+j), NSSelectorFromString("action:"), "") // ここでActionも設定 // Targetを設定 setTarget(menu21, makeTarget(itemIdentifier)) // タグ setTag(menu21, 900+j) // タグだけ判別するので、同じActionメソッドを使用するメニュー間で固有の数値にする(今回の例では一つしかないので決め打ちしているが、複数ある場合は工夫が必要) // メニューにサブメニューを追加 addItem(menu20, menu21) // 解放 release(menu21) next pos=pos+cnt // メニュー項目にメニュー(サブメニューを持っている)をセット setSubmenu(menu2, menu20) // 解放 release(menu20) else // 通常のメニュー // メニュー項目の生成と初期化 menu2 = alloc(menu2) menu2 = initWithTitleActKey(menu2, list(pos), NSSelectorFromString("action:"), "") // ここでActionも設定 // Targetを設定 setTarget(menu2, makeTarget(itemIdentifier)) // タグ setTag(menu2, tag0+pos) // タグだけ判別するので、同じActionメソッドを使用するメニュー間で固有の数値にする end if // メニューにメニュー項目を追加 addItem(menu1, menu2) // リストが終了したら抜ける pos=pos+1 if pos>list.Ubound then exit end if loop // メニューを返す return menu1 End Function
- 以下をNSToolbarにペースト
Private Shared Function makeMenuAction(itemIdentifier As String) as Ptr Dim list(-1) As String // サブメニューとセパレータの仕様は独自のものです。必要なら適宜変更して下さい。 list.Append "新規フォルダ" list.Append "新規ウィンドウで開く" list.Append "sub:2:開く" // sub = サブメニューあり, 2 = サブメニュー個数 list.Append "開く 1" // サブメニュー1個目 list.Append "開く 2" // サブメニュー2個目 list.Append "閉じる" return makeMenu(itemIdentifier,list,201) End Function
- 以下をNSToolbarにペースト
Private Shared Function makeMenuSort(itemIdentifier As String) as Ptr Dim list(-1) As String // サブメニューとセパレータの仕様は独自のものです。必要なら適宜変更して下さい。 list.Append "名前" list.Append "種類" list.Append "---" // セパレータを示す list.Append "なし" return makeMenu(itemIdentifier,list,101) End Function
- 以下をNSToolbarにペースト
Private Shared Function makeTarget(name As String) as 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 TargetInstance <> nil then return TargetInstance end if // クラス名を引数のname(名前は任意だが、重複を避けるためにアイテムのIdentifierにしている。)、メタクラス名をNSObjectにして、生成 Dim newClassId As Ptr = objc_allocateClassPair(NSClassFromString("NSObject"), name, 0) // ランタイムに登録(参照を可能とするため) objc_registerClassPair newClassId // Tarrgetに送られてきたActionの受け口となるメソッドを追加(action:をXojo側で用意したactionEventメソッドで受け取る。) if not class_addMethod (newClassId, NSSelectorFromString("action:"), AddressOf actionEvent, "@@:@") then msgBox "error." return nil end if // Delegateの対象となるメソッド(Protocol?)を追加(validateMenuItem:をXojo側で用意したvalidateMenuItemメソッドで受け取る。) if not class_addMethod (newClassId, NSSelectorFromString("validateMenuItem:"), AddressOf validateMenuItem, "c@:@") 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 targetId As Ptr = init(alloc(newClassId)) // インスタンスを保持 TargetInstance = targetId // インスタンスを返す return targetId End Function
- 以下をNSToolbarにペースト
Private Shared Sub makeToolbarInstance(win As Window) // 文字列を指定してクラスオブジェクト/セレクタを取得する。最初に一回宣言しておけばよい。 Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr Declare Function NSSelectorFromString Lib "Cocoa" (aSelName As CFStringRef) As Ptr // create the toolbar object Dim toolbar1 As Ptr = NSClassFromString("NSToolbar") Declare Function toolbarAlloc Lib "Cocoa" Selector "alloc" (receiver As Ptr) As Ptr toolbar1 = toolbarAlloc(toolbar1) Declare Function toolbarInit Lib "Cocoa" Selector "initWithIdentifier:" (receiver As Ptr, identifier As CFStringRef) As Ptr toolbar1 = toolbarInit(toolbar1, "MySampleToolbar") // set initial toolbar properties Declare Sub setAllowsUserCustomization Lib "Cocoa" Selector "setAllowsUserCustomization:" (receiver As Ptr, value As Boolean) setAllowsUserCustomization(toolbar1, true) Declare Sub setAutosavesConfiguration Lib "Cocoa" Selector "setAutosavesConfiguration:" (receiver As Ptr, value As Boolean) setAutosavesConfiguration(toolbar1, false) // debug時にはoffの方がよさそう Declare Sub setDisplayMode Lib "Cocoa" Selector "setDisplayMode:" (receiver As Ptr, value As Integer) setDisplayMode(toolbar1, 1) // 0=Default, 1=Icon & Text, 2=Icon Only, 3=Text Only // set our controller as the toolbar delegate Declare Sub setDelegate Lib "Cocoa" Selector "setDelegate:" (receiver As Ptr, id As Ptr) setDelegate toolbar1, makeDelegate() // Delegateの設定 // attach the toolbar to our window Declare Sub setToolbar Lib "Cocoa" Selector "setToolbar:" (receiver As WindowPtr, toolbar As Ptr) setToolbar(win, toolbar1) // clean up Declare Sub release Lib "Cocoa" Selector "release" (toolbar As Ptr) release(toolbar1) End Sub
- 以下をNSToolbarにペースト(大幅に改訂(2018.01.17))
Private Shared Function setToolItemSearch(itemIdentifier As String) as 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, "NSSearchField") 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") // サーチフィールドクリック後、直ちに文字入力を可能とするための設定 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) // 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 End Function
- 以下をNSToolbarにペースト
Private Shared Function setToolItemSegment(itemIdentifier As String) as 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 image0 As Ptr = NSClassFromString("NSImage") Dim image1 As Ptr = NSClassFromString("NSImage") Dim image2 As Ptr = NSClassFromString("NSImage") Dim image3 As Ptr = NSClassFromString("NSImage") Declare Function imageNamed Lib "Cocoa" Selector "imageNamed:" (receiver As Ptr, name As CFStringRef) As Ptr image0 = imageNamed(image0, "NSIconViewTemplate") image1 = imageNamed(image1, "NSListViewTemplate") image2 = imageNamed(image2, "NSColumnViewTemplate") image3 = imageNamed(image3, "NSFlowViewTemplate") 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,111,24)) Declare Sub setSegmentCount Lib "Cocoa" Selector "setSegmentCount:" (receiver As Ptr, cnt As Integer) setSegmentCount(segment1, 4) Declare Sub setImage Lib "Cocoa" Selector "setImage:forSegment:" (receiver As Ptr, image As Ptr, no As Integer) setImage(segment1, image0, 0) setImage(segment1, image1, 1) setImage(segment1, image2, 2) setImage(segment1, image3, 3) Declare Sub setWidth Lib "Cocoa" Selector "setWidth:forSegment:" (receiver As Ptr, w As Single, no As Integer) setWidth(segment1, 26, 0) setWidth(segment1, 26, 1) setWidth(segment1, 26, 2) setWidth(segment1, 26, 3) 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) setSelected(segment1, false, 3) 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), 501, 0) setTag(cell(segment1), 502, 1) setTag(cell(segment1), 503, 2) setTag(cell(segment1), 504, 3) Declare Sub setToolTip Lib "Cocoa" Selector "setToolTip:forSegment:" (receiver As Ptr, text As CFStringRef, no As Integer) setToolTip(cell(segment1), "Segmented Control 0", 0) setToolTip(cell(segment1), "Segmented Control 1", 1) setToolTip(cell(segment1), "Segmented Control 2", 2) setToolTip(cell(segment1), "Segmented Control 3", 3) 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, "NSSegmentedControl") Declare Sub setPaletteLabel Lib "Cocoa" Selector "setPaletteLabel:" (receiver As Ptr, label As CFStringRef) setPaletteLabel(toolbarItem, "Segmented Control") Declare Sub setView Lib "Cocoa" Selector "setView:" (receiver As Ptr, actionTarget As Ptr) setView(toolbarItem, segment1) 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 End Function
- 以下をNSToolbarにペースト
Private Shared Function setToolItemSegment1(itemIdentifier As String, label As String, labelL As String, tooltip As String, icon As String, tag As Integer) as 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 image1 As Ptr = NSClassFromString("NSImage") Declare Function imageNamed Lib "Cocoa" Selector "imageNamed:" (receiver As Ptr, name As CFStringRef) As Ptr image1 = imageNamed(image1, icon) // セグメンテッドコントロール初期化 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,38,24)) // セグメント数/アイコン/幅/選択状態/タグ設定 Declare Sub setSegmentCount Lib "Cocoa" Selector "setSegmentCount:" (receiver As Ptr, cnt As Integer) setSegmentCount(segment1, 1) Declare Sub setImage Lib "Cocoa" Selector "setImage:forSegment:" (receiver As Ptr, image As Ptr, no As Integer) setImage(segment1, image1, 0) Declare Sub setWidth Lib "Cocoa" Selector "setWidth:forSegment:" (receiver As Ptr, w As Single, no As Integer) setWidth(segment1, 34, 0) Declare Sub setSelected Lib "Cocoa" Selector "setSelected:forSegment:" (receiver As Ptr, selected As Boolean, no As Integer) setSelected(segment1, false, 0) // 非選択 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), tag, 0) // タグだけ判別するので、同じ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, label) Declare Sub setPaletteLabel Lib "Cocoa" Selector "setPaletteLabel:" (receiver As Ptr, label As CFStringRef) setPaletteLabel(toolbarItem, labelL) Declare Sub setToolTip Lib "Cocoa" Selector "setToolTip:" (receiver As Ptr, text As CFStringRef) setToolTip(toolbarItem, tooltip) // アイテムのビューにセグメンテッドコントロールを設定 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 End Function
- 以下をNSToolbarにペースト(メニューを示す下向き矢印の表示を、標準機能に改めた。(2021.05.11))
以下の旧版は、実装方法の一つではあるので、参考まで。Private Shared Function setToolItemSegment1Menu(itemIdentifier As String, label As String, labelL As String, tooltip As String, icon As String, menu As Ptr) as 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 image1 As Ptr = NSClassFromString("NSImage") Declare Function imageNamed Lib "Cocoa" Selector "imageNamed:" (receiver As Ptr, name As CFStringRef) As Ptr image1 = imageNamed(image1, icon) Declare Sub setTemplate Lib "Cocoa" Selector "setTemplate:" (receiver As Ptr, flg As Boolean) setTemplate(image1, true) // 選択時のカラー反転や、ディアクティベート時のグレー化 // セグメンテッドコントロール初期化 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,40,22)) // セグメント数/イメージ/選択状態/メニュー Declare Sub setSegmentCount Lib "Cocoa" Selector "setSegmentCount:" (receiver As Ptr, cnt As Integer) setSegmentCount(segment1, 1) Declare Sub setImage Lib "Cocoa" Selector "setImage:forSegment:" (receiver As Ptr, image As Ptr, no As Integer) setImage(segment1, image1, 0) Declare Sub setWidth Lib "Cocoa" Selector "setWidth:forSegment:" (receiver As Ptr, w As CGFloat, no As Integer) setWidth(segment1, 36, 0) Declare Sub setSelected Lib "Cocoa" Selector "setSelected:forSegment:" (receiver As Ptr, selected As Boolean, no As Integer) setSelected(segment1, false, 0) // 非選択 Declare Function cell Lib "Cocoa" Selector "cell" (receiver As Ptr) As Ptr Declare Sub setMenu Lib "Cocoa" Selector "setMenu:forSegment:" (receiver As Ptr, menu As Ptr, no As Integer) setMenu(cell(segment1), menu, 0) Declare Sub setShowsMenuIndicator Lib "Cocoa" Selector "setShowsMenuIndicator:forSegment:" (receiver As Ptr, flg As Boolean, no As Integer) setShowsMenuIndicator(segment1, true, 0) // メニューを示す下向き矢印表示 // アイテム初期化 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, label) Declare Sub setPaletteLabel Lib "Cocoa" Selector "setPaletteLabel:" (receiver As Ptr, label As CFStringRef) setPaletteLabel(toolbarItem, labelL) Declare Sub setToolTip Lib "Cocoa" Selector "setToolTip:" (receiver As Ptr, text As CFStringRef) setToolTip(toolbarItem, labelL) // アイテムのビューにセグメンテッドコントロールを設定 Declare Sub setView Lib "Cocoa" Selector "setView:" (receiver As Ptr, actionTarget As Ptr) setView(toolbarItem, segment1) // 生成したアイテムを返す return toolbarItem End Function
Private Shared Function setToolItemSegment1Menu(itemIdentifier As String, label As String, labelL As String, tooltip As String, icon As String, menu As Ptr) as 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 image0 As Ptr = NSClassFromString("NSImage") image0 = alloc(image0) Declare Function initWithSize Lib "Cocoa" Selector "initWithSize:" (receiver As Ptr, size As NSSize) As Ptr image0 = initWithSize(image0, NSMakeSize(40,24)) // 標準イメージの取得 Dim image1 As Ptr = NSClassFromString("NSImage") Dim image2 As Ptr = NSClassFromString("NSImage") Declare Function imageNamed Lib "Cocoa" Selector "imageNamed:" (receiver As Ptr, name As CFStringRef) As Ptr image1 = imageNamed(image1, icon) image2 = imageNamed(image2, "NSDropDownIndicatorTemplate") // イメージの合成 Declare Sub lockFocus Lib "Cocoa" Selector "lockFocus" (receiver As Ptr) lockFocus(image0) Declare Sub compositeToPoint Lib "Cocoa" Selector "compositeToPoint:operation:" (receiver As Ptr, item1 As NSPoint, item2 As Integer) compositeToPoint(image1, NSMakePoint(5, 5), 2) compositeToPoint(image2, NSMakePoint(25, 10), 2) Declare Sub unlockFocus Lib "Cocoa" Selector "unlockFocus" (receiver As Ptr) unlockFocus(image0) Declare Sub setTemplate Lib "Cocoa" Selector "setTemplate:" (receiver As Ptr, flg As Boolean) setTemplate(image0, true) // 選択時のカラー反転や、ディアクティベート時のグレー化 // セグメンテッドコントロール初期化 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,40,22)) // セグメント数/アイコン/幅/選択状態/メニュー Declare Sub setSegmentCount Lib "Cocoa" Selector "setSegmentCount:" (receiver As Ptr, cnt As Integer) setSegmentCount(segment1, 1) Declare Sub setImage Lib "Cocoa" Selector "setImage:forSegment:" (receiver As Ptr, image As Ptr, no As Integer) setImage(segment1, image0, 0) Declare Sub setWidth Lib "Cocoa" Selector "setWidth:forSegment:" (receiver As Ptr, w As Single, no As Integer) setWidth(segment1, 36, 0) Declare Sub setSelected Lib "Cocoa" Selector "setSelected:forSegment:" (receiver As Ptr, selected As Boolean, no As Integer) setSelected(segment1, false, 0) // 非選択 Declare Function cell Lib "Cocoa" Selector "cell" (receiver As Ptr) As Ptr Declare Sub setMenu Lib "Cocoa" Selector "setMenu:forSegment:" (receiver As Ptr, menu As Ptr, no As Integer) setMenu(cell(segment1), menu, 0) // アイテム初期化 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, label) Declare Sub setPaletteLabel Lib "Cocoa" Selector "setPaletteLabel:" (receiver As Ptr, label As CFStringRef) setPaletteLabel(toolbarItem, labelL) Declare Sub setToolTip Lib "Cocoa" Selector "setToolTip:" (receiver As Ptr, text As CFStringRef) setToolTip(toolbarItem, labelL) // アイテムのビューにセグメンテッドコントロールを設定 Declare Sub setView Lib "Cocoa" Selector "setView:" (receiver As Ptr, actionTarget As Ptr) setView(toolbarItem, segment1) // 生成したアイテムを返す return toolbarItem End Function
- 以下をNSToolbarにペースト
Private Shared Function setToolItemSegmentPair(itemIdentifier As String) as 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 image0 As Ptr = NSClassFromString("NSImage") Dim image1 As Ptr = NSClassFromString("NSImage") Declare Function imageNamed Lib "Cocoa" Selector "imageNamed:" (receiver As Ptr, name As CFStringRef) As Ptr image0 = imageNamed(image0, "NSGoLeftTemplate") image1 = imageNamed(image1, "NSGoRightTemplate") Declare Sub setTemplate Lib "Cocoa" Selector "setTemplate:" (receiver As Ptr, flg As Boolean) setTemplate(image0, true) // 選択時のカラー反転や、ディアクティベート時のグレー化 setTemplate(image1, true) // 選択時のカラー反転や、ディアクティベート時のグレー化 // セグメンテッドコントロール初期化 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,51,24)) // セグメント数/外観/アイコン/幅/選択状態/ツールチップ Declare Sub setSegmentCount Lib "Cocoa" Selector "setSegmentCount:" (receiver As Ptr, cnt As Integer) setSegmentCount(segment1, 2) Declare Sub setSegmentStyle Lib "Cocoa" Selector "setSegmentStyle:" (receiver As Ptr, cnt As Integer) setSegmentStyle(segment1, 8) // 8だとImageのTemplateが効かない > OS標準でもそのようなので仕様? Declare Sub setImage Lib "Cocoa" Selector "setImage:forSegment:" (receiver As Ptr, image As Ptr, no As Integer) setImage(segment1, image0, 0) setImage(segment1, image1, 1) Declare Sub setWidth Lib "Cocoa" Selector "setWidth:forSegment:" (receiver As Ptr, w As Single, no As Integer) setWidth(segment1, 23, 0) setWidth(segment1, 23, 1) Declare Sub setSelected Lib "Cocoa" Selector "setSelected:forSegment:" (receiver As Ptr, selected As Boolean, no As Integer) setSelected(segment1, false, 0) setSelected(segment1, false, 1) 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), 701, 0) setTag(cell(segment1), 702, 1) Declare Sub setToolTip Lib "Cocoa" Selector "setToolTip:forSegment:" (receiver As Ptr, text As CFStringRef, no As Integer) setToolTip(cell(segment1), "Segmented Control 0", 0) setToolTip(cell(segment1), "Segmented Control 1", 1) // アイテム初期化 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, "Button Pair") Declare Sub setPaletteLabel Lib "Cocoa" Selector "setPaletteLabel:" (receiver As Ptr, label As CFStringRef) setPaletteLabel(toolbarItem, "Button Pair") // アイテムのビューにセグメンテッドコントロールを設定 Declare Sub setView Lib "Cocoa" Selector "setView:" (receiver As Ptr, actionTarget As Ptr) setView(toolbarItem, segment1) 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 End Function
- 以下をNSToolbarにペースト
注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)Private Shared Function toolbarAllowedItemIdentifiers(id As Ptr, SEL As CString, toolbar As Ptr) as 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) Declare Sub addObjectNil Lib "Cocoa" Selector "addObject:" (receiver As Ptr, obj As Ptr) addObject(arr, SegmentedControlPairToolbarItemIdentifier) // ユーザ定義アイテム addObject(arr, SegmentedControlToolbarItemIdentifier) // ユーザ定義アイテム addObject(arr, ToolbarItemIdentifierSort) // ユーザ定義アイテム addObject(arr, ToolbarItemIdentifierShare) // ユーザ定義アイテム addObject(arr, ToolbarItemIdentifierTag) // ユーザ定義アイテム addObject(arr, ToolbarItemIdentifierQuick) // ユーザ定義アイテム addObject(arr, ToolbarItemIdentifierAction) // ユーザ定義アイテム addObject(arr, SearchToolbarItemIdentifier) // ユーザ定義アイテム addObject(arr, "NSToolbarSpaceItem") addObject(arr, "NSToolbarFlexibleSpaceItem") return arr End Function
- 以下をNSToolbarにペースト
注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)Private Shared Function toolbarDefaultItemIdentifiers(id As Ptr, SEL As CString, toolbar As Ptr) as 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) Declare Sub addObjectNil Lib "Cocoa" Selector "addObject:" (receiver As Ptr, obj As Ptr) addObject(arr, SegmentedControlPairToolbarItemIdentifier) // ユーザ定義アイテム addObject(arr, "NSToolbarFlexibleSpaceItem") addObject(arr, SegmentedControlToolbarItemIdentifier) // ユーザ定義アイテム addObject(arr, ToolbarItemIdentifierSort) // ユーザ定義アイテム addObject(arr, ToolbarItemIdentifierShare) // ユーザ定義アイテム addObject(arr, ToolbarItemIdentifierTag) // ユーザ定義アイテム addObject(arr, "NSToolbarSpaceItem") addObject(arr, ToolbarItemIdentifierQuick) // ユーザ定義アイテム addObject(arr, ToolbarItemIdentifierAction) // ユーザ定義アイテム addObject(arr, "NSToolbarFlexibleSpaceItem") addObject(arr, SearchToolbarItemIdentifier) // ユーザ定義アイテム return arr End Function
- 以下をNSToolbarにペースト
注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)Private Shared Function toolbarItemForItemIdentifierWillBeInsertedIntoToolbar(id As Ptr, SEL As CString, toolbar As Ptr, itemIdentifier As CFStringRef, flag As Boolean) as Ptr if itemIdentifier = SearchToolbarItemIdentifier then return setToolItemSearch(itemIdentifier) elseif itemIdentifier = SegmentedControlToolbarItemIdentifier then return setToolItemSegment(itemIdentifier) elseif itemIdentifier = ToolbarItemIdentifierShare then return setToolItemSegment1(itemIdentifier,"Button","Button","Button","NSShareTemplate",601) elseif itemIdentifier = ToolbarItemIdentifierTag then return setToolItemSegment1(itemIdentifier,"Button","Button","Button","NSBookmarksTemplate",611) // 本来はタグアイコンを代替使用 elseif itemIdentifier = ToolbarItemIdentifierQuick then return setToolItemSegment1(itemIdentifier,"Button","Button","Button","NSQuickLookTemplate",621) elseif itemIdentifier = ToolbarItemIdentifierSort then return setToolItemSegment1Menu(itemIdentifier,"Btn Menu","Btn Menu","Btn Menu","NSHomeTemplate",makeMenuSort(itemIdentifier)) // 本来はソートアイコンを代替使用 elseif itemIdentifier = ToolbarItemIdentifierAction then return setToolItemSegment1Menu(itemIdentifier,"Btn Menu","Btn Menu","Btn Menu","NSActionTemplate",makeMenuAction(itemIdentifier)) elseif itemIdentifier = SegmentedControlPairToolbarItemIdentifier then return setToolItemSegmentPair(itemIdentifier) else return nil end if End Function
- 以下をNSToolbarにペースト
注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)Private Shared Function toolbarSelectableItemIdentifiers(id As Ptr, SEL As CString, toolbar As Ptr) as Ptr // 選択(凹んだ)状態にしたいアイテムのリストを返す return nil End Function
- 以下をNSToolbarにペースト
注)SELの型をPtrとしていたが、CStringの方が相応しいので変更した。(未使用なので変更しなくても実害はなし。)(2018.07.30)Private Shared Function validateMenuItem(id As Ptr, SEL As CString, sender As Ptr) as Boolean // インスタンスメソッドに渡す return ActionHandler1.Invoke(sender) // クラス生成元でActionを受け取るメソッドを呼び出す End Function
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:ActionHandler、データ型:ActionDelegate、を追加)
Private Shared Property ActionHandler as ActionDelegate
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:ActionHandler1、データ型:ActionDelegate1、を追加)
Private Shared Property ActionHandler1 as ActionDelegate1
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:SearchDelegateInstance、データ型:Ptr、を追加)
Private Shared Property SearchDelegateInstance as Ptr
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:SearchToolbarItemIdentifier、データ型:String、標準値:My Search Toolbar Item、を追加)
Private Shared Property SearchToolbarItemIdentifier as String = "My Search Toolbar Item"
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:SegmentedControlPairToolbarItemIdentifier、データ型:String、標準値:My Segmented Control Pair Toolbar Item、を追加)
Private Shared Property SegmentedControlPairToolbarItemIdentifier as String = "My Segmented Control Pair Toolbar Item"
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:SegmentedControlToolbarItemIdentifier、データ型:String、標準値:My Segmented Control Toolbar Item、を追加)
Private Shared Property SegmentedControlToolbarItemIdentifier as String = "My Segmented Control Toolbar Item"
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:TargetInstance、データ型:Ptr、を追加)
Private Shared Property TargetInstance as Ptr
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:ToolbarItemIdentifierAction、データ型:String、標準値:My Action Toolbar Item、を追加)
Private Shared Property ToolbarItemIdentifierAction as String = "My Action Toolbar Item"
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:ToolbarItemIdentifierQuick、データ型:String、標準値:My Quick Look Toolbar Item、を追加)
Private Shared Property ToolbarItemIdentifierQuick as String = "My Quick Look Toolbar Item"
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:ToolbarItemIdentifierShare、データ型:String、標準値:My Share Toolbar Item、を追加)
Private Shared Property ToolbarItemIdentifierShare as String = "My Share Toolbar Item"
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:ToolbarItemIdentifierSort、データ型:String、標準値:My Sort Toolbar Item、を追加)
Private Shared Property ToolbarItemIdentifierSort as String = "My Sort Toolbar Item"
- 以下をNSToolbarにペースト(できなければ共有プロパティに、名前:ToolbarItemIdentifierTag、データ型:String、標準値:My Tag Toolbar Item、を追加)
Private Shared Property ToolbarItemIdentifierTag as String = "My Tag Toolbar Item"
- 他に、NSMakePoint/NSMakeRect/NSMakeSize(メソッド)、NSPoint/NSRect/NSSize(構造体)が必要ですが、それらはmacoslibからコピーさせて頂きました。(上記NSToolbarにコピーする。)
おわりに
今回も仕組みを理解するために、極力シンプルな書き方を心懸けています。
(例えば、allocした変数の一部は然るべきタイミングでReleaseするべきと思われますが、そのためにはコードを工夫する必要があります。)
実用目的であれば、macoslibをそのまま利用させて頂くことを考えた方がいいでしょう。
追記:削除したサーチフィールドの実装は代替法として有効であり、ケースによっては使い勝手がいいこともあるため、復活しておきました。内容はこちら。
お世話になったサイト
貴重な情報をご提供頂いている皆様に、お礼申し上げます。(以下、順不同)
参考サイト(1):cocoa - How to force NSToolBar validation? - Stack Overflow
参考サイト(2):Fucking NSImage Syntax
参考サイト(3):OS Xステータスバーアプリケーションの作り方 — Genji App Blog(ステータス項目を表示する、の5.項)
更新履歴
2022.01.27 おわりにの記述に、追記を追加。
2021.05.11 方針のその他の方針を変更。Xojoでの実装、の2826項を変更。
2018.07.30 Xojoでの実装、の16,30,31,32,33,3416,28,29,30,31,32項を改訂。
2018.01.17 Xojoでの実装、のソースのうち、controlTextViewDoCommandBySelector/makeDelegateTextViewを削除、setToolItemSearchを大幅改訂。
2016.11.25 新規作成
[Home] [MacSoft] [Donation] [History] [Privacy Policy] [Affiliate Policy]