2015-05-18 3 views
0

Я занимаюсь этим весь день, (вперед и смеюсь), и я не вижу никаких решений старой возрастной проблемы Форм мерцающих элементов управления. Мое управление - TabControl, и я использую DrawMode OwnerDrawFixed. Я подключаю следующие события. Короче, я создаю TabControl с закрывающимися кнопками «X», которые представляют собой ресурсы 12x12 png. Кнопки закрытия все серые, но если я наведите курсор на один, он должен использовать другое изображение (красный X).Мерцающая вкладка Управление с помощью мыши. Определение того, что рисовать

  1. MouseDown: Контуры всего TabPages и проверяет, если я нажал на прямоугольнике, где я рисую мою кнопку закрытия изображения.

  2. MouseLeave: Мне нужно Invalidate, когда я оставляю TabControl, чтобы убедиться, что все правильно

  3. MouseMove обнажен Loops все TabPages и проверяет, является ли я наведении мышки на прямоугольнике, где я рисую моя кнопка закрытия изображения. Если я замалчиваю, я сохраняю индекс вкладки, чтобы моя краска могла изменить изображение, используемое для кнопки закрытия.

  4. DrawItem: Здесь я просто нарисовать изображение

вещи я испытал, но не повезло ...

  1. Создание свой собственный класс TabControl, который наследует TabControl и в конструктор I SetStyles для OptimizedDoubleBuffering To true (я установил другие флаги, соответствующие true)

  2. Я попытался переопределить CreateParams, чтобы я мог или нет v alue ... createParams.ExStyle | = 0x00000020; (Я понятия не имею, что это, но читать пользователь не предложил сделать это.

  3. Настройка формы DoubleBuffered (ничего не делает)

В любом случае, я не могу думать, что делать, и я прочитать об этом на некоторое время.

Вот мой код для всех событий. Я просто хочу, чтобы иметь близкие кнопки на моих закладках, которые получают подсвечивается, когда я мыши над ними. Спасибо.

private int mousedOver = -1;//indicates which close button is moused over 
    private void tabControl_DrawItem(object sender, DrawItemEventArgs e) 
    { 
     e.Graphics.DrawImage(e.Index == mousedOver ? Resources.redX : Resources.grayX, e.Bounds.Right - 15, e.Bounds.Top + 4); 
    } 
    private void tabControl_MouseDown(object sender, MouseEventArgs e) 
    { 
     TabControl tc = sender as TabControl; 
     if (tc.TabCount == 1) return; 

     for (int i = 0; i < tc.TabPages.Count; i++) 
     { 
      Rectangle r = tc.GetTabRect(i); 
      Rectangle closeButton = new Rectangle(r.Right - 15, r.Top + 4, 12, 12); 
      if (closeButton.Contains(e.Location)) 
      { 
       TabPage tp = tc.TabPages[i]; 
       tc.TabPages.Remove(tp); 
       tp.Dispose(); 
       break; 
      } 
     } 
    } 
    private void tabControl_MouseMove(object sender, MouseEventArgs e) 
    { 
     TabControl tc = sender as TabControl; 
     for (int i = 0; i < tc.TabPages.Count; i++) 
     { 
      Rectangle r = tc.GetTabRect(i); 
      Rectangle closeButton = new Rectangle(r.Right - 15, r.Top + 4, 12, 12); 
      if (closeButton.Contains(e.Location)) 
      { 
       mousedOver = i; 
       tc.Invalidate(); 
       return; 
      } 
     } 

     mousedOver = -1; 
     tc.Invalidate(); 
    } 
    private void tabControl_MouseLeave(object sender, EventArgs e) 
    { 
     TabControl tc = sender as TabControl; 
     mousedOver = -1; 
     tc.Invalidate(); 
    } 
+0

Попробуйте создать массив или Список всех этих прямоугольников 'CloseButton' и заполнить их во время последнего события« Загрузка »для формы. (Извините, я забыл заказ).Таким образом, вы не выполняете всю эту математику во время каждого события move/click. Обычно это не так много обработки, но во время события перемещения оно действительно накапливается и вызывает зависание потока пользовательского интерфейса. – krillgar

+0

Вы также должны реорганизовать свой код, чтобы вы не повторялись так часто. Большая часть вашего кода между двумя вашими событиями одинакова. – krillgar

+2

Практика лучших практик теперь, так что, когда вы разрабатываете настоящий проект, лучший код приходит естественным путем. – krillgar

ответ

0

Это похоже на то, что вы слишком часто недействительны. Попробуйте ее фильтрацию, так что вы только аннулируете его, когда необходимо управлению, чтобы быть повторно окрашено:

private void tabControl_MouseMove(object sender, MouseEventArgs e) { 
    TabControl tc = sender as TabControl; 
    for (int i = 0; i < tc.TabPages.Count; i++) { 
    Rectangle r = tc.GetTabRect(i); 
    Rectangle closeButton = new Rectangle(r.Right - 15, r.Top + 4, 12, 12); 
    if (closeButton.Contains(e.Location)) { 
     if (mousedOver != i) { 
     mousedOver = i; 
     tc.Invalidate(r); 
     } 
    } else if (mousedOver == i) { 
     int oldMouse = mousedOver; 
     mousedOver = -1; 
     tc.Invalidate(tc.GetTabRect(oldMouse)); 
    } 
    } 
} 

Я хотел бы сохранить переопределение CreateParams, но в качестве контроля нативных окон, вы можете, вероятно, никогда полностью устранить некоторое мерцание.

0

Можно также попробовать установить свойство DoubleBuffered элемента управления, делая

Control.DoubleBuffered = true; 

Я знаю, что это работает с DataGridViews, ListViews, форм и панелей.

Документация можно найти на MSDN.

Смежные вопросы