Eraser on inkcanvas in wpf - c#

private void inkcanvas_StrokeErased(object sender, RoutedEventArgs e)
{
var erasedstrokes = (sender as InkCanvas).Strokes;
aftererasedstrokecollection = erasedstrokes;
foreach (var item in aftererasedstrokecollection)
{
removedstrokes.Add(item);
}
}
private void inkcanvas_StrokeErasing(object sender InkCanvasStrokeErasingEventArgs e)
{
var beforeerased = (sender as InkCanvas).Strokes;
beforeerasedstrokecollection = beforeerased;
foreach (var item in beforeerasedstrokecollection)
{
unremovedstrokes.Add(item);
}
}
private void btnUndo_Click(object sender, RoutedEventArgs e)
{
if (DrawingTool == "Eraser" || DrawingTool == "Delete")
{
int length = removedstrokes.Count;
for (int i = 0; i < length; i++)
{
estroke = removedstrokes[i];
inkcanvas.Strokes.Remove(estroke);
}
for (int i = 0; i < unremovedstrokes.Count; i++)
{
estroke = unremovedstrokes[i];
inkcanvas.Strokes.Add(estroke);
}
}
else
{
if (inkcanvas.Strokes.Count > 0)
{
int i = inkcanvas.Strokes.Count;
inkcanvas.Strokes.RemoveAt(i - 1);
}
}
removedstrokes.Clear();
DrawingTool = "UnDo";
HighlightSelectedButton(sender);
IsDrawing = false;
inkcanvas.EditingMode = InkCanvasEditingMode.None;
}
I want to draw again erased strokes on undo click in WPF. through above code i do this for single stroke but i want to do same for multiple strokes.
please suggest any idea.
how i get only erased point by erasedbypoint method of inkcanvas

Related

Moving Pictureboxes from left to right

I have 4 pictureBoxes. I need they move until hit right side and then move to left side and again. But after 1st picturebox hit left side other move closer to him. How fix it ??
link on video with problem
int changePositionX;
bool change = true;
private void timer1_Tick(object sender, EventArgs e)
{
foreach (Control x in this.Controls)
{
if (x is PictureBox && x.Tag != null && x.Tag.ToString() == "enemy")
{
if (x.Location.X < 750 && change == true)
{
changePositionX = x.Location.X + 50;
x.Location = new Point(changePositionX, x.Location.Y);
}
else
{
change = false;
}
if(x.Location.X >= 100 && change == false)
{
changePositionX = x.Location.X - 50;
x.Location = new Point(changePositionX, x.Location.Y);
}
else
{
change = true;
}
}
}
}
Try it like this instead:
private int jumpDistance = 50;
private bool goingRight = true;
private List<PictureBox> PBs = new List<PictureBox>();
private void Form1_Load(object sender, EventArgs e)
{
foreach (PictureBox pb in this.Controls.OfType<PictureBox>())
{
if (pb.Tag != null && pb.Tag.ToString() == "enemy")
{
PBs.Add(pb);
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (goingRight)
{
if (PBs.Any(pb => pb.Location.X >= 750))
{
goingRight = !goingRight;
}
}
else
{
if (PBs.Any(pb => pb.Location.X < 100))
{
goingRight = !goingRight; ;
}
}
foreach (PictureBox pb in PBs)
{
if (goingRight)
{
pb.Location = new Point(pb.Location.X + jumpDistance, pb.Location.Y);
}
else // going left
{
pb.Location = new Point(pb.Location.X - jumpDistance, pb.Location.Y);
}
}
}
Here's my code doing its thing with four PictureBoxes:

return to main after paying

i have POS system to fastfood, created by c# and sql server.
after the payment process show me window "Order Successfully Paid" after clicking to ok return to form ProductsReceiptPreview again,
i want after payment process go to the form main.
this is my code.......
private void lblPayments_Click(object sender, EventArgs e)
{
if (pnlPayments.Height != lbl.Height)
{
pnlPayments.Height = lbl.Height;
btnDone.Text = "DONE";
lbl.Text = "RECEIPT";
btnDone.Image = Resources.done;
Data.Show();
}
else
{
pnlPayments.Height = 394;
btnDone.Text = "RECEIPT";
lbl.Text = "AMOUNT";
btnDone.Image = Resources.receipt;
Data.Hide();
}
}
private void Touch_Click(object sender, EventArgs e)
{
var btn = (Button)sender;
txtCashReceived.Text += btn.Text;
}
private void btnClear_Click(object sender, EventArgs e)
{
if(txtCashReceived.Text.Length >0) txtCashReceived.Text =
txtCashReceived.Text.Remove(txtCashReceived.Text.Length - 1);
}
double totalBill = 0;
private void btnPay_Click(object sender, EventArgs e)
{
if (txtCashReceived.Text.Length > 0 && totalBill <=
Convert.ToInt32(txtCashReceived.Text) && Data.RowCount > 0)
{
int i = 0;
foreach (var rep in ListReports)
{
i++;
var report = new ModelReports();
report.Productname = rep.Productname;
report.TotalSales = rep.TotalSales;
report.TotalTransactions = rep.TotalTransactions;
report.Save();
}
var rpd = new ProductsReceiptPreview(dataReceiptBindingSource,
txtTotal.Text, txtCashReceived.Text, txtChange.Text);
rpd.ShowDialog();
if (i == ListReports.Count)
{
MessageBox.Show("Order Successfully Paid");
}
pnlProducts.Controls.Clear();
pnlCategoryPanel.Visible = false;
dataReceiptBindingSource.Clear();
LoadTables();
btnDone.PerformClick();
}
else
{
MessageBox.Show("Please pay your order.");
txtCashReceived.Text = "0";
}
}
private void btnPay_Click_1(object sender, EventArgs e)
{
if (txtCashReceived.Text.Length > 0 && totalBill <=
Convert.ToInt32(txtCashReceived.Text) && Data.RowCount > 0)
{
int i = 0;
foreach (var rep in ListReports)
{
i++;
var report = new ModelReports();
report.Productname = rep.Productname;
report.TotalSales = rep.TotalSales;
report.TotalTransactions = rep.TotalTransactions;
report.Save();
}
if (i == ListReports.Count)
{
MessageBox.Show("Order Successfully Paid");
txtCashReceived.Text = "0";
}
pnlProducts.Controls.Clear();
pnlCategoryPanel.Visible = false;
dataReceiptBindingSource.Clear();
LoadTables();
btnDone.PerformClick();
}
else
{
MessageBox.Show("Please pay your order.");
}
}
If you call some code from main then it will return to main when the call is finished. In the case of a Form, it's handled on a different thread started from main. The thread will never return back to main in this context. If you are using a click event to do some action and want to call some other code when that happens, then you need to re-design your infrastructure. Look into SOLID development principles and dependency injection.
https://www.codeproject.com/Tips/1033646/SOLID-Principle-with-Csharp-Example
https://simpleinjector.readthedocs.io/en/latest/windowsformsintegration.html

Difficulty on passing a variable along with event

I need to pass the value for maxColumns to a method that will be used repeatedly by other items. How can I go about passing maxColumns in this scenario?
public partial class ValResults : Form
{
public ValResults()
{
InitializeComponent();
this.Table1Requirements();
}
private void Table1Requirements()
{
int maxColumns = 6;
this.table1LayoutPanelPrime.CellPaint += new TableLayoutCellPaintEventHandler(tableLayoutPaint);
}
void tableLayoutPaint(object sender, TableLayoutCellPaintEventArgs e)
{
for (int i = 0; i < maxColumns; i++)
{
if (e.Row == 0 && e.Column == i)
{
Graphics g = e.Graphics;
Rectangle r = e.CellBounds;
g.FillRectangle(Brushes.LightGray, r);
}
}
}
}
If its in the same class, just define the variable at the class level.
private int _maxColumns;
public ValResults()
{
InitializeComponent();
this.Table1Requirements();
SetColumnCount();
}
private void SetColumnCount(){
_maxColumns= 6;
}
void tableLayoutPaint(object sender, TableLayoutCellPaintEventArgs e)
{
for (int i = 0; i < _maxColumns; i++)
{
if (e.Row == 0 && e.Column == i)
{
Graphics g = e.Graphics;
Rectangle r = e.CellBounds;
g.FillRectangle(Brushes.LightGray, r);
}
}
}
you can essentially pre build a function using lambdas...
private void Table1Requirements()
{
int maxColumns = 6;
this.table1LayoutPanelPrime.CellPaint += new TableLayoutCellPaintEventHandler(tableLayoutPaint(maxColumns));
}
Action<object,TableLayoutCellPaintEventArgs> tableLayoutPaint(int columns)
return (sender, e) =>
{
for (int i = 0; i < columns; i++)
{
if (e.Row == 0 && e.Column == i)
{
Graphics g = e.Graphics;
Rectangle r = e.CellBounds;
g.FillRectangle(Brushes.LightGray, r);
}
}
}
that way you can generate different event handles with different max column settings

Removing an item from a listbox in C#

Hello I'm trying to click a button to remove and item but I keep getting an
'IndexOutOfRange' Exception.
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
clientNum = clientList.Items.Count;
for (int i = 0; i < clientNum; i++)
{
nameSeletion[i] = clientList.Items[i].ToString();
}
if (dateSeletion[clientList.SelectedIndex] != null)
{
dateCalender.SelectionStart = todayDate[clientList.SelectedIndex];
Check();
}
else
{
nameLbl.Text = nameSeletion[clientList.SelectedIndex];
dateText.Text = "";
}
}
The if (dateSeletion[clientList.SelectedIndex] != null) is where I'm having the error.
The button code is
private void button1_Click(object sender, EventArgs e)
{
clientList.Items.Remove(clientList.Items[clientList.SelectedIndex]);
}
the dateSelection is defined in the save button and Initialization
private void SaveBtn_Click(object sender, EventArgs e)
{
//save the list array for names
for (int i = 0; i < clientNum; i++)
{
nameSeletion[i] = clientList.Items[i].ToString();
}
dateSeletion[clientList.SelectedIndex] = dateCalender.SelectionStart.Date.ToShortDateString() +
" " + clientTime.Value.ToShortTimeString();
todayDate[clientList.SelectedIndex] = dateCalender.SelectionStart;
dateCalender.BoldedDates = todayDate;
Check();
}
public ClientForm()
{
InitializeComponent();
clientNum = clientList.Items.Count;
todayDate = new DateTime[clientNum];
dateSeletion = new string[clientNum];
nameSeletion = new string[clientNum];
clientTime.CustomFormat = "hh:mm tt";
//initialize the list array for names
for (int i = 0; i < clientNum; i++)
{
nameSeletion[i] = clientList.Items[i].ToString();
}
}
Try this
clientList.RemoveAt(clientList.SelectedIndex);

DataGrid auto scrolling when doing selection

I have a custom Datagrid, in that datagrid I change the way we select element.
I have some feature added to the selection, like :
When we select element, it's like the "Ctrl" key was press.
When we click on a selected row, the row become unselected.
When we do a multiple selection, all the row change the selectedValue for the one that the first row is going to have.
When we do a multiple selection (mouse down, move, then mouse up) with Right click it's reversing the selected value of the rows.
It's a DataGrid extension, so I am coding only in C#.
For doing that I added event handle on PreviewMouseDown and MouseUp of for the datagridrow.
private enum ButtonClicked {Left, Middle, Right};
private ButtonClicked m_oMouseButtonClicked;
private void PreviewMouseDownHandler(object sender, MouseButtonEventArgs e)
{
DataGridRow row = sender as DataGridRow;
if (e.LeftButton == MouseButtonState.Pressed)
{
row.IsSelected = !row.IsSelected;
m_oMouseButtonClicked = ButtonClicked.Left;
}
else if (e.RightButton == MouseButtonState.Pressed)
{
//row.IsSelected = !row.IsSelected;
m_oMouseButtonClicked = ButtonClicked.Right;
}
row.CaptureMouse();
row.MouseMove += row_MouseMove;
e.Handled = true;
}
void row_MouseMove(object sender, MouseEventArgs e)
{
Point oPosFromThis = e.GetPosition(this);
if (oPosFromThis.Y > this.ActualHeight)
{
}
else if (oPosFromThis.Y < 0)
{
}
}
void Row_MouseUp(object sender, MouseButtonEventArgs e)
{
int nStart;
int nEnd;
DataGridRow row = sender as DataGridRow;
row.ReleaseMouseCapture();
row.MouseMove -= row_MouseMove;
int nStartRowIndex = ItemContainerGenerator.IndexFromContainer(row);
Point oPosFromRow = e.MouseDevice.GetPosition(row);
int nEndRowIndex = nStartRowIndex + (int)Math.Floor(oPosFromRow.Y / row.ActualHeight);
if (nStartRowIndex < nEndRowIndex)
{
nStart = Math.Max(nStartRowIndex, 0);
nEnd = Math.Min(nEndRowIndex, Items.Count - 1);
}
else
{
nStart = Math.Max(nEndRowIndex, 0);
nEnd = Math.Min(nStartRowIndex, Items.Count - 1);
}
for (; nStart <= nEnd; ++nStart)
{
DataGridRow oTmp = ((DataGridRow)ItemContainerGenerator.ContainerFromIndex(nStart));
if (m_oMouseButtonClicked == ButtonClicked.Left)
{
oTmp.IsSelected = row.IsSelected;
}
else if (m_oMouseButtonClicked == ButtonClicked.Right)
{
oTmp.IsSelected = !oTmp.IsSelected;
}
}
e.Handled = true;
}
I give the mouse capture to my row i clicked, to be able to catch the mouseUp even if i go outside the datagrid.
But with my code, I lost a feature that i would like to have. The auto scrolling when I do a multiple selection and i go under or upper the datagrid. I know that iI will have to add MouseMove Handler to do it, but for now i am stuck cause I don't know how to do it.
I finally found a solution by try-error attempts. I added method to get the scrollviewer element, then i am starting a Timer to execute the scroll alone.
public claa AAA
{
private enum ButtonClicked {Left, Middle, Right};
private ButtonClicked m_oMouseButtonClicked;
private DispatcherTimer m_oTimer;
private double m_nScrollOffset;
private ScrollViewer m_oScrollBar;
public IcuAlertGrid()
{
this.Initialized += IcuAlertGrid_Initialized;
this.Loaded += IcuAlertGrid_Loaded;
m_oTimer = new DispatcherTimer();
m_oTimer.Tick += m_oTimer_Tick;
m_oTimer.Interval = new TimeSpan(2500000);
}
void IcuAlertGrid_Initialized(object sender, EventArgs e)
{
setStyle0(true);
//throw new NotImplementedException();
}
void IcuAlertGrid_Loaded(object sender, RoutedEventArgs e)
{
m_oScrollBar = GetScrollViewer(this);
}
void m_oTimer_Tick(object sender, EventArgs e)
{
if (m_oScrollBar != null)
{
m_oScrollBar.ScrollToVerticalOffset(m_oScrollBar.VerticalOffset + m_nScrollOffset);
}
}
private void PreviewMouseDownHandler(object sender, MouseButtonEventArgs e)
{
DataGridRow row = sender as DataGridRow;
if (e.LeftButton == MouseButtonState.Pressed)
{
row.IsSelected = !row.IsSelected;
m_oMouseButtonClicked = ButtonClicked.Left;
}
else if (e.RightButton == MouseButtonState.Pressed)
{
//row.IsSelected = !row.IsSelected;
m_oMouseButtonClicked = ButtonClicked.Right;
}
row.CaptureMouse();
row.MouseMove += row_MouseMove;
e.Handled = true;
}
private void row_MouseMove(object sender, MouseEventArgs e)
{
DataGridRow oRow = sender as DataGridRow;
Point oPosFromThis = e.GetPosition(this);
if (oPosFromThis.Y < 0)
{
m_nScrollOffset = -1.0;
m_oTimer.Start();
}
else if (this.ActualHeight < oPosFromThis.Y)
{
m_nScrollOffset = 1.0;
m_oTimer.Start();
}
else
{
m_oTimer.Stop();
}
}
private void Row_MouseUp(object sender, MouseButtonEventArgs e)
{
int nStart;
int nEnd;
m_oTimer.Stop();
DataGridRow row = sender as DataGridRow;
row.ReleaseMouseCapture();
row.MouseMove -= row_MouseMove;
int nStartRowIndex = ItemContainerGenerator.IndexFromContainer(row);
Point oPosFromRow = e.MouseDevice.GetPosition(row);
int nEndRowIndex = nStartRowIndex + (int)Math.Floor(oPosFromRow.Y / row.ActualHeight);
if (nStartRowIndex < nEndRowIndex)
{
nStart = Math.Max(nStartRowIndex, 0);
nEnd = Math.Min(nEndRowIndex, Items.Count - 1);
}
else
{
nStart = Math.Max(nEndRowIndex, 0);
nEnd = Math.Min(nStartRowIndex, Items.Count - 1);
}
for (; nStart <= nEnd; ++nStart)
{
DataGridRow oTmp = ((DataGridRow)ItemContainerGenerator.ContainerFromIndex(nStart));
if (m_oMouseButtonClicked == ButtonClicked.Left)
{
oTmp.IsSelected = row.IsSelected;
}
else if (m_oMouseButtonClicked == ButtonClicked.Right)
{
oTmp.IsSelected = !oTmp.IsSelected;
}
}
e.Handled = true;
}
private static ScrollViewer GetScrollViewer(DependencyObject p_oParent)
{
ScrollViewer child = default(ScrollViewer);
int numVisuals = VisualTreeHelper.GetChildrenCount(p_oParent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(p_oParent, i);
child = v as ScrollViewer;
if (child == null)
{
child = GetScrollViewer(v);
}
if (child != null)
{
break;
}
}
return child;
}
}

Categories