Single instance and showing a form

M

Matt

Hi

I have an app that runs without a main form, just a notification icon, when
the user clicks the icon the form is shown, and when the form is minimized
it's hidden.

This all works great, and I have implemented single instance so that when
another instance is run, an event gets signalled in the 1st instance, and
what I would like to do is to show the form. I can do this using Form.Invoke
to show the form in most cases, however at startup of my app the form isn't
shown and if the user runs the app again, I can't use Form.Invoke as there
isn't a valid window handle.

How can I call my code to show the form in the context of the UI thread? If
I call Form.Show from the thread that is waiting on the event (which is from
the threadpool) the form doesn't show properly and all hell breaks loose :)

Thanks in advance!

Matt
 
M

Matt

Hi Pete

Thanks for the ideas, I had looked at SynchronizationContext briefly, but
every time i accessed SynchronizationContext.Current it always returned null,
although I was only doing this early on in the app before I had called
Application.Run, so that might have been the issue.

I had tried instantiating the MainForm object and then calling Create, but
that did not allow me to use Invoke, although I haven't tried using
CreateHandle, I'll give that a try later and look into the
SynchronizationContext in more detail as well. I can't try anything at the
moment as my development machine b0rked this morning :(

Also your comments about not calling Application.Run until I need to show
the form are interesting, hadn't thought of that one, thanks for pointing it
out! :) One question though, do I need to call Application.Run for the
notification icon to work? I'll give it a try and see what happens later,
when my machine is back up and running :)

Cheers

Matt

Peter Duniho said:
[...]
How can I call my code to show the form in the context of the UI thread?
If
I call Form.Show from the thread that is waiting on the event (which is
from
the threadpool) the form doesn't show properly and all hell breaks loose
:)

There is a class call SynchronizationContext that you can use in lieu of a
Control instance for invoking a delegate on a particular thread. It's
possible that using that would address your need.

Alternatively, you could go ahead and create the form instance immediately
when your application starts, and then call Control.CreateHandle() in your
form's constructor to ensure that its window handle is created and that it
can receive messages (necessary for Invoke() to work). Then you have the
form instance available for calling Invoke(), even though it hasn't been
shown yet. I haven't had a chance to test that particular technique, but
I think it should work.

Finally, you might consider having your main thread not call
Application.Run() until you're ready to show the form for the first time.
Just have it wait (e.g. using an AutoResetEvent or with the Monitor
class), and then have logic in your window-showing code that, if the form
hasn't been created yet, signals the main thread to proceed with creating
and showing the form instance, and then calling Application.Run(). If the
form has been created, then of course you'd just show it. The former
wouldn't require calling Invoke() -- you'd just be using the inter-thread
communication object to release the main thread -- and of course the
latter can call Invoke() since you'd have created the form instance by
then.

Pete
 
M

Matt

Thanks again Pete for your help, I'll try out your ideas and let you know
about the Application.Run() with the NotifyIcon, I'm interested to know
myself.

You were correct, I did mean CreateControl, sorry, not having access to my
PC (lol, it won't even turn on, I'm waiting for an engineer to arrive) I
can't access the source code, it sounds like CreateHandle is what I need, so
I'll give that a try once my pc is back up and running.

And as far as using the application context, I have to agree with you, seems
like a bit of a hack and only to be used if all else fails :)

Thanks again for your help!

Matt
 
M

Matt

Hi Peter

I finally have got a development PC back up and running again, and have
given your ideas a try, and I'm happy to say that the Control.CreateHandle
idea has worked a treat! So now I have a nice single instance class that can
notify the running instance when it's run a second time and will show the
form correctly in all cases.

I took another look at the documentation, and according to that,
CreateControl is supposed to be the method to use, as it creates the handle
and also any child controls, but it definitely doesn't create the handle, oh
well :)

Many thanks for your suggestions!

Matt
 
M

Matt

Yeah it was the docs for Control.CreateHandle... it says you should use
CreateControl as the preferred method, which was why I tried CreateControl
originally, but I did miss the part about the visible flag in the docs for
CreateControl... Doh! Sorry about that

Thanks again

Matt
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top