In my main form, I am running this:
this.disableForm();
btnAbort.Enabled = true;
disableForm is an extension method for Form in my program defined as the following:
public static void disableForm(this Form f)
{
foreach (Control c in f.Controls)
{
f.Enabled = false;
}
f.Cursor = Cursors.WaitCursor;
}
The problem is that the next command btnAbort.Enabled = true; doesn't do anything.
It works if I put the code directly in the method and not call disableForm(). Why is this happening? Does it have something to do with threads?
This line:
f.Enabled = false;
Should be
c.Enabled = false;
The problem is because you are accidentally disabling your entire form.
public static void disableForm(this Form f)
{
foreach (Control c in f.Controls)
{
//f.Enabled = false;
c.Enabled = false;
}
f.Cursor = Cursors.WaitCursor;
}
Related
I want to define my own Cursor as the Current Cursor in my WPF Application, but wenn I try to create a new Cursor Object from my .cur File, I get an Error.
My Code is
private void NewFile()
{ ...
iEvent_dragdrop = (HTMLDocumentEvents2_Event)doc;
iEvent_dragdrop.ondragstart += new HTMLDocumentEvents2_ondragstartEventHandler(IEvent_ondragstart);
}
private bool IEvent_ondragstart(IHTMLEventObj pEvtObj)
{
x_start = pEvtObj.x; // Read position of Mouse
y_start = pEvtObj.y;
....
if (File.Exists("MyCursor.cur"))
{
System.Windows.Forms.Cursor myCursor = new System.Windows.Forms.Cursor(GetType(), "MyCursor.cur");
System.Windows.Forms.Cursor.Current = myCursor;
//System.Windows.Forms.MessageBox.Show("File exist");
}
else System.Windows.Forms.MessageBox.Show("File does not exist");
return false;
}
When I try to drag the HTML Object, I get the error System.NullReferenceException wasn´t handled in the source-code. But I tested if the File exists ....
Can anyone tell me, what´s my mistake?
Thanks!
I recommend searching the web before asking. First search result for the title explains everything you should need to know.
Try this out:
class Program {
[System.STAThread]
static void Main(string[] args) {
byte[] cursorBytes = new System.Net.WebClient().DownloadData(#"https://github.com/tlorach/nvGraphy/raw/master/cursor1.cur");
System.IO.Stream cursorStream = new System.IO.MemoryStream(cursorBytes, false);
System.Windows.Forms.Cursor cursor = new System.Windows.Forms.Cursor(cursorStream);
System.Windows.Forms.Form mainForm = new System.Windows.Forms.Form();
mainForm.Cursor = cursor;
System.Windows.Forms.Application.Run(mainForm);
}
}
Or this:
class Program {
[System.STAThread]
static void Main(string[] args) {
System.Windows.Forms.OpenFileDialog openDialog = new System.Windows.Forms.OpenFileDialog();
openDialog.Filter = "Cursor (*.cur)|*.cur";
switch(openDialog.ShowDialog()) {
case System.Windows.Forms.DialogResult.OK:
System.Windows.Forms.Cursor cursor = new System.Windows.Forms.Cursor(openDialog.FileName);
System.Windows.Forms.Form mainForm = new System.Windows.Forms.Form();
mainForm.Cursor = cursor;
System.Windows.Forms.Application.Run(mainForm);
break;
}
}
}
I am developing a chat application using jabber-net opensource library..
my aim is to display a form (chat window ) when a message is coming.
But when I use this code, Form appears in the task bar,,, not perfectly rendered...
seems like this... More over I can see the form only when I mousehover the Icon on taskbar (Hail Windows 7)... Any form are like this...
Click here for Output Image
my code is this...
public jabber.client.JabberClient jabberClient1;
jabberClient1.User = UserName;
jabberClient1.Password = Password;
jabberClient1.Resource = resource;
jabberClient1.AutoRoster = true;
jabberClient1.OnMessage += new MessageHandler(jabberClient1_OnMessage);
private void jabberClient1_OnMessage(object sender, jabber.protocol.client.Message msg)
{
try
{
chatWindow chw = new chatWindow();
chw.Left = 0;
chw.Top = 0;
chw.TopMost = true;
//chw.LoadChat(msg.From.User, msg.From.Bare, "0");
//chw.SetMessage(msg);
chw.Show();
}
}
you have to use chw.ShowDialog()
or use if invokerequired
private delegate void dlgInvokeRequired();
public void InvokeMethode()
{
if (this.InvokeRequired == true)
{
dlgInvokeRequired d = new dlgInvokeRequired(InvokeMethode);
this.Invoke(d);
} else
{
chatWindow chw = new chatWindow();
chw.Left = 0;
chw.Top = 0;
chw.TopMost = true;
//chw.LoadChat(msg.From.User, msg.From.Bare, "0");
//chw.SetMessage(msg);
chw.Show();
}
}
I have solved it myself...
I have to use
JabberClient1.InvokeControl = FormInstance;
and, the FormInstance should be shown Before the chat window appears....
ie, It can be the contact window (Roster)....
I have one MDIPrent Form that is my main form. Now I am logging out form Main_Form by clicking LogOut MenuStrip. In my code I have prevented duplicate instance. But I get this error. I have googled so much, tried so many things but error doesn't go away.
Below is code for Program.cs file:
using System.Diagnostics;
static class Program
{
[STAThread]
static void Main()
{
LoggedInUser = string.Empty;
loginSuccess = false;
String thisprocessname = Process.GetCurrentProcess().ProcessName;
if (Process.GetProcesses().Count(p => p.ProcessName == thisprocessname) > 1)
return;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MyApplicationContext context = new MyApplicationContext();
Application.Run(context);
}
public class MyApplicationContext : ApplicationContext
{
private Login_Form lgFrm = new Login_Form();
public MyApplicationContext()
{
try
{
lgFrm.ShowDialog();
if (lgFrm.LogonSuccessful)
{
////lgFrm.Close();
lgFrm.Dispose();
FormCollection frm = Application.OpenForms;
try
{
foreach (Form fc in frm)
fc.Close();
}
catch (Exception ex){}
Application.Run(new Main_Form());
}
}
catch (Exception ex){}
}
}
}
Below is the code for Login_Form
public bool LogonSuccessful
{
get
{
return Program.loginSuccess;
}
set
{
Program.loginSuccess = value;
}
}
private void BtnEnter_Click(object sender, EventArgs e)
{
Login_Form lgn = new Login_Form();
Program.loginSuccess = true;
this.Hide();
Program.LoggedInUser = TxtBxUserName.Text;
}
Below is for Main_Form
private void LogOutMenuItem_Click(object sender, EventArgs e)
{
Login_Form lgFrm = new Login_Form();
lgFrm.LogonSuccessful = false;
Program.loggedOut = true;
Program.LoggedInUser = string.Empty;
this.Close();
////FormCollection frm = Application.OpenForms;
////foreach (Form fc in frm)
////{
//// MessageBox.Show(fc.ToString());
////}
Program.MyApplicationContext context = new Program.MyApplicationContext();
Application.Run(context);
}
I have used context, because I want to make Main_Form, the only OpenForm of application. Somewhere I got the idea of using the context.
Your exception is because you call Application.Run(...) inside another Application.Run(...), modify as follow:
//MyApplicationContext constructor
public MyApplicationContext()
{
try
{
lgFrm.ShowDialog();
if (lgFrm.LogonSuccessful)
{
////lgFrm.Close();
lgFrm.Dispose();
FormCollection frm = Application.OpenForms;
try
{
foreach (Form fc in frm)
fc.Close();
}
catch (Exception ex){}
//Application.Run(new Main_Form()); <<<---- Remove this
MainForm = new Main_Form();
}
}
catch (Exception ex){}
//Add the ThreadExit event handler here
ThreadExit += (s,e) => {
if(Program.loggedOut) {
Program.MyApplicationContext ctxt = new Program.MyApplicationContext();
Application.Run(ctxt);
}
};
}
}
//
private void LogOutMenuItem_Click(object sender, EventArgs e)
{
Login_Form lgFrm = new Login_Form();
lgFrm.LogonSuccessful = false;
Program.loggedOut = true;
Program.LoggedInUser = string.Empty;
this.Close(); //I think you want to call Application.Restart() here?
//if so, you don't need the ThreadExit event handler added in the MyApplicationContext() constructor.
}
try this: instead of firing a new application when logging off, just dispose your window and replace MyApplicationContext() in this:
public MyApplicationContext()
{
bool isSuccessful = false;
do
{
try
{
lgFrm = new Login_Form();
lgFrm.ShowDialog();
if (lgFrm.LogonSuccessful)
{
isSuccessful = lgFrm.LogonSuccessful;
////lgFrm.Close();
lgFrm.Dispose();
FormCollection frm = Application.OpenForms;
try
{
foreach (Form fc in frm)
fc.Close();
}
catch (Exception ex){}
Application.Run(new Main_Form());
}
}
catch (Exception ex){}
}while(isSuccessful);
}
i had the same problem
the best way to solve this is Using
Application.Restart();
you should Use it when ever a User Log out , so the main UI close
and the log in dialog appear !!
but with Log in Form U gotta use this
ControlBox = False;
so the User can't bypass it by closing it!!
Simply U can add an Exit Button with code
Application.Exit();
this is how i solved this problem with out any additional Usings or Errors ...
I'm trying to change an Object's properties from another class, like so.
abilities.cs (class)
public static void hideAllButtons()
{
frmFight fight = new frmFight();
fight.btnAbility1.Visible = false;
fight.btnAbility2.Visible = false;
fight.btnAbility3.Visible = false;
fight.btnAbility4.Visible = false;
fight.btnAbility5.Visible = false;
fight.btnAbility6.Visible = false;
vars.buttonsVisible = false;
}
I'm trying to use the method from the previous class to change the object's properties in the following Form;
frmFight.cs (form)
private void btnAbility1_Click(object sender, EventArgs e)
{
abilities.hideAllButtons();
btnAbilities.Enabled = false;
}
I've tried everything in my knowledge and understanding, and a lot of looking up on the internet. I've tried making the objects static, public, creating the object within the class. But nothing works. Usually I get StackOverFlow errors.
I'm pretty new to OOP, too, but I'm not an idiot so don't think to go too 'lightly' on me with a possible fix, or cause, of my problem - if you understand, that is.
Method hideAllButtons is static so should have a Form argument.
public static void hideAllButtons(frmFight fight)
{
fight.btnAbility1.Visible = false;
fight.btnAbility2.Visible = false;
fight.btnAbility3.Visible = false;
fight.btnAbility4.Visible = false;
fight.btnAbility5.Visible = false;
fight.btnAbility6.Visible = false;
//vars.buttonsVisible = false; // What about this???
}
and call this method in click handler,
hideAllButtons(this);
This really wont work because your controls is on your frmFight.
You need to do is place
private void hideAllButtons()
{
btnAbility1.Visible = false;
btnAbility2.Visible = false;
btnAbility3.Visible = false;
btnAbility4.Visible = false;
btnAbility5.Visible = false;
btnAbility6.Visible = false;
vars.buttonsVisible = false;
}
on your frmFight.cs (form) as private method and just call it on your button click to make it simpler.
private void btnAbility1_Click(object sender, EventArgs e)
{
hideAllButtons();
btnAbilities.Enabled = false;
}
Regards
Im trying to load a dataGridView which takes some time, so ive come up with an idea of hiding the datagridview and put an image over the top which says Loading... when finished, the image goes away and the datagrid reappears. Ive tried to do this using threading but having no luck.
Can somebody tell me if i am approaching this in the right way?
Label loadingText = new Label();
PictureBox loadingPic = new PictureBox();
private void TelephoneDirectory_Load(object sender, EventArgs e)
{
dataGridView1.Visible = false;
Thread i = new Thread(LoadImage);
i.Start();
Thread t = new Thread(LoadData);
t.Start();
}
void LoadImage()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(LoadImage));
}
else
{
loadingPic.Image = Properties.Resources.ReportServer;
loadingPic.Location = new Point(0, 0);
loadingPic.Name = "loadingPic";
loadingPic.Dock = DockStyle.Fill;
loadingPic.SizeMode = PictureBoxSizeMode.CenterImage;
loadingText.Text = "Loading, please wait...";
loadingText.Name = "loadingText";
loadingText.TextAlign = ContentAlignment.MiddleCenter;
loadingText.Size = new Size(this.Size.Width, 30);
loadingText.Font = new System.Drawing.Font("Segoe UI", 9);
loadingText.Location = new Point(0, (this.Size.Height / 2 + 10));
this.Controls.AddRange(new Control[] { loadingPic, loadingText });
loadingText.BringToFront();
}
}
private void LoadData()
{
if (dataGridView1.InvokeRequired)
{
dataGridView1.Invoke(new MethodInvoker(this.LoadData));
}
else
{
DirectorySearcher sea = null;
DirectoryEntry dir = null;
DirectoryEntry d = null;
string domainname = System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain().Name;
domainname = domainname.Replace(".", ",DC=");
try
{
dir = new DirectoryEntry();
dir.Path = "LDAP://DC=" + domainname;
sea = new DirectorySearcher(dir);
sea.Filter = "(&(objectClass=user)(extensionAttribute1=1)(telephoneNumber=*))";
sea.PageSize = 2000;
SearchResultCollection res = sea.FindAll();
foreach (SearchResult result in res)
{
//DO ALL MY STUFF
dataGridView1.Rows.Add(row);
}
}
catch { }
LoadDataComplete();
}
}
void LoadDataComplete()
{
PictureBox loadingGraphic = this.Controls["loadingPic"] as PictureBox;
Label LoadingLabel = this.Controls["loadingText"] as Label;
DataGridView dataGrid = this.Controls["dataGridView1"] as DataGridView;
dataGrid.Visible = true;
LoadingLabel.Visible = false;
LoadingLabel.Dispose();
loadingGraphic.Visible = false;
loadingGraphic.Dispose();
dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Ascending);
dataGridView1.ClearSelection();
}
Spawning threads for this might not be the best idea, you could use ThreadPool or BackgroundWorker
Loading image should be fast enough that you could just do it synchronously, so make sure you actually need to do some operation on the other thread before you actually need it.
Ask yourself questions like: what if actually my image will load later then my dataTable? ("but it loads faster every time I checked" is not an valid argument when talking about threads)
At the beginning of your methods you are using .Invoke which basically means "wait for UI thread and invoke my code on it synchronously" which bombards your whole idea.
Try something like this:
Load image synchronously
Use ThreadPool to load your DataTable in it, but without using .Invoke
When it's loaded and you need to interact with UI -> then put your code in .Invoke()
Pseudocode coud look like this:
private void TelephoneDirectory_Load(object sender, EventArgs e)
{
dataGridView1.Visible = false;
LoadImage();
ThreadPool.QueueUserWorkItem(new WaitCallback(o => LoadData()));
}
void LoadData()
{
//...Do loading
//but don't add rows to dataGridView
if (dataGridView1.InvokeRequired)
{
//Invoke only the ui-interaction code
dataGridView1.Invoke(new MethodInvoker(this.LoadDataComplete));
}
}
void LoadDataComplete()
{
foreach (SearchResult result in res)
{
//DO ALL MY STUFF
//If do all my stuff is compute intensive and doesn't require UI,
//put it before Invoke() (like here)
dataGridView1.Rows.Add(row);
}
//Rest of code
}