14 Replies - 3487 Views - Last Post: 30 June 2020 - 10:12 AM Rate Topic: -----

#1 Dreamfall   User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 177
  • Joined: 26-January 15

ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 03 May 2016 - 06:53 AM

Hi Guys, after adding the class horizontal Scroll to a combobox with properties drawfixed, the text becomes unreadable when scrolling horizontal or vertical, only with the mouseover the text you update.

Can anyone help me understand the problem, it is as if not redraws the text while scrolling bar.. :no:/>/>/>

I posted the video example:
My Video

This post has been edited by Dreamfall: 03 May 2016 - 06:54 AM


Is This A Good Question/Topic? 0
  • +

Replies To: ComboBox in DrawMode Fixed... Items of Text Unreadable

#2 modi123_1   User is online

  • Suitor #2
  • member icon



Reputation: 15782
  • View blog
  • Posts: 63,260
  • Joined: 12-June 08

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 03 May 2016 - 06:58 AM

Why would you even have a horizontal scrolling combobox drop down?
Was This Post Helpful? 0
  • +
  • -

#3 Dreamfall   User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 177
  • Joined: 26-January 15

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 03 May 2016 - 07:37 AM

@modi123_1...I'm sorry but I do not understand your question, you can be more precise...
The horizontal scroll bar I added at a later date in order to scroll longer texts on the size of the combobox.
The combobox can not have a greater width to problems of space in the application.

This post has been edited by Dreamfall: 03 May 2016 - 07:40 AM

Was This Post Helpful? 0
  • +
  • -

#4 maceysoftware   User is offline

  • Member Title
  • member icon

Reputation: 395
  • View blog
  • Posts: 1,664
  • Joined: 07-September 13

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 03 May 2016 - 07:44 AM

I am in agreement with modi, I have no idea why you would want this however can you be more precious with your issue?

I am not clicking links at work, either upload a picture or clearly explain what you mean by unreadable. for example transforming valid text to wingdings would make it unreadable to me.
Was This Post Helpful? 0
  • +
  • -

#5 Dreamfall   User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 177
  • Joined: 26-January 15

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 03 May 2016 - 08:14 AM

View Postmaceysoftware, on 03 May 2016 - 07:44 AM, said:

I am not clicking links at work, either upload a picture or clearly explain what you mean by unreadable. for example transforming valid text to wingdings would make it unreadable to me.

I uploaded a video for be as clear possible, now I have to upload a photo with the problem? .... for those who have viewed the video I posted it have any ideas to fixing the problem... I can post the code of the addition of the bar horizontal, or drawItem event, you tell me. :huh2:
Was This Post Helpful? 0
  • +
  • -

#6 IronRazer   User is offline

  • Custom Control Freak
  • member icon

Reputation: 1544
  • View blog
  • Posts: 3,869
  • Joined: 01-February 13

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 03 May 2016 - 09:53 AM

It appears to me that the reason would be that the DrawItem event of the ComboBox is not being called to refresh the custom drawing. Unfortunately, there is not a simple method that can be called to cause the DropDown to repaint all of its Items. That will only happen when the mouse is moved over the top of one or more of the Items.

There may be a way using some Win32 Api functions but, i can`t say for sure at this time. I will need to look and see.

This post has been edited by IronRazer: 03 May 2016 - 09:55 AM

Was This Post Helpful? 0
  • +
  • -

#7 Dreamfall   User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 177
  • Joined: 26-January 15

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 03 May 2016 - 10:37 AM

Thank Razer for the answer is always a pleasure to hear your, I also think the same thing the problem and redraw the text while scrolling.

This is the class built to add horizontal scrolling:
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Windows.Forms

Namespace HorizontallyScrollingComboBox
    Partial Public Class ComboBox

        Inherits System.Windows.Forms.ComboBox

#Region "Private Member Declarations"
        Private Const CB_SETHORIZONTALEXTENT As Integer = &H15E
        Private Const WS_HSCROLL As Integer = &H100000
#End Region

#Region "Private Class Methods"
        <DllImport("user32.dll")> _
        Private Shared Function SendMessage(hWnd As IntPtr, msg As UInt32, wParam As IntPtr, lParam As IntPtr) As IntPtr
        End Function
#End Region

#Region "Public Methods"
        Public Sub SetHorizontalExtent()
            Dim MaxWith As Integer
            MaxWith = 0
            For Each item As Object In Me.Items
                Dim TextSize As Size
                TextSize = TextRenderer.MeasureText(item.ToString(), Me.Font)
                If TextSize.Width > MaxWith Then
                    MaxWith = TextSize.Width
                End If
            Next
            Me.SetHorizontalExtent(MaxWith)
        End Sub
        Public Sub SetHorizontalExtent(width As Integer)
            SendMessage(Me.Handle, CB_SETHORIZONTALEXTENT, New IntPtr(width), IntPtr.Zero)
        End Sub

#End Region

#Region "Protected Properties"
        Protected Overrides ReadOnly Property CreateParams() As CreateParams
            Get
                Dim Create_Params_1 As CreateParams
                Create_Params_1 = MyBase.CreateParams
                Create_Params_1.Style = Create_Params_1.Style Or WS_HSCROLL
                Return Create_Params_1
            End Get
        End Property

#End Region

    End Class

End Namespace




Activate horizontal scrolling using the event load:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ComboBox1.SetHorizontalExtent()
    End Sub



Finally redesigned the custom combobox via DrawItem Event:
    Private Sub ComboBox1_DrawItem(sender As Object, e As System.Windows.Forms.DrawItemEventArgs) Handles ComboBox1.DrawItem
        If e.Index < 0 Then Return
        e.DrawBackground()
        'Draw Item Text Using Multi-Colors
        Dim TheBrush As Brush
        Dim TheBackColor As Color = Color.Black
        Dim TheForeColor As Color = Color.Crimson
        Dim TextFont As Font = New Font("MS Reference Sans Serif", 7.4, FontStyle.Regular)
        If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then ' Mouse-Over Zoom Glass Effect
            TextFont = New Font("MS Reference Sans Serif", 8.25, FontStyle.Regular)
            TheBackColor = Color.Black
            TheForeColor = Color.Silver
        End If
        TheBrush = New SolidBrush(TheBackColor)
        e.Graphics.FillRectangle(TheBrush, e.Bounds)
        TheBrush = New SolidBrush(TheForeColor)
        e.Graphics.DrawString(ComboBox1.Items(e.Index).ToString, TextFont, TheBrush, New RectangleF(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height))
        e.DrawFocusRectangle()
        Me.ComboBox1.Cursor = Cursors.Hand
    End Sub



Last thing before you add the class "HorizontallyScrollingComboBox" in the combobox, the event DrawItem worked perfectly. <_</>

This post has been edited by Dreamfall: 03 May 2016 - 10:42 AM

Was This Post Helpful? 0
  • +
  • -

#8 IronRazer   User is offline

  • Custom Control Freak
  • member icon

Reputation: 1544
  • View blog
  • Posts: 3,869
  • Joined: 01-February 13

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 03 May 2016 - 12:07 PM

Well, as i said, there is not a method that you can call to make the DropDown repaint itself. The only way i see it happening is if you use some crazy hack job of some sort such as using a regular ComboBox with a separate ListBox.

You can custom draw the Items of the ListBox the same way you custom draw the Items of a ComboBox. However, a ListBox has a Horizontal ScrollBar already that will allow all the drawing to be done correctly when it is scrolled. You just need to use the DropDown event of the ComboBox to tell when to show the ListBox. Then use the ListBox`s Leave and SelectedIndexChanged events to tell when to hide the ListBox.

There is a method that you can use to get the DropDown rectangle of the ComboBox using the CB_GETDROPPEDCONTROLRECT message with the SendMessage Api function so that you can set the bounds of the ListBox to the same rectangle location and size before making it visible.

It would be quite a hack job but, if you really need the functionality of a horizontal scrollbar, then it wont matter which way you go about it, it will be a hack job. ComboBoxes just where not made for doing this.

The only other way i can think might work, not sure though, is to use the CB_GETCOMBOBOXINFO message with SendMessage to fill a COMBOBOXINFO structure. You can get the handle of the ComboBox`s DropDown from that and try using the RedrawWindow Api function with that handle to see if you can get it to repaint the DropDown window.
Was This Post Helpful? 0
  • +
  • -

#9 Dreamfall   User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 177
  • Joined: 26-January 15

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 03 May 2016 - 12:52 PM

Wo :w00t:/> oo Razer i comes only cry :fuck-8:/> ... it's too much of a mess do not think that I would be able :no:/>

EDIT...BRO...You gave me a great idea .... I dried her tears with the last roll of toilet paper left ... and I solved it. :bananaman:
It now stay just the way to adapt the combobox to listbox DrawItem...
You are great Razer. :^:

This post has been edited by Dreamfall: 03 May 2016 - 01:40 PM

Was This Post Helpful? 0
  • +
  • -

#10 IronRazer   User is offline

  • Custom Control Freak
  • member icon

Reputation: 1544
  • View blog
  • Posts: 3,869
  • Joined: 01-February 13

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 03 May 2016 - 02:18 PM

Well, i am glad it gave you an idea that helped. Anyways, i would really recommend changing the name of your ComboBox class because it is the name as the .Net ComboBox class and may very well cause some conflicts at some point.

Also, i have played around with the combobox class and got it working using the RedrawWindow Api function. However, you would need to use the same font that the ComboBox uses for all the items. That is because the part that measures the items to find the longest item text is using the ComboBox.Font. If you use different Fonts, that method has no way to get the accurate width of the items.

As far as redrawing the window, it needed to be done with a Timer in the combobox class because, the combobox will not receive a WM_HSCROLL (horizontal scroll) message. Even after setting the ComboBox to be DoubleBuffered, it does not make the DropDown window DoubleBuffered which makes it so that you will see some random flickering in the DropDown here and there when it redraws.

As i said, it will be somewhat of a hack job, it is just figuring out the most reliable hack job for it.

If you want, you can try this in a new form project. It is not perfect though as i said.

This is the ComboBoxEx class
Imports System.Runtime.InteropServices

Public Class ComboBoxEx
    Inherits System.Windows.Forms.ComboBox

    Private WithEvents Tmr As New Timer With {.Interval = 500}
    Private cbi As New tagCOMBOBOXINFO With {.cbSize = CUInt(Marshal.SizeOf(GetType(tagCOMBOBOXINFO)))}
    Private Const WS_HSCROLL As Integer = &H100000
    Private Const RDW_INVALIDATE As Integer = &H1
    Private Const RDW_UPDATENOW As Integer = &H100
    Private Const CB_SETHORIZONTALEXTENT As Integer = &H15E
    Private Const CB_ADDSTRING As Integer = &H143
    Private Const CB_DELETESTRING As Integer = &H144
    Private Const CB_INSERTSTRING As Integer = &H14A
    Private Const CB_RESETCONTENT As Integer = &H14B

    <StructLayout(LayoutKind.Sequential)>
    Private Structure tagCOMBOBOXINFO
        Public cbSize As UInteger
        Public rcItem As tagRECT
        Public rcButton As tagRECT
        Public stateButton As UInteger
        Public hwndCombo As IntPtr
        Public hwndItem As IntPtr
        Public hwndList As IntPtr
    End Structure

    <StructLayout(LayoutKind.Sequential)>
    Private Structure tagRECT
        Public left, top, right, bottom As Integer
    End Structure

    <DllImport("user32.dll", EntryPoint:="SendMessageW")>
    Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByRef lParam As UInteger) As Integer
    End Function

    <DllImport("user32.dll", EntryPoint:="GetComboBoxInfo")>
    Private Shared Function GetComboBoxInfo(ByVal hwndCombo As IntPtr, ByRef pcbi As tagCOMBOBOXINFO) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    <DllImport("user32.dll", EntryPoint:="RedrawWindow")>
    Private Shared Function RedrawWindow(ByVal hWnd As IntPtr, ByVal lprcUpdate As IntPtr, ByVal hrgnUpdate As IntPtr, ByVal flags As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    Protected Overrides ReadOnly Property CreateParams() As CreateParams
        Get
            Dim cp As CreateParams = MyBase.CreateParams
            cp.Style = (cp.Style Or WS_HSCROLL) 'add the Horizontal Scroll Style to the combobox when it is being created
            Return cp
        End Get
    End Property

    Protected Overrides Sub ondropDown(e As EventArgs)
        Tmr.Start() 'when the DropDown is opened, start the Timer which will keep redrawing the DropDown window
        MyBase.ondropDown(e)
    End Sub

    Protected Overrides Sub ondropDownClosed(e As EventArgs)
        Tmr.Stop() 'when the DropDown is closed, we can stop the Timer
        MyBase.ondropDownClosed(e)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)
        MyBase.WndProc(m)
        'Detect if any Items have been added or removed from the ComboBox so that you can reset the Horizontal Extent to the current longest Item
        If m.Msg = CB_ADDSTRING Or m.Msg = CB_DELETESTRING Or m.Msg = CB_INSERTSTRING Or m.Msg = CB_RESETCONTENT Then
            Dim MaxWith As Integer = 0
            For Each item As Object In Me.Items
                Dim TextSize As Size
                TextSize = TextRenderer.MeasureText(item.ToString(), Me.Font)
                If TextSize.Width > MaxWith Then
                    MaxWith = TextSize.Width
                End If
            Next
            SendMessageW(Me.Handle, CB_SETHORIZONTALEXTENT, MaxWith + (SystemInformation.VerticalScrollBarWidth * 3), 0)
        End If
    End Sub

    Protected Overrides Sub Dispose(disposing As Boolean)
        If Tmr IsNot Nothing Then Tmr.Dispose() 'when the Form is closed it will call the Dispose method of the ComboBox. When the combobox is Disposed, you need to Dispose the Timer
        MyBase.Dispose(disposing)
    End Sub

    Private Sub Tmr_Tick(sender As Object, e As EventArgs) Handles Tmr.Tick
        If GetComboBoxInfo(Me.Handle, cbi) Then 'if the comboboxinfo is successfully filled, then redraw the DropDown window
            RedrawWindow(cbi.hwndList, IntPtr.Zero, IntPtr.Zero, RDW_INVALIDATE Or RDW_UPDATENOW)
        End If
    End Sub
End Class



Here is an example of the Form`s code where all that is needed is to add some items, set the DrawMode, and handle the DrawItem event. The DrawItem event could be handled in the class too though if you wanted.

As a side note, you need to dispose of any new SolidBrushes and Fonts that you create in the DrawItem event or you will wind up with a kind of Memory Leak. I kind of redid your drawing event just to show a Using block that will dispose the new SolidBrush.
Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        With ComboBoxEx1
            .DrawMode = DrawMode.OwnerDrawFixed
            .Items.Add("abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz1234567890")
            .Items.Add("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz1234567890")
            .Items.Add("1234567890abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
        End With
    End Sub

    Private Sub CmbBox1_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ComboBoxEx1.DrawItem
        e.DrawBackground()
        If e.Index >= 0 Then
            Using TheBrush As New SolidBrush(Color.Crimson)
                If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
                    TheBrush.Color = Color.Silver
                End If
                e.Graphics.DrawString(ComboBoxEx1.Items(e.Index).ToString, e.Font, TheBrush, e.Bounds)
            End Using
        End If
    End Sub
End Class


This post has been edited by IronRazer: 03 May 2016 - 03:43 PM
Reason for edit:: Added some comments to the ComboBoxEx class

Was This Post Helpful? 1
  • +
  • -

#11 IronRazer   User is offline

  • Custom Control Freak
  • member icon

Reputation: 1544
  • View blog
  • Posts: 3,869
  • Joined: 01-February 13

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 03 May 2016 - 03:17 PM

Just so that you are aware, i edited my last post and updated the ComboBoxEx class code. I cleaned up a few things that i noticed after posting it. I also changed your SendMessage signature and used the GetComboBoxInfo Api function to fill the COMBOBOXINFO structure.

It still works the same but, is cleaned up a little. 8)
Was This Post Helpful? 0
  • +
  • -

#12 Dreamfall   User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 177
  • Joined: 26-January 15

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 04 May 2016 - 12:59 AM

Hi Razer, timer set to 1ms redrawing and fast enough but suffers from flickering, increasing the time of the timer decreases the flicker, but the time of the redrawing increased to much, and remains too apparent.
With my method, and thanks to your idea, I managed to get something fairly satisfactory.

Test:
LINK
Was This Post Helpful? 0
  • +
  • -

#13 GIS-Monkey   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 30-June 20

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 30 June 2020 - 09:53 AM

Hey guys, I appreciate this thread and think it might be the golden ticket to my problem. I have a bound combobox control that's bound to a list of file paths. I want to reformat those paths for display to something like "D:/.../<my filename>" to make them more intelligible to the user. And I'm running into the same problem where the entries in the dropdown won't refresh without a mouseover action. I'd like to implement the listbox solution IronRazor mentioned, but my API skills are quite a bit rusty in regard to my operating environment of c#.NET. Everything's going fine, but I can't quite acquire the reference to the dropdown rectangle from the lParam reference pointer of the SendMessage function. The problem seems to be converting from a pointer to an object reference. I feel that I'm so close but so far away. Any recommendations on moving forward here would be hugely appreciated!

View PostIronRazer, on 03 May 2016 - 12:07 PM, said:

There is a method that you can use to get the DropDown rectangle of the ComboBox using the CB_GETDROPPEDCONTROLRECT message with the SendMessage Api function so that you can set the bounds of the ListBox to the same rectangle location and size before making it visible.

Was This Post Helpful? 0
  • +
  • -

#14 modi123_1   User is online

  • Suitor #2
  • member icon



Reputation: 15782
  • View blog
  • Posts: 63,260
  • Joined: 12-June 08

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 30 June 2020 - 10:06 AM

@GIS-Monkey - good to hear the topic is helping!

You may want to start a new thread, reference this one, and post your relevant code and information on your problem.
Was This Post Helpful? 0
  • +
  • -

#15 GIS-Monkey   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 30-June 20

Re: ComboBox in DrawMode Fixed... Items of Text Unreadable

Posted 30 June 2020 - 10:12 AM

Thank you - will do.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1