ホームページ開発ツール>Xojo / Real Studio Trial and Error・CocoaのDeclareでコントロールのカスタマイズ2題

 Xojo / Real Studio Trial and Error

CocoaのDeclareでコントロールのカスタマイズ2題

目次
 はじめに

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

 コントロール全般のカラー(アピアランス・カラー)と、セグメンテッドコントロールのラベル、のカスタマイズについて少し調べてみました。

 なお検証には、Xojo 2016 Release 3を用いています。(Mac mini mid 2010 + macOS 10.13.6 High Sierra)


 経緯

 アピアランス・カラー

 コントロールの中には、チェックボックスのチェック時や、ポップアップメニューの矢印部分のように、カラー(注1)が適用されるものがあります。
注1)正式名称が分からないので、本項では「アピアランス・カラー」と記している。
 このアピアランス・カラーは、システム環境設定>一般>アピアランス、で指定できますが、選択肢はブルーとグラファイトのみで、おまけにコントロールだけでなく、システム全体(メニューバーやウィンドウのタイトルバーとか)に影響を及ぼすので、おいそれとは変更できません。

 一方、OS X Yosemite以降ではフラットデザインが採用され、FinderやOS添付アプリのツールバーアイコン等もフラット&モノトーン化されています。
 ツールバーをフラット&モノトーン化するのであれば、ウィンドウ内もそれに合わせた色あいにしたい、という場合も出てくるかと思われます。
(ただし、アップルのガイドラインは未調査のため、アピアランス・カラーの変更は何らかの規定に抵触する可能性がない訳ではありませんが…)

 そこで、コントロール個別に設定するる方法がないものか調べてみたところ、以下がヒットしました。チェックボックスに限らず、応用できそうです。

 参考サイト(1):Xcode - NSButtonのチェックボックスの色を変える|teratail

 問題はコードでどう表現するかですが、CIFilterで調べると写真加工のような事例が多くヒットして、なかなかコントロールにまでは辿り着けませんでした。
 ようやくNSViewのsetContentFilters:でセットできるところまでは分かったのですが、これだけ実装しても何も変わりませんでした。
 更に調べると、setWantsLayer:が必要なことがわかり、セットしてみたら上手くいきました。

 なお、このフィルターは、セットしたViewが内包する全てのViewに適用されるようで、例えばウィンドウ(のView)に設定すると、一発で全コントロールに適用できる反面、キャンバス等に描かれた図像は大変なことになります。
 個別指定するにしても、タブパネルは要注意で、キャンバスを内包させたい場合には使えません。セグメンテッドコントロール+グループボックス+ページパネルで自作するとかが必要になりそうです。
S Shot1 S Shot2
ノーマル ウィンドウのViewにCIFilter(CIColorMonochrome、色は赤)を適用

 セグメンテッドコントロールのラベル

 セグメンテッドコントロールには、他のコントロールにあるフォント関連の設定項目がありません。
 これはXojoに限ったことではなく、Xcodeでも同様です。(注:Interface Builderでは可能。なぜできるのかは謎(笑)です。)
 理由は分かりませんが、例えば以下のトピックの回答者(1の方)が指摘していることとも関係がありそうです。

 参考サイト(2):cocoa - NSSegmentedControl (subclass NSSegmentCell) Text Color - Stack Overflow

 という訳で、文字で表現するのは難しいと考えられるものの、アイコンは貼り付けられるという特性を利用して、アイコン代わりに文字を描いたイメージを貼る、という方法は使えそうです。
 イメージは、画像ソフトであらかじめ作っておいてセットする方法もありますが、ここではカスタマイズの容易さを優先して、実行時に生成する方法にしてみました。
(具体的には、NSMutableAttributedStringを生成後、NSBitmapImageRep経由で描画し、NSImageに変換後、setImage:forSegment:で各セグメントにセットする、というもの。)
S Shot3
注)フォント種別ことのベースライン調整は行なっていない。また、文字色設定は後述するTemplate設定と排他的なため、以下の実装では行なっていない。

 また、パラメータはIDEで設定できるようにしてみます。
 やり方はXojoのドキュメント(UserGuide-UserInterface.pdf P115)にあるとおり、「インスペクタ・ビヘイビア...」で表示されるダイアログを使います。
 なお、フォントについては、名前とサイズだけでは通常のテキストボックスが表示されるだけですが、ボールド/イタリック/アンダーラインを追加すると、他のコントロールと同様のフォントに特化したものとなる(?)ようです。
 あと、ネイティブにフォント設定可能なコントロールと異なり、フォント情報を変更してもIDE上の表示には反映されません。


 サンプルの仕様

 仕様は、以下の通りとしました。

 アピアランス・カラー
 セグメンテッドコントロールのラベル

 Xojoでの実装(アピアランス・カラー)
【ソースコードのコピー&ペーストについて】
ソースコード(グレー背景部分の全文)をコピーし、指定のウィンドウ/クラスにペーストすると、(新規作成して名前等を個別にコピー&ペーストしなくても)復元されます。
ただし、この方法は、メソッドでは問題ないようですが、イベント/アクション/プロパティでは不安定?なので、ペーストできない場合は、各項目のカッコ内を適用して下さい。
  1. Xojoで新規プロジェクトを作成
  2. Window1に、RadioButton2個(Name:RadioButton1、Name:RadioButton2)、PopupMenu(Name:PopupMenu1)を追加
  3. 以下をWindow1にペースト(できなければ、Sub - Endの間をOpenイベントに記述)
    Sub Open() Handles Open
      SetContentFilters(RadioButton1.Handle,RGB(148,148,148))
      SetContentFilters(RadioButton2.Handle,RGB(148,148,148))
      SetContentFilters(PopupMenu1.Handle,RGB(148,148,148))
    End Sub
    
  4. 以下をWindow1にペースト
    Private Sub SetContentFilters(hndl As Integer, rgbc As Color)
      // 文字列を指定してクラスオブジェクト/セレクタを取得する。最初に一回宣言しておけばよい。
      Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
      
      // CIFilterにCIColorMonochromeをセット
      Dim filter1 As Ptr = NSClassFromString("CIFilter")
      Declare Function filterWithName Lib "Cocoa" Selector "filterWithName:" (receiver As Ptr, fnam As CFStringRef) As Ptr
      filter1 = filterWithName(filter1, "CIColorMonochrome")
      
      // カラーをセット
      Dim clrCI As Ptr = NSClassFromString("CIColor")
      Declare Function alloc Lib "Cocoa" Selector "alloc" (receiver As Ptr) As Ptr
      clrCI = alloc(clrCI)
      Declare Function initWithColor Lib "Cocoa" Selector "initWithColor:" (receiver As Ptr, clr As Ptr) As Ptr
      clrCI = initWithColor(clrCI, XojColorToNSColor(rgbc))  // Xojo RGB -> NSColor -> CIColor
      
      // 実数をNSNumber型に変換
      Dim num As Ptr = NSClassFromString("NSNumber")
      #if Target32Bit
        Declare Function numberWithReal Lib "Cocoa" Selector "numberWithFloat:" (receiver As Ptr, num As Single) As Ptr
      #endif
      #if Target64Bit
        Declare Function numberWithReal Lib "Cocoa" Selector "numberWithDouble:" (receiver As Ptr, num As Double) As Ptr
      #endif
      num = numberWithReal(num, 1.0)
      
      // パラメータをセット
      Declare Sub setValue Lib "Cocoa" Selector "setValue:forKey:" (receiver As Ptr, val As Ptr, key As CFStringRef)
      setValue(filter1, clrCI, "inputColor")  // カラー
      setValue(filter1, num, "inputIntensity")  // 強度
      
      // 名前をセット(参照しないので不要?)
      Declare Sub setName Lib "Cocoa" Selector "setName:" (receiver As Ptr, nam As CFStringRef)
      setName(filter1, "filter1")
      
      // パラメータをArrayに格納
      Dim arr As Ptr = NSClassFromString("NSMutableArray")
      Declare Function getArray Lib "Cocoa" Selector "array" (receiver As Ptr) As Ptr
      arr = getArray(arr)
      Declare Sub addObject Lib "Cocoa" Selector "addObject:" (receiver As Ptr, obj As Ptr)
      addObject(arr, filter1)
      
      // CALayerの使用を有効にする(重要!)
      Declare Sub wantsLayer Lib "Cocoa" Selector "setWantsLayer:" (receiver As Integer, flg As Boolean)
      wantsLayer(hndl, true)
      
      // コントロール(のView)にCIFilterをセット
      Declare Sub setContentFilters Lib "Cocoa" Selector "setContentFilters:" (receiver As Integer, arry As Ptr)
      setContentFilters(hndl, arr)
      
      // clean up
      Declare Sub release Lib "Cocoa" Selector "release" (receiver As Ptr)
      release(clrCI)
    End Sub
    
  5. 以下をWindow1にペースト
    Private Function XojColorToNSColor(clrC As Color) as Ptr
      Dim r, g, b As CGFloat
      
      // 0〜255 を 0.0〜1.0 にマッピング
      r=clrC.Red/255
      g=clrC.Green/255
      b=clrC.Blue/255
      
      // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。
      Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
      
      // カラーの取得
      Dim clr As Ptr = NSClassFromString("NSColor")
      
      // RGB値からカラーを生成
      Declare Function colorWithCalibrate Lib "Cocoa" Selector "colorWithCalibratedRed:green:blue:alpha:" (receiver As Ptr, red As CGFloat, green As CGFloat, blue As CGFloat, alpha As CGFloat) As Ptr
      clr = colorWithCalibrate(clr, r, g, b, 1.0)  // alpha値は常に1.0
      
      // カラーを返す
      return clr
    End Function
    
 実行してみたところ、アピアランス・カラーが変更されることを確認しました。
S Shot4

 Xojoでの実装(セグメンテッドコントロールのラベル)
【ソースコードのコピー&ペーストについて】
ソースコード(グレー背景部分の全文)をコピーし、指定のウィンドウ/クラスにペーストすると、(新規作成して名前等を個別にコピー&ペーストしなくても)復元されます。
ただし、この方法は、メソッドでは問題ないようですが、イベント/アクション/プロパティでは不安定?なので、ペーストできない場合は、各項目のカッコ内を適用して下さい。
  1. Xojoで新規プロジェクトを作成
  2. 新規クラス(名前は、ここでは「SegmentedControlStyle」)を作成し、Superを「SegmentedControl」にする。
  3. 以下をSegmentedControlStyleにペースト(できなければイベント定義に、イベント名:Openを追加)
    Event Open()
    
  4. 以下をSegmentedControlStyleにペースト(できなければ、Sub - Endの間をOpenイベントに記述)
    Sub Open() Handles Open
      // フォーカスリングを無効に
      Declare Sub setFocusRingType Lib "Cocoa" Selector "setFocusRingType:" (receiver As Integer, type As Integer)
      setFocusRingType(me.Handle, 1)
      
      // セグメント毎のラベルセット
      InitSegmentTitle()
      
      // インスタンスのOpen()に継承
      RaiseEvent Open()
    End Sub
    
  5. 以下をSegmentedControlStyleにペースト
    Private Function BoolToInt(val As Boolean) as Integer
      if val then
        return 1
      else
        return 0
      end if
    End Function
    
  6. 以下をSegmentedControlStyleにペースト
    Private Function GenAttrText(st As String) as Ptr
      // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。
      Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
      
      Declare Function alloc Lib "Cocoa" Selector "alloc" (receiver As Ptr) As Ptr
      Declare Function init Lib "Cocoa" selector "init" (obj_id As Ptr) As Ptr
      Declare Sub addAttribute Lib "Cocoa" Selector "addAttribute:value:range:" (receiver As Ptr, nane As CFStringRef, val As Ptr, range As NSRange)
      
      // アトリビュートを持たない、プレーンなスタイル付テキストを生成
      Dim attr As Ptr = NSClassFromString("NSMutableAttributedString")
      attr = alloc(attr)
      Declare Function initWithString Lib "Cocoa" Selector "initWithString:" (receiver As Ptr, str As CFStringRef) As Ptr
      attr = initWithString(attr, st)
      
      Declare Function length Lib "Cocoa" Selector "length" (receiver As Ptr) As Integer
      Dim ll As Integer = length(attr)  // 文字列長
      
      Declare Sub beginEditing Lib "Cocoa" Selector "beginEditing" (receiver As Ptr)
      beginEditing(attr)  // 編集開始
      
      // フォント(名前、サイズ、ボールド、イタリック)
      Dim font As Ptr = NSClassFromString("NSFont")
      Declare Function fontWithName Lib "Cocoa" Selector "fontWithName:size:" (receiver As Ptr, fname As CFStringRef, size As CGFloat) As Ptr
      font = fontWithName(font, GetFontName(), GetFontSize())  // GetFontName()で、ボールド/イタリック設定を反映したフォント名を取得
      addAttribute(attr, "NSFont", font, NSMakeRange(0, ll))
      
      // フォント(アンダーライン)
      Dim num As Ptr = NSClassFromString("NSNumber")
      Declare Function numberWithInteger Lib "Cocoa" Selector "numberWithInteger:" (receiver As Ptr, num As Integer) As Ptr
      num = numberWithInteger(num, BoolToInt(Underline))
      addAttribute(attr, "NSUnderline", num, NSMakeRange(0, ll))
      
      // フォント(カラー>Template指定するので、常に黒)
      Dim clr As Ptr = NSClassFromString("NSColor")
      Declare Function blackColor Lib "Cocoa" Selector "blackColor" (receiver As Ptr) As Ptr
      clr = blackColor(clr)
      addAttribute(attr, "NSColor", clr, NSMakeRange(0, ll))
      
      // 段落(ParagraphStyle)の生成
      Dim pgf As Ptr = NSClassFromString("NSMutableParagraphStyle")
      pgf = init(alloc(pgf))
      
      // 揃えの設定
      Declare Sub setAlignment Lib "Cocoa" Selector "setAlignment:" (receiver As Ptr, algn As Integer)
      setAlignment(pgf, LabelAlign)
      
      // 段落設定を適用
      addAttribute(attr, "NSParagraphStyle", pgf, NSMakeRange(0, ll))
      
      // clean up
      Declare Sub release Lib "Cocoa" Selector "release" (receiver As Ptr)
      release(pgf)
      
      Declare Sub endEditing Lib "Cocoa" Selector "endEditing" (receiver As Ptr)
      endEditing(attr)  // 編集終了
      
      // 矛盾の解消(効果ある??)
      declare sub fixAttributesInRange lib "Cocoa" selector "fixAttributesInRange:" (receiver as Ptr, range As NSRange)
      fixAttributesInRange(attr, NSMakeRange(0, ll))
      
      return attr
    End Function
    
  7. 以下をSegmentedControlStyleにペースト
    Private Function GenTextImage(w As Integer, attr As Ptr) as Ptr
      // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。
      Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
      
      // 描画領域の生成
      Dim rect As NSRect = NSMakeRect(0,0,w,GetFontSize()+BaseOffset)
      
      // NSBitmapImageRep初期化
      Dim bitmapImageRep As Ptr = NSClassFromString("NSBitmapImageRep")
      Declare Function alloc Lib "Cocoa" Selector "alloc" (receiver As Ptr) As Ptr
      bitmapImageRep = alloc(bitmapImageRep)
      Declare Function initWithBitmapDataPlanes Lib "Cocoa" Selector "initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:" _
      (receiver As Ptr, planes As Ptr, w As Integer, h As Integer, bps As Integer, spp As Integer, alpha As Boolean, isPlanar As Boolean, colorSpaceName As CFStringRef, bfmt As Integer, rBytes As Integer, pBits As Integer) As Ptr
      bitmapImageRep = initWithBitmapDataPlanes(bitmapImageRep, nil, rect.w, rect.h, 8, 4, true, false, "NSDeviceRGBColorSpace", 0, 0, 0)
      
      // bitmapImageRepからグラフィックコンテキストを取得
      Dim context As Ptr = NSClassFromString("NSGraphicsContext")
      Declare Function graphicsContextWithBitmapImageRep Lib "Cocoa" Selector "graphicsContextWithBitmapImageRep:" (receiver As Ptr, irep As Ptr) As Ptr
      context = graphicsContextWithBitmapImageRep(context, bitmapImageRep)
      if context=nil then
        return nil
      end if
      
      // 現在のグラフィックコンテキストを退避
      Dim context1 As Ptr = NSClassFromString("NSGraphicsContext")
      Declare Sub saveGraphicsState Lib "Cocoa" Selector "saveGraphicsState" (receiver As Ptr)
      saveGraphicsState(context1)
      
      // 現在のグラフィックコンテキストにセット
      Dim context2 As Ptr = NSClassFromString("NSGraphicsContext")
      Declare Sub setCurrentContext Lib "Cocoa" Selector "setCurrentContext:" (receiver As Ptr, cntx As Ptr)
      setCurrentContext(context2, context)
      
      // 背景色を指定しての塗りつぶしは行わないので、透明が適用される
      
      // テキストの描画
      Declare Sub drawInRect Lib "Cocoa" selector "drawInRect:" (class_id As Ptr, rect As NSRect)
      drawInRect(attr, rect)
      
      // 退避したグラフィックコンテキストを戻す
      Dim context3 As Ptr = NSClassFromString("NSGraphicsContext")
      Declare Sub restoreGraphicsState Lib "Cocoa" Selector "restoreGraphicsState" (receiver As Ptr)
      restoreGraphicsState(context3)
      
      // bitmapImageRepからサイズを取得
      Declare Function mySize Lib "Cocoa" Selector "size" (receiver As Ptr) As NSSize
      Dim size As NSSize = mySize(bitmapImageRep)
      
      // bitmapImageRepのサイズでイメージを生成
      Dim image As Ptr = NSClassFromString("NSImage")
      image = alloc(image)
      Declare Function initWithSize Lib "Cocoa" Selector "initWithSize:" (receiver As Ptr, size As NSSize) As Ptr
      image = initWithSize(image, size)
      
      // イメージに画像をセット
      Declare Sub addRepresentation Lib "Cocoa" selector "addRepresentation:" (class_id As Ptr, bmap As Ptr)
      addRepresentation(image, bitmapImageRep)
      
      // clean up
      Declare Sub release Lib "Cocoa" Selector "release" (receiver As Ptr)
      release(bitmapImageRep)
      
      // イメージを返す
      return image
    End Function
    
  8. 以下をSegmentedControlStyleにペースト
    Private Function GetFontBoldItalic(fname As String, bFlg As Boolean, iFlg As Boolean) as Ptr
      // NSItalicFontMask = 0x00000001
      // NSBoldFontMask = 0x00000002
      
      // マスクをセット
      Dim flg As Integer = 0
      if bFlg then
        flg=flg+2
      end if
      if iFlg then
        flg=flg+1
      end if
      
      // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。
      Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
      
      // sharedFontManager取得
      Dim fmgr As Ptr = NSClassFromString("NSFontManager")
      Declare Function sharedFontManager Lib "Cocoa" Selector "sharedFontManager" (receiver As Ptr) As Ptr
      fmgr = sharedFontManager(fmgr)
      
      // フォントの取得
      Declare Function fontWithFamily Lib "Cocoa" Selector "fontWithFamily:traits:weight:size:" (receiver As Ptr, fname As CFStringRef, trait As Integer, wait As Integer, size As CGFloat) As Ptr
      Dim font As Ptr = fontWithFamily(fmgr, fname, flg, 0, 12)  // 名前の取得が目的なので、フォントサイズは常に12ポイントとしている
      
      // フォントを返す(nilの場合あり)
      return font
    End Function
    
  9. 以下をSegmentedControlStyleにペースト
    Private Function GetFontName() as String
      Dim font As Ptr
      Dim fname As String
      
      Declare Function fontName Lib "Cocoa" Selector "fontName" (receiver As Ptr) As CFStringRef
      
      // フォント名のセット
      if TextFont="System" then
        fname=GetFontNameSystem()  // Systemに割り当てられているフォントの名前を取得
      else
        fname=TextFont
      end if
      
      // 修飾なし
      if Bold=false and Italic=false then
        return fname  // 指定フォント名を返す
      end if
      
      // ボールドのみ
      if Bold and Italic=false then
        font = GetFontBoldItalic(fname,true,false)
        if font<>nil then
          return fontName(font)  // ボールド書体が取得できれば書体名を返す
        else
          return fname  // ボールド書体が取得できなければ指定フォント名を返す
        end if
      end if
      
      // イタリックのみ
      if Bold=false and Italic then
        font = GetFontBoldItalic(fname,false,true)
        if font<>nil then
          return fontName(font)  // イタリック書体が取得できれば書体名を返す
        else
          return fname  // イタリック書体が取得できなければ指定フォント名を返す
        end if
      end if
      
      // ボールド+イタリック
      if Bold and Italic then
        font = GetFontBoldItalic(fname,true,true)
        if font<>nil then
          return fontName(font)  // ボールド+イタリック書体が取得できれば書体名を返す
        end if
        font = GetFontBoldItalic(fname,true,false)
        if font<>nil then
          return fontName(font)  // ボールド書体が取得できれば書体名を返す
        end if
        font = GetFontBoldItalic(fname,false,true)
        if font<>nil then
          return fontName(font)  // イタリック書体が取得できれば書体名を返す
        end if
        return fname  // ボールドもイタリックも取得できなければ指定フォント名を返す
      end if
    End Function
    
  10. 以下をSegmentedControlStyleにペースト
    Private Function GetFontNameSystem() as String
      // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。
      Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr
      
      // システムフォントの取得
      Dim font As Ptr = NSClassFromString("NSFont")
      Declare Function systemFontOfSize Lib "Cocoa" Selector "systemFontOfSize:" (receiver As Ptr, size As CGFloat) As Ptr
      font = systemFontOfSize(font, 12)
      
      // システムフォントを返す
      Declare Function fontName Lib "Cocoa" Selector "fontName" (receiver As Ptr) As CFStringRef
      return fontName(font)
    End Function
    
  11. 以下をSegmentedControlStyleにペースト
    Private Function GetFontSize() as CGFloat
      // 単位換算
      select case TextUnit
      case FontUnits.Default  // On Macintosh, font units is in points
        return TextSize
      case FontUnits.Pixel
        return TextSize * 0.75
      case FontUnits.Point
        return TextSize
      case FontUnits.Inches
        return TextSize * 72
      case FontUnits.Millimeter
        return TextSize * 2.834
      end select
    End Function
    
  12. 以下をSegmentedControlStyleにペースト
    Private Sub InitSegmentTitle()
      Dim sItem As SegmentedControlItem
      
      Declare Sub setTemplate Lib "Cocoa" Selector "setTemplate:" (receiver As Ptr, flg As Boolean)
      Declare Sub setImage Lib "Cocoa" Selector "setImage:forSegment:" (receiver As Integer, label As Ptr, no As Integer)
      Declare Sub release Lib "Cocoa" Selector "release" (receiver As Ptr)
      
      // セグメント毎
      for i As Integer=0 to me.Items.Ubound
        
        // 各セグメントの取得
        sItem=me.Items(i)
        
        // 属性付テキスト生成
        Dim attr As Ptr = GenAttrText(sItem.Title)
        
        // 画像化
        Dim image As Ptr = GenTextImage(sItem.Width,attr)
        
        // 選択時のカラー反転や、ディアクティベート時のグレー化
        setTemplate(image, true)
        
        // セグメントコントロールにセット
        setImage(me.Handle, image, i)
        
        // clean up
        release(attr)
        release(image)
        
        // 文字列の方はクリアしておく
        sItem.Title=""
        
      next
    End Sub
    
  13. 以下をWindow1にペースト(できなければプロパティに、名前:BaseOffset、データ型:Integer、標準値:1、を追加)
    Public Property BaseOffset as Integer = 1
    
  14. 以下をWindow1にペースト(できなければプロパティに、名前:Bold、データ型:Boolean、を追加)
    Public Property Bold as Boolean
    
  15. 以下をWindow1にペースト(できなければプロパティに、名前:Italic、データ型:Boolean、を追加)
    Public Property Italic as Boolean
    
  16. 以下をWindow1にペースト(できなければプロパティに、名前:LabelAlign、データ型:Integer、標準値:2、を追加)
    Public Property LabelAlign as Integer = 2
    
  17. 以下をWindow1にペースト(できなければプロパティに、名前:TextFont、データ型:String、標準値:System、を追加)
    Public Property TextFont as String = "System"
    
  18. 以下をWindow1にペースト(できなければプロパティに、名前:TextSize、データ型:Single、標準値:12、を追加)
    Public Property TextSize as Single = 12
    
  19. 以下をWindow1にペースト(できなければプロパティに、名前:TextUnit、データ型:FontUnits、を追加)
    Public Property TextUnit as FontUnits
    
  20. 以下をWindow1にペースト(できなければプロパティに、名前:Underline、データ型:Boolean、を追加)
    Public Property Underline as Boolean
    
  21. 他に、NSMakeRange/NSMakeRect(メソッド)、NSRange/NSRect/NSSize(構造体)が必要ですが、それらはmacoslibからコピーさせて頂きました。(上記SegmentedControlStyleにコピーする。)
  22. SegmentedControlStyleクラスをcontrol+クリック(またはマウスの右クリック)して表示されるメニューの「インスペクタ・ビヘイビア...」を選択
  23. ダイアログ左下の「+」ボタンを押してHeadingを追加し、ラベルをFontにする
  24. 追加したプロパティ(リストの最後尾にある)をFontにドラッグ移動する
  25. OKボタンを押してダイアログを閉じる
    S Shot6
  26. Xojoプロジェクトウィンドウ>ナビゲーターのWindow1をクリックし、SegmentedControlStyleをレイアウトエディタにドラッグ&ドロップ
    (レイアウトエディタとナビゲーターのWindow1>Controlsに、SegmentedControlStyleクラスのインスタンス(SegmentedControlStyle1)が生成される)
  27. インスペクタの「編集」ボタンを押してダイアログを表示し、Labelを設定する(ここでは「項目1〜4」)
 実行してみたところ、セグメンテッドコントロールのラベルが変更されることを確認しました。
S Shot5

 おわりに

 内包するコントロールに、アピアランス・カラーを継承させない方法は、調べてはいるのですが見つかっていません。
 ちなみに、setCanDrawSubviewsIntoLayer:は、自身のSubViewに関するもので、内包するコントロールには適用されないようです。
 この件につきまして、ご存知の方がいらっしゃいましたら教えて頂けると助かります。

 もう一つ、Xojoでの実装(セグメンテッドコントロールのラベル)でのTextSizeプロパティは、本来CGFloat型にしたいところですが、そうするとIDE上に表示できなくなるため、ここでは(他のコントロールに合わせて)Single型にしています。この場合、64bitではSingleからDoubleへのキャストが発生するので、(実行結果を見る限りは問題なさそうですが、安全を期すのであれば)一工夫しておいた方がいいかもしれません。


 お世話になったサイト

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

 参考サイト(1):Xcode - NSButtonのチェックボックスの色を変える|teratail
 参考サイト(2):cocoa - NSSegmentedControl (subclass NSSegmentCell) Text Color - Stack Overflow


 更新履歴

 2018.11.26 新規作成


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