Проблемы с фокусом в WinMobile ImageButton

вторник, 11 августа 2009, Александр Краковецкий

Всем доброго дня!

Проблема следующая: требуется элемент управления 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 } }

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

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

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

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

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

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

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

Также нужно переопределить методы 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();
}

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

P.S. Если есть другие варианты решения проблемы с фокусом, просьба поделиться.

Компании из статьи


Microsoft Украина


Сайт:
http://www.microsoft.com/ukr/ua/

Microsoft Украина Украинское подразделение компании Microsoft.

Ищите нас в интернетах!

Комментарии

Свежие вакансии