Visual Basic 中学校 掲示板 投稿内容
タグのない投稿を抽出 統計 RSS

Visual Basic 中学校 > 投稿一覧 >

ラベルの文字の綺麗な縦書き表示について 解決済み

タグの編集...

投稿者   (高校生)   投稿日時 2016/7/27 16:18:48
自分はリッチテキストボックスに入力した文字をラベルとしてパネルに表示し、印刷するということをしています。自分はラベルのロケーションにより文字を縦書きしているのですが、印刷した時に文字が曲がってしまっています。調べては見たのですが、どれもピクチャーボックスに描画するという方法しかありません。そこでピクチャーボックスを使わずにラベルの文字を綺麗な縦書き表示にしたいのですが、わかりません。わかる方いましたらお願いします。
リッチテキストボックスで入力してパネルに表示するコードを載せておきます。
Private Sub Nryoku_Click(ByVal sender As ObjectByVal e As System.Windows.Forms.MouseEventArgs)
        If Rtext.Text = "*" Then
            MsgBox("テキストを入力してください")
        Else
            If Mmax < 50 Then
                Te = Rtext.Text
                Me.mozi = New Label()
                Me.mozi.Name = "Text1"
                Me.mozi.Text = Te


                Me.mozi.AutoSize = True
                Me.mozi.Font = New Font("@明朝", 24, FontStyle.Bold)
                Me.mozi.ForeColor = Rtext.ForeColor
                Me.mozi.BackColor = Color.Transparent
                mozi.ContextMenuStrip = ContextMenuStrip1



                AddHandler mozi.MouseDown, AddressOf mozi_MouseDown
                AddHandler mozi.MouseMove, AddressOf mozi_MouseMove
                AddHandler mozi.MouseUp, AddressOf mozi_MouseUp
                AddHandler mozi.Click, AddressOf mozi_Click
                Panel1.Controls.Add(Me.mozi)

                Rtext.Clear()
                Mmax = Mmax + 1
            Else
                MsgBox("これ以上配置できません", 16)
            End If
        End If
    End Sub



投稿者 (削除されました)   ()   投稿日時 2016/7/28 12:32:42
(削除されました)

投稿者 魔界の仮面弁士   (社会人)   投稿日時 2016/7/28 12:36:09
本題からは外れて、縦書きリッチテキストボックスを試作してみました。
コンパイルすると、ツールボックスに「VerticalRichTextBox」が追加されます。

'======= VerticalRichTextBox.vb ======= 
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports System.Text
Public Class VerticalRichTextBox
    Inherits RichTextBox

    Private Declare Unicode Function LoadLibrary Lib "kernel32" Alias "LoadLibraryW" ( _
        ByVal libName As String _
    ) As IntPtr
    Private Declare Unicode Function SendMessage Lib "user32" Alias "SendMessageW" ( _
        ByVal hWnd As IntPtr, _
        ByVal Msg As Integer, _
        ByVal wParam As IntPtr, _
        ByVal lParam As IntPtr _
    ) As IntPtr
    Private Declare Unicode Function FreeLibrary Lib "kernel32" ( _
        ByVal hModule As IntPtr _
    ) As <MarshalAs(UnmanagedType.Bool)> Boolean

    Private Const ES_VERTICAL As Integer = &H400000
    Private Const EM_SETOPTIONS As Integer = 1101
    Private Const ECOOP_OR As Integer = 2
    Private Const WM_KEYDOWN As Integer = &H100
    Private Const WM_KEYUP As Integer = &H101

    Private hmRichEdit As IntPtr = IntPtr.Zero

    Public Sub New()
        'アジア圏の言語では、ES_VERTICAL を指定すると縦書きモードになります 
        SendMessage(Handle, EM_SETOPTIONS, New IntPtr(ECOOP_OR), New IntPtr(ES_VERTICAL))
    End Sub

    Protected Overrides ReadOnly Property CreateParams As CreateParams
        Get
            'ES_VERTICAL は、Rich Edit 2.0 や 3.0 ではサポートされていないため、 
            '対応したバージョンに書き換える必要があります 
            hmRichEdit = LoadLibrary("msftedit.dll")
            If hmRichEdit = IntPtr.Zero Then
                MessageBox.Show(Marshal.GetLastWin32Error().ToString())
                Throw New Win32Exception("内部エラー: LoadLibrary(""Msftedit.dll"")")
            End If
            Dim cp As CreateParams = MyBase.CreateParams
            cp.ClassName = "RICHEDIT50W"    'Rich Edit Version 4.1 を指定 
            Return cp
        End Get
    End Property

    Public Overrides Function PreProcessMessage(ByRef msg As Message) As Boolean
        Select Case msg.Msg
            Case WM_KEYDOWN, WM_KEYUP
                Dim keyCode As Keys = CType(msg.WParam, Keys) And Keys.KeyCode
                '矢印キーの動作を90度回転させます 
                Select Case keyCode
                    Case Keys.Left
                        msg.WParam = New IntPtr(Keys.Down)
                    Case Keys.Right
                        msg.WParam = New IntPtr(Keys.Up)
                    Case Keys.Up
                        msg.WParam = New IntPtr(Keys.Left)
                    Case Keys.Down
                        msg.WParam = New IntPtr(Keys.Right)
                End Select
        End Select
        Return MyBase.PreProcessMessage(msg)
    End Function

    Protected Overrides Sub OnResize(e As EventArgs)
        Me.Invalidate()
        MyBase.OnResize(e)
    End Sub

    Protected Overrides Sub Dispose(disposing As Boolean)
        If Not IntPtr.Zero.Equals(hmRichEdit) Then
            FreeLibrary(hmRichEdit)
            hmRichEdit = IntPtr.Zero
        End If
        MyBase.Dispose(disposing)
    End Sub
End Class


投稿者   (高校生)   投稿日時 2016/7/28 21:19:43
作成ありがとうございました。
このコードを使ってみて何か進展があるかもしれないので、やってみたいと思います。
ありがとうございます。

投稿者   (高校生)   投稿日時 2016/8/2 10:22:00
魔界の仮面弁士さんが投稿していただいたコードを使ってみてテキストボックスに縦書き表示することができました。しかしその文字をラベルに表示することができません。
よろしければ教えていただきたいです。

投稿者   (高校生)   投稿日時 2016/8/2 10:22:01
魔界の仮面弁士さんが投稿していただいたコードを使ってみてテキストボックスに縦書き表示することができました。しかしその文字をラベルに表示することができません。
よろしければ教えていただきたいです。

投稿者 shu   (社会人)   投稿日時 2016/8/2 11:16:40
N88-BASICさんが2016/7/20 13:30:12に質問された

『縦書き印字で下端を揃えたたい』

のスレッドを参考にLabelにオーナードローで描画してみるのは

どうでしょう?

投稿者 (削除されました)   ()   投稿日時 2016/8/2 11:49:19
(削除されました)

投稿者 魔界の仮面弁士   (社会人)   投稿日時 2016/8/2 11:56:42
Windows Forms や WPF に、縦書き表示用のコントロールはありません。
ご存知のように、そのためのコードを自身で作りこんでいく必要があります。

また、縦書き表示が目的の場合、System.Windows.Forms.Label を使うことはお勧めできません。
標準の横書き機能が実装の邪魔となり、むしろ扱いにくいと思います。

たとえば下記は、ラベルを90度回転させるサンプルです。
フォームデザイナへの対応が不十分ですし、
そもそも求めている縦書き機能とは異なると思いますが。
http://hanatyan.sakura.ne.jp/vbnetbbs/wforum.cgi?mode=allread&no=11698&page=0

このサンプルでは、Label を継承して作成しましたが、
標準の Text プロパティが描画の邪魔になったたため、
追加の回避コードを書く手間が必要になりました。

ユーザーからの入力操作が不要で、単にテキストを表示させるだけなら
System.Windows.Forms.Label ではなく、
 ・System.Windows.Forms.Control
 ・System.Windows.Forms.UserControl
 ・System.Windows.Forms.PictureBox
などに描画した方が手っ取り早いかもしれません。


> どれもピクチャーボックスに描画するという方法しかありません。
ピクチャーボックスに描画できるなら、その手順を応用すれば、
それ以外のコントロールに対しても対処できそうに思います。

そのサンプルが Uniscribe API を用いているものなのか、GDI+ の Graphics.DrawString によるものなのか(StringFormatFlags.DirectionVertical)、具体的な内容は分からないので何とも言えませんが……ピクチャーボックスで無ければ描画できないような手順になっているのでしょうか?


> ピクチャーボックスを使わずに
ところで、ピクチャーボックスを使いたくない理由は何ですか?
場合によっては、コントロールを追加せずに、親コンテナ(Form とか Panel とか)に直接描画するという選択肢もありそうです。どちらが楽かは案件次第ですが。

投稿者   (高校生)   投稿日時 2016/8/2 12:56:25
ラベルにしたかったのはピクチャーボックスだと複数作った時に重くなると思ったからです。

投稿者 魔界の仮面弁士   (社会人)   投稿日時 2016/8/2 15:15:36
RichTextBox では、文字単位でフォントや色を変えられますよね。

それと同様、一つの大きなコントロールを用意して、
その中に何行もの縦書き文字列を表示するという手もありますよ。


> 印刷するということをしています。
印刷というと、PrintDocument クラスのことでしょうか。

それとも、Graphics.CopyFromScreen などで画面をキャプチャして
画像ファイルとしてから、別のソフトで印刷するのでしょうか。

あるいは、印刷用のコンポーネントを別途用いているとか?
たとえば Word を印刷ツールとして使えば、縦書き印刷も可能ですね。


> ラベルに表示することができません。
ご存知のように、Label 自体には縦書き機能がありません。

また、「っゃゅょ」「“”()」「ー~」「、。」などのことを考えると、
文字単位の改行や位置調整だけでは対処しきれません。


となると、ラベルが持つ本来の機能を使わないようにした上で、
画面への『描画処理』を独自に上書きするほかありません。
(たとえば、先述した DirectionVertical などを使うなど)


そして、その『描画処理』を実装するために
Paint イベント/OnPaint メソッドを用いるのだとしたら、
Label よりも UserControl や PictureBox の方が良いと思います。
あるいは、Panel 上に直接描いてしまうという手もありますね。


また、描画内容があまり変動しない場合には、Bitmap に動的に描画してから、
それを Image プロパティに割り当てるという手もあります。
Image プロパティとは別に、BackgroundImage プロパティに割り当てることもできます。
(BackgroundImage は、プロパティ一覧からは隠されています)

いずれにせよ、Label に描画処理を実装するのであれば、
Text プロパティを空にしておいてください。そうしないと、
自身の描画処理にテキストが被って表示されてしまうことになります。



> 複数作った時に
同時に表示する個数はどの程度でしょうか。
5個? 50個? 500個?


> 重くなると思ったからです。

同じ数だけ貼り付けた場合、それぞれどの程度重くなるのか、
事前に検証してみましたか?


重いとみなすか軽いとみなすかは、PC スペックにもよりますし、
「縦書き」のためのコードの有無によっても異なるでしょうから、
単純に比較することは出来ませんが…手元の環境で
下記を実行した限りは、どちらも大差無い程度に感じました。


Public Class Form1
    Private panel1 As FlowLayoutPanel

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        panel1 = New FlowLayoutPanel()
        panel1.Dock = DockStyle.Fill
        panel1.AutoScroll = True
        panel1.FlowDirection = FlowDirection.LeftToRight

        'AppendGreenLabel(200) 
        'AppendBluePictureBox(200) 

        'AppendGreenLabel(400) 
        'AppendBluePictureBox(400) 

        Controls.Add(panel1)
    End Sub

    Private Sub AppendGreenLabel(count As Integer)
        Dim lbl As Label
        For n = 1 To count
            lbl = New Label()
            lbl.BackColor = Color.FromArgb(32, (n Or &H80) And &HFF, 0)
            lbl.AutoSize = False
            lbl.Size = New Size(70, 30)
            lbl.BorderStyle = BorderStyle.Fixed3D
            lbl.Margin = New Padding(3)
            panel1.Controls.Add(lbl)
        Next
    End Sub

    Private Sub AppendBluePictureBox(count As Integer)
        Dim pic As PictureBox
        For n = 1 To count
            pic = New PictureBox()
            pic.BackColor = Color.FromArgb(32, 0, (n Or &H80) And &HFF)
            pic.Size = New Size(70, 30)
            pic.BorderStyle = BorderStyle.Fixed3D
            pic.Margin = New Padding(3)
            panel1.Controls.Add(pic)
        Next
    End Sub
End Class


投稿者   (高校生)   投稿日時 2016/8/4 19:31:28
仮面弁士さんのを参考にしていろいろやってみたらできました。
いろいろ面倒くさくてすみませんでした。
ありがとうございました。