Image RotateFlip only working when called directly - c#

I have a class for my sprites like so:
public class Sprite : System.ICloneable
{
public Image SpriteImage { get; private set; }
public Image SpriteMask { get; private set; }
public Sprite(Image img, Image maskImg = null)
{
this.SetImage(img, maskImg);
}
public void SetImage(Image img, Image maskImg = null)
{
this.SpriteImage = new Bitmap(img,img.Width,img.Height);
if (maskImg != null)
{
this.SpriteMask = new Bitmap(maskImg, maskImg.Width, maskImg.Height);
}
else
{
this.SpriteMask = this.SpriteImage;
}
}
public virtual object Clone()
{
return new Sprite(this.SpriteImage,this.SpriteMask);
}
public void FlipHorizontally()
{
this.SpriteImage.RotateFlip(RotateFlipType.RotateNoneFlipX);
this.SpriteMask.RotateFlip(RotateFlipType.RotateNoneFlipX);
}
public void FlipVertically()
{
this.SpriteImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
this.SpriteMask.RotateFlip(RotateFlipType.RotateNoneFlipY);
}
}
since I have SpriteMask and SpriteImage I created a function to rotate them both without hassle. In another class I have:
public void ChangeDirection(bool facingRight)
{
if (facingRight != this.FacingRight)
{
for(int i = 0; i < this.Sprites.Count; i++)
{
this.Sprites[i].FlipHorizontally();
}
foreach (Weapon weapon in this.CollectedWeapons)
{
weapon.ChangeDirection(facingRight);
}
this.FacingRight = facingRight;
}
}
this.Sprites is List<Sprite> Sprites;. Now when this code is ran, the sprites to not flip, but if I change sprite.FlipHorizontally to this.Sprites[i].SpriteImage.RotateFlip(RotateFlipType.RotateNoneFlipX); it works fine. Why is this?

In your Sprite constructor you allow the sprite mask argument to be null. If it is null, look at what you do :
if (maskImg != null)
{
this.SpriteMask = new Bitmap(maskImg, maskImg.Width, maskImg.Height);
}
else
{
this.SpriteMask = this.SpriteImage;
}
You set SpriteMask to SpriteImage - since an image is a reference type you are only assigning the reference. There is still only one Image object but both variables are pointing to it. When you call :
public void FlipHorizontally()
{
this.SpriteImage.RotateFlip(RotateFlipType.RotateNoneFlipX);
this.SpriteMask.RotateFlip(RotateFlipType.RotateNoneFlipX);
}
...since SpriteImage and SpriteMask are the same object, you are flipping the image and then flipping it back again. What you might consider is making a copy of the sprite image for the mask if the mask is not provided :
if (maskImg != null)
{
this.SpriteMask = new Bitmap(maskImg, maskImg.Width, maskImg.Height);
}
else
{
this.SpriteMask = new Bitmap(this.SpriteImage);
}

Related

I have an int[] member in a class that reassings value to every instance of the class with each new declaration

I have a class for saving interactions in a game, when a person reacts takes values from the status of the game to create a new instance of this class, then send it, this is fine, the problem is when I try to get the value at the end of the level, then every instance of the class has the same value for that property with coincides with the last object declared of that class
public class reactionOrOmission
{
public bool reacted
{
get { return _reacted; }
set { _reacted = value; }
}
public float reactionTime
{
get { return _reactionTime; }
set { _reactionTime = value; }
}
public bool correct
{
get { return _correct; }
set { _correct = value; }
}
public int[] flagType
{
get { return _flagType; }
set { _flagType = value; }
}
public float generalTime
{
get { return _generalTime; }
set { _generalTime = value; }
}
public string focus
{
get
{
return _focus != null ? _focus : "non_focusable";
}
set { _focus = value; }
}
private bool _reacted;
private float _reactionTime;
private bool _correct;
private int[] _flagType;
private float _generalTime;
private string _focus;
public reactionOrOmission(bool Reacted, float ReactionTime, bool Correct, int[] FlagType, float GeneralTime)
{
reacted = Reacted;
reactionTime = ReactionTime;
correct = Correct;
flagType = FlagType;
generalTime = GeneralTime;
if (Tobii.Gaming.TobiiAPI.GetFocusedObject() == null)
{
focus = "non_focusable";
}
else
{
///nonimportant///
}
}
}
Thought it may have been something relating to an integer array but i have tried arrayList and list and the same happens.
I think your class is correct but you use incorrect instances or maybe incorrect usage after create instances...I ran your class and set 4 different instance , each instance has different values.
so your usage of class is incorrect!

Issue with the MapElements for UWP Maps control

The funny thing is stack gives me a warning saying "questions with a matching tittle have been closed for being too broad", So I'll try to keep it on point.
What is the issue:
On my map control, I am adding a polyline (maybe 3, depending upon
response from server).
Now when I add MapIcons or any MapElement or a MapItemsControl (basically anything) it doesn't show up. After debugging, I found out even though the MyMap.MapElements.Add(myMapIcon); runs perfectly, the MyMap.MapElements.Count only shows the polyline(s). Only the polyline is added.
So I removed my Polyline and guess what all the above mentioned components they all are added to the MapControl and are visible.
I dug a little deeper and found out that each time I call my MyMap.MapElements.Add(myMapIcon) it calls to add the already added polyline as polylines are added via attached properties and binding.
My Code:
My Polyline creator attached class:
public class PolylineCollection
{
public static readonly DependencyProperty PathDataCollectionProperty =
DependencyProperty.Register("PathDataCollection", typeof(ObservableCollection<IPolylinePath>), typeof(PolylineCollection), new PropertyMetadata(null, OnPathCollectionChanged));
public static void SetPathCollection(UIElement element, ObservableCollection<IPolylinePath> value)
{
element.SetValue(PathDataCollectionProperty, value);
}
public static ObservableCollection<IPolylinePath> GetPathCollection(UIElement element)
{
return (ObservableCollection<IPolylinePath>)element.GetValue(PathDataCollectionProperty);
}
private static void OnPathCollectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e?.NewValue != null)
{
if (e.NewValue is IEnumerable<IPolylinePath> polylineCollection)
{
var mapControl = d as MapControl;
if (mapControl == null)
{
throw new InvalidOperationException(
"Polyline.Track property can only be attached to a MapControl!");
}
mapControl.MapElements.Clear();
foreach (var polyline in GetPathCollection(mapControl))
{
mapControl.MapElements.Add(CreateMapPolyline(polyline));
}
}
}
}
private static MapPolyline CreateMapPolyline(IPolylinePath track)
{
var polyline = new MapPolyline()
{
StrokeColor = track.PolylineColor.Color,
StrokeThickness = track.PolylineThinkness,
StrokeDashed = false,
Path = track.PolylineGeopath,
};
if (track.PolylineColorMode == Enums.PolylineColorMode.Selected)
polyline.ZIndex = 5;
else
polyline.ZIndex = 1;
return polyline;
}
The PolylineColorMode is a quick enum to help me find out which polyline is selected and perform operations please ignore it.
My XAML:
<maps:MapControl x:Name="MyMap" extentions:PolylineCollection.PathCollection="{x:Bind ViewModel.PolylinePoints,Mode=OneWay}">
Where the extentions is a namespace where the above class (polylineCollection) resides.
The CodeBehind:
MapIcon errorIcon = new MapIcon()
{
Location = ViewModel.CurrentDriftLocation,
NormalizedAnchorPoint = new Windows.Foundation.Point(0.5, 1.0),
Title = "Drifted",
ZIndex = 3,
Image = Windows.Storage.Streams.RandomAccessStreamReference.CreateFromUri(new System.Uri("ms-appx:///SharedAssets/ErrorAnalysysAssets/DriftPoint.png"))
};
MyMap.MapElements.Add(errorIcon);
The ViewModelBacking property For Polyline
private ObservableCollection<Extentions.Map.Extentions.IPolylinePath> polylinePoints;
public ObservableCollection<Extentions.Map.Extentions.IPolylinePath> PolylinePoints
{
get { return polylinePoints; }
set { polylinePoints = value; RaisePropertyChanged(nameof(PolylinePoints)); }
}
The IPolylinePath
public interface IPolylinePath
{
SolidColorBrush PolylineColor { get; }
int PolylineThinkness { get; set; }
string PolylineTag { get; set; }
IEnumerable<BasicGeoposition> PolylinePoints { get; set; }
Geopath PolylineGeopath { get; }
PolylineColorMode PolylineColorMode { get; set; }
}
Can anyone tell me why does this happen? or how can I handle it so that my mapControl can show other elements as well?

Class for controlling properties of the PictureBox (C# forms)

I am trying to write something along of a "clean" code... I want to make a Pong game, for now based on Forms.
I want to divide the game nicely into classes.
I want to have a ball class, AI that inherits from player class, I want to use the premade Form class for setting main Form properties (width etc).
I made a player class as such and I would like to ask you if the approach for naming, getters and setters and the general idea is correct. Isn't certain bits (if not all of it) rather redundant or badly written, I do not want to base entire "project" on bad assumptions and multiply the same mistakes all over the code.
namespace Pong
{
public class Player
{
protected PictureBox PaddleBox { get; set; }
protected Size PlayerSize
{
get
{
return PlayerSize;
}
set
{
if (PlayerSize.Height > 0 && PlayerSize.Width > 0)
{
PlayerSize = new Size(value.Width, value.Height);
PaddleBox.Size = PlayerSize;
}
}
}
protected Point Location
{
get
{
return Location;
}
set
{
PaddleBox.Location = new Point(value.X, value.Y);
}
}
protected Color BackColor
{
get
{
return BackColor;
}
set
{
PaddleBox.BackColor = value;
}
}
public Player()
{
PaddleBox = new PictureBox();
}
}
}
FORM class looks something along of this for now, maybe I should pass parameters such as size,location and color in the constructor? What is the best?
namespace Pong
{
public partial class Form1 : Form
{
public Timer gameTime;
const int screenWidth = 1248;
const int screenHeight = 720;
public Form1()
{
InitializeComponent();
this.Height= screenHeight;
this.Width=screenWidth;
this.StartPosition=FormStartPosition.CenterScreen;
Player player = new Player();
player.PaddleBox.Size = new Size(20, 50);
player.PaddleBox.Location = new Point(player.PaddleBox.Width / 2, ClientSize.Height/2-player.PaddleBox.Height/2);
player.PaddleBox.BackColor = Color.Blue;
this.Controls.Add(player.PaddleBox);
gameTime = new Timer();
gameTime.Enabled = true;
}
void gameTime_Tick(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
You got an issue here:
protected Point Location
{
get
{
return Location; // <--- this is a circular reference..
// meaning, it will recall this getter again.
}
set
{
PaddleBox.Location = new Point(value.X, value.Y);
}
}
use this instead:
protected Point Location
{
get
{
return PaddleBox.Location;
}
set
{
PaddleBox.Location = value;
}
}
Same with protected Color BackColor
Here is an example, how I would implement it (in your current programming style (powered by notepad))
namespace Pong
{
public partial class Form1 : Form
{
public Timer gameTime;
const int screenWidth = 1248;
const int screenHeight = 720;
public Form1()
{
InitializeComponent();
this.Height= screenHeight;
this.Width=screenWidth;
this.StartPosition=FormStartPosition.CenterScreen;
Player player = new Player(this);
player.PlayerSize = new Size(20, 50);
player.Location = new Point(player.PaddleBox.Width / 2, ClientSize.Height/2-player.PaddleBox.Height/2); // <-- the location is always the upperleft point. don't do this...
player.BackColor = Color.Blue;
gameTime = new Timer();
gameTime.Enabled = true;
}
private void gameTime_Tick(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
public class Player
{
private PictureBox _paddleBox;
protected Size PlayerSize
{
get
{
return _paddleBox.Size;
}
set
{
if (PlayerSize.Height == 0 || PlayerSize.Width == 0)
throw new ArgumentException("Size must be greater than 0");
_paddleBox.Size = value;
}
}
protected Point Location
{
get { return PaddleBox.Location; }
set { PaddleBox.Location = value; }
}
protected Color BackColor
{
get { return PaddleBox.BackColor; }
set { PaddleBox.BackColor = value; }
}
public Player(Form form)
{
PaddleBox = new PictureBox();
form.Controls.Add(PaddleBox);
}
}
}
You should try to isolate the picturebox in your player class, this will separate the functionality of the form and the picturebox...

How can I access methods within a UserControl that is stored in a System.Collections.CollectionBase?

I created a UserControl that has a FlowLayoutPanel on it. I populate this panel in runtime with a CollectionBase of PictureBoxes. I then have a FlowLayoutPanel on my WindowsForm that I populate in runtime using a CollectionBase of my UserControls.
Now, I want to be able to access a custom function within my UserControl in order to add another PictureBox to an instanciated (existing) UserControl's FlowLayoutPanel. How do I access the function to do this?
The function is public within the UserControl but I am unable to get through the CollectionBase in order to use it.
Here is my code for the UserControl:
public partial class UserDisplay : UserControl
{
public UserDisplay()
{
InitializeComponent();
myEquipArray = new ImageArray(flpnlTools);
}
public void AddEquip(string EquipName, Image EquipImage)
{
myEquipArray.AddNewEquip(EquipName, EquipImage);
}
//Accessor
public ControlCollection Equips
{
get
{
return flpnlEquips.Controls;
}
}
}
public class ImageArray : System.Collections.CollectionBase
{
private readonly System.Windows.Forms.FlowLayoutPanel HostPanel;
public ImageArray(FlowLayoutPanel hostPanel)
{
HostPanel = hostPanel;
}
public System.Windows.Forms.PictureBox AddNewEquip(string EquipName, Image EquipImage)
{
PictureBox pbA = new PictureBox();
this.List.Add(pbA);
HostPanel.Controls.Add(pbA);
pbA.Tag = EquipName;
pbA.Image = EquipImage;
return pbA;
}
public void RemoveEquip(string EquipName)
{
if (this.Count > 0)
{
int i = 0;
while (EquipName != HostPanel.Controls[i].Tag.ToString())
{
i++;
}
HostPanel.Controls.Remove(this[EquipName]);
this.List.RemoveAt(i);
}
}
public PictureBox this[string EquipName]
{
get
{
int i = 0;
while (EquipName != HostPanel.Controls[i].Tag.ToString())
{
i++;
}
return (PictureBox)this.List[i];
}
}
}
I use this Class to implement the UserConrol on my WindowsForm:
public class UserDsp : System.Collections.CollectionBase
{
private readonly System.Windows.Forms.FlowLayoutPanel HostPanel;
public DisplayControl.UserDisplay AddNewUser(Int64 UserID, string UserName, Image UserImage, string EquipName, Image EquipImage)
{
DisplayControl.UserDisplay newUser = new DisplayControl.UserDisplay();
this.List.Add(newUser);
HostPanel.Controls.Add(newUser);
newUser.Tag = UserID;
newUser.UserName = UserName;
newUser.UserImage = UserImage;
newUser.AddEquip(EquipName, EquipImage); //THIS ADDS THE PICTUREBOX CORRECTLY
return newUser;
}
public void AddNewEquip(Int64 UserID, Int64 EquipID, string EquipName, Image EquipImage)
{
if (this.Count > 0)
{
int i = 0;
while (UserID != Convert.ToInt64(HostPanel.Controls[i].Tag))
{
i++;
}
// Found the Control with UserID
HostPanel.Controls[i].AddEquip(EquipName, EquipImage); //THIS DOES NOT WORK
}
}
public UserDsp(System.Windows.Forms.FlowLayoutPanel hostPanel)
{
HostPanel = hostPanel;
}
public void RemoveUser(Int64 UserID)
{
if (this.Count > 0)
{
int i = 0;
while (UserID != Convert.ToInt64(HostPanel.Controls[i].Tag))
{
i++;
}
HostPanel.Controls.Remove(this[UserID]);
this.List.RemoveAt(i);
}
UsersLogdIn.Remove(UserID);
}
public DisplayControl.UserDisplay this[Int64 UserID]
{
get
{
int i = 0;
while (UserID != Convert.ToInt64(HostPanel.Controls[i].Tag))
{
i++;
}
return (DisplayControl.UserDisplay)this.List[i];
}
}
public List<long> usersLogdIn
{
get
{
return UsersLogdIn;
}
}
}
}
In this code I can create a new PictureBox in the Control's FlowLayoutPanel when instantiating the Control:
newUser.AddEquip(EquipName, EquipImage); //THIS ADDS THE PICTUREBOX CORRECTLY
But when I try to access it through the CollectionBase:
public void AddNewEquip(Int64 UserID, Int64 EquipID, string EquipName, Image EquipImage)
{
if (this.Count > 0)
{
int i = 0;
while (UserID != Convert.ToInt64(HostPanel.Controls[i].Tag))
{
i++;
}
// Found the Control with UserID
HostPanel.Controls[i].AddEquip(EquipName, EquipImage); //THIS DOES NOT WORK
}
}
I also tried to pull the control out like this:
public void AddNewEquip(Int64 UserID, Int64 EquipID, string EquipName, Image EquipImage)
{
if (this.Count > 0)
{
int i = 0;
while (UserID != Convert.ToInt64(HostPanel.Controls[i].Tag))
{
i++;
}
// Found the Control with UserID
UserDisplay newUserDisplay = HostPanel.Controls[i] as UserDisplay //THIS DOES NOT WORK
}
}
I have looked everywhere for help on this but have not found anything related. Please Help!
Thank you.
I figured it out with some outside help.
Basically I need to typecast the control as UserDisplay. I don't know why it didn't work when I pulled it out using:
UserDisplay newUserDisplay = HostPanel.Controls[i] as UserDisplay
but I used this code instead:
(HostPanel.Controls[i] as UserDisplay).AddEquip(EquipName, EquipImage);
I did make sure that the control was the correct type before I declared it so this way:
if (HostPanel.Controls[i] is UserDisplay)
Thanks for the help.

How to include an animated gif in a DataGridView?

I have included an animated gif in a DataGridView, but the image is shown static. Is it possible?
I implemented a DataGridViewImageAnimator class that takes care of the gif images' animations for any DataGridView. Instances of DataGridViewImageAnimator monitor a given DataGridView and animate any gif image displayed in it. You may download the source code from https://docs.google.com/open?id=0B1r6und31C6BQXktM2VQN1Jza2c
You can create an animator in the form that includes a DataGridView as follows:
public partial class YourForm : Form
{
private DataGridViewImageAnimator dataGridImageAnimator;
public YourForm()
{
InitializeComponent();
dataGridImageAnimator = new DataGridViewImageAnimator(dataGridView1);
}
// ...
}
Alternatively, you can use a DataGridView-derived class that already does this in its constructor, as it's shown below for the AnimatedDataGridView class below (code available at https://docs.google.com/open?id=0B1r6und31C6BQnZUaTBjVXA4SkE)
using System.Windows.Forms;
namespace JLR.Utils
{
public class AnimatedDataGridView : DataGridView
{
private DataGridViewImageAnimator _imageAnimator;
public AnimatedDataGridView()
: base()
{
_imageAnimator = new DataGridViewImageAnimator(this);
}
}
}
The entire code for the DataGridViewImageAnimator is shown below:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
namespace JLR.Utils
{
public class DataGridViewImageAnimator
{
private class RowCol
{
public int Column { get; set; }
public int Row { get; set; }
public RowCol(int column, int row)
{
Column = column;
Row = row;
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
RowCol other = obj as RowCol;
if (other == null)
return false;
return (other.Column == Column && other.Row == Row);
}
public bool Equals(RowCol other)
{
if (other == null)
return false;
return (other.Column == Column && other.Row == Row);
}
public override int GetHashCode()
{
return Column.GetHashCode() ^ Row.GetHashCode();
}
public static bool operator ==(RowCol a, RowCol b)
{
// If both are null, or both are same instance, return true.
if (object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
{
return false;
}
// Return true if the fields match:
return a.Column == b.Column && a.Row == b.Row;
}
public static bool operator !=(RowCol a, RowCol b)
{
return !(a == b);
}
}
private class AnimatedImage
{
private DataGridView DataGridView { get; set; }
private HashSet<RowCol> _cells = new HashSet<RowCol>();
public Image Image { get; set; }
public AnimatedImage(Image image, DataGridView dataGridView)
{
Image = image;
DataGridView = dataGridView;
}
public bool IsUsed { get { return _cells.Count > 0; } }
public void AddCell(RowCol rowCol)
{
Debug.Assert(!_cells.Contains(rowCol));
if (!_cells.Contains(rowCol))
{
_cells.Add(rowCol);
if (_cells.Count == 1)
{
// this is the first cell we are using this image, so start animation
ImageAnimator.Animate(Image, new EventHandler(OnFrameChanged));
}
}
}
public void RemoveCell(RowCol rowCol)
{
Debug.Assert(_cells.Contains(rowCol));
if (_cells.Contains(rowCol))
{
_cells.Remove(rowCol);
if (_cells.Count == 0)
{
// this was the last cell we were using this image, so stop animation
ImageAnimator.StopAnimate(Image, new EventHandler(OnFrameChanged));
}
}
}
private void OnFrameChanged(object o, EventArgs e)
{
// invalidate each cell in which it's being used
RowCol[] rcs = new RowCol[_cells.Count];
_cells.CopyTo(rcs);
foreach (RowCol rc in rcs)
{
DataGridView.InvalidateCell(rc.Column, rc.Row);
}
}
}
private Dictionary<RowCol, Image> _values = new Dictionary<RowCol, Image>();
private Dictionary<Image, AnimatedImage> _animatedImages = new Dictionary<Image, AnimatedImage>();
private DataGridView _dataGridView;
public DataGridViewImageAnimator(DataGridView dataGridView)
{
_dataGridView = dataGridView;
_dataGridView.CellPainting += new DataGridViewCellPaintingEventHandler(OnDatagridCellPainting);
}
void OnDatagridCellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
{
object value = _dataGridView[e.ColumnIndex, e.RowIndex].Value;
CheckValue(e.ColumnIndex, e.RowIndex, value);
ImageAnimator.UpdateFrames();
}
}
private void AddImage(RowCol rowCol, Image image)
{
_values[rowCol] = image;
AnimatedImage animatedImage;
if (!_animatedImages.TryGetValue(image, out animatedImage))
{
animatedImage = new AnimatedImage(image, _dataGridView);
_animatedImages[image] = animatedImage;
}
animatedImage.AddCell(rowCol);
}
private void RemoveImage(RowCol rowCol, Image image)
{
Debug.Assert(_values.ContainsKey(rowCol));
Debug.Assert(_animatedImages.ContainsKey(image));
_values.Remove(rowCol);
AnimatedImage animatedImage;
if (_animatedImages.TryGetValue(image, out animatedImage))
{
animatedImage.RemoveCell(rowCol);
if (!animatedImage.IsUsed)
{
_animatedImages.Remove(image);
}
}
}
private void CheckValue(int columnIndex, int rowIndex, object value)
{
RowCol rowCol = new RowCol(columnIndex, rowIndex);
// is the new value an Image, and can it be animated?
Image newImage = value as Image;
bool newValueIsImage = (newImage != null && ImageAnimator.CanAnimate(newImage));
// is there a previous image value?
Image oldImage;
if (_values.TryGetValue(rowCol, out oldImage))
{
if (newImage == oldImage)
{
// same old image --> nothing else to do
return;
}
RemoveImage(rowCol, oldImage);
}
if (newValueIsImage)
{
AddImage(rowCol, newImage);
}
}
}
}
Regards,
Following the link only answer by #AseemGautam which links to same question posted in another forum with another link only answer which links to a rar file containing a complex project, it boils down to a simple answer.
Including image directly from resource will not play its animation. So we include the image in a 1x1 pixel image on same form as grid (this 1x1 image cannot hide behind other components otherwise animation wont work, hopefully that 1 pixel is transparent in gif file). Then using a timer invalidate the cell every 60ms (or smallest frame duration in gif animation) intervals. Most probably this will cause flicker on images so by adding a RowPostPaint event which draws a 1 pixel line will sync cell drawing.
void frmMain_Load(object sender, EventArgs e) {
DataGridView1.Rows.Clear();
DataGridView1.Rows.Add(PictureBox1.Image);
}
void Timer1_Tick(object sender, EventArgs e) {
if (DataGridView1.Rows.Count > 0) {
DataGridView1.Rows[0].Cells[0].Value = PictureBox1.Image;
DataGridView1.InvalidateCell(0, 0);
}
}
void DataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e) {
e.Graphics.DrawLine(new Pen(SystemColors.ActiveBorder), 0, 0, 1, 1);
}

Categories

Resources