1

Similar questions have been already asked (e.g., here), however I've not found an answer for my specific case. I'm building a custom control based on a DevExpress control, which in turns is based on standard TextBox and I've a flickering problem that seems due to the base TextBox component, which tries to update selection.

Without explaining all the details of my custom control, to reproduce the problem you just need to place a TextBox inside a Form and then use this code:

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        textBox1.MouseMove += TextBox1_MouseMove;
    }

    private void TextBox1_MouseMove(object sender, MouseEventArgs e) {
        (sender as TextBox).Text = DateTime.Now.Ticks.ToString();
    }
}

If you launch it, you click on the TextBox and then you move the cursor toward right you will notice the flickering problem (see video here). For my custom control I would need to avoid this flickering. I'm bound to use a TextBox (so no RichTextBox). Any idea?

Community
  • 1
  • 1
Mauro Ganswer
  • 1,379
  • 1
  • 19
  • 33
  • Do you want to avoid selection at all or do you want to allow selection but it should not flicker when the text changes? – René Vogt Feb 21 '17 at 13:27
  • I tried your example and there is no flickering after click. It should be other event override, can you share other events – kgzdev Feb 21 '17 at 13:28
  • From MSDN `Be careful when you write code for a MouseMove handler. MouseMove will frequently occur while the user is interacting with the application or with the specific object area that has the handler. Any computationally or graphically intensive code in a MouseMove handler can potentially introduce a noticeable lag in how the mouse pointer (or stylus pointer) draws and how the application generally behaves.` I'd say it's happening because it's updating multiple times during the mouse move. – Barry O'Kane Feb 21 '17 at 13:29
  • @IkramTurgunbaev the flickering occurs when you _select_ the text. Left-click in the textbox (and _keep the mouse button down_) and move over the text to select it. The blue selection color flickers as the text is changed by the mousemove-handler. – René Vogt Feb 21 '17 at 13:31
  • @RenéVogt yes you are right, thank you for clarifying – kgzdev Feb 21 '17 at 13:32
  • @RenéVogt I would like to avoid selection at all but of course to be able to restore it when needed – Mauro Ganswer Feb 21 '17 at 13:42
  • [Disable the selection highlight in RichTextBox or TextBox](http://stackoverflow.com/a/39592157/3110834) – Reza Aghaei Feb 21 '17 at 16:25
  • @RezaAghaei this works thanks! If you post it as an answer I'll mark it as the solution – Mauro Ganswer Feb 22 '17 at 11:04
  • @MauroGanswer You're welcome, Probably I'll post a `TextBox` version of the code in the [first link](http://stackoverflow.com/questions/13256720/disable-selecting-text-in-a-textbox) which you shared. Thanks for the feedback and and thanks for the kind offer. You have my vote :) – Reza Aghaei Feb 22 '17 at 11:11
  • @RezaAghaei ok please post your solution so I can link to that – Mauro Ganswer Feb 22 '17 at 12:11
  • [Here](http://stackoverflow.com/a/42391380/3110834) you can find the solution for `TextBox`. – Reza Aghaei Feb 22 '17 at 12:33

3 Answers3

1

The solution has been provided in the meantime by Reza Aghaei by overriding WndProc and intercepting WM_SETFOCUS messages. See here

Community
  • 1
  • 1
Mauro Ganswer
  • 1,379
  • 1
  • 19
  • 33
0

Depending on what u want to do there are several solutions:

If you want to prevent the selection it would be:

        private void TextBox1_MouseMove(object sender, MouseEventArgs e)
    {
        (sender as TextBox).Text = DateTime.Now.Ticks.ToString();
        (sender as TextBox).SelectionLength = 0;
    }

Or for selecting all:

        private void TextBox1_MouseMove(object sender, MouseEventArgs e)
    {
        (sender as TextBox).Text = DateTime.Now.Ticks.ToString();
        (sender as TextBox).SelectAll();
    }

And besides that u also could specify the conditions for selecting, for example:

        private void TextBox1_MouseMove(object sender, MouseEventArgs e)
    {
        (sender as TextBox).Text = DateTime.Now.Ticks.ToString();
        if (MouseButtons == MouseButtons.Left) (sender as TextBox).SelectAll();
        else (sender as TextBox).SelectionLength = 0;
    }

But as long as you want to select the text you always will get some flickering, because a normal Textbox has not the possibility to use things like BeginEdit and EndEdit and so it will change the text first and then select it.

AdrianS
  • 1
  • 2
  • I want to avoid selection as stated in my question and by doing this I want to avoid flickering. The first solution you provided (`(sender as TextBox).SelectionLength = 0;`) does not prevent flickering – Mauro Ganswer Feb 21 '17 at 16:20
0

Looking at the video it looks like your textbox is calling WM_ERASEBKGND unnecessarily. In order to remedy this problem you can subclass the textbox class and intercept these messages. Below is sample code which should do the trick (untested) Disclaimer: I have used this technique for other WinForm controls that had the type of flicker shown in your video but not TextBox. If it does work for you, please let me know. Good luck!

// textbox no flicker
public partial class TexttBoxNF : TextBox
{
    public TexttBoxNF()
    {
    }

    public TexttBoxNF(IContainer container)
    {
        container.Add(this);

        InitializeComponent();

        //Activate double buffering
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

        //Enable the OnNotifyMessage event so we get a chance to filter out 
        // Windows messages before they get to the form's WndProc
        this.SetStyle(ControlStyles.EnableNotifyMessage, true);
    }

    //http://stackoverflow.com/questions/442817/c-sharp-flickering-listview-on-update
    protected override void OnNotifyMessage(Message m)
    {
        //Filter out the WM_ERASEBKGND message
        if (m.Msg != 0x14)
        {
            base.OnNotifyMessage(m);
        }
    }
}
Dave S
  • 973
  • 9
  • 17
  • @MauroGanswer - What you can try to do is add some code i nthe OnNotifyMessage function that will either display or better yet, record the messages coming in. The messages of interest would be during the time you see the flicker. It may be that during this time you may need to filter out a different WM message. For your reference here are the list of WM msgs - https://wiki.winehq.org/List_Of_Windows_Messages – Dave S Feb 22 '17 at 11:19