1

it's been a while since I posted. Haven't had much time for programming for a while. Just got back into it a couple of days ago. I'm working on a personal project which is a kind of Project Manager with a fairly complete text editor. I am working with VB.NET in the Visual Studio IDE. I have been trying to mimic the behaviour of Word and other editors as follows:

FONT FAMILY: This code actually works to change the Font Family in the Font Picker Combo Box in real time according to text formatting at cursor position. i.e. click on different text formats in the Rich Text Box and the Font Family is displayed in the Combo Box! I am using a Tool Strip Combo Box!

BUG: The Font Family code (i.e. penultimate snippet) removes the formatting from text when it is reselected after formatting?

FONT SIZE: This code changes the Font Size in the Font Size Combo Box when Ctrl+Shift+< OR Ctrl+Shift+> keyboard shortcuts are used.

BUG: The Font Size code (i.e. Last snippet) affects Font Size when using the ,.<> keys because these keys are configured in the code to alter the value of the Font size in the Font Size ComboBox. So, pressing the keys causes the Font Size in the Combo Box to increase or decrease which also means the font in the RTB increases or decreases?!

WHAT I NEED: 1. Selecting formatted text should not remove formatting, but Font Family should be displayed in Combo Box according to formatting in the RTB. 2. The Font Size Combo Box value should only be altered when I use the keyboard shortcuts, Ctrl+Shift+< OR Ctrl+Shift+> to display the true Font Size in real time. Using the current code increments/reduces in steps of 2 rather than one Font Size at a time??? I realize this code is fairly simple and understand roughly why it's not working, but I can't seem to find a way to fix the issue? Any help would be greatly appreciated!

WHAT I HAVE TRIED

Rich Text Box (i.e. RTB = Description):

FONT FAMILY COMBO BOX CODE: (uses a timer)

Private Sub tbSelectFont_SelectedIndexChanged(sender As Object, e As EventArgs) Handles tbSelectFont.SelectedIndexChanged

        Dim NewFont As New Font(tbSelectFont.SelectedItem.ToString(),
                                Description.SelectionFont.Size,
                                Description.SelectionFont.Style)
        Description.SelectionFont = NewFont

    End Sub

FONT SIZE COMBO BOX CODE:

Private Sub tbSelectSize_SelectedIndexChanged(sender As Object, e As EventArgs) Handles tbSelectSize.SelectedIndexChanged

        Dim NewSize As Single = tbSelectSize.SelectedItem
        Dim NewFont As New Font(Description.SelectionFont.Name, NewSize, Description.SelectionFont.Style)
        Description.SelectionFont = NewFont

    End Sub

RELATED FORM LOAD EVENTS:

'Display Installed Fonts In Font Picker (tbSelectFont):

        Dim fonts As New InstalledFontCollection()
        For fntFamily As Integer = 0 To fonts.Families.Length - 1
            tbSelectFont.Items.Add(fonts.Families(fntFamily).Name)
        Next

        'Display Font Size in Font Size Picker:

        For fntSize = 10 To 75
            tbSelectSize.Items.Add(fntSize)
        Next

FONT FAMILY:

Private Sub Description_SelectionChanged(sender As Object, e As EventArgs) Handles Description.SelectionChanged

        If Description.SelectionFont IsNot Nothing Then

            Dim fontSize As Single = Description.SelectionFont.Size
            tbSelectSize.Text = fontSize

            tbSelectFont.Text = Description.SelectionFont.Name

        End If

End Sub

FONT SIZE:

If (Keys.Control AndAlso Keys.Shift AndAlso e.KeyCode = Keys.Oemcomma) Then

tbSelectSize.Text -= 1

ElseIf (Keys.Control AndAlso Keys.Shift AndAlso e.KeyCode = Keys.OemPeriod) Then

tbSelectSize.Text += 1

End If

OTHER CODE I TRIED:

THIS CODE WORKS, BUT WHEN YOU SELECT FORMATTED TEXT IT THROWS AN EXCEPTION OR REMOVES FORMATTING: System.NullReferenceException: 'Object reference not set to an instance of an object.' SOURCE: MY OWN COMMENT FROM: how to get the fontsize of a certain line in a richtextbox in c# using winforms

Dim fontName As String = Description.SelectionFont.Name
    Dim fontSize As Single = Description.SelectionFont.Size

    tbSelectFont.Text = fontName
    tbSelectSize.Text = fontSize

    tbSelectFont.SelectedIndex = tbSelectFont.FindStringExact(Description.SelectionFont.Name)

    tbSelectSize.SelectedIndex = tbSelectSize.FindStringExact(Description.SelectionFont.Size)

THIS CODE WORKS, BUT WHEN YOU SELECT FORMATTED TEXT IT THROWS AN EXCEPTION: System.NullReferenceException: 'Object reference not set to an instance of an object.' SOURCE: how to get the fontsize of a certain line in a richtextbox in c# using winforms - MarkusEgle's solution.

Dim comboBox1Index As Integer = tbSelectFont.FindStringExact(Description.SelectionFont.Name)
Dim comboBox2Index As Integer = tbSelectSize.FindStringExact(Description.SelectionFont.Size.ToString())
tbSelectFont.SelectedIndex = comboBox1Index
tbSelectSize.SelectedIndex = comboBox2Index
  • You need to orchestrate the events here and prevent the events loop somehow. An event code fires another event while the first one hasn't finished yet. A `Boolean` _halt_ class field for example will do. [Here's](https://stackoverflow.com/a/58789825/14171304) something to go. – dr.null Jun 23 '22 at 01:15
  • You should handle the `SelectionChangeCommitted` event of your ComboBox Controls, not `SelectedIndexChanged`. Call methods to change the Font of the current selection and to update the UI accordingly, don't try to generate cascading events, it will backfire in a way or another. -- The code that tries to modify the Font size is simply wrong, I suggest you set `Option Strict On` right away. You could have `if e.KeyData = (Keys.Control or Keys.Shift or Keys.Oemcomma) then ...`. You should store the hotkeys you handle and, in `KeyDown`, compare `e.KeyData` with the hotkeys (as a combined Key). – Jimi Jun 23 '22 at 02:07
  • Hey dr.null and Jimi thanks for your comments and help! It's getting late and your answers look like it will take some time to check things out and apply the code. Maybe I'll get to it tomorrow. I'll let you guys know how I get on and if I have any more questions. Thanks for the moment! Catch you tomorrow! – John Michael Wilkinson Jun 23 '22 at 02:18
  • As a note, not all Keyboards have the `<` and `>` symbols in the same keys as the comma and period. It could be `Keys.OemBackslash` in many countries in Europe, but also be `Keys.OemQuestion` (e.g., Dutch) and others. Only considering `QWERTY` / `AZERTY` standard layouts. – Jimi Jun 23 '22 at 02:32
  • dr.null created new project like your demo. mine doesn't work correctly? Font Family or Font Size combos change the whole text in RTB (similar to Notepad)? a few doubts: 1. Does "To populate the combo boxes" code go in the Form_Load event? 2. Your code starts with Text Box. Do you mean RichTextBox as per your Demo Gif? Your code changes to txtEditor? Is that the same as TextBox? 3. Placed variable: Private IsSelectionChanged As Boolean = False in Declarations section below Public Class Form1? 4. InstalledFontCollection requires following import: Imports System.Drawing.Text? – John Michael Wilkinson Jun 23 '22 at 16:21
  • Jimi I didn't find SelectionChangeCommitted in VS2019/VB.NET. Tried what you suggest in SelectedIndexChanged. It stops the issue I was having, but now the Font Size is no longer automatically shown in the Font Size combo? I found some new code above, but selecting formatted text throws an exception? – John Michael Wilkinson Jun 23 '22 at 20:23
  • You cannot possibly miss the `SelectionChangeCommitted` event in a ComboBox, it's been there since forever. Try again. -- Remember that you have to prefix a nickname with `@` to ping someone. – Jimi Jun 23 '22 at 21:10
  • hey @jimi, Properties = Sorted to alphabetic order and only see SelectedIndexChanged. Manually inserted SelectionChangeCommitted handler = BC30590: Event 'SelectionChangeCommitted' cannnot be found. I'm using VB.NET/Winforms. – John Michael Wilkinson Jun 23 '22 at 22:22
  • Are you using a ComboBox or a LIstBox? The latter has no `SelectionChangeCommited` event, of course, the former does. You said you have ComboBox Controls there, so you must have the event. Otherwise, be clear about the Controls you're describing here. – Jimi Jun 24 '22 at 02:07
  • @jimi in my post above I have stated that I'm using a Combo Box. However, just had a thought and checked the regular Combo and it has the event you mention. But, I'm using the ToolStripComboBox because I have a couple of Toolstrips in my editor. Sorry if I'm a bit rusty! Haven't been programming for quite a while! I'm still learning programming so if I'm not at the same level, please be patient! I have edited my post accordingly! – John Michael Wilkinson Jun 24 '22 at 14:29
  • All right. The underlying Control is still a ComboBox, the internal reference is returned by the `[ToolStripComboBox].ComboBox` property. So you can subscribe to the event as, e.g., `tbSelectSize.ComboBox.SelectionChangeCommitted += (o, _) => Console.WriteLine($"ToolStripComboBox Index: {(o as ComboBox)?.SelectedIndex}");` -- Here' using a Lambda for testing, but you should use a standard handler. – Jimi Jun 24 '22 at 15:14
  • hey @jimi thanks for your example! I'm sorry, but I don't understand how to use it? For example which handler should the code be placed in? Also, will writing the event to the Console cause the Combo to show the size of font at the cursor position? Won't this just pass a value to the Console? – John Michael Wilkinson Jun 24 '22 at 21:56

0 Answers0