2017-02-21 38 views
1

Аналогичные вопросы уже заданы (например, here), однако я не нашел ответа для своего конкретного случая. Я создаю настраиваемый элемент управления на основе элемента управления DevExpress, который по очереди основан на стандарте TextBox, и у меня есть мерцающая проблема, которая возникает из-за базового компонента TextBox, который пытается обновить выбор.Предотвращение выбора текста в TextBox

Не объясняя все детали моего пользовательского элемента управления, чтобы воспроизвести проблему нужно просто поместить TextBox внутри Form, а затем использовать этот код:

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(); 
    } 
} 

Если вы запустите его, вы нажимаете на TextBox, а затем вы перемещаете курсор вправо, вы заметите мерцающую проблему (см. Видео here). Для моего пользовательского контроля мне нужно было бы избежать этого мерцания. Я обязан использовать TextBox (так нет RichTextBox). Есть идеи?

+0

Вы хотите, чтобы избежать выбора вообще или вы хотите разрешить выбор, но он не должен мерцать при изменении текста? –

+0

Я попробовал ваш пример, и после щелчка не мерцает. Это должно быть другое переопределение события, вы можете делиться другими событиями –

+0

Из MSDN 'Будьте осторожны, когда вы пишете код для обработчика MouseMove. MouseMove будет часто возникать, когда пользователь взаимодействует с приложением или с конкретной областью объекта, которая имеет обработчик. Любой вычислительный или графически интенсивный код в обработчике MouseMove может потенциально представить заметное отставание в том, как рисует указатель мыши (или указатель стилуса) и как обычно работает приложение. «Я бы сказал, что это происходит, потому что он обновляется несколько раз во время перемещения мыши , –

ответ

1

Решение было предоставлено в то же время Реза Aghaei переопределив WndProc и перехватывать WM_SETFOCUS сообщений. См. here

0

В зависимости от того, что и хотят сделать, есть несколько решений:

Если вы хотите, чтобы предотвратить выделение было бы:

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

Или для выбора всех:

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

И кроме того, вы также можете указать условия для выбора, например:

 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; 
    } 

Но пока вы хотите выбрать текст, вы всегда будете мерцать, потому что в обычном текстовом поле нет возможности использовать такие вещи, как BeginEdit и EndEdit, и поэтому он сначала изменит текст, а затем выберет его.

+0

Я хочу избежать выбора, как указано в моем вопросе, и, делая это, я хочу избежать мерцания. Первое решение, которое вы предоставили ('(отправитель как TextBox) .SelectionLength = 0;'), не мешает мерцанию –

0

Глядя на видео, похоже, что ваше текстовое поле без необходимости вызывает WM_ERASEBKGND. Чтобы исправить эту проблему, вы можете подклассифицировать класс текстового поля и перехватить эти сообщения. Ниже приведен пример кода, который должен сделать трюк (untested). Отказ от ответственности: я использовал эту технику для других элементов управления WinForm, у которых был тип мерцания, показанный в вашем видео, но не TextBox. Если это сработает для вас, пожалуйста, дайте мне знать. Удачи!

// 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); 
     } 
    } 
} 
+0

Я пробовал ваше решение, но не работает –

+0

@MauroGanswer - Что вы можете попробовать сделать, это добавить код inthe OnNotifyMessage function которые будут либо отображаться, либо еще лучше, записывать входящие сообщения. Сообщения, представляющие интерес, будут отображаться во время мигания. Возможно, в это время вам может понадобиться отфильтровать другое сообщение WM. Для справки: список WM-сообщений - https://wiki.winehq.org/List_Of_Windows_Messages –