I currently have 2 PopupWindow, one dismisses straight away upon Button press.
private async void ClosePopupWindow(object sender, View.TouchEventArgs e)
{
_popUpReceiptWindow.Dismiss();
await Task.Delay(5000);
Intent intent = new Intent(this, typeof(MainActivity));
intent.SetFlags(Intent.Flags);
Finish();
}
Due to the nature of that PopupWindow it closes and then switches to a different Activity.
The window that does not dismiss correctly is this line of code.
private void CloseEftWindow(object sender, View.TouchEventArgs e)
{
_popupEftWindow.Dismiss();
}
Here is the initialisation of the window that doesn't close properly:
private void EftButton_OnTouchedAsync(object sender, View.TouchEventArgs e)
{
_eftButton.Touch -= EftButton_OnTouchedAsync;
var popupEftView = LayoutInflater.Inflate(Resource.Layout.CreditCardPopupWindow, null);
_creditCardState = EftType.EftCardInserted;
_popUpCashbackButton = popupEftView.FindViewById<Button>(Resource.Id.popupCreditCardCashBackButton);
_popupEFTCancelButton = popupEftView.FindViewById<Button>(Resource.Id.popupCreditCardCancel);
_popupEftWindow = new PopupWindow(popupEftView, _subTotalLayout.Width, 500, true);
_popupEftWindow.ShowAtLocation(_subTotalLayout, GravityFlags.Bottom, 0, 0);
_popupEFTCancelButton.Touch += CloseEftWindow;
SubscribeCreditCardElements(popupEftView);
CreditCardStateTranstion(EftType.EftCardInserted);
_popUpCashbackButton.Touch += CashbackButtonSelected;
_eftButton.Touch += EftButton_OnTouchedAsync;
}
And here is the initialisation that does close properly:
private void UnderZeroBalanceReached()
{
View popUpView = LayoutInflater.Inflate(Resource.Layout.PopupView, null);
if (_totalAmount <= 0)
{
_popUpOkButton = popUpView.FindViewById<Button>(Resource.Id.popupReceiptYesButton);
_popUpReceiptWindow = new PopupWindow(popUpView, _subTotalLayout.Width, 500, true);
_popUpReceiptWindow.ShowAtLocation(_subTotalLayout, GravityFlags.Bottom, 0, 0);
_popUpOkButton.Touch += ClosePopupWindow;
DisableRightSidePaneButtons();
}
}
Is anyone able to see what I'm doing wrong? I've used breakpoints on the dismissal of the eft popupwindow but cant see why it's not actually shutting down.
I'm not entirely sure why but within the Method DisableRightSidePaneButtons(), there are lines of code that disable elements such as Buttons and TextViews and make them invisible. The PopUpWindow would only be dismissed if the button that initiates it had been disabled and been made invisible.
Related
I am trying to do some animations with panels and a timer in a C# Windows Forms project. Currently, there is a panel (in my code called 'pnSideBlock') which is located at the left edge of the window. Right next to it is a button.
The idea is that if the mouse enters the button, then the panel should relocate outside of the window (in my project the panel has a width of 20px, therefor I make its new location 20px outside of the window) and will move into it again with the help of a timer. As soon as the panel has reached a specific location, in my case 0px, then the timer should stop and the panel should stop moving.
But at the moment, the timer just keeps on going, which causes the panel to keep moving to the right.
private void btnMainMenu_MouseEnter(object sender, EventArgs e)
{
pnSideBlock.Left = -20;
timerForAnim.Enabled = true;
if(pnSideBlock.Left == 0)
{
timerForAnim.Enabled = false;
}
}
private void btnMainMenu_MouseLeave(object sender, EventArgs e)
{
timerForAnim.Enabled = false;
}
private void timerForAnim_Tick(object sender, EventArgs e)
{
pnSideBlock.Left += 1;
}
according to your code you need to change it to be like this:
private void btnMainMenu_MouseEnter(object sender, EventArgs e)
{
pnSideBlock.Left = -20;
timerForAnim.Enabled = true;
}
private void btnMainMenu_MouseLeave(object sender, EventArgs e)
{
timerForAnim.Enabled = false;
}
private void timerForAnim_Tick(object sender, EventArgs e)
{
pnSideBlock.Left += 1;
if(pnSideBlock.Left == 0)
{
timerForAnim.Enabled = false;
}
}
this change is required becouse btnMainMenu_MouseEnter happen only once when you enter to the button with the mouse.
and you need to check if the panel in place after every move.
Something similar, using a async Method.
Make your Button's MouseEnter handler async and call the async Task SlidePanel() method, specifying the initial and final position of the Control to slide and the speed of the animation (expressed in milliseconds).
When the Control is first entered, it's MouseEnter handler is detached (so it won't be raised again if the mouse pointer enters it while the animation is playing) and is be wired again when the animation finishes.
You can interact with the Button as usual.
The animation will be performed to its end even if the Button shows a modal Window when clicked (a MessageBox, for example).
Visual behaviour:
private async Task SlidePanel(Control control, int start, int end, int speed)
{
while (start < end)
{
await Task.Delay(speed);
start += 1;
control?.BeginInvoke(new Action(() => control.Left += 1));
}
}
private async void btnSlider_MouseEnter(object sender, EventArgs e)
{
btnMainMenu.MouseEnter -= btnMainMenu_MouseEnter;
pnSideBlock.Left -= pnSideBlock.Width;
await SlidePanel(pnSideBlock, pnSideBlock.Left, pnSideBlock.Width, 100);
btnMainMenu.MouseEnter += btnMainMenu_MouseEnter;
}
I've created my own dragable control. The dragging is very simple:
bool moving = false; Point click = new Point(0, 0);
private void _MouseDown(object sender, MouseButtonEventArgs e)
{
moving = true;
click = Mouse.GetPosition(this);
}
private void _MouseUp(object sender, MouseButtonEventArgs e) { moving = false; }
private void _MouseMove(object sender, MouseEventArgs e)
{
if (moving == true)
{
Point po = Mouse.GetPosition(this);
this.Margin = new Thickness(this.Margin.Left + (po.X - click.X), this.Margin.Top + (po.Y - click.Y), 0, 0);
}
}
My problem is that if I drag too fast the cursor "escapes" my control. It's obvious why, however it's not too obvious how to fix this since I can't easily subscribe to every other control's mousemove in the window, and my control is small (about 35,15 px) so this happends a lot. I think that if I can easily force the mouse cursor to stay in the controll that would be a solution(not ideal, though).
So what is the bast way to fix this? How professinoal controls handle this?
P.S. I'm learning WPF, so I'm probably doing some things wrong
Your cursor leaves the usercontrol on fast moves and the MouseMove event will not be triggered anymore.
As said in the comments from the author in Drag Drop UserControls using the MouseMove event of a surrounding Canvas should help.
I've figured it out, it's very simple, using a timer.
bool moving = false; Point click = new Point(0, 0);
System.Timers.Timer _MOVER = new System.Timers.Timer();
public PersonControl()
{
InitializeComponent();
_MOVER.Elapsed += new System.Timers.ElapsedEventHandler((o, v) => { Dispatcher.Invoke(Move); });
_MOVER.Enabled = true;
_MOVER.Interval = 10;
}
private void _MouseDown(object sender, MouseButtonEventArgs e)
{
moving = true;
click = Mouse.GetPosition(this);
Canvas.SetZIndex(this, 100);
_MOVER.Start();
}
private void _MouseUp(object sender, MouseButtonEventArgs e)
{
moving = false;
Canvas.SetZIndex(this, 0);
_MOVER.Stop();
}
private void Move()
{
if (moving == true)
{
Point po = Mouse.GetPosition(this);
this.Margin = new Thickness(this.Margin.Left + (po.X - click.X), this.Margin.Top + (po.Y - click.Y), 0, 0);
}
}
I've made a TextBox that retains what you type, and when you click the button associated it gives you a messagebox. When people want to click no, I want the button to change location so people cannot click it so they are forced to click yes,Well the problem is mousehover works just 1 time and does not go back to initial position after i leave my pointer out. Can you help me? Here is the code:
{
MsgBox = new CustomMsgBox();
MsgBox.label1.Text = Text;
MsgBox.button1.Text = btnOK;
MsgBox.button2.Text = btnCancel;
MsgBox.Text = Caption;
result = DialogResult.No;
MsgBox.ShowDialog();
return result;
}
private void button2_Click(object sender, EventArgs e)
{
button2.Location = new Point(25, 25);
}
private void button2_MouseHover(object sender, EventArgs e)
{
button2.Location = new Point(+50, +50);
}
private void button2_MouseLeave(object sender, EventArgs e)
{
button2.Location = new Point(+100, +100);
}
You should not use MouseLeave because when you move the button in the MouseHover, the button will move so the mouse will leave the button area. Meaning the No button will flip from the original position to the new position and back again all the time. What you could do is use the MouseMove to see if the user moved away from the area where the Button2 was originally and then move it back. Or include a non-visible control, like an empty label behind the button2. And set the MouseLeave on the label instead.
Oh and don't forget to set button2.TabStop = false, otherwise the user can use tab to get to the button.
Made a quick and dirty proof of concept for this, hope that helps ;)
public partial class Form1 : Form
{
private Rectangle buttonRectangle;
private bool checkRectangle = false;
public Form1()
{
InitializeComponent();
button2.TabStop = false;
buttonRectangle = button2.ClientRectangle;
buttonRectangle.Location = button2.Location;
}
private void button2_Click(object sender, EventArgs e)
{
button2.Location = new Point(25, 25);
}
private void button2_MouseHover(object sender, EventArgs e)
{
button2.Location = new Point(50, 50);
checkRectangle = true;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (!checkRectangle)
{
return;
}
if (!buttonRectangle.Contains(e.X, e.Y))
{
checkRectangle = false;
button2.Location = buttonRectangle.Location;
}
}
}
The buttonRectangle is set based on where the button is found during construction of the form. It has a contains method that can be used to check if a certain point (mouse move) is contained in it.
I also set the button2.TabStop to false so it will no longer be active during tab cycles.
When your hover (can change this to mouse enter, but just used your code) event fires, I set checkRectangle to true. I use this in the mouse move event handler to see if anything should be checked (prevents from doing anything when the mouse is not "over" the button).
If the buttonRectangle and the mouse location are not intersected this means we left the area where the button was, so we can move the button back.
Basically, I've got multiple button in my Form, and I want for it show a Stopwatch in the button.Text when the button is pressed. (Button is modified to be a toggle button.) and to stop and reset the timmer when the button is toggled off. Simple enough it seemed but because I have multiple buttons that could be pressed in any order, and I don't know anything about threading, this seems to be much more difficult that I presumed.
My origional intent was to have a function that constantly runs every second and interates a interager only if the button is pressed using this code:
public void Jogger()//purpose is to step up time[0] every second only when a button is on.
{
while (true)
{
for (int i = 0; i < 16; i++)
{
if (btnstat[i])
time[i]++;
}
Thread.Sleep(1000);
}
}
Problem is, I don't know threading so when I call the function, its stuck doing this and only this.
Either way, once this is called, all i do us call my update function that updates all the buttons including the button.Text which displays the time[0]; (array built around buttons)
Is their a better way of doing this that doesn't cause so much CPU use and/or simply works?
Thanks for all the help!
-John Ivey
Assuming you using checkbox with property Button = Appearence, in event handler for CheckedChanged:
private void CheckBoxCheckedChanged(object sender, EventArgs e)
{
CheckBox checkBox = (CheckBox) sender;
if (checkBox.Checked)
{
Timer timer = new Timer {Interval = 1000};
timer.Tick += Jogger;
timer.Start();
timer.Tag = new CheckboxCounter {CheckBox = checkBox, Time = 0};
checkBox.Tag = timer;
}
else
{
Timer timer = checkBox.Tag as Timer;
if (timer != null)
{
timer.Tag = null;
timer.Stop();
timer.Dispose();
checkBox.Tag = null;
}
}
}
Change your Jogger function:
private void Jogger(object a_sender, EventArgs a_eventArgs)
{
Timer timer = (Timer) a_sender;
CheckboxCounter data = (CheckboxCounter)timer.Tag;
data.Time++;
data.CheckBox.Text = data.Time.ToString();
}
You also need some simple class to store checkbox and current time:
class CheckboxCounter
{
public CheckBox CheckBox;
public int Time;
}
Then you can add any number of checkboxes and just set event CheckedChanged to CheckBoxCheckedChanged.
Try this out. After re-building or running, you should have the new "ButtonTimer" at the top of your ToolBox. Drop a couple on your Form, run it, and see what happens when you click them. Right click them to "Reset" them:
public class ButtonTimer : CheckBox
{
private System.Windows.Forms.Timer Tmr = new System.Windows.Forms.Timer();
private System.Diagnostics.Stopwatch SW = new System.Diagnostics.Stopwatch();
public ButtonTimer()
{
this.Tmr.Interval = 500;
this.Tmr.Tick += new EventHandler(tmr_Tick);
this.Appearance = System.Windows.Forms.Appearance.Button;
this.CheckedChanged += new EventHandler(ButtonTimer_CheckedChanged);
ContextMenuStrip cms = new ContextMenuStrip();
ToolStripItem tsi = cms.Items.Add("Reset");
tsi.Click += new EventHandler(tsi_Click);
this.ContextMenuStrip = cms;
}
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
this.Text = TimeSpan.Zero.ToString(#"hh\:mm\:ss");
}
private void ButtonTimer_CheckedChanged(object sender, EventArgs e)
{
if (this.Checked)
{
this.SW.Start();
this.Tmr.Start();
}
else
{
this.SW.Stop();
this.Tmr.Stop();
}
}
private void tmr_Tick(object sender, EventArgs e)
{
this.UpdateTime();
}
private void UpdateTime()
{
this.Text = this.SW.Elapsed.ToString(#"hh\:mm\:ss");
}
private void tsi_Click(object sender, EventArgs e)
{
if (this.SW.IsRunning)
{
SW.Restart();
}
else
{
SW.Reset();
}
this.UpdateTime();
}
}
Application.DoEvents() for simplicity put inside loop . . but it is advisable to start to lean threading . you will just learn how to start thread and how make cross thread safe call
Next simple will be to use backgroundworker . look this http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
ok here is thread solution also as you wanted . Tested too . as a stop variable i used Tag. But u can inherit button to make state button.it be more clear way . And below code will use one thread per button . So u should make it in one thread to make it better solution . You can modify this code to do all checkings inside one thread . For this you start thread once can make delegate for attaching dinamically count function for each button or you can pass buttons before . With one word there are more than one way to do it. Good luck
this.button1.Click += new System.EventHandler(this.button_Click);
this.button2.Click += new System.EventHandler(this.button_Click);
...and so on
private void button_Click(object sender, EventArgs e)
{
Thread x= new Thread(new ParameterizedThreadStart(Jogger2));
x.Start(sender);
}
private void button_Click(object sender, EventArgs e)
{
Button mybtn=sender as Button;
if((string)mybtn.Tag=="start"){
mybtn.Tag ="";
return;
}
mybtn.Tag = "start";
Thread x= new Thread(new ParameterizedThreadStart(Jogger2));
x.Start(sender);
}
private bool setResult(object obj,string text)
{
if (this.textBox1.InvokeRequired)
{
Func<Button,string, bool > d = new Func<Button,string,bool >(setResult);
return (bool)this.Invoke(d,obj,text);
}
else
{
Button btn=obj as Button;
if (btn != null)
{
btn.Text = text;
if ((string)btn.Tag !="start") return false;
}
return true;
}
}
private void Jogger2(object mybtn)
{
int ii = 0;
while (true)
{
Thread.Sleep(1000);
//replace with your code
ii += 1;
if (!setResult(mybtn, ii.ToString())) break;
}
}
Is there any way to make the form semi-transparent while it is being moved and then become opaque when it's not being moved anymore? I have tried the Form_Move event with no luck.
I'm stuck, any help?
The reason the form loads as semi-transparent is because the form has to be moved into the starting position, which triggers the Move event. You can overcome that by basing whether the opacity is set, on whether the form has fully loaded.
The ResizeEnd event fires after a form has finished moving, so something like this should work:
bool canMove = false;
private void Form1_Load(object sender, EventArgs e)
{
canMove = true;
}
private void Form1_Move(object sender, EventArgs e)
{
if (canMove)
{
this.Opacity = 0.5;
}
}
private void Form1_ResizeEnd(object sender, EventArgs e)
{
this.Opacity = 1;
}
To do it properly I expect you'd need to override the message processing to respond to the title bar being held, etc. But you could cheat, and just use a timer so that you make it opaque for a little while when moved, so continuous movement works:
[STAThread]
static void Main()
{
using (Form form = new Form())
using (Timer tmr = new Timer())
{
tmr.Interval = 500;
bool first = true;
tmr.Tick += delegate
{
tmr.Stop();
form.Opacity = 1;
};
form.Move += delegate
{
if (first) { first = false; return; }
tmr.Stop();
tmr.Start();
form.Opacity = 0.3;
};
Application.Run(form);
}
}
Obviously you could tweak this to fade in/out, etc - this is just to show the overall concept.