By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,219 Members | 1,110 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,219 IT Pros & Developers. It's quick & easy.

Initiating GUI control creation from a non-GUI thread

P: n/a
Hi,

I have a GUI application that responds to events coming from an externaql
application. In the implementing code for the event I need to create a GUI
control and "parent" the control into the GUI. Doing this directly fails, it
is not allowed to parent a control that was not created on the main GUI
thread into the main GUI through another thread (an exception is thrown on
"control.Parent = container;").

So I have to create the control on the main thread but I don't want to
create a pool of controls upfront because there is no telling how many I
will need (it depends on the type of events that may be recieved).

So, the control needs to be created on the main thread yet this action has
to be initiated just in time from the external thread. In any Win32
application I would implement the control creation code in a message handler
of the main form, invoke it using SendMessage with WM_COMMAND and some
custom message from the other thread and retrieve the control pointer
through a private variable in the main form.

Now I could import SendMessage and hack around with some handles but I would
rather do it the .NET way.

What is the .NET way?

Regards,

Martin.
Nov 15 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
TB

----- Martin Maat [EBL] wrote: ----

Hi

I have a GUI application that responds to events coming from an externaq
application. In the implementing code for the event I need to create a GU
control and "parent" the control into the GUI. Doing this directly fails, i
is not allowed to parent a control that was not created on the main GU
thread into the main GUI through another thread (an exception is thrown o
"control.Parent = container;")

So I have to create the control on the main thread but I don't want t
create a pool of controls upfront because there is no telling how many
will need (it depends on the type of events that may be recieved)

So, the control needs to be created on the main thread yet this action ha
to be initiated just in time from the external thread. In any Win3
application I would implement the control creation code in a message handle
of the main form, invoke it using SendMessage with WM_COMMAND and som
custom message from the other thread and retrieve the control pointe
through a private variable in the main form

Now I could import SendMessage and hack around with some handles but I woul
rather do it the .NET way

What is the .NET way

Your main form should declare one or more delegates that will take the responsibility for creating the controls. Your worker thread should then use Form.Invoke to call those delegates so that the delegates run in the owning thread of the form

Look into Invoke( ), BeginInvoke( )/EndInvoke( ), and the C# delegate mechanism for more information.

-- T
Nov 15 '05 #2

P: n/a
"TB" <tb*********@kaxy.NOSPAM.com> wrote in message
news:DE**********************************@microsof t.com...
Your main form should declare one or more delegates that will take
the responsibility for creating the controls. Your worker thread should
then use Form.Invoke to call those delegates so that the delegates run
in the owning thread of the form.
Look into Invoke( ), BeginInvoke( )/EndInvoke( ), and the C# delegate

mechanism for more information.

Thank you very much for the quick response, this is indeed what I needed and
it works now. Implementing it raised one other question though. This is my
code now:
// delegate declaration in main form
private delegate RichTextBox RtbCreationDelegate();

// part run by external thread
RtbCreationDelegate del = new RtbCreationDelegate(CreateRtb);
RichTextBox rtb = (RichTextBox)Invoke(del);

// control creating method in main form
private RichTextBox CreateRtb()
{
RichTextBox rtb = new RichTextBox();
rtb.Parent = pnlMiddle;
rtb.Dock = DockStyle.Fill;
rtb.ReadOnly = true;
return rtb;
}
and like I said it works nice. I had to make the delegate return the
RichTextBox as a return value though. I initially had the delegate declared
like this:

private delegate void RtbCreationDelegate(ref RichTextBox rtb);

and then I had to pass the uninitialized rtb by ref but I could not do it. I
tried
RichTextBox rtb = null;
RtbCreationDelegate del = new RtbCreationDelegate(CreateRtb);
object[] args = new object[1];
args[0] = rtb;
Invoke(del, args);
which doesn't work, I am not passing rtb by ref so it doesn't come back. And
the address operator is not allowed on rtb (RichTextBox* cannot be
implicitely converted to object). How can I pass rtb by ref through the args
array element?

This is probably really simple and straightforward, but my curiosity
outweighs my sense of shame.

Martin.
Nov 15 '05 #3

P: n/a
Martin,
what does EBL in your signature mean? Is this some form of certification
that I must pursue...

--
Regards,
Alvin Bruney [ASP.NET MVP]
Got tidbits? Get it here...
http://tinyurl.com/3he3b
"Martin Maat [EBL]" <du***@somewhere.nl> wrote in message
news:10*************@corp.supernews.com...
"TB" <tb*********@kaxy.NOSPAM.com> wrote in message
news:DE**********************************@microsof t.com...
Your main form should declare one or more delegates that will take
the responsibility for creating the controls. Your worker thread should
then use Form.Invoke to call those delegates so that the delegates run
in the owning thread of the form.
Look into Invoke( ), BeginInvoke( )/EndInvoke( ), and the C# delegate mechanism for more information.

Thank you very much for the quick response, this is indeed what I needed

and it works now. Implementing it raised one other question though. This is my
code now:
// delegate declaration in main form
private delegate RichTextBox RtbCreationDelegate();

// part run by external thread
RtbCreationDelegate del = new RtbCreationDelegate(CreateRtb);
RichTextBox rtb = (RichTextBox)Invoke(del);

// control creating method in main form
private RichTextBox CreateRtb()
{
RichTextBox rtb = new RichTextBox();
rtb.Parent = pnlMiddle;
rtb.Dock = DockStyle.Fill;
rtb.ReadOnly = true;
return rtb;
}
and like I said it works nice. I had to make the delegate return the
RichTextBox as a return value though. I initially had the delegate declared like this:

private delegate void RtbCreationDelegate(ref RichTextBox rtb);

and then I had to pass the uninitialized rtb by ref but I could not do it. I tried
RichTextBox rtb = null;
RtbCreationDelegate del = new RtbCreationDelegate(CreateRtb);
object[] args = new object[1];
args[0] = rtb;
Invoke(del, args);
which doesn't work, I am not passing rtb by ref so it doesn't come back. And the address operator is not allowed on rtb (RichTextBox* cannot be
implicitely converted to object). How can I pass rtb by ref through the args array element?

This is probably really simple and straightforward, but my curiosity
outweighs my sense of shame.

Martin.

Nov 15 '05 #4

P: n/a
"Alvin Bruney [MVP]" <vapor at steaming post office> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
what does EBL in your signature mean? Is this some form of certification
that I must pursue...


Some weeks ago there was a thread on MVP and what it meant. It is typically
American to use titles and hang signs of competence over your work spot in
the office. Most Europeans would frown on the habit, it's a culture thing.
We would acknowledge that it will be practicle and appropriate at times to
do so but at the same time we feel uncomfortable doing it ourselves. It
feels embarrassing, in Europe people would typically be ridiculed for
overdisplaying their education. Like "one doesn't display wealth", one
should not display education too much. It probably goes back to Calvinism.
Pride is not a virtue, "one should be modest and grateful".

While reading that thread on MVP I got the idea to join in and put a title
behind my name too. It is a joke, EBL stands for "Eenvoudige Boeren Lul"
which is Dutch. The translation would be "simple dickhead from the
countryside", it is a qualification one typically assigns oneself when one
is expressing one doesn't know. "Hey, what do I know? I'm just one of those
EBL's like the most of us".

The abbreviation is not widely recognized but most Dutch people would be
able to figure it out and appreciate the joke. I could have used LDB too
which would be more easily recognized and has similar meaning though would
be harder to translate.

I will take it out now, once everyone knows it's not half that funny
anymore.

Martin.
Nov 15 '05 #5

P: n/a
TB

----- Martin Maat [EBL] wrote: ----
"TB" <tb*********@kaxy.NOSPAM.com> wrote in messag
news:DE**********************************@microsof t.com..
Your main form should declare one or more delegates that will tak
the responsibility for creating the controls. Your worker thread shoul
then use Form.Invoke to call those delegates so that the delegates ru
in the owning thread of the form
Look into Invoke( ), BeginInvoke( )/EndInvoke( ), and the C# delegat

mechanism for more information

Thank you very much for the quick response, this is indeed what I needed an
it works now. Implementing it raised one other question though. This is m
code now

[snip]

How can I pass rtb by ref through the arg
array element

This is probably really simple and straightforward, but my curiosit
outweighs my sense of shame

Hmmm... good question! I haven't actually tried this to see if it works, but it should..
Declare a new class that just encapsulates a RichTextBox..

class RTBWrappe

public RichTextBox rtb

RTBWrapper( ) { rtb = null;
Now, setup your delegate to take an RTBWrapper instead of a RichTextBox. The delegate can access the internal RichTextBox and assign it an actual control and when you get control back in your worker thread you should be able to access the now non-null value. Something like this..

RTBWrapper wrapper = new RTBWrapper()
Invoke(new RtbCreationDelegate(CreateRtb), new object[] {wrapper})
/
// Now you can reference wrapper.rtb for the actual contro

This does seem a little kludgey though... This is basically "boxing" the RichTextBox explicitly in this auxiliary class. Perhaps one can box a reference type in a generic Object in the same way one boxes a value type, but I'm not sure how that would work

-- TB
Nov 15 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.