C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

タブコントロールのタブの文字色"だけ"を変えたい [1]

[トピック内 24 記事 (21 - 24 表示)]  << 0 | 1 >>

■102609 / inTopicNo.21)  Re[15]: タブコントロールのタブの文字色"だけ"を変えたい
  
□投稿者/ KOZ (432回)-(2023/11/25(Sat) 01:16:32)
No102607 (KOZ) に返信

最終バージョン?

Option Strict On
Imports System.ComponentModel
Imports System.Runtime.InteropServices

Public Class CustomTabControl
    Inherits TabControl

    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
    Public ReadOnly Property ColoredTabs As New List(Of Integer)()

    Public Sub New()
        DoubleBuffered = True
        ResizeRedraw = True
        SetStyle(ControlStyles.UserPaint, False)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)
        Select Case m.Msg
            Case WM_PAINT
                SetStyle(ControlStyles.UserPaint, True)
                MyBase.WndProc(m)
                SetStyle(ControlStyles.UserPaint, False)
            Case TCM_SETITEMA, TCM_SETITEMW
                ReplaceTcItem(m)
            Case TCM_INSERTITEMA, TCM_INSERTITEMW
                ReplaceTcItem(m)
            Case Else
                MyBase.WndProc(m)
        End Select
    End Sub

    Private Sub ReplaceTcItem(ByRef m As Message)
        Dim item As TCITEM = Marshal.PtrToStructure(Of TCITEM)(m.LParam)
        Dim pszText As String = Marshal.PtrToStringAuto(item.pszText)
        Dim adSpace As String = AdjustSpace(pszText)
        item.pszText = Marshal.StringToCoTaskMemAuto(adSpace)
        item.cchTextMax = adSpace.Length
        Dim lParam As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(item))
        Try
            Marshal.StructureToPtr(item, lParam, False)
            Dim newMessage As Message = Message.Create(m.HWnd, m.Msg, m.WParam, lParam)
            MyBase.WndProc(newMessage)
            m.Result = newMessage.Result
        Finally
            Marshal.FreeCoTaskMem(item.pszText)
            Marshal.FreeCoTaskMem(lParam)
        End Try
    End Sub

    Private Function AdjustSpace(pszText As String) As String
        Using g As Graphics = CreateGraphics()
            Dim nLen As Integer = pszText.Length
            Dim nWidth As Integer = TextRenderer.MeasureText(pszText, Font).Width
            Do
                Dim tmpStr As New String(" "c, nLen)
                If TextRenderer.MeasureText(tmpStr, Font).Width >= nWidth Then
                    Return New String(" "c, nLen + 1)
                End If
                nLen += 1
            Loop
        End Using
    End Function

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        Dim hdc As IntPtr = e.Graphics.GetHdc()
        Dim m As Message = Message.Create(Handle, WM_PAINT, hdc, IntPtr.Zero)
        DefWndProc(m)
        e.Graphics.ReleaseHdc()
        For i As Integer = 0 To TabPages.Count - 1
            Dim page As TabPage = TabPages(i)
            Dim rect As Rectangle = GetTabRect(i)
            Dim tabColor As Color
            Dim tabFont As Font
            Dim flags As TextFormatFlags = TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter
            Dim needDispose As Boolean = False
            If ColoredTabs.Contains(i) Then
                tabColor = Color.Red
                tabFont = New Font(Font.FontFamily, Font.Size, FontStyle.Bold)
                needDispose = True
            Else
                tabColor = ForeColor
                tabFont = Font
            End If
            If i = SelectedIndex Then
                rect.Y -= 1
            Else
                rect.Y += 1
            End If
            TextRenderer.DrawText(e.Graphics, page.Text,
                                  tabFont, rect, tabColor, flags)
            If needDispose Then
                tabFont.Dispose()
            End If
        Next
        MyBase.OnPaint(e)
    End Sub

    Private Const WM_PAINT As Integer = &HF
    Private Const TCM_FIRST As Integer = &H1300
    Private Const TCM_SETITEMA As Integer = TCM_FIRST + 6
    Private Const TCM_SETITEMW As Integer = TCM_FIRST + 61
    Private Const TCM_INSERTITEMA As Integer = TCM_FIRST + 7
    Private Const TCM_INSERTITEMW As Integer = TCM_FIRST + 62

    <StructLayout(LayoutKind.Sequential)>
    Private Structure TCITEM
        Public mask As Integer
        Public dwState As Integer
        Public dwStateMask As Integer
        Public pszText As IntPtr
        Public cchTextMax As Integer
        Public iImage As Integer
        Public lParam As IntPtr
    End Structure

End Class

引用返信 編集キー/
■102613 / inTopicNo.22)  Re[15]: タブコントロールのタブの文字色"だけ"を変えたい
□投稿者/ カルミーア (10回)-(2023/11/25(Sat) 21:48:15)
No102603 (魔界の仮面弁士 さん) に返信

返信ありがとう御座います。

>>ようやく祭日に少し試してみました
> 祭日ではなく、祝日ですよね?

その通りですね。祝祭日という言葉と混同して間違えました。
余談ですが日本語で間違えたというと過去の私の文章
「面倒というよりも目的と剥離しているような気がしました。」
も、「剥離(はくり)」ではなく、正しくは「乖離(かいり)」でした。

剥離は網膜剥離みたいに、それまで密着していたものが剥がれてしまう。
乖離は互いの意識が乖離しているなど、背き離れることを意味するので後者が適切でした。

コーディングの色々なアドバイスを頂きありがとう御座います。
金曜日は責任者が休みの為相談はできませんでしたが、おそらくは優先順位が低いのは変わらずで
今ある課題を片付けた後、余裕があればタブ文字の変更をやる可能性があるとみています。


No102607 (KOZ さん) に返信

私の為に色々と工夫頂いてありがとう御座います。
もしタブ文字の案が採用されれば試してみます。感謝します。

>>元質問だと、「選択されたタブの文字色を太字赤色にする」ではなく
>>「特定タブの耳の文字だけを太字赤色にしたい」なんですよね。
>
> おおう、これは勘違いしてました。

厳密にいえばこのシステムはログインして使用するものですが、権限がある人は全てのタブの切り替えができる。
権限がない人は複数の特定のタブは開けないという仕様にしたいようです。
開けない場合はそこを赤太文字にできないかというのが始まりです。
(タブのハイドはしない方向です)

引用返信 編集キー/
■102619 / inTopicNo.23)  Re[16]: タブコントロールのタブの文字色"だけ"を変えたい
□投稿者/ 魔界の仮面弁士 (3721回)-(2023/11/26(Sun) 11:39:30)
No102613 (カルミーア さん) に返信
> 開けない場合はそこを赤太文字にできないかというのが始まりです。

使用不可なら淡色表示(グレーなど)にするのが一般的な気がしますけれどね。

色やフォントを変えるとなると標準機能には無いので、KOZ さんの例のように、多少の手間が必要ですね。
海外掲示板では、取り消し線を引いて表現する例もあったのですが、漢字圏だと相性が悪い。
 TabPage5.Text = "TabPage5"
 TabPage5.Text = String.Join("", TabPage5.Text.SelectMany(Function(c) ChrW(&H336) & c))


> 権限がない人は複数の特定のタブは開けないという仕様にしたいようです。
Selecting イベントでキャンセルすれば開けなくはなりますね。
キーボードの矢印キーによるタブ切替が阻害されるため、使い勝手が多少悪くなりますが。

 'TabPage 番号 0, 2, 3 は開けるが
 'TabPage 番号 1, 4, 5 は開けない
 Private LockedTabPageIndices() As Integer = {1, 4, 5}
 Private Sub TabControl1_Selecting(sender As Object, e As TabControlCancelEventArgs) Handles TabControl1.Selecting
  If LockedTabPageIndices.Contains(e.TabPageIndex) Then
   e.Cancel = True
  End If
 End Sub
 ' https://dobon.net/vb/dotnet/control/tabdisabledpage.html
引用返信 編集キー/
■102624 / inTopicNo.24)  Re[17]: タブコントロールのタブの文字色"だけ"を変えたい
□投稿者/ カルミーア (11回)-(2023/11/27(Mon) 22:16:35)
No102619 (魔界の仮面弁士 さん) に返信

>
> 使用不可なら淡色表示(グレーなど)にするのが一般的な気がしますけれどね。

社内の設計者も同じことを言っていたので、現在顧客に確認中です。
ただ、赤が薄いグレーになったところで手間は同じなので聞く優先順位としては低いですが。。


> 色やフォントを変えるとなると標準機能には無いので、KOZ さんの例のように、多少の手間が必要ですね。
> 海外掲示板では、取り消し線を引いて表現する例もあったのですが、漢字圏だと相性が悪い。
>  TabPage5.Text = "TabPage5"
>  TabPage5.Text = String.Join("", TabPage5.Text.SelectMany(Function(c) ChrW(&H336) & c))
>

そんなのがあるんですね。勉強になります。

魔界の仮面弁士様、KOZ様、本当にありがとう御座いました。
KOZ様には長いサンプルも御教示戴きまして感謝しています。

本件は解決済みとさせて頂きます。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示

<前の20件
トピック内ページ移動 / << 0 | 1 >>

このトピックに書きこむ