|
the code from which i constrcuted the code tell to use
Form::WndProc(m);
but if try to use it it tell me "candidate function(s) not accessible"
cause Form::WndProc is a private code.
|
|
|
|
|
it works in C#:
public class extendedDateTimePicker : DateTimePicker {
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
}
}
BTW: the message parameter takes a reference.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Luc Pattyn wrote: the message parameter takes a reference.
Do you have any idea why it is passed as reference?
|
|
|
|
|
the message is a struct you may want to modify and pass on.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Ahh. That was simple. I was not aware that Message is a struct.
Thanks
|
|
|
|
|
With the number of messages flying around in Windows, they'd better be structs.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Correct syntax is BaseClassName::MethodName . So you write DateTimePicker::WndProc(m) .
public ref class extendedDateTimePicker : DateTimePicker
{
protected:
[SecurityPermission(SecurityAction::Demand, Flags=SecurityPermissionFlag::UnmanagedCode)]
virtual void WndProc( Message% m ) override
{
if ( m.Msg == (int) 0x0014 ) { }
DateTimePicker::WndProc(m);
}
};
|
|
|
|
|
antd the winner is "N a v a n e e t h" ...thank you man...you pointed out the problem...still i'm wondering why i didn't get it by my self
|
|
|
|
|
Winner should be Luc as he pointed out the problem. I am just a syntax provider.
modified on Monday, September 28, 2009 10:22 AM
|
|
|
|
|
yes...but i know only c++ and base for me before today was an unknown identifier... now i know it's a pointer to the "base class" from which i derive mine
|
|
|
|
|
I have a background worker thread which I run to analyse some data the results of which I want to dipslay in the GUI. My question is how do I inform the main GUI thread that the worker thread has finished (the data is ready) so that it can update the GUI. I do not want to pause the main GUI thread to wait for the worker thread.
The only method I know (used back before Managed C++/CLI) is to send a windows message from the worker thread. This is handled in the message loop of the main GUI thread and so the GUI can be updated. However this feels a bit clunky to me and can cause problems when a dialog is open and the windows message is handled in the dialog's message loop and not that of the main application.
Does anybody know of a better method?
|
|
|
|
|
LetsMond wrote: how do I inform the main GUI thread that the worker thread has finished (the data is ready) so that it can update the GUI
Once done, call a method that updates GUI thread. Only thing to take care is to use Invoke/BeginInvoke. Here is a sample code.
MethodInvoker^ method = gcnew MethodInvoker(this, &YourForm::UpdateUI);
this->BeginInvoke(method); This sends a message to the main thread's message loop. You can update the controls inside the method UpdateUI .
MethodInvoker is delegate supplied with .NET framework. If you want to pass additional arguments to method, you may need to create your own delegates.
LetsMond wrote: The only method I know (used back before Managed C++/CLI) is to send a windows message from the worker thread. This is handled in the message loop of the main GUI thread and so the GUI can be updated.
This is the correct method. Message sending is encapsulated inside Invoke or BeginInvoke methods. These methods calls win32 SendMessage and PostMessage .
|
|
|
|
|
Thanks. This will do what I need.
|
|
|
|
|
Good to hear that it helped.
If you are interested, another possible method to do cross thread communication is to use SynchronizationContext[^] class. This will do the marshaling and provide a neat way for cross-thread communication.
Here is a sample code.
SynchronizationContext^ context = SynchronizationContext::Current;
Thread^ t = gcnew Thread(gcnew ParameterizedThreadStart(this, &YourForm::Execute));
t->Start(context);
void Execute(Object^ obj)
{
SynchronizationContext^ context = dynamic_cast<SynchronizationContext^>(obj);
context->Post(gcnew SendOrPostCallback(this, &YourForm::UpdateUI), "Sample text");
}
void UpdateUI(Object^ obj)
{
}
|
|
|
|
|
LetsMond wrote: However this feels a bit clunky to me and can cause problems when a dialog is open and the windows message is handled in the dialog's message loop and not that of the main application.
I didn't get that fully.
Are you saying the updates will not be visible when you have a modal window shown? If yes, that shouldn't be a problem. You will see updates happening to parent form even if a modal windows is shown.
|
|
|
|
|
You can also use a BackgroundWorker . Set the DoWork event to be your worker method, and the WorkerCompleted event to be the method that updates your GUI. I believe the WorkerCompleted event executes on the thread that started the worker thread (which in most cases will be your GUI thread).
Dybs
|
|
|
|
|
dybs wrote: I believe the WorkerCompleted event executes on the thread that started the worker thread
Nope.
Both the ProgressChanged and RunWorkerCompleted event handler will execute on the main (aka GUI) thread, no matter which thread created or started the BackgroundWorker instance. So they basically execute a MainForm.Invoke() for you.
Luc Pattyn
Have a look at my entry for the lean-and-mean competition; please provide comments, feedback, discussion, and don’t forget to vote for it! Thank you.
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Thanks for the clarification. I've always been starting a BackgroundWorker from the GUI thread anyway, so I haven't actually tested which thread the WorkerComplete event ran on. Good to know.
Dybs
|
|
|
|
|
Looks like I started a big thread discussion with that question!
I actually ended up using the BackgroundWorker class to solve my problem; however I'm having a slight problem with it. My WorkerComplete event is not always being called from the main GUI thread. I have 4 threads now which use a base class to handle the management of a BackgroundWorker object and then override functions for DoWork and WorkerComplete. In 2 cases the WorkerComplete call comes from the main GUI thread and in the other 2 cases it comes from a completely different worker thread. I'm a bit confused by this as the same code is used to create and start the BackgroundWorker in all 4 cases.
Does anybody have any ideas as to what might cause the WorkerComplete event to be called from a worker thread and not the main GUI thread?
|
|
|
|
|
LetsMond wrote: My WorkerComplete event is not always being called from the main GUI thread
I doubt that very much. what makes you think so?
I suggest you check by logging the value of Thread.CurrentThread.ManagedThreadId
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
I'm looking in the "Threads" Window to see which thread I'm on when I hit a breakpoint in the RunWorkerCompleted function. In the 2 bad cases I can see that it's not on the main thread (which is helpfully shown in green). Also if I then go on to try and perform a GUI operation things go horribly wrong.
|
|
|
|
|
Hi,
I ran some tests and there seems to be something wrong with BackgroundWorkers.
Contrary to what the documentation says, it seems like the (ProgressChanged and) RunWorkerCompleted event only executes on the GUI thread if the BGW was created (or got started?) on the GUI thread.
My investigation continues...
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Thanks for investigating!
I've been looking into the issue and I think I've found the problem, if not a good solution. When the BackgroundWorker doesn't work correctly I have created, displayed and closed a Form before starting the thread. The From changes the current SynchronizationContext object to its own thread. This becomes invalid after the Form closes (it doesn’t change it back to the original SynchronizationContext) and causes the strange behaviour when the BackgroundWorker is used.
The reason I'm seeing this might be because (for various unchangeable reasons) my program is an MFC App which also uses CLI.
I have no idea how to solve the problem. Yet
|
|
|
|
|
Hi,
seems my previous post, which was based on theory (documentation) and limited experience (only created and started on GUI), isn't correct; the BGW does not fire its progress/done events on the GUI event when it wasn't created/started on the GUI thread. I'll investigate further.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Hi there,
In my project I'm creating a Bitmap from a char-ptr (as Scan0 IntPtr).
Now the bitmap (->the char ptr) gets a changed size as a single region of the image
ist cut out. If the stride is not a multiple of four, the createbitmap function causes
an exception! Now what can I do? I have no possiblity to change the incoming char-ptr
(because I get it sent on my interface).
If I calculate the next %4 stride value and use it, my bitmap isn't displayed correctly.
BTW: It's a monochrome image with a manually assigned MonoPalette, 1 BytePerPixel: Format8bppIndexed
Thanks for always helping me so much! Special thanks to NAVANEETH!
************************************************
A little side question:
From time to time my windows forms application is hanging in a strange way. I make a snapshot of a bitmap
and display it in one of the two picture boxes. Now when I drag my mouse down on the forms, i. e. to maximize/minimize
the form, there is no reaction and the application "hangs".
My app is not run as an exe, it's loaded as a DLL from a superior application.
It also occurs, that I am in the "main app" to calculate the image, then call the forms DLL to display it, but I do not
get the "forms application" (although it is loaded) popped up from the task bar. Usually I have to click on the "forms app"
in the taskbar -> then send an image from the main app -> and then the forms project gets popped up (you see, by aiming to
popping it up before). But that is crap and shouldn't behave that way!
modified on Friday, September 11, 2009 8:39 AM
|
|
|
|