VB.NET Twips と Pixel
(Visual Studio 2015 版)

投稿日 2016/05/08

[Home] 

はじめに

VB.NET が出る前には Classic Visual Basic が使われていました。この最後のバージョンが VB6 で現在でも使用しているところがあるようです。

VB6 から VB.NET へ移行する場合、よく問題になるのが長さの単位です。VB.NET ではピクセルでコントロールの位置やサイズを指定しますが、VB6 では Twips という単位が使われています。ここではピクセルと Twips の変換について考えてみたいと思います。

 

GetDeviceCaps API 関数について

変換は Twips の定義がわかれば、一見簡単そうなのですが、表示デバイス固有の情報が必要になるのでやや面倒です。この情報の取得には Win32 GetDeviceCaps API 関数を呼び出す必要があります。この関数は次のように定義されています。

int GetDeviceCaps(
   HDC hdc,     // デバイスコンテキストのハンドル
   int nIndex   // 能力のインデックス
);

hdc ですが、Win32 ではよく使われるパラメータですが、.NET では直接扱うことはありません。しかし、隠されているだけで存在するパラメータです。これは、Graphics オブジェクトの GetHdc() メソッドで取得できます。型の HDC ですが、.NET では IntPtr に読み替えます。

nIndex は MSDN の説明にあるように定数 LOGPIXELSX と LOGPIXELSY を指定します。この具体的な値は MSDN にも出ていないので、C++ などで簡単なプログラムを作って表示させるか、Win32 のヘッダーファイルを検索して調べる必要があります。具体的には、LOGPIXELSX = 88, LOGPIXELSY = 90 のようです。

 

サンプル

このサンプルでは Pixel を Twips に変換するメソッド ToTwip とその逆変換を行うメソッド ToPixel を定義しています。

Imports System.Runtime.CompilerServices

Public Module ModuleTwip
    ''' <summary>
    ''' Pixel を Twip に変換する。
    ''' </summary>
    ''' <param name="g">Graphics オブジェクト</param>
    ''' <param name="pixel">Pixel の値</param>
    ''' <returns>Twips の値</returns>
    Public Function ToTwip(ByRef g As Graphics, ByVal pixel As Integer) As Double
        Const LOGPIXELSY = 90
        Dim hdc As IntPtr = g.GetHdc()
        Dim pixelsY As Int32 = GetDeviceCaps(hdc, LOGPIXELSY)
        g.ReleaseHdc(hdc)
        Return pixel * 1440 / pixelsY
    End Function

    ''' <summary>
    ''' Twip を Pixel に変換する。
    ''' </summary>
    ''' <param name="g">Graphics オブジェクト</param>
    ''' <param name="twips">Twips の値</param>
    ''' <returns>Pixel の値</returns>
    Public Function ToPixel(ByRef g As Graphics, ByVal twips As Double) As Integer
        Const LOGPIXELSX = 88
        Dim hdc As IntPtr = g.GetHdc()
        Dim pixelsX As Int32 = GetDeviceCaps(hdc, LOGPIXELSX)
        g.ReleaseHdc(hdc)
        Return twips * pixelsX / 1440
    End Function

    ''' <summary>
    ''' Win32 API 関数 GetDeviceCaps
    ''' </summary>
    ''' <param name="Phdc">デバイスコンテキストのハンドル</param>
    ''' <param name="cIndex">能力のインデックス</param>
    ''' <returns>デバイス固有の情報</returns>
    
    Private Function GetDeviceCaps(ByVal Phdc As IntPtr, ByVal cIndex As Int32) As Int32

    End Function

End Module

 

(例) これらのメソッドの使い方は下のようになります。

Private Sub btnConvert_Click(sender As Object, e As EventArgs) Handles btnConvert.Click
    ErrorProvider1.Clear()
    Dim g As Graphics = Me.CreateGraphics()
    Try
        If String.IsNullOrEmpty(txtValue.Text) Then
            ErrorProvider1.SetError(txtValue, "入力が空欄です。")
            Return
        End If

        ' 文字列にカンマが含まれている場合は、2つの値があるとみなす。
        If txtValue.Text.Contains(","c) Then
            Dim ss() As String = txtValue.Text.Split(",")
            txtPixel.Text = ModuleTwip.ToPixel(g, CDbl(ss(0).Trim())) & "," & ModuleTwip.ToPixel(g, CDbl(ss(1).Trim()))
            txtTwips.Text = ModuleTwip.ToTwip(g, CDbl(ss(0).Trim())) & "," & ModuleTwip.ToTwip(g, CDbl(ss(1).Trim()))
        Else
            txtPixel.Text = ModuleTwip.ToPixel(g, CDbl(txtValue.Text))
            txtTwips.Text = ModuleTwip.ToTwip(g, CInt(txtValue.Text))
        End If
    Catch ex As Exception
        MessageBox.Show("例外を検出。" & ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub

 

 


 

 開設 2014年12月   著作権 2014-2016 bonk.red  連絡先: こちらからメッセージを送ってください(お仕事も大募集)