I would like to check the state of the Insert key in a C# Windows Form application. Here is minimal code (which does not work; form with two RadioButtons):
using System;
using System.Windows.Forms;
using System.Windows.Input;
// Also added PresentationCore and WindowsBase refereneces
namespace InsertModeDemo1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (Keyboard.IsKeyToggled(Key.Insert))
radioButtonInsert.Checked = true;
else
radioButtonOverstrike.Checked = true;
}
}
}
Try using Control.IsKeyLocked instead.
private void Form1_Load(object sender, EventArgs e)
{
if (Control.IsKeyLocked(Keys.Insert))
radioButtonInsert.Checked = true;
else
radioButtonOverstrike.Checked = true;
}
References: Control.IsKeyLocked
Note
The documentation says the method only works with CAPS LOCK, NUM LOCK, or SCROLL LOCK key only. But testing the method with Keys.Insert has proven that it also work for INSERT key.
You have two options:
Listen to key change events, meaning, you'll need to keep track on the status yourself according to when the button is pressed.
Using win32 interop, take a look here for example.
Related
I have two forms, "FrmRunEntry" and "FrmPartNumEntry". When I enter a value on the FrmRunEntry form, it displays the FrmPartNumEntry from and a combobox. After selecting a value in the combobox, I want to press the ENTER key and carry the selected value from the combobox back to a textbox on the FrmRunEntry form. But I cant get it to work. My combobox and form Keydown events never get triggered. My program just sits on the combobox and does nothing after I press ENTER. I've search the forum extensively and have tried the following solutions without success:
How to pass value from one form into another's combobox
How to get selected items of Combobox from one form to another form in C#
I've also tried a few other solutions that didn't work. I'm a new C# programmer and I admit I don't have a deep understanding of how C# events work. I'm hoping someone can assist in solving this problem and help me understand what I'm doing wrong. Here's the code I'm using:
FORM 1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace HydroProgram
{
public partial class FrmRunEntry : Form
{
public string selectedPartNumber = "";
public FrmRunEntry()
{
InitializeComponent();
this.ActiveControl = TxtHydro;
TxtHydro.Focus();
}
private void FrmRunEntry_Load(object sender, EventArgs e)
{
//Text Boxes
TxtHydro.CharacterCasing = CharacterCasing.Upper;
if (!string.IsNullOrEmpty(selectedPartNumber))
{
TxtPartNum.Text = selectedPartNumber;
}
}
private void TxtHydro_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
this.Hide();
FrmPartNumEntry f = new FrmPartNumEntry();
f.ShowDialog();
}
}
}
}
FORM 2
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace HydroProgram
{
public partial class FrmPartNumEntry : Form
{
public FrmPartNumEntry()
{
InitializeComponent();
this.ActiveControl = CboPartNum;
}
private void FrmPartNumEntry_Load(object sender, EventArgs e)
{
//Combo Box
CboPartNum.Location = new Point(668, 240);
CboPartNum.Size = new Size(255, 23);
CboPartNum.Focus();
CboPartNum.SelectedIndex = 1;
}
private void CboPartNum_KeyDown(object sender, KeyEventArgs e) <-- NOT BEING TRIGGERED
{
processRequest(e);
}
private void FrmPartNumEntry_KeyDown(object sender, KeyEventArgs e) <-- NOT BEING TRIGGERED
{
processRequest(e);
}
private void processRequest(KeyEventArgs e) <-- NEVER REACHED
{
if (e.KeyCode == Keys.Enter && this.ActiveControl == CboPartNum)
{
this.Hide();
FrmRunEntry f = new FrmRunEntry();
f.selectedPartNumber = Convert.ToString(CboPartNum.SelectedItem);
f.ShowDialog();
}
}
}
}
you can overload the constructor of the form for example
public FrmPartNumEntry()
{
InitializeComponent();
this.ActiveControl = CboPartNum;
}
To This
public public FrmPartNumEntry(int value)
{
InitializeComponent();
this.ActiveControl = CboPartNum;
}
Then store value in a private variable. Then you can use it anyway as you want.
if you want to pass anything simply use an object as a parameter then cast it inside the constructor. for example
public public FrmPartNumEntry(object value)
{
InitializeComponent();
int x = (int) value;
this.ActiveControl = CboPartNum;
}
in your situation where both forms are running.
assume you form1 contains combobox and form2 need the data of it then
Make a static field in form1 and make it public.
use textchanged event in combobox to assign the value to static field
access by form1.staticfieldname from form2.
I am not getting the same result as you describe. When I click on the combo box in the frmPartNumEntry form, then press the “Enter” key… the CboPartNum_KeyDown event fires as expected. So the posted code does not demonstrate what you describe.
In addition and more importantly, your code is “creating” and “hiding” multiple forms that are only displayed once, then hid and never used again. This certainly will cause confusion and problems. One issue is that if you execute the complete code, then try to “exit” the program by clicking the red x in the top right of the form… you may notice that execution does NOT stop. The code continues to run and this is because the hidden forms are technically still executing as they were never closed.
To show this… let us look at the code in the first form FrmRunEntry TxtHydro_KeyDown event. If the user presses the “Enter” key, then the currently displayed FrmRunEntry is hidden…
this.Hide();
Then a new second form FrmPartNumEntry is created and it is displayed using a ShowDialog();… This may appear correct, however there is one big problem with this code… when the user closes the second form and code execution returns to THIS code… the current FrmRunEntry is never UN-HIDDEN.
The code in second form’s FrmPartNumEntry processRequest method follows this same odd pattern, hide the current form, then it creates a NEW FrmRunEntry? ... This is NOT going to be the same FrmRunEntry form which was previously hidden. In reality NOW you have TWO (2) FrmRunEntry forms and one is hidden. If you continue to execute this code, each time the steps are duplicated… 2 NEW forms are created and hidden.
I am confident this is NOT what you want.
The posted duplicate link shows several ways to pass data between forms. In your particular case, one possible solution is the make the ComboBox on the second form a “public” combo box. Then make the following changes to the processRequest method. First, we do not want to “hide” this form… we want to CLOSE it. In addition we do NOT want to create a new FrmRunEntry form, we want to UN-hide the one that was previously hidden. So, in the processRequest all we need is to close the form. Something like…
private void processRequest(KeyEventArgs e) {
if (e.KeyCode == Keys.Enter && this.ActiveControl == CboPartNum) {
this.Close();
}
}
When this form closes, then execution will go back to the first form. Specifically the TxtHydro_KeyDown event. Execution will begin right after the…
f.ShowDialog();
line of code. So it is here where want to UN-Hide/Show the previously hidden FrmRunEntry form. In addition, we want to get the selected ComboBox value from the now closed FrmPartNumEntry. Fortunately, even though the second form is “technically” closed and not displayed… we should still be able to access the “public” variables on the form. As noted previously, if the ComboBox has it's Modifiers property set to public then the following code should work and give the first form access to the second forms ComboBox. Something like…
private void TxtHydro_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.Enter) {
this.Hide();
FrmPartNumEntry f = new FrmPartNumEntry();
f.ShowDialog();
this.Show();
TxtHydro.Text = f.CboPartNum.Text;
}
}
I hope this makes sense and helps.
Thanks to JohnG, the solution to my problem was amazingly simple. All I needed was a single line of code in the form constructor to subscribe the combobox to the event handler like this:
public FrmPartNumEntry()
{
InitializeComponent();
this.ActiveControl = CboPartNum;
CboPartNum.KeyDown += new KeyEventHandler(CboPartNum_KeyDown); <-- SOLUTION
}
One solution would be to:
on form1 define the variable as static:
public partial class Form1 : Form
{
public static string name = "xxx";
}
then on form2 access the variable from form1:
public partial class Form2 : Form
{
lblName.Text = Form1.name;
}
another option is to use an event. The following is a generic code sample which has Main form with a ComboBox and button. Press the button to show the child form and when the ComboBox selection changes an event is fired for any listeners which Form1 does listen for in a method which first checks to see if the item is in the ComboBox in Form1, if not exists, add it and select it.
Child form (Form2)
using System;
using System.Linq;
using System.Windows.Forms;
using static System.Globalization.DateTimeFormatInfo;
namespace CodeSample
{
public partial class Form2 : Form
{
public delegate void SelectionChange(string sender);
public event SelectionChange OnSelectionChange;
public Form2()
{
InitializeComponent();
MonthsComboBox.DataSource =
Enumerable.Range(1, 12).Select((index) =>
CurrentInfo.GetMonthName(index)).ToList();
MonthsComboBox.SelectedIndexChanged +=
MonthsComboBoxOnSelectedIndexChanged;
}
private void MonthsComboBoxOnSelectedIndexChanged(object sender, EventArgs e)
{
OnSelectionChange?.Invoke(MonthsComboBox.Text);
}
}
}
Form1 main form
Note I use ShowDialog, Show may be used instead.
using System;
using System.Windows.Forms;
namespace CodeSample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void ShowChildForm_Click(object sender, EventArgs e)
{
var f = new Form2();
f.OnSelectionChange += OnSelectionChange;
try
{
f.ShowDialog();
}
finally
{
f.OnSelectionChange -= OnOnSelectionChange;
f.Dispose();
}
}
private void OnSelectionChange(string sender)
{
if (MonthsComboBox.FindString(sender) != -1) return;
MonthsComboBox.Items.Add(sender);
MonthsComboBox.SelectedIndex = MonthsComboBox.Items.Count - 1;
}
}
}
Is this possible to detect a mouse click (Left/Right) anywhere (Inside and Outside the Form) in an if statement? And if it's possible, how?
if(MouseButtons.LeftButton == MouseButtonState.Pressed){
...
}
Here is a starter, if I understood your needs of "clicking from outside the window" and Hans Passant's suggestion doesn't fit your needs. You might need to add an event handler for Form1_Click.
CAUTION: This code is provided to illustrate the concept. The threading synchronization in this sample is not 100% correct. Check the history of this answer for an attempt at a more "threading correct" one that sometimes throws exceptions. As an alternative, to get rid of all threading issues, you could have the task in StartWaitingForClickFromOutside be instead always running (aka be always in "listen" mode) as opposed to trying to detect the "within the form" or "outside the form" states and starting/stopping the loop accordingly.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.MouseLeave += Form1_MouseLeave;
this.Leave += Form1_Leave;
this.Deactivate += Form1_Deactivate;
this.MouseEnter += Form1_MouseEnter;
this.Activated += Form1_Activated;
this.Enter += Form1_Enter;
this.VisibleChanged += Form1_VisibleChanged;
}
private AutoResetEvent are = new AutoResetEvent(false);
// You could create just one handler, but this is to show what you need to link to
private void Form1_MouseLeave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void Form1_Leave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void Form1_Deactivate(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void StartWaitingForClickFromOutside()
{
are.Reset();
var ctx = new SynchronizationContext();
var task = Task.Run(() =>
{
while (true)
{
if (are.WaitOne(1)) break;
if (MouseButtons == MouseButtons.Left)
{
ctx.Send(CLickFromOutside, null);
// You might need to put in a delay here and not break depending on what you want to accomplish
break;
}
}
});
}
private void CLickFromOutside(object state) => MessageBox.Show("Clicked from outside of the window");
private void Form1_MouseEnter(object sender, EventArgs e) => are.Set();
private void Form1_Activated(object sender, EventArgs e) => are.Set();
private void Form1_Enter(object sender, EventArgs e) => are.Set();
private void Form1_VisibleChanged(object sender, EventArgs e)
{
if (Visible) are.Set();
else StartWaitingForClickFromOutside();
}
}
}
If I understood you incorrectly, you might find this useful: Pass click event of child control to the parent control
When user clicks outside the form control, it losses the focus and you can make use of that.which means you have to use the _Deactivate(object sender, EventArgs e) event of the form control to make this work. Since which will trigger when the form loses focus and is no longer the active form. Let Form1 be the form, then the event will be like the following:
private void Form1_Deactivate(object sender, EventArgs e)
{
// Your code here to handle this event
}
One method is to cover the entire screen with a borderless form with the properties set to transparent (a few percent above completely transparent, not sure if total transparency works but you won't notice the difference) and also set to topmost. Then use the events from the form. As soon as a click is detected this will not affect anything underneath the form (which in my application is something I want to happen) but the form could be closed and another mouse click simulated a fraction of a second later to activate the controls that are underneath. I had no problem using the windows API to use mouse hooks in VB6 but cannot seem to find something that works in c# with the 2019 version of .NET so this is a good workaround. Of course to be really clever you could use an irregular forms method to make the transparent form the same shape as the mouse and follow it.
Note: I have just found the complete code to do it using hooks that mere mortals can get up and running at once! KeyboardMouseHooks C# Library - CodePlex Archive
PS if you use my (dumb) method remember to create an escape key or button or you will have to restart your computer unless the form is programmed to disappear for real clicks as suggested!
I know this is late but maybe it helps someone. Using the MouseEventArgs of the MouseUp event of any control you can check for mouse button and wheel among other things. Here is an example.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.MouseUp += Form1_MouseUp;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
DoSomething_LeftClick();
}
else if(e.Button == MouseButtons.Right)
{
DoSomething_RightClick();
}
}
private void DoSomething_LeftClick()
{
//Here some code
}
private void DoSomething_RightClick()
{
//Here some code
}
}
I am currently trying to make my mp3 player for a project.
I have written this code by following a guide:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string[] files, path;
[STAThread]
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
files = openFileDialog1.SafeFileNames;
path = openFileDialog1.FileNames;
for (int i = 0; i < files.Length; i++)
{
listBox1.Items.Add(files[i]);
}
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
axWindowsMediaPlayer1.URL = path[listBox1.SelectedIndex];
}
}
}
And heres a screen of my form:
For some reason when I click the OPEN button, nothing happens. First when I used this code I got an error about "Form1_load", but since I wasn't using this, I just deleted the error line and then there was no errors found.
I am very clueless, so anyone with ANY idea what is wrong?
I followed this guide completely:
http://www.c-sharpcorner.com/UploadFile/8ea152/mp3-media-player-in-C-Sharp-4-0/
Thanks
First of all make sure that you have assigned click event for your button for that just double click on your button from design window if it redirects you to the buttonclick method then everything is fine and if it does not then assign it first. For that
public Form1()
{
InitializeComponent();
button1.Click += button1_Click;
}
And
Why do you require [STAThread] here? I mean just remove the attribute and try again because [STAThread] is used for below reson:-
The STAThreadAttribute marks a thread to use the Single-Threaded COM
Apartment if COM is needed. By default, .NET won't initialize COM at
all. It's only when COM is needed, like when a COM object or COM
Control is created or when drag 'n' drop is needed, that COM is
initialized. When that happens, .NET calls the underlying
CoInitializeEx function, which takes a flag indicating whether to join
the thread to a multi-threaded or single-threaded apartment.
For more information :-
http://blogs.msdn.com/b/jfoscoding/archive/2005/04/07/406341.aspx
I'm trying to develop a simple app for Windows Phone 8, and there are many requirements for the use of the Back Button. As I don't want the Back Button to simply GoBack in back stack, I'd like to pop up a message box to warn the user that this action will bring him back to main menu.
Problem is, this page has to be reloaded some times, and the following code stop working properly after 1 reload. The messagebox opens multiple times. And the more times I reload, the more MessageBox appears.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using BackButtonTests.Resources;
namespace BackButtonTests
{
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
NavigationService.Navigating += NavigationService_Navigating;
}
void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e)
{
if (e.NavigationMode == NavigationMode.Back)
{
e.Cancel = true;
MessageBox.Show("Quit");
}
}
private void Restart_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/MainPage.xaml?reload=" + DateTime.Now.ToString(), UriKind.RelativeOrAbsolute));
//Use this fake reload query with unique value as a way to "deceive" the system, as windowsphone does not support NavigationService.Reload, and using simply the Uri of the same page will not properly load everything
}
private void Quit_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Quit");
}
}
}
This is just a test code I wrote, that shows exactly the problem I'm experiencing in my actual project. Of course there are 2 buttons written in xaml.
And the code won't work until you first reload the page, as it's not NavigatedTo when it's the front page (not a problem in my actual project).
Any clues of what I'm doing wrong?
NOTE: I'm not interested in changing the event handler (to OnBackKeyPress, for instance). I'm interested in understanding what's going on with the handler I chose (NavigationService.Navigating, NavigationMode.Back). Thanks
Updated following additional information that clarifies the questing
Changing your navigating event handler to will mean the event isn't fired on every page in the stack
void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e)
{
NavigationService.Navigating -= NavigationService_Navigating;
if (e.NavigationMode == NavigationMode.Back)
{
e.Cancel = true;
MessageBox.Show("Quit");
}
}
No longer neccessary
Override OnBackKeypress instead of navigating
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
var DoYouWantToQuit = MessageBox.Show("Are you sure you want to Quit", "Quit", MessageBoxButtons.OkCancel);
if (DoYouWantToQuit != MessageBoxButton.Ok)
{
e.Cancel = true
}
base.OnBackKeyPress(e);
}
I know this question has been asked many of times about how to create a search button. I am very new to C# programming and I am having a hard time creating a search and just haven't found what I am looking for from other posts. So I hope someone can help me.
I have created a Windows Form Application and I have a form setup using "Details" view from my DataSet and the data shows up correctly in the application when I scroll from record to record. My data is stored in a sdf file. I want to have people either enter in an "account number" or a persons "last name" and then be able to hit the search button. And after the search button the prearranged fields would update with the information. For the ability to either choose the "last name" or the "account number" I can have the items listed in a combo box if need be.
I have included a copy of the code some of the naming of the items have been changed as to not disclose my profession. Any help is greatly appreciated.
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void custtableBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.Validate();
this.custtableBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.custDataSet);
}
private void label1_Click(object sender, EventArgs e)
{
}
private void tableLayoutPanel1_Paint(object sender, PaintEventArgs e)
{
}
private void custtableBindingNavigatorSaveItem_Click_1(object sender, EventArgs e)
{
this.Validate();
this.custtableBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.custDataSet);
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'custDataSet.custtable' table. You can move, or remove it, as needed.
this.custtableTableAdapter.Fill(this.custDataSet.custtable);
}
private void file_Name_12TextBox_TextChanged(object sender, EventArgs e)
{
}
private void fillByToolStripButton_Click(object sender, EventArgs e)
{
try
{
this.custtableTableAdapter.FillBy(this.custDataSet.custtable);
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
private void btnfind_Click(object sender, EventArgs e)
{
}
}
}
What is the custtableBindingNavigatorSaveItem_Click and custtableBindingNavigatorSaveItem_Click_1 ? Thet are the same, if they are two buttons doing the same thing then you can use the same method from both buttons (though why two buttons to do the same thing I do not know).
Anyway, you have some choices and it depends on the datasize, speed needed, whether the data should be offline or db locked and so on...
Set you queries/stored procedures (sprocs are safer) to allow for limiting the result. This lets the DB do all the hard work - it is what DB's are designed for.
Read everything into memory (your table fill) and select off the table - not to disimilar really with Linq queries. This means all the data is offline and you will need to decide when and how you write it back to the database (if at all).
PS: I am intrigued, what is your profession that your pseudonym here is not enough to hide behind? Imagination gone wild !