Anonymous functions/delegate? - c#

I'm converting my C# Windows Application to a C++\CLI app.
I'm stuck with 'converting' this code:
void LoadWindow(Mode mode) {
if (timer != null && timer.Enabled) return;
int currentIndex = Windows.IndexOf(panel.Controls[0]);
int loadInex = 0, exitLeft = 0, entranceLeft = 0, stopLeft = 0;
if (mode == Mode.Next)
{
loadInex = currentIndex == Windows.Count - 1 ? 0 : ++currentIndex;
exitLeft = -((panel.Width / 2 - Windows[currentIndex].Width / 2) + Windows[currentIndex].Width);
entranceLeft = panel.Width;
}
else
{
loadInex = currentIndex == 0 ? Windows.Count - 1 : --currentIndex;
exitLeft = panel.Width;
entranceLeft = -panel.Width;
}
stopLeft = panel.Width / 2 - Windows[loadInex].Width / 2;
Windows[loadInex].Left = entranceLeft;
panel.Controls.Add(Windows[loadInex]);
timer = new System.Windows.Forms.Timer();
timer.Interval = 10;
timer.Tick += new EventHandler(delegate(object sender, EventArgs e) {
if (mode == Mode.Next)
{
if (exitLeft <= panel.Controls[0].Left)
panel.Controls[0].Left -= 50;
if (stopLeft <= panel.Controls[1].Left)
panel.Controls[1].Left = panel.Controls[1].Left - 50 < stopLeft ? stopLeft : panel.Controls[1].Left - 50;
if (exitLeft >= panel.Controls[0].Left && stopLeft >= panel.Controls[1].Left)
{
panel.Controls.RemoveAt(0);
timer.Enabled = false;
}
}
if (mode == Mode.Previous)
{
if (exitLeft >= panel.Controls[0].Left)
panel.Controls[0].Left += 50;
if (stopLeft >= panel.Controls[1].Left)
panel.Controls[1].Left = panel.Controls[1].Left + 50 > stopLeft ? stopLeft : panel.Controls[1].Left + 50;
if (exitLeft <= panel.Controls[0].Left && stopLeft <= panel.Controls[1].Left)
{
panel.Controls.RemoveAt(0);
timer.Enabled = false;
}
}
});
timer.Enabled = true;
}
AFAIK C++\CLI doesn't support anonymous methods (I can't even take advantage of lambdas).
This wouldn't be a problem if the EventHandler delegate didn't use local variables in the LoadWindow function.
How can I implement this? I considered using a simple functor class, but is there a more 'elegant' way?
Thanks,
Alex

Related

Why doesn't my richtextbox change the color?

I'm trying to give the letters in my richtextbox different colors for my subnet calculator, but the richtextbox doesn't change the colors until the 26th letter.
How it looks:
int iValueSm = trackBarSmMask.Value;
rtbScroll.Text = "";
rtbScroll.SelectionStart = rtbScroll.TextLength;
rtbScroll.SelectionLength = 0;
for (int i = 1; i <= iValueSm; i++)
{
rtbScroll.SelectionColor = Color.Blue;
rtbScroll.AppendText("N");
if (i%8==0 && i != 32)
{
rtbScroll.Text = rtbScroll.Text + ".";
}
}
for (int i = iValueSm+1; i <= 32; i++)
{
rtbScroll.SelectionColor = Color.Red;
rtbScroll.AppendText("H");
if (i % 8 == 0 && i != 32)
{
rtbScroll.Text = rtbScroll.Text + ".";
}
}
labelAmountNetID.Text = "/" + iValueSm.ToString();
Well, can be a lot of approaches to deal with this problem but here is one suggestion:
// Track bar definitions...
private void SetTrackBarVals()
{
trackBar1.Minimum = 0;
trackBar1.Maximum = 31;
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
var counter = 0;
var dotsCounter = 0;
rtbScroll.Text = "";
int iValueSm = trackBar1.Value + 1; // +1 because we start counting from 0
for (int i = 1; i <= 32; i++)
{
if (counter > 0 && counter % 8 == 0)
{
// new octet
rtbScroll.AppendText(".");
dotsCounter++;
}
if (i > iValueSm)
{
// It is red
rtbScroll.AppendText("H");
rtbScroll.SelectionStart = (i - 1) + dotsCounter;
rtbScroll.SelectionLength = 1 ;
rtbScroll.SelectionColor = Color.Red;
}
else
{
rtbScroll.AppendText("N");
}
counter++;
}
}
Anytime you set the .Text() property, you RESET all formatting back to black and white.
Here is how I'd write it using SelectedText:
private void Form1_Load(object sender, EventArgs e)
{
updateRTB();
}
private void trackBarSmMask_ValueChanged(object sender, EventArgs e)
{
updateRTB();
}
private void trackBarSmMask_Scroll(object sender, EventArgs e)
{
updateRTB();
}
private void updateRTB()
{
rtbScroll.Text = "";
rtbScroll.SelectionStart = 0;
rtbScroll.SelectionLength = 0;
int iValueSm = trackBarSmMask.Value;
labelAmountNetID.Text = "/" + iValueSm.ToString();
for (int i = 1; i <= 32; i++)
{
rtbScroll.SelectionColor = (i <= iValueSm) ? Color.Blue : Color.Red;
rtbScroll.SelectedText = (i <= iValueSm) ? "N" : "H";
if (i % 8 == 0 && i != 32)
{
rtbScroll.SelectionColor = Color.Black;
rtbScroll.SelectedText = ".";
}
}
}

Using Yield to make a function wait until something is true Unity C#

I'm trying to use Yield so my functions wait to spawn more enemies in scene if the max amount has been reached. But now the functions skips all this while cycle in its entirety.
I have never use yield so maybe I'm understanding wrong what it does while reading the documentation.
Also maybe there is a better way to do it.
while ( i < clonesASpawnear.Length)
{
if (j <= endList)
{
if (clonesASpawnear[i] == null)
{
if (sPCurrent == sPMax)
{
sPCurrent = 0;
}
yield return new WaitUntil(() => aliveEnemies < maxAmmoutOfEnemiesOnStage);
clonesASpawnear[i] = Instantiate(enemyTypeList[j], spawnPoints[sPCurrent].transform.position, Quaternion.Euler(0, 0, 0)) as GameObject;
clonesASpawnear[i].SetActive(true);
clonesASpawnear[i].GetComponent<EnemyMovement_DCH>().player = Target;
aliveEnemies += 1;
clonesASpawnear[i].GetComponent<EnemyDamageHandler_DCH>().SpawnerEnemies = this;
j++;
i++;
sPCurrent++;
}
}
else
{
j = startList;
}
}
}
Edited as requested: here is the update where the function is called
void Update()
{
if (pdh.playerIsDead == false && roundOver==false)
{
playerAliveTime += Time.deltaTime;
}
if (waveNumer <= 3 )
{
timeForNextSpawn -= Time.deltaTime;
if (timeForNextSpawn <= 0 && aliveEnemies == 0)
{
nextWaveTextUI.text = nextWaveText;
int waitT = (int)waitTimeForNewWave;
StartCoroutine(delayXSeconds(waitT));
timeForNextSpawn = waitTimeForNewWave;
auxWaveThisRound--;
waveNumer++;
spawnEnemies();
}
}
else
{
if(aliveEnemies == 0 && auxWaveThisRound <= 0)
{
clearedRoundTextUI.text = clearedRoundText;
roundOver = true;
StartCoroutine(waiterReset());
}
}
accuracy = successfulProjectiles / projectileFired;
}
And the complete function where the above code is
IEnumerator spawnEnemies()
{
int percentForWave=0;
int percentForType=0;
int TotalEnemies = (int)enemySpawnsThisRound;
if (waveNumer == 1)
{
Debug.Log("Entro al wave 1");
percentForWave = 20;
percentForType = 20;
startList = 0;
}
if (waveNumer == 2)
{
Debug.Log("Entro al wave 2");
percentForWave = 70;
percentForType = 70;
startList = endList;
}
if (waveNumer == 3)
{
Debug.Log("Entro al wave 3");
percentForWave = 10;
percentForType = 10;
startList = endList;
}
int enemiesThisWave = Decimal.ToInt32(Math.Round(TotalEnemies * ((decimal)percentForWave / 100), 1));
int enemiesForType = Decimal.ToInt32(Math.Round(lenghtList * ((decimal)percentForType / 100), 1));
endList = enemiesForType + startList;
clonesASpawnear = new GameObject[enemiesThisWave];
int i = 0;
int j = startList;
while ( i < clonesASpawnear.Length)
{
if (j <= endList)
{
if (clonesASpawnear[i] == null)
{
if (sPCurrent == sPMax)
{
sPCurrent = 0;
}
yield return new WaitUntil(() => aliveEnemies < maxAmmoutOfEnemiesOnStage);
clonesASpawnear[i] = Instantiate(enemyTypeList[j], spawnPoints[sPCurrent].transform.position, Quaternion.Euler(0, 0, 0)) as GameObject;
clonesASpawnear[i].SetActive(true);//lo activo
clonesASpawnear[i].GetComponent<EnemyMovement_DCH>().player = Target;
aliveEnemies += 1;
clonesASpawnear[i].GetComponent<EnemyDamageHandler_DCH>().SpawnerEnemies = this;
j++;
i++;
sPCurrent++;
}
}
else
{
j = startList;
}
}
}
Do not use a while loop. Instead, use "Update()".
void Update() {
if (aliveEnemies < maxAmmoutOfEnemiesOnStage && j <= endList)
{
if (clonesASpawnear[i] == null)
{
if (sPCurrent == sPMax)
{
sPCurrent = 0;
}
clonesASpawnear[i] = Instantiate(enemyTypeList[j], spawnPoints[sPCurrent].transform.position, Quaternion.Euler(0, 0, 0)) as GameObject;
clonesASpawnear[i].SetActive(true);
clonesASpawnear[i].GetComponent<EnemyMovement_DCH>().player = Target;
aliveEnemies += 1;
clonesASpawnear[i].GetComponent<EnemyDamageHandler_DCH>().SpawnerEnemies = this;
j++;
i++;
sPCurrent++;
}
}
else
{
j = startList;
}
}
This is the idea of the Update frame. Logic in here is hit every frame. It will only continue if the number of enemies is below the max. This method MUST go into a class that extends MonoBehaviour, or else it will not be invoked. Given the intended logic, it makes sense that this would be attached to some master "game monitoring" GameObject that is managing the meta of the game along with win states etc.
EDIT (After more content):
Heres one problem "spawnEnemies();". That is an IEnumerator, but you don't use "StartCoroutine(spawnEnemies())". So the method will literally not execute. There will be no errors, but nothing in the method will occur.

Countdown timer goes into negative number (00:00:00)

I made a simple countdown timer but the timer goes into negative -1 : 59 : 59 when i input 0 : 0 : 0 on the textboxes. i tried to input 0 : 0 : 1 and the timer stopped at 0 : 0 : 0 and the messagebox appear on the screen
i have tried this code to prevent negative value but it stopped at -1 : 59 : 58
if (label1.Text == "-1")
{
timer1.Stop()
}
tried this code but it stopped at -1 : 59 : 59
if (h < 0)
{
timer1.Stop();
}
here is the codes
namespace Timer
{
public partial class Form1 : Form
{
int h;
int m;
int s;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text == "")
{
textBox1.Text = "0";
}
if (textBox2.Text == "")
{
textBox2.Text = "0";
}
if (textBox3.Text == "")
{
textBox3.Text = "0";
}
h = Convert.ToInt32(textBox1.Text);
m = Convert.ToInt32(textBox2.Text);
s = Convert.ToInt32(textBox3.Text);
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
s = s - 1;
if(s == -1)
{
m = m - 1;
s = 59;
}
if (m == -1)
{
h = h - 1;
m = 59;
}
if (h == 0 && m == 0 && s == 0)
{
timer1.Stop();
MessageBox.Show("Times up!", "Time");
}
string hh = Convert.ToString(h);
string mm = Convert.ToString(m);
string ss = Convert.ToString(s);
label1.Text = hh;
label2.Text = mm;
label3.Text = ss;
}
private void button2_Click(object sender, EventArgs e)
{
timer1.Stop();
}
}
}
You code is doing exactly what you are telling it to do, the problem is that you are not dealing with the edge case of starting at 0:0:0.
I assume this would be considered an invalid input, so probably the easiest way to deal with this would be to check before you even start the timer in the button click:
h = Convert.ToInt32(textBox1.Text);
m = Convert.ToInt32(textBox2.Text);
s = Convert.ToInt32(textBox3.Text);
// one of these must be non-zero
if (h != 0 || m != 0 || s != 0)
{
timer1.Start();
}
else
{
// handle this how ever you want but you don't need to start a timer
// and really shouldn't start the timer
}
It would actually be a mistake to let the timer tick if the user entered all zeros because then they would get 1 second, when they asked for 0 seconds.
Even better would be to actually disable the button until a non-zero time has been entered. To do that I would suggest replacing the TextBox with NumericUpDown (because only numeric inputs are valid anyway) and then add handlers for their ValueChanged event. In that handler check in any of the three controls have a non-zero value and enable the button if they do. If they are all zero, disable the button.
An important aside here - the System.Windows.Forms.Timer is not particularly accurate so don't expect a timer set to tick every 1 second to actually tick every one second. It will be at least 1 second between each tick, but often it will be a few ms more. So your countdown will drift. If you set it to count down 1 minute (i.e. 60 seconds), don't be surprised if it actually takes 62 seconds to count down. If that's important to you, then you should record the current time when you start the timer and then check the difference between the current time and the time when you started the timer and use that to update your labels.
A better overall solution might look something like this:
DateTime end;
private void button1_Click(object sender, EventArgs e)
{
var h = hourNumericUpDown.Value;
var m = minuteNumericUpDown.Value;
var s = secondsNumericUpDown.Value;
if (h != 0 || m != 0 || s != 0)
{
var start = DateTime.Now;
var timeSpan = new TimeSpan(0,h,m,s);
end = start.Add(timeSpan);
countDownLabel.Text = timeSpan.ToString();
timer1.Start();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
var timeleft = end - DateTime.Now;
if (timeLeft.Ticks < 0)
{
countDownLabel.Text = "00:00:00";
timer1.Stop();
MessageBox.Show("Times up!", "Time");
}
else
{
countDownLabel.Text = string.Format("{0:D2}:{1:D2}:{2:D2}",
timeLeft.Hours, timeLeft.Minutes, timeLeft.Seconds);
}
}
And then you'd probably be better off setting the timer to fire faster. Maybe every half second, or every quarter second so that the display is never off by more than about that much.
You're not covering the case in which 0:0:0 is provided.
Replace this:
s = s - 1;
if(s == -1)
{
m = m - 1;
s = 59;
}
if (m == -1)
{
h = h - 1;
m = 59;
}
with this:
if(s > 0 || m > 0 || h > 0)
{
s = s - 1;
if(s == -1)
{
m = m - 1;
s = 59;
}
if (m == -1)
{
h = h - 1;
m = 59;
}
}
You are not checking when h becomes negative, I have added one you can add yours.
if (s == -1)
{
m = m - 1;
s = 59;
}
if (m == -1)
{
h = h - 1;
m = 59;
}
/*I added such condition*/
if(h < 0)
{
h = 0;
m = 0;
s = 0;
}
if (h == 0 && m == 0 && s == 0)
{
timer1.Stop();
MessageBox.Show("Times up!", "Time");
return;//return early
}

Prevent the Chrome Tabs dragged out of the window screen

I am currently developing a program that is using tab same like Google Chrome Tabs,
The tab is working fine, no problem.
But I come into a condition that I can drag the tab even out of monitor screen (left and right edge).
The Question is, how can I restrict the tab dragged into the edge of the screen??
So the tab will not go pass through the screen. Basically it is only about aesthetic purpose..
Be reminded that I have made research from the google and this website but still can't figure it out how to do it..
Here is a piece of the codes.
private bool draggingWindow;
private Size finalSize;
private double overlap;
private double leftMargin;
private double rightMargin;
private double maxTabWidth;
private double minTabWidth;
private double defaultMeasureHeight;
private double currentTabWidth;
private int captureGuard;
private int originalIndex;
private int slideIndex;
private List<double> slideIntervals;
private ChromeTabItem draggedTab;
private Point downPoint;
private ChromeTabControl parent;
public Rect addButtonRect;
private Size addButtonSize;
public Button addButton;
private bool modifyLeftOffset, modifyTopOffset;
private Point origCursorLocation;
private double origHorizOffset, origVertOffset;
protected override void OnPreviewMouseMove(MouseEventArgs e)
{
try
{
base.OnPreviewMouseMove(e);
if (this.addButtonRect.Contains(e.GetPosition(this)) && this.addButton.Background != Brushes.White && this.addButton.Background != Brushes.DarkGray)
{
this.addButton.Background = Brushes.White;
this.InvalidateVisual();
}
else if (!this.addButtonRect.Contains(e.GetPosition(this)) && this.addButton.Background != null)
{
this.addButton.Background = null;
this.InvalidateVisual();
}
if (this.draggedTab == null || this.draggingWindow) { return; }
Point nowPoint = e.GetPosition(this);
this.addButton.Visibility = Visibility.Hidden;
double newHorizontalOffset;
if (this.modifyLeftOffset)
newHorizontalOffset = this.origHorizOffset + (nowPoint.X - this.origCursorLocation.X);
else
newHorizontalOffset = this.origHorizOffset - (nowPoint.X - this.origCursorLocation.X);
Thickness margin = new Thickness(nowPoint.X - this.downPoint.X, 0, this.downPoint.X - nowPoint.X, 0);
this.draggedTab.Margin = margin;
Rect elemRect = this.CalculateDragElementRect(newHorizontalOffset, 1);
bool leftAlign = elemRect.Left < 0;
bool rightAlign = elemRect.Right > this.ActualWidth;
if (leftAlign)
newHorizontalOffset = modifyLeftOffset ? 0 : this.ActualWidth - elemRect.Width;
else if (rightAlign)
newHorizontalOffset = modifyLeftOffset ? this.ActualWidth - elemRect.Width : 0;
if (this.modifyLeftOffset)
Canvas.SetLeft(this.draggedTab, newHorizontalOffset);
else
Canvas.SetRight(this.draggedTab, newHorizontalOffset);
base.OnPreviewMouseMove( e );
if (margin.Left != 0)
{
int guardValue = Interlocked.Increment(ref this.captureGuard);
if (guardValue == 1)
{
this.originalIndex = this.draggedTab.Index;
this.slideIndex = this.originalIndex + 1;
this.slideIntervals = new List<double>();
this.slideIntervals.Add(double.NegativeInfinity);
for (int i = 1; i <= this.Children.Count; i += 1)
{
var diff = i - this.slideIndex;
var sign = diff == 0 ? 0 : diff / Math.Abs(diff);
var bound = Math.Min(1, Math.Abs(diff)) * ((sign * this.currentTabWidth / 3) + ((Math.Abs(diff) < 2) ? 0 : (diff - sign) * (this.currentTabWidth - this.overlap)));
this.slideIntervals.Add(bound);
}
this.slideIntervals.Add(double.PositiveInfinity);
this.CaptureMouse();
}
else
{
int changed = 0;
if (this.slideIntervals != null)
{
if (margin.Left < this.slideIntervals[this.slideIndex - 1])
{
SwapSlideInterval(this.slideIndex - 1);
this.slideIndex -= 1;
changed = 1;
}
else if (margin.Left > this.slideIntervals[this.slideIndex + 1])
{
SwapSlideInterval(this.slideIndex + 1);
this.slideIndex += 1;
changed = -1;
}
}
if (changed != 0)
{
var rightedOriginalIndex = this.originalIndex + 1;
var diff = 1;
if (changed > 0 && this.slideIndex >= rightedOriginalIndex)
{
changed = 0;
diff = 0;
}
else if (changed < 0 && this.slideIndex <= rightedOriginalIndex)
{
changed = 0;
diff = 2;
}
ChromeTabItem shiftedTab = this.Children[this.slideIndex - diff] as ChromeTabItem;
if (shiftedTab != this.draggedTab)
{
StickyReanimate(shiftedTab, changed * (this.currentTabWidth - this.overlap), .13);
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
Any response and attention is really appreciated..
Thank you

Timer pause without thread.sleep

I try make timers without thread.sleep to stop lag so any ideas how to make this code without thread.sleep but it stop 20ms. Thanks for help! :) And sorry my bad english.
Timer BulletTimer = new Timer();
BulletTimer.Tick += (s, args) => BulletKillPlayer(Bullet);
BulletTimer.Interval = 20;
BulletTimer.Start();
private void BulletKillPlayer(Bullet)
{
bool pX, pY, pD1, pD2, nX, nY, nD1, nD2;
pX = false; pY = false; pD1 = false; pD2 = false; nX = false; nY = false;
for (int i = 1; i < 20; i++)
{
if (User.Range >= i)
{
Thread.Sleep(20);
foreach (MapItem MapItem in MapItem.Boxs.Values)
{
if (MapItem.X == Bullet.X && MapItem.Y == Bullet.Y + i && !pX) { pX = BreakBox(Bullet, MapItem); KillPlayer(Bullet, MapItem); }
if (MapItem.X == Bullet.X && MapItem.Y == Bullet.Y - i && !pY) { pY = BreakBox(Bullet, MapItem); KillPlayer(Bullet, MapItem); }
if (MapItem.X == Bullet.X + i && MapItem.Y == Bullet.Y && !nX) { nX = BreakBox(Bullet, MapItem); KillPlayer(Bullet, MapItem); }
if (MapItem.X == Bullet.X - i && MapItem.Y == Bullet.Y && !nY) { nY = BreakBox(Bullet, MapItem); KillPlayer(Bullet, MapItem); }
}
}
}
}

Categories

Resources