Pull to refresh

Windows Mobile: проблемы с фокусом в ImageButton

Reading time4 min
Views477
Всем доброго дня!

Проблема следующая: требуется элемент управления ImageButton для Windows Mobile Application, который совмещал бы поведение элементов управления Button и PictureBox.

Варианты ImageButton:
1. Использовать элемент управления Button. Проблема: отсутствие свойства Image как в WinForms аналога.
2. Использовать элемент управления PictureBox, который поддерживает событие OnClick. Проблема: PictureBox не поддерживает метод Focus (а также его наследники), Справедливости ради надо сказать, что программно можно вызвать этот метод, но визуально это никак не будет заметно. Кроме того, мы не можем переключаться с помощью таба между несколькими элементами управления типа PictureBox.
3. Унаследоваться от Button и попробовать реализовать свойство Image самостоятельно. Этим способом у меня не получилось добиться желаемого результата.
4. Унаследоваться от Control и реализовать свою логику отрисовки элемента управления, как это рекомендует делать Mictrosoft. Проблема: не прорисовывается рамка фокуса. Именно эту проблему мы и попробуем решить.


ImageButton от Microsoft


Microsoft предлагает унаследоваться от Control и реализовать всю логику отрисовки самостоятельно. Вот что получается (подаю с небольшими изменениями кода, сам элемент управления можно скачать отсюда):

public class ImageButton : Control
{
  public Image Image
  {
    get;
    set;
  }

  private Bitmap m_bmpOffscreen;

  public ImageButton()
  {
    this.Size = new Size(21, 21);
  }

  protected override void OnPaint(PaintEventArgs e)
  {
    try
    {

      if (this.Image != null)
      {
        Graphics gxOff; //Offscreen graphics

        if (m_bmpOffscreen == null) //Bitmap for doublebuffering
        {
          m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);
        }

        gxOff = Graphics.FromImage(m_bmpOffscreen);

        //gxOff.Clear(this.BackColor);
        //Draw some bitmap
        gxOff.DrawImage(this.Image, 0, 0, this.ClientRectangle, GraphicsUnit.Pixel);

        //Boundary rectangle
        Rectangle rc = this.ClientRectangle;
        rc.Width--;
        rc.Height--;

        //Draw boundary
        gxOff.DrawRectangle(new Pen((this.Focused) ? Color.Black : Color.Transparent), rc);

        //Draw from the memory bitmap
        e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);

        gxOff.Dispose();
      }
    }
    catch (Exception ex)
    {

    }
  }

  private Color BackgroundImageColor(Image image)
  {
    Bitmap bmp = new Bitmap(image);
    return bmp.GetPixel(0, 0);
  }

  protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
  {
  }

  protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
  {
  }

  protected override void OnPaintBackground(PaintEventArgs e)
  {
    //Do nothing
  }
}


* This source code was highlighted with Source Code Highlighter.


В оригинальном коде предлагается использовать double buffering, но у меня в такой реализации ImageButton притормаживает.

Рисуем рамку в фокусе


В принципе все работает, кроме одного - не прорисовывается рамка контрола в состоянии focused. Честно признаюсь - долго не мог найти решение. В итоге что получилось:

В методе OnPaint вместо:

gxOff.DrawRectangle(new Pen(Color.Transparent), rc);

* This source code was highlighted with Source Code Highlighter.


использовать:

gxOff.DrawRectangle(new Pen((this.Focused) ? Color.Black : Color.Transparent), rc);

* This source code was highlighted with Source Code Highlighter.


Также нужно переопределить методы OnGotFocus и OnLostFocus, где принудительно нужно вызвать метод Invalidate для перерисовки контрола:

protected override void OnGotFocus(EventArgs e)
{
  base.OnGotFocus(e);
  this.Invalidate();
}

protected override void OnLostFocus(EventArgs e)
{
  base.OnLostFocus(e);
  this.Invalidate();
}


* This source code was highlighted with Source Code Highlighter.


Таким образом в состоянии Focused будет рисоваться черная рамка, в противополодном случае - прозрачная. Цвет рамки можно задать любой. Конечно, это не родное поведение фокуса, но все же лучше, чем ничего.

P.S. Если есть другие варианты решения проблемы с фокусом, просьба поделиться.
Tags:
Hubs:
Total votes 2: ↑0 and ↓2-2
Comments0

Articles