|
Yeah, no need for try catch. I called Settings.Instance.ShowDialog(); twice in succession and it was no problem. ShowDialog returns with the form's visible state to false so it's not possible.
The only way that can happen is if the method that uses the ShowDialog is being called asynchronously from another thread, or if Show() has previously been used and the form wasn't closed, or the Settings form tries to show itself whilst already visible.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
im not too sure whats going on with it then.
the showdialog() is ran whenever i click a button in a right click menu of an icon... i think the event is allowed to be called even when the form is already there, so perhaps the problem is here:
ToolStripMenuItem COMMenuItem = new ToolStripMenuItem("COM Port", null, new EventHandler(COMMenuItem_Click));
|
|
|
|
|
samskiter wrote: is allowed to be called even when the form is already there
Yeah, that's your problem.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
so making a it a singleton wont work?
|
|
|
|
|
A singleton fulfils you original objective of only having one instance of the form and it not being instanciated right at the start of your application.
If you're trying to show the same instance again before the first one is closed then you've got some serious problems elsewhere in your code that need rethinking.
Using a try...catch to solve a bad coding issue is no real solution. Identify and fix the problem.
Are you trying to show the dialog again from itself? If not, how can anything else (menus or otherwise) be accessible? The dialog form will block until closed.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
Where is this menu - is it a context menu on a NotifyIcon?
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
yes, its a notifyicon
it is defined in the Main() of my program:
public void OldMain()
{
if (SerPort.OpenPort())
{
icn = new NotifyIcon();
ContextMenuStrip menu = new ContextMenuStrip();
icn.ContextMenuStrip = menu;
ToolStripMenuItem COMMenuItem = new ToolStripMenuItem("COM Port", null, new EventHandler(this.COMMenuItem_Click));
ToolStripMenuItem ExitMenuItem = new ToolStripMenuItem("Exit", null, new EventHandler(ExitMenuItem_Click));
ToolStripSeparator separator = new ToolStripSeparator();
menu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { COMMenuItem, separator, ExitMenuItem });
icn.Visible = true;
icn.Icon = Properties.Resources.ehshell_IDI_APP1;
icn.ShowBalloonTip(3000, "Connected", "Duke Box is Connected", ToolTipIcon.Info);
MediaCenterController MCC = new MediaCenterController();
MCC.MediaStateChange += new MediaCenterController.MediaCenterHandler(SerPort.MediaCenter_Running);
MCC.MediaStateChange += new MediaCenterController.MediaCenterHandler(MediaCenter_Running);
Thread trd = new Thread(new ThreadStart(MCC.MediaCenterRunning));
trd.IsBackground = true;
trd.Start();
Application.Run();
}
else
{
}
}
i have checked the thread is not causing the problem, there is not way for the event to be fired from the thread...
|
|
|
|
|
samskiter wrote: yes, its a notifyicon
... now it makes sense!
No need to try/catch, just disable the menu item in the click handler before the ShowDialog and enable it again afterwards.
private void COMMenuItem_Click(object sender, EventArgs e)
{
COMMenuItem.Enabled = false;
Settings.ShowDialog();
COMMenuItem.Enabled = true;
}
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
BAGH! more of the same; despite declaring like this: public ToolStripMenuItem COMMenuItem;
im getting another "Object reference not set to an instance of an object." error when i click the button!
i quite like the behaviour of the properties window of the system clock (right click the clock and click properties twice)...
|
|
|
|
|
That line of code doesn't create an instance of a ToolStripMenuItem. It needs to be:
public ToolStripMenuItem COMMenuItem = new ToolStripMenuItem();
That's not done with ShowDialog. It's a normal Show() and it just checks to see if it's already visible. If not, it shows it. if it is, it justs focuses it.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
DaveyM69 wrote: That line of code doesn't create an instance of a ToolStripMenuItem
sorry, i thought the instance created in my OldMain method would be public and so would work... i tried what you suggested with showdialog before and got another error, but with show its alright.
just a couple more things:
1. it doesnt give focus, is this something i should include int he singleton code
2. upon closing and reopening the form, i get an error "Cannot access a disposed object." i think this is part of the forms coding, to dispose itself when it is closed? when i was using try...catch, i had to include a couple of lines after showdialog:
setting.Dispose();
setting = null;
i believe this is the solution so im trying to do that with Settings.Instance, but its throwing up an error about being read only. so, after removing the = null; line it ran, but the form would close straight away, which has led me to realise that...
because i am using Show, disabling the button isn't working as the button is re-enabled straight away! so im still getting the same error if i try and open the form twice!
|
|
|
|
|
Yeah, using show the form will close and dispose when closed. You can catch the FormClosing event from the main program and cancel the close but hide instead.
void Instance_FormClosing(object sender, FormClosingEventArgs e)
{
if (!Disposing)
{
e.Cancel = true;
Settings.Instance.Hide();
}
}
private void COMMenuItem_Click(object sender, EventArgs e)
{
if (Settings.Instance.Visible)
Settings.Instance.Focus();
else
Settings.Instance.Show();
}
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
ok, but doesnt hiding it mean that once created the form will always exist?
|
|
|
|
|
OK, back to square one. I thought that's what you wanted.
If not, then just create an instance each time you need it testing IsDisposed and null and forget about show dialog, singletons and everything else!
Settings formSettings;
private void COMMenuItem_Click(object sender, EventArgs e)
{
if (formSettings == null || formSettings.IsDisposed)
formSettings = new Settings();
if (formSettings.Visible)
formSettings.Focus();
else
formSettings.Show();
}
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
haha! sorry for the trouble! getting confused talking to 3 people, what i have told who!
so that is a less heavy version of:
try
{
setting.Activate();
}
catch
{
setting = new Settings();
setting.ShowDialog();
setting.Dispose();
setting = null;
}
?
just tried it and it works perfectly, thanks for the help! out of interest, if this code is run after a form has previously been created and then closed, i assume the formSettings.IsDisposed case deals with it? but does the new formSettings replace the old one? or does it create new ones over and over and fill up memory?
while your here, do you know if it is possible to include a driver installation along with my project (drivers not made by me)? i do not have a .exe for the drivers, just the files which you have to point windows in the direction of when the device is first plugged in that are then installed by windows.
thanks again!
|
|
|
|
|
No memory overhead at all. The GC will clean up automatically for you.
Yeah, if there's no installer you can include the files in your setup project and copy them to
Environment.GetFolderPath(Environment.SpecialFolder.System)) and windows should be able to find them automatically.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
your a star! im not at the stage of testing that yet, but thats great!
i followed this guide earlier: [^]
is this bad practise to create a loop to fire an event?
|
|
|
|
|
I haven't read the whole article, just a quick 'speed skim' but I wouldn't day it's bad practice as such. If an event needs to fire at a regular time, I'd do it asynchronously so the invoked method doesn't block the callee.
I have an article Events Made Simple[^] that may be worth a read if you want to learn about events.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
interesting, your final solution looks similar to what i have in my code. but doesnt it rely on an event that is built into a textbox (textBox1_TextChanged)? what if (like i found) there is nothing to start the event? specifically, i wanted to check if a process has begun or ended. i created a method that can check for this, but surely, even if i run it asynchronously, it will only check once, then return? so at the heart of an event that is always checking, there must be a loop?
i heard the word "hook" thrown around... would a 'hook' allow me to utilise a system event for a specific process ending/starting?
i think i have done it asynchronously in my project, by creating a new thread for the method, a bit like BeginInvoke does...
|
|
|
|
|
There's basically two ways of finding out about things that are happening in a system, by listening for messages/callbacks(events) from the system or going looking for them yourself and polling/monitoring them.
If there's an existing message you can hook into then that's the best way. If not then you're left with no alternative but to loop and poll.
I have no experience of dealing with external processes in .NET so I can't advise you there. I would imagine there would already me some events but you never know!
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
ok then, ill stick with my existing loop, and put that in the "todo if have time" list, which is kinda unlikely to get done as im working on two projects at the moment
if ur interested, this is what i botched together:
class MediaCenterController
{
private bool on;
public bool DataSelect(byte data)
{
return true;
}
public delegate void MediaCenterHandler(object MCRunning, MediaCenterEventArg StateInfo);
public event MediaCenterHandler MediaStateChange;
public void MediaCenterRunning()
{
for (; ; )
{
Thread.Sleep(1000);
bool onoff = (System.Diagnostics.Process.GetProcessesByName("calc").Length != 0);
Debug.WriteLine(onoff);
if (onoff != on)
{
MediaCenterEventArg StateInfo = new MediaCenterEventArg(onoff);
if (MediaStateChange != null)
{
MediaStateChange(this, StateInfo);
}
}
on = onoff;
}
}
}
public class MediaCenterEventArg : EventArgs
{
public MediaCenterEventArg(bool on)
{
this.on = on;
}
public readonly bool on;
}
changing Thread.Sleep(1000); directly affects the amount of cpu the app is using :P
|
|
|
|
|
This[^] might be of interest
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
brilliant! clearly my googling skills need some work! so there's already a nice win 32 handler: EventArrivedEventHandler , along with .EventArrived that does all the hard work for me!
much more pro than a loop, i must say!
so it registers up with WMI, using a "WQL process query string" to tell it to fire an EventArrived event whenever a process is created, modified, deleted.
presumably, i could strip off some of this for my application (eg, go straight to Init, get rid of the "modified".)
fingers crossed windows media centre doesnt screw this up like it did when i was trying to send windows messages to it...
its normal to have to use .start and .stop?
thanks
|
|
|
|
|
If your app needs to show a Form on occasion, you only have two options:
- instantiate and show the Form every time you need it;
- instantiate it once, and Show/Hide it as needed.
The amount of code will not vary much; keeping the Form alive but hidden has the characteristic that all Controls retain their settings (e.g. text entered in a TextBox by the user). The price to pay is the memory the Form is using.
BTW: you don't have to instantiate the Form right away, as in initialization code
(private Form myForm=new Form...); you can also have one or more if (myForm==null) myForm=new Form(); so the Form gets instantiated if and when it is needed for the first time.
Luc Pattyn [Forum Guidelines] [My Articles]
- before you ask a question here, search CodeProject, then Google
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get
- use the code block button (PRE tags) to preserve formatting when showing multi-line code snippets
modified on Sunday, June 12, 2011 8:23 AM
|
|
|
|
|
Luc Pattyn wrote: If your app needs to show a Form on occasion, you only have two options:
- instantiate and show the Form every time you need it;
- instantiate it once, and Show/Hide it as needed.
brill, i think i had got into my head that it could some how be instantiated without new so i could just use show when i liked, and if it was already showing, the show command would do nothing.
i think my choice will be the first one, as the settings box will be used rarely, and as you say (and i had the feeling it would), the alternative uses more memory. im not too bothered about keeping a textbox full, whenever the form loads, i will load settings onto the various controls, and when the use hits apply, i will save into settings, and hopefully code in for the settings to be updated back in the main application.
also thanks for the code for initializing the form, i think it is the same as my try...catch solution?
|
|
|
|
|