Το παρακάτω παράδειγμα που σου στέλνω (κάλλιο αργά παρά ποτέ) είναι ένας από τους πάρα πολλούς τρόπους που μπορείς να το κάνεις.
Είναι ένα custom control το οποίο ζωγραφίζει τα νούμερα και μετά κάνωντας click απάνω σε κάποιο νούμερο ζωγραφίζει μία έλλειψη.
Χρησιμοποιεί το graphics object που δημιουργείται στην onpaint method του control.
Για να το δοκιμάσεις φτιάξε ένα winforms application, πρόσθεσε ένα custom control, ονόμασε το KinoControl και ρίξε τον παρακάτω κώδικα.
Μετά βάλε το control απάνω στην φόρμα και τρέξε την εφαρμογή σου. Αν θέλεις να αντικαταστήσεις τα νούμερα που βάζω απλά χρησιμοποίησε την DrawImage method του graphics object
και βάλε το δελτίο του kino αντί αυτών.
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace KinoUI
{
[ToolboxBitmap(typeof(DataGridView))]
public partial class KinoControl : Control
{
public KinoControl()
{
InitializeComponent();
_elements = new List<Element>(80);
// Γιά το bouble buffer
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
int count = 1;
for (int row = 0; row < 8; row++)
{
for (int column = 0; column < 10; column++)
{
Element element = new Element(row, column, count++.ToString());
_elements.Add(element);
}
}
}
private List<Element> _elements;
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
pe.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
foreach (Element element in _elements)
element.Draw(pe.Graphics);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left)
{
foreach (Element element in _elements)
{
if (element.rect.Contains(e.Location))
{
element.Mark = !element.Mark;
Invalidate(element.rect);
return;
}
}
}
}
private sealed class Element
{
public bool Mark = false;
public int Column, Row;
public Rectangle rect;
public string Text;
private static int _size;
private static Font _font;
static Element()
{
_size = 64;
_font = new Font("Arial", _size / 2, FontStyle.Bold, GraphicsUnit.Pixel);
}
public Element(int row, int column, string text)
{
Column = column;
Row = row;
Text = text;
}
public void Draw(Graphics graphics)
{
/*
https://msdn.microsoft.com/en-us/library/403ezxd2(v=vs.100).aspx
Remarks
--------------------------------------------------------------------------------
The MeasureString method is designed for use with individual strings and includes a small amount
of extra space before and after the string to allow for overhanging glyphs. Also, the DrawString
method adjusts glyph points to optimize display quality and might display a string narrower than reported by MeasureString.
To obtain metrics suitable for adjacent strings in layout(for example, when implementing formatted text),
use the MeasureCharacterRanges method or one of the MeasureString methods that takes a StringFormat,
and pass GenericTypographic. Also, ensure the TextRenderingHint for the Graphics is AntiAlias.
*/
SizeF size = graphics.MeasureString(Text, _font, new SizeF(_size, _size), StringFormat.GenericTypographic);
Brush textBrush = new SolidBrush(Color.FromArgb(255, 68, 137, 153));
rect = new Rectangle(Column * _size, Row * _size, _size, _size);
graphics.FillRectangle(new SolidBrush(Color.FromArgb(255, 5, 66, 94)), rect);
if (Mark)
{
GraphicsPath path = new GraphicsPath();
Rectangle inflateRect = Rectangle.Inflate(rect, -6, -12); // ζούπα το και κάντο έλλειψη
path.AddEllipse(inflateRect); // Βάλε το στο path.
PathGradientBrush pathGradientBrush = new PathGradientBrush(path)
{
CenterColor = Color.Yellow,
SurroundColors = new Color[] { Color.Orange },
FocusScales = new PointF(0.4f, 0.8f)
};
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.FillEllipse(pathGradientBrush, inflateRect);
graphics.SmoothingMode = SmoothingMode.None;
textBrush = Brushes.Black;
}
graphics.DrawString(Text, _font, textBrush,
Column * _size + (_size - size.Width) / 2,
Row * _size + (_size - size.Height) / 2,
StringFormat.GenericTypographic);
}
}
}
}