הערה
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות להיכנס או לשנות מדריכי כתובות.
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות לשנות מדריכי כתובות.
Question
Saturday, February 13, 2016 10:29 AM
Hi There
Is There A Way For Combobox To Center Align Its Text
Regards
All replies (6)
Saturday, February 13, 2016 10:49 AM ✅Answered
Hello,
See the answer here. In short center align is not supported, you need to use a custom ComboBox.
Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
VB Forums - moderator
Saturday, February 13, 2016 11:54 AM ✅Answered
Just to add, the example at the link provided by Kareninstructor will work good if you want to have your ComboBox.DropDownStyle set to DropDownList so that you can not type anything into the ComboBox. However, if you want the DropDownStyle set to the standard DropDown style so the user can type in the combobox then below is an example of creating a small combobox class that does that.
Imports System.Runtime.InteropServices
Public Class ComboBoxEx
Inherits ComboBox
Protected Overrides Sub OnHandleCreated(ByVal e As System.EventArgs)
MyBase.OnHandleCreated(e)
CenterText()
End Sub
Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
CenterText()
MyBase.OnTextChanged(e)
End Sub
Private Sub CenterText()
If Not Me.DropDownStyle = ComboBoxStyle.DropDownList Then
Dim hEdit As IntPtr = Apis.FindWindowExW(Me.Handle, IntPtr.Zero, "Edit", Nothing)
If Not hEdit = IntPtr.Zero Then
Dim textWidth As Integer = TextRenderer.MeasureText(Me.Text, Me.Font).Width
Dim rct As Apis.RECT
Apis.GetWindowRect(hEdit, rct)
Dim leftMargin As Integer = (rct.Width - textWidth) \ 2
Apis.SendMessageW(hEdit, Apis.EM_SETMARGINS, Apis.EC_LEFTMARGIN, leftMargin)
End If
End If
End Sub
End Class
Public Class Apis
<StructLayout(LayoutKind.Sequential)> _
Public Structure RECT
Public left, top, right, bottom As Integer
Public ReadOnly Property Width As Integer
Get
Return (Me.right - Me.left)
End Get
End Property
End Structure
Public Const EM_SETMARGINS As Integer = &HD3
Public Const EC_LEFTMARGIN As Integer = &H1
<DllImport("user32.dll", EntryPoint:="FindWindowExW")> _
Public Shared Function FindWindowExW(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr
End Function
<DllImport("user32.dll", EntryPoint:="GetWindowRect")> _
Public Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", EntryPoint:="SendMessageW")> _
Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer) As Integer
End Function
End Class
If you say it can`t be done then i`ll try it
Wednesday, March 20, 2019 2:56 AM
Hi Dear
The Above Code works for Center, but How can it be modify to Align Right Rather than Center? Please help Me
Friday, April 5, 2019 8:08 PM
Hi Dear
The Above Code works for Center, but How can it be modify to Align Right Rather than Center? Please help Me
You can simply remove the \ 2 from the end of the line in the CenterText Sub, the line below.
Dim leftMargin As Integer = (rct.Width - textWidth) \ 2
Or if you are interested, you could modify the sub so that you can pass a Left, Center, or Right horizontal alignment to it like the below example. Notice I added a TextAlign property to the ComboBoxEx class which can be used to set the text alignment.
Imports System.Runtime.InteropServices
Public Class Form1
Private Sub RadioButton1_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton1.CheckedChanged, RadioButton2.CheckedChanged, RadioButton3.CheckedChanged
Select Case True
Case RadioButton1.Checked
ComboBoxEx1.TextAlign = HorizontalAlignment.Left
Case RadioButton2.Checked
ComboBoxEx1.TextAlign = HorizontalAlignment.Center
Case RadioButton3.Checked
ComboBoxEx1.TextAlign = HorizontalAlignment.Right
End Select
End Sub
End Class
Public Class ComboBoxEx
Inherits ComboBox
Private _TextAlign As HorizontalAlignment = HorizontalAlignment.Left
Public Property TextAlign As HorizontalAlignment
Get
Return _TextAlign
End Get
Set(value As HorizontalAlignment)
If value <> _TextAlign Then
_TextAlign = value
SetTextAlignment(_TextAlign)
End If
End Set
End Property
Protected Overrides Sub OnHandleCreated(ByVal e As EventArgs)
MyBase.OnHandleCreated(e)
SetTextAlignment(TextAlign)
End Sub
Protected Overrides Sub OnTextChanged(ByVal e As EventArgs)
SetTextAlignment(TextAlign)
MyBase.OnTextChanged(e)
End Sub
Private Sub SetTextAlignment(alignment As HorizontalAlignment)
If Not Me.DropDownStyle = ComboBoxStyle.DropDownList Then
Dim hEdit As IntPtr = Apis.FindWindowExW(Me.Handle, IntPtr.Zero, "Edit", Nothing)
If Not hEdit = IntPtr.Zero Then
Dim textWidth As Integer = TextRenderer.MeasureText(Me.Text, Me.Font).Width
Dim rct As Apis.RECT
Apis.GetWindowRect(hEdit, rct)
Dim leftMargin As Integer = 0 '0 would be the Left alignment
If alignment = HorizontalAlignment.Center Then
leftMargin = (rct.Width - textWidth) \ 2
ElseIf alignment = HorizontalAlignment.Right Then
leftMargin = (rct.Width - textWidth)
End If
Apis.SendMessageW(hEdit, Apis.EM_SETMARGINS, Apis.EC_LEFTMARGIN, leftMargin)
End If
End If
End Sub
End Class
Public Class Apis
<StructLayout(LayoutKind.Sequential)>
Public Structure RECT
Public left, top, right, bottom As Integer
Public ReadOnly Property Width As Integer
Get
Return (Me.right - Me.left)
End Get
End Property
End Structure
Public Const EM_SETMARGINS As Integer = &HD3
Public Const EC_LEFTMARGIN As Integer = &H1
<DllImport("user32.dll", EntryPoint:="FindWindowExW")>
Public Shared Function FindWindowExW(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr
End Function
<DllImport("user32.dll", EntryPoint:="GetWindowRect")>
Public Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", EntryPoint:="SendMessageW")>
Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer) As Integer
End Function
End Class
Here is the example I posted above...
If you say it can`t be done then i`ll try it
Friday, April 5, 2019 8:49 PM | 1 vote
The Above Code works for Center, but How can it be modify to Align Right Rather than Center? Please help Me
For DropDown ComboBoxes, you can also just set the ES_RIGHT style to the Edit control
Friday, April 5, 2019 11:24 PM
For DropDown ComboBoxes, you can also just set the ES_RIGHT style to the Edit control
Yes that will work too. 8)
Just to let others know, it seems that you can only set the ES_LEFT, ES_CENTER, and ES_RIGHT styles just once when the control is created but, can not change them after that unless you dispose and then recreate a new ComboBox with the new style. Not sure if that was of any concern or not though.
So, if you plan on keeping the text right aligned all the time, this works. This example can be tested in a Form with 3 standard ComboBox controls on it. Again, they must all have their DropDownStyle property set to DropDown.
It may also be worth noting that the msdn documents recommend using the GetWindowLongPtr and SetWindowLongPtr functions to make your app compatible with 32 and 64 bit windows versions.
Also, I did not include the constant for the ES_LEFT style because, that is the default style and would not need to be set.
Imports System.Runtime.InteropServices
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
SetComboBoxTextAlignment(ComboBox2, ES_CENTER)
SetComboBoxTextAlignment(ComboBox3, ES_RIGHT)
End Sub
Private Sub SetComboBoxTextAlignment(cbx As ComboBox, txtalign As Integer)
Dim hEdit As IntPtr = FindWindowExW(cbx.Handle, IntPtr.Zero, "EDIT", Nothing)
Dim Style As Integer = GetWindowLongW(hEdit, GWL_STYLE)
SetWindowLongW(hEdit, GWL_STYLE, Style Or txtalign)
End Sub
Const ES_CENTER As Integer = &H1
Const ES_RIGHT As Integer = &H2
Const GWL_STYLE As Integer = -16
<DllImport("user32.dll", EntryPoint:="GetWindowLongW")>
Public Shared Function GetWindowLongW(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
End Function
<DllImport("user32.dll", EntryPoint:="SetWindowLongW")>
Public Shared Function SetWindowLongW(ByVal hWnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
End Function
<DllImport("user32.dll", EntryPoint:="FindWindowExW")>
Public Shared Function FindWindowExW(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr
End Function
End Class
If you say it can`t be done then i`ll try it