I want to check if the Clipboard consists of a data and if not, let the "Paste" Button be enabled. But unfortunately, even after I clear the Clipboard it still doesn't show it's null. I am working with Windows Forms.
I manually clear the clipboard:
private void button2_Click(object sender, EventArgs e)
{
Clipboard.Clear();
}
and then I add the following code to the Form LoadEvent:
if (Clipboard.GetDataObject() != null)
{
this.pn1_BtnPaste.Enabled = true;
}
And it makes a button enabled which is weird to me. Can anybody explain why is that happening?
EDIT:
Because I got understood wrong, let me change the code to make it more clear:
private void button2_Click(object sender, EventArgs e)
{
Clipboard.Clear();
if (Clipboard.GetDataObject() != null)
{
this.pn1_BtnPaste.Enabled = true;
}
else
this.pn1_BtnPaste.Enabled = false;
}
I click the "button2" and the "pn1_BtnPaste" is enabled anyway.
Data can appear on the clipboard at any time. The Application.Idle event is a decent way to update the button state:
public Form1() {
InitializeComponent();
Application.Idle += Application_Idle;
}
You have to unsubscribe it again when the window closes to be on the safe side:
protected override void OnFormClosed(FormClosedEventArgs e) {
Application.Idle -= Application_Idle;
base.OnFormClosed(e);
}
Clipboard.GetDataObject() does not work the way you think it does, it never returns null. If you want to handle any data then you can write the event handler like this:
private void Application_Idle(object sender, EventArgs e) {
PasteButton.Enabled = Clipboard.GetDataObject().GetFormats().Length > 0;
}
But it is pretty likely you'll find out that handling every possible format is lot let practical than you assumed.
Related
i have a windows forms app which i want a certain button to change to enable if the textbox is not empty i tried to compare it to string.Empty but it wont work so i decided to compare to TextLength wont work either ..
Code down below:
private void Form1_Activated(object sender, EventArgs e)
{
if (firstDisplayTxtBox.TextLength > 0)
{
plusButton.Enabled = true;
}
}
mayble i place the if statement in the wrong method Let me know where i am wrong Big Thanks for helpers
Probably, you want to use TextChanged event, which fires every time when text in your firstDisplayTxtBox is changed.
public Form1()
{
InitializeComponent();
firstDisplayTxtBox.TextChanged += OnTextChange;
}
private void OnTextChange(object sender, EventArgs e)
{
plusButton.Enabled = firstDisplayTxtBox.Text.Length > 0
}
or
private void MeretOK_Click(object sender, EventArgs e)
{
//code
}
private void MeretTB_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode==Keys.Enter)
{
MeretOK_Click();
}
}
How can I start an event with a hotkey?
(I know I can just copy the code there but that is ugly)
If I just copy the code and run it I hear a beep. Why?
First, you have to allow your form to handle key events globally (set the form KeyPreview property to true) and to mark your event as internally handled. Second, if the purpose of this code is to simulate the mouse click on a specific control (programmatic click), for example a button, there is an easier way to accomplish it:
private void MeretTB_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
e.Handled = true;
myButton.PerformClick();
}
}
I've got the code, and all seems correct, I've had it reviewed and it seems impossible to find out why the button isn't doing what its coded to do. I'm making a Music player, and when I press the play button, it will be sent to the back and the pause button will become visible, when I next click the pause button, nothing happens and its primary function stops working all together. Here is the code for people to examine.
private void btnPlay_Click(object sender, EventArgs e)
{
try
{
if (_mp3Player != null)
_mp3Player.Play();
btnPlay.SendToBack();
btnPause.BringToFront();
}
catch (Win32Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnPause_Click(object sender, EventArgs e)
{
if (_mp3Player != null)
_mp3Player.Stop();
btnPause.SendToBack();
btnPlay.BringToFront();
}
Perhaps it would be best to use visibility?
private void btnPause_Click(object sender, EventArgs e)
{
if (_mp3Player != null)
{
_mp3Player.Stop();
}
btnPause.Visible = False;
btnPlay.Visible = True;
}
Or even the enabled property?
... btnPause.Enabled = false; ...
However I feel you could make it better by having it be the same button, with a value, so just have a value on it of true if it's player or false if it's pause and then in the click event check against that value to determine what it is currently and then just execute the relevant functionality and change the text or image that you have on the button.
I want to do something after the document have completely load... I dont want to use WebBrowser.DocumentCompleted Event, so please don't suggest me this.
I tried 2 ways to do it but they not work. Can someone tell me what I doing wrong?
Example 1
wb.Navigate("http://www.google.com");
while(wb.ReadyState != WebBrowserReadyState.Complete) { }
richtextdocument.Text = wb.DocumentText;
Example 2
wb.Navigate("http://www.google.com");
while(wb.isBusy == true) { }
richtextdocument.Text = wb.DocumentText;
Try to use timer to validate document load state.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
if(webBrowser1.ReadyState == WebBrowserReadyState.Complete)
{
timer1.Enabled = false;
richTextBox1.Text = webBrowser1.DocumentText;
}
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
webBrowser1.Navigate("http://www.google.com");
}
}
What you are dealing with here is trying to call an inherently asynchronous method synchronously.
As you mentioned in the comments to your question that the reason for not using DocumentCompleted is that you will need to use that event for other purposes, what I suggest you do is to use the DocumentCompleted event, coupled with a private class boolean flag to determine if this is the special case of DocumentCompleted or not.
private bool wbNeedsSpecialAction; //when you need to call the special case of Navigate() set this flag to true
public Form1()
{
InitializeComponent();
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
}
void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (wbNeedsSpecialAction)
{
richtextdocument.Text = wb.DocumentText;
wbNeedsSpecialAction = false;
}
else
{
//other cases of using DocumentCompleted...
}
}
public void Browse()
{
wbNeedsSpecialAction = true; //make sure the event is treated differently
wb.Navigate("http://www.google.com");
}
This will still allow you to control other cases within the event handler.
You must take special care to ensure that your user is not able to trigger another call to Navigate() before this 'special action' page finishes loading, otherwise it may steal the special case event. One way could be to block the UI until the page finishes loading, e.g.:
Cursor.Current = Cursors.WaitCursor;
while(wb.ReadyState != WebBrowserReadyState.Complete) {application.doevents }
I'd like to use a BackgroundWorker for background operations because I thought there is no need to take care of "BeginInvoke" etc. when updating WinForm-Controls. Is that right? As far as I know, you can update WinForms controls directly by using the ProgressChanged and RunWorkerCompleted eventhandlers.
But I can't, I although get the following exception:
Control control name accessed from a thread other than the thread it was created on
Some code:
public partial class ConfigurationForm : Form
{
public ConfigurationForm()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
label1.Text = String.Empty;
// [...]
}
private void StartButton_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy != true)
{
label1.Text = "Converting...";
backgroundWorker1.RunWorkerAsync();
}
}
private void CancelButton_Click(object sender, EventArgs e)
{
if (backgroundWorker1.WorkerSupportsCancellation == true)
{
backgroundWorker1.CancelAsync();
}
progressBar1.Dispose();
this.Close();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
// EXCEPTION here, why?
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
Converter c = new Converter();
c.Start(worker, e);
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// EXCEPTION in all cases, why?
if (e.Cancelled == true)
{
label1.Text = "Canceled";
}
else if (e.Error != null)
{
label1.Text = "Error: " + e.Error.Message;
}
else
{
label1.Text = "Done!";
}
}
}
I have to say, this is not a WinForms application but an VSTO PowerPoint add-in. The Form above gets created by the add-in like this when the user is clicking an icon in the ribbon bar of PowerPoint:
//Do I need [STAThread] here? but doesn't seem to work anyway
private void button1_Click(object sender, RibbonControlEventArgs e)
{
ConfigurationForm config = new ConfigurationForm();
config.Show();
}
Can you tell me what's the problem here?
I posted the link but I don't actually think it is the best solution. Clearly the failure occurs because you never called Application.Run() or used Form.ShowDialog(). You can assign the context explicitly as shown but you can get some very tricky problems if you don't do it right. Like assigning it more than once.
The better fix is to ask it to automatically install itself. Which then ensures that whatever form you create will then install it only when it wasn't done before. Put this in front of the form creation code:
WindowsFormsSynchronizationContext.AutoInstall = true;
With the big advantage that if the code ever gets repeated, you won't create another instance of it and potentially screw up the thread's ExecutionContext.
Do consider ShowDialog() as another fix. If I'm not mistaken then you now also have a problem with tabbing and shortcut keystrokes.
Your assumption would be correct for Windows Forms. The way it works though is BackgroundWorkers uses the SynchronizationContext of the current thread. In a windows app, that will be a WindowsFormsSynchronizationContext, which does the marshalling for you.
In a VSTO app, it won't be. It will probably just be the default one, which simply executes the methods. The link from Hans Passant has the code you need to get it to work as expected. I.e.:
System.Threading.SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
...create and start your background worker here...