【VB.NET】文字列からバイト数を指定して部分文字列を取得(Shift_JIS)

Imports System.Text

''' <summary>
''' 文字列からバイト数を指定して部分文字列を取得する。
''' </summary>
''' <param name="value">対象文字列。</param>
''' <param name="startIndex">開始位置。(バイト数)</param>
''' <param name="length">長さ。(バイト数)</param>
''' <returns>部分文字列。</returns>
''' <remarks>文字列は <c>Shift_JIS</c> でエンコーディングして処理を行います。</remarks>
Public Shared Function SubstringByte(ByVal value As String, ByVal startIndex As Integer, ByVal length As Integer) As String
    Dim sjisEnc As Encoding = Encoding.GetEncoding("Shift_JIS")
    Dim byteArray() As Byte = sjisEnc.GetBytes(value)

    If byteArray.Length < startIndex + 1 Then
        Return ""
    End If

    If byteArray.Length < startIndex + length Then
        length = byteArray.Length - startIndex
    End If

    Dim cut As String = sjisEnc.GetString(byteArray, startIndex, length)

    ' 最初の文字が全角の途中で切れていた場合はカット
    Dim left As String = sjisEnc.GetString(byteArray, 0, startIndex + 1)
    Dim first As Char = value(left.Length - 1)
    If 0 < cut.Length AndAlso Not first = cut(0) Then
        cut = cut.Substring(1)
    End If

    ' 最後の文字が全角の途中で切れていた場合はカット
    left = sjisEnc.GetString(byteArray, 0, startIndex + length)

    Dim last As Char = value(left.Length - 1)
    If 0 < cut.Length AndAlso Not last = cut(cut.Length - 1) Then
        cut = cut.Substring(0, cut.Length - 1)
    End If

    Return cut
End Function

【VB.NET】切り上げ/切り捨て/四捨五入

''' <summary>
''' 切り上げ。
''' </summary>
''' <param name="value">対象の数値。</param>
''' <param name="decimalPlaces">有効小数桁数。</param>
''' <returns>切り上げした数値。</returns>
Public Shared Function RoundUp(ByVal value As Decimal, ByVal decimalPlaces As UInt32) As Decimal
    Dim rate As Decimal = CDec(Math.Pow(10.0R, decimalPlaces))

    If value < 0 Then
        Return (Math.Ceiling(value * -1D * rate) / rate) * -1D
    Else
        Return Math.Ceiling(value * rate) / rate
    End If
End Function

''' <summary>
''' 切り捨て。
''' </summary>
''' <param name="value">対象の数値。</param>
''' <param name="decimalPlaces">有効小数桁数。</param>
''' <returns>切り捨てした数値。</returns>
Public Shared Function RoundDown(ByVal value As Decimal, ByVal decimalPlaces As UInt32) As Decimal
    Dim rate As Decimal = CDec(Math.Pow(10.0R, decimalPlaces))

    If value < 0 Then
        Return (Math.Floor(value * -1D * rate) / rate) * -1D
    Else
        Return Math.Floor(value * rate) / rate
    End If
End Function

''' <summary>
''' 四捨五入。
''' </summary>
''' <param name="value">対象の数値。</param>
''' <param name="decimalPlaces">有効小数桁数。</param>
''' <returns>四捨五入した数値。</returns>
Public Shared Function Round(ByVal value As Decimal, ByVal decimalPlaces As UInt32) As Decimal
    Return Math.Round(value, CInt(decimalPlaces), MidpointRounding.AwayFromZero)
End Function

【VB.NET】ファイル・フォルダに対しフルアクセスを許可

Imports System.IO
Imports System.Security.AccessControl

''' <summary>
''' ファイル・フォルダに対しフルアクセスを許可する。
''' </summary>
''' <param name="path">パス。</param>
Public Shared Sub AddFullAccessRule(ByVal path As String)
    Dim fileInfo As New FileInfo(path)
    Dim fileSec As FileSecurity = fileInfo.GetAccessControl()

    ' アクセス権限をEveryoneに対しフルコントロール許可
    Dim accessRule As New FileSystemAccessRule("Everyone", FileSystemRights.FullControl, AccessControlType.Allow)
    fileSec.AddAccessRule(accessRule)
    fileInfo.SetAccessControl(fileSec)

    ' ファイルの読み取り専用属性を削除
    If (fileInfo.Attributes And FileAttributes.ReadOnly) = FileAttributes.ReadOnly Then
        fileInfo.Attributes = FileAttributes.Normal
    End If
End Sub

【VB.NET】コントロールを配置位置で並べ替え

下記のようにすることで、コントロールを配置位置でソートできるようにします。

Dim controlList As New List(Of Control)()
...
controlList.Sort(AddressOf CompareByPosition)

上記のソートを行うためのComparisonジェネリック デリゲートは下記の通りです。

Imports System.Windows.Forms
Imports System.Runtime.InteropServices

''' <summary>
''' コントロールを位置で比較する。
''' </summary>
''' <param name="x">比較元コントロール。</param>
''' <param name="y">比較先コントロール。</param>
''' <returns>比較結果。</returns>
''' <remarks><see cref="List(Of Control)"/>.<c>Sort</c> メソッドのパラメータとして指定可能。</remarks>
Public Shared Function CompareByPosition(ByVal x As Control, ByVal y As Control) As Integer
    ' 許容範囲
    Const AcceptableRange As Integer = 5

    ' 上座標で比較
    Dim ret As Integer = x.Top - y.Top
    If 0 < Math.Abs(ret) - AcceptableRange Then
        Return ret
    End If

    ' 左座標で比較
    ret = x.Left - y.Left
    If 0 < Math.Abs(ret) - AcceptableRange Then
        Return ret
    End If

    ' Zオーダーで比較
    ret = CompareByZOrder(x, y)
    If Not ret = 0 Then
        Return ret
    End If

    ' コントロール名で比較
    Return CompareByName(x, y)
End Function

''' <summary>
''' コントロールをZオーダーで比較する。
''' </summary>
''' <param name="x">比較元コントロール。</param>
''' <param name="y">比較先コントロール。</param>
''' <returns>比較結果。</returns>
Private Shared Function CompareByZOrder(ByVal x As Control, ByVal y As Control) As Integer
    Dim h As IntPtr = GetWindow(x.Handle, GetWindowCmd.GW_HWNDNEXT)

    While h <> IntPtr.Zero
        If h = y.Handle Then
            Return -1
        End If
        h = GetWindow(h, GetWindowCmd.GW_HWNDNEXT)
    End While

    h = GetWindow(x.Handle, GetWindowCmd.GW_HWNDPREV)
    While h <> IntPtr.Zero
        If h = y.Handle Then
            Return 1
        End If
        h = GetWindow(h, GetWindowCmd.GW_HWNDPREV)
    End While

    Return 0
End Function

''' <summary>
''' コントロールを名前で比較する。
''' </summary>
''' <param name="x">比較元コントロール。</param>
''' <param name="y">比較先コントロール。</param>
''' <returns>比較結果。</returns>
Private Shared Function CompareByName(ByVal x As Control, ByVal y As Control) As Integer
    ' コントロール名で比較
    Return String.Compare(x.Name, y.Name)
End Function

''' <summary>
''' 指定されたウィンドウと指定された関係(またはオーナー)にあるウィンドウのハンドルを返す。
''' </summary>
''' <param name="hwd">元ウィンドウのハンドル。</param>
''' <param name="uCmd">関係。</param>
''' <returns>関数が成功すると、ウィンドウのハンドルが返ります。指定した関係を持つウィンドウがない場合は、NULL が返ります。拡張エラー情報を取得するには、 関数を使います。</returns>
<DllImport("user32.dll")> _
Private Shared Function GetWindow(ByVal hwd As IntPtr, ByVal uCmd As Integer) As IntPtr
End Function

''' <summary>
''' GetWindow関数のコマンド。
''' </summary>
Private Enum GetWindowCmd
    ''' <summary>
    ''' 指定したウィンドウと同じ種類で最も高い Z オーダーを持つウィンドウのハンドルを取得します。<br/>
    ''' 指定したウィンドウが最前面ウィンドウの場合は、最も高い Z オーダーを持つ最前面ウィンドウのハンドルが返ります。<br/>
    ''' 指定したウィンドウがトップレベルウィンドウの場合は、最も高い Z オーダーを持つトップレベルウィンドウのハンドルが返ります。<br/>
    ''' 指定したウィンドウが子ウィンドウの場合は、最も高い Z オーダーを持つ兄弟ウィンドウのハンドルが返ります。
    ''' </summary>
    GW_HWNDFIRST = 0

    ''' <summary>
    ''' 指定したウィンドウと同じ種類で最も低い Z オーダーを持つウィンドウのハンドルを取得します。<br/>
    ''' 指定したウィンドウが最前面ウィンドウの場合は、最も低い Z オーダーを持つ最前面ウィンドウのハンドルが返ります。<br/>
    ''' 指定したウィンドウがトップレベルウィンドウの場合は、最も低い Z オーダーを持つトップレベルウィンドウのハンドルが返ります。<br/>
    ''' 指定したウィンドウが子ウィンドウの場合は、最も低い Z オーダーを持つ兄弟ウィンドウのハンドルが返ります。
    ''' </summary>
    GW_HWNDLAST = 1

    ''' <summary>
    ''' 指定したウィンドウより Z オーダーが 1 つ下のウィンドウのハンドルを取得します。<br/>
    ''' 指定したウィンドウが最前面ウィンドウの場合は、1 つ下の最前面ウィンドウのハンドルが返ります。<br/>
    ''' 指定したウィンドウがトップレベルウィンドウの場合は、1 つ下のトップレベルウィンドウのハンドルが返ります。<br/>
    ''' 指定したウィンドウが子ウィンドウの場合は、1 つ下の兄弟ウィンドウのハンドルが返ります。
    ''' </summary>
    GW_HWNDNEXT = 2

    ''' <summary>
    ''' 指定したウィンドウより Z オーダーが 1 つ上のウィンドウのハンドルを取得します。<br/>
    ''' 指定したウィンドウが最前面ウィンドウの場合は、1 つ上の最前面ウィンドウのハンドルが返ります。<br/>
    ''' 指定したウィンドウがトップレベルウィンドウの場合は、1 つ上のトップレベルウィンドウのハンドルが返ります。<br/>
    ''' 指定したウィンドウが子ウィンドウの場合は、1 つ上の兄弟ウィンドウのハンドルが返ります。
    ''' </summary>
    GW_HWNDPREV = 3

    ''' <summary>
    ''' 指定したウィンドウのオーナーウィンドウのハンドルを取得します。
    ''' </summary>
    ''' <remarks>
    ''' 詳細については、「Owned Windows」を参照してください。
    ''' </remarks>
    GW_OWNER = 4

    ''' <summary>
    ''' 指定したウィンドウが親ウィンドウの場合は、Z オーダーが一番上の子ウィンドウのハンドルを取得します。<br/>
    ''' それ以外の場合は、NULL が返ります。<br/>
    ''' この関数は、指定されたウィンドウの子ウィンドウだけを調べます。<br/>
    ''' それより下位の子孫は調べません。
    ''' </summary>
    GW_CHILD = 5

    ''' <summary>
    ''' Windows 2000:指定したウィンドウをオーナーとする有効なポップアップウィンドウのハンドルを取得します。<br/>
    ''' (この検索では、GW_HWNDNEXT で見つかる最初のウィンドウを使います。)<br/>
    ''' 有効なポップアップウィンドウがない場合は、指定したウィンドウのハンドルが返ります。<br/>
    ''' </summary>
    GW_ENABLEDPOPUP = 6
End Enum

許容範囲という値を設定していますが、これはこの範囲内の位置の差であれば同じ位置であるとみなすというものです。
許容範囲なしにしてしまうと、わずか1ピクセル揃っていないだけで並び順に影響してしまいます。

実際に使用する際にはコンテナを考慮して再帰的に呼び出す事によって、タブ順を自動制御するなどしています。

【C#】コントロール上にマウスカーソルが含まれるかどうかを判断

using System.Windows.Forms;

/// <summary>
/// コントロール上にマウスカーソルが含まれるかどうかを判断する。
/// </summary>
/// <param name="control">コントロール。</param>
/// <returns>コントロール上にマウスカーソルが含まれるかどうか。</returns>
public static bool ContainsMouseCursor(Control control)
{
    return control.ClientRectangle.Contains(control.PointToClient(Cursor.Position));
}

【C#】コンテナを考慮してアクティブなコントロールを取得

using System.Windows.Forms;

/// <summary>
/// コンテナを考慮してアクティブなコントロールを取得する。
/// </summary>
/// <param name="container">コンテナ。</param>
/// <returns>アクティブなコントロール。</returns>
public static Control GetActiveControl(IContainerControl container)
{
    if (container.ActiveControl is IContainerControl)
    {
        // アクティブコントロールがコンテナの場合は再帰
        return GetActiveControl((IContainerControl)container.ActiveControl);
    }
    else
    {
        return container.ActiveControl;
    }
}

【C#】画像をマージ

using System.Drawing;

/// <summary>
/// 画像をマージする。
/// </summary>
/// <param name="sourceImage">元画像。</param>
/// <param name="overlayImage">オーバーレイする画像。</param>
/// <returns>マージした画像(Image)。</returns>
public static Image MargeImage(Image sourceImage, Image overlayImage)
{
    using (Graphics g = Graphics.FromImage(sourceImage))
    {
        g.DrawImage(overlayImage,
                    0,
                    0,
                    overlayImage.Width,
                    overlayImage.Height);
    }

    return sourceImage;
}