|
Thanks for your quick reply, Navaneeth!! And now, the delegate thing is works perfectly!! I has been searching a lot about this in the internet without a result and now it's solved! Thanks a lot Navaneeth!!
I dunno if my question is beyond the topic, but can I ask about another thing? this is about the answers that Navaneeth wrote
N a v a n e e t h wrote: Because you are instantiating a new instance in the child form. You need to pass the main form's instance to child form (through constructor injection or some setter methods).
constructor injection? I'm still a beginner in C++, so I'm barely hear about this. When you say constructor injection, is it something like dependency injection? I'm googling it in the internet, and this is that came up. Correct me if I was wrong, but from what I read in Internet, this dependency injection can be done using a container (??), created by third party developer (they mentioned something about pico container and others). It can not be done by .NET itself? I'm still confused
|
|
|
|
|
roshihans wrote: constructor injection?
By constructor injection, I meant to pass the first form's object to second form via constructor. Something like
Form2(Form1^ form1)
{
} As I said, go with delegates. It's the approaprite solution for your scenario.
|
|
|
|
|
N a v a n e e t h wrote: By constructor injection, I meant to pass the first form's object to second form via constructor. Something like
Form2(Form1^ form1)
{
}
But Form1 already include Form2.h (in my case Form1 act as a "parent" form, and instantiate Form2). So I think I can't declare Form2 (Form1^ form1) and keep the form1 object, like you have mentioned above, because I need to include Form1.h inside Form2.h, and that will give me this "fatal error C1014: too many include files : depth = 1024". Or maybe I don't need to include Form1.h inside Form2.h?
Thanks
|
|
|
|
|
roshihans wrote: But Form1 already include Form2.h (in my case Form1 act as a "parent" form, and instantiate Form2). So I think I can't declare Form2 (Form1^ form1) and keep the form1 object, like you have mentioned above
Fair point! You will get circular dependency problems. To solve this, you need to have good understanding about C++ compiling and linking.
You have to use forward declaration and declare parent form in child form's header file. Assume your parent form is named as PForm and child form as CForm . Here is how your PForm 's header file looks like
public ref class PForm : public System::Windows::Forms::Form{
public:
void UpdateText(String^ str)
{
textBox1->Text = str;
}
}; Here is your CForm 's header
ref class PForm;
public ref class CForm : public System::Windows::Forms::Form{
public:
CForm(PForm^ pf)
{
InitializeComponent();
pForm = pf;
}
private:
System::Void textBox1_TextChanged(System::Object^, System::EventArgs^);
PForm^ pForm;
}; CForm.cpp contains
#include "CForm.h"
#include "PForm.h"
System::Void CForm::textBox1_TextChanged(System::Object ^sender, System::EventArgs ^e){
if(pForm != nullptr)
pForm->UpdateText(textBox1->Text);
} You show the CForm from PForm like
CForm^ cForm = gcnew CForm(this);
cForm->Show(); This should work fine. But if you use delegates, you can avoid all these and implementation will be pretty straight forward. So please stick with delegates unless you have a good reason to go with the above method.
Hope it is clear now.
|
|
|
|
|
Thanks a lot Navaneeth, you have help me solve those two problems!! Pheww.. I kinda confused at first because of this circular dependency problems, but it's has clear now.
|
|
|
|
|
I've already posted this on the C# forum, but since I will be implimenting it in managed c++ soon after, I thought I would just run it by you folks also.
I have been building a GUI that interfaces with 3 services via remoted interfaces. I'm using GenuineChannels (http://www.genuinechannels.com) broadcast engine as the framework for event based communication between services & the GUI. Since you can only register one remoted object per AppDomain (I hope that statement is correct), I've had to create a seperate AppDomain for each UserControl in the GUI so more than one remoted object can be registered. Each UserControl contains a TreeView that needs to be updated via messages from the broadcast engine, or remoted events. Everything appears to be working just as I had hoped, but here is my problem. I've tried using different types of delegates at different scopes within the code & also tried refactoring my code, but I cannot seem to come up with a way to update the TreeView instance within the UserControl from a remoted object in a seperate AppDomain. Here's most of the code from the classes involved. Unimportant peices have been removed.
namespace Console
{
public partial class ControlDelegate : UserControl
{
public ControlDelegate()
{
InitializeComponent();
// Create appdomainsetup information for the new appdomain.
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = System.Environment.CurrentDirectory;
setup.ApplicationName = ("Delegate-" + AppDomain.CurrentDomain.FriendlyName);
//Create evidence for new appdomain.
Evidence evidence = AppDomain.CurrentDomain.Evidence;
// Create the application domain.
AppDomain domain = AppDomain.CreateDomain(("Delegate-" + AppDomain.CurrentDomain.FriendlyName), evidence, setup);
DelegateMessenger remote = (DelegateMessenger)domain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, Assembly.GetCallingAssembly().GetName().Name + ".DelegateMessenger");
Thread thread = new Thread(new ThreadStart(remote.Construct));
thread.Start();
}
/****************************/
this method must be static to refer to it, which is my problem.
/****************************/
public static void tViewDelegateHeartBeat(Objects.Message message, String nickname)
{
System.Console.WriteLine(message.action);
/****************************/
The line below is part of the update to TreeView instance, but it's
the root of my problem right now.
/****************************/
//tViewDelegate.Nodes.Add(message.action + " " + nickname);
}
}
public class DelegateMessenger : MarshalByRefObject, IDelegateMessenger
{
public static String Nickname = "Delegate-" + Assembly.GetExecutingAssembly().GetName().Name;
public static DelegateMessenger Instance = new DelegateMessenger();
public static IDelegateChat iDelegateChat;
public static IDelegateServer iDelegateServer;
public static Object IDelegateChatLock = new Object();
public void Construct()
{
try
{
// Setup remoting with assembly objects as remote object.
IDictionary props = new Hashtable();
props["name"] = "gtcpd";
props["prefix"] = "gtcpd";
props["priority"] = "100";
props["port"] = "0";
GenuineTcpChannel channel = new GenuineTcpChannel(props, null, null);
ChannelServices.RegisterChannel(channel, false);
WellKnownClientTypeEntry remotetype = new WellKnownClientTypeEntry(typeof(SharedChannels.GenuineTcp.GenuineTcpChannel), "gtcpd://127.0.0.1:48886/DelegateMessenger");
RemotingConfiguration.RegisterWellKnownClientType(remotetype);
// Bind client's receiver.
RemotingServices.Marshal(Instance, "DelegateMessenger");
// Subscribe to the chat event.
lock (IDelegateChatLock)
{
iDelegateServer = (IDelegateServer)Activator.GetObject(typeof(IDelegateChat), "gtcpd://127.0.0.1:48886/DelegateServer");
iDelegateChat = iDelegateServer.JoinDialog(Nickname);
}
}
catch (Exception ex)
{
MessageBox.Show(Environment.NewLine + String.Format("Exception: {0}. Stack trace: {1}.", ex.Message, ex.StackTrace));
}
}
public Object ReceiveMessage(Objects.Message message, String nickname)
{
/*****************************/
this works fine if the receiving function is static, but I
need to refer to an instance method to be able to update
the UserControl TreeView (tViewDelegate).
/*****************************/
AppDomain.CurrentDomain.DoCallBack(delegate { ControlDelegate.tViewDelegateHeartBeat(message, nickname); });
/*****************************/
this works if I register only one remoted object within
the GUI AppDomain, which won't work with my current design
since I need to access several remoted objects from other
UserControls within the GUI.
/*****************************/
// http://blogs.msdn.com/csharpfaq/archive/2004/03/17/91685.aspx
/* if (tViewDelegate.IsHandleCreated)
{
try
{
tViewDelegate.Invoke(new tViewDelegateCallback(this.tViewDelegateHeartBeat), new Object[] { message, nickname });
}
catch (Exception ex)
{
MessageBox.Show(Environment.NewLine + String.Format("Exception: {0}. Stack trace: {1}.", ex.Message, ex.StackTrace));
}
}
*/
return null;
}
public override Object InitializeLifetimeService()
{
return null;
}
}
}
I'm hoping someone sees something silly that I'm doing and can point it out. The project is still in its infancy, so I could refactor everything if need be. Any ideas?
|
|
|
|
|
Hi, i have lots of textbox on my form, instead of adding several eventhandlers for textchanged or keypressed, i wrote a single one for all. It worked then i decided to move it to another class, but i can't bind it to eventhandler. I don't know what i did wrong. Can anyone help me please?
//If i put the code on form's class it works
this->textBox7->KeyPress += gcnew System::Windows::Forms::KeyPressEventHandler(this, &AA::SM_KeyPress);
private: System::Void SM_KeyPress(System::Object^ sender, System::Windows::Forms::KeyPressEventArgs^ e) { ...}
//But when i try to do this, i got several errors
//1>error C2276: '&' : illegal operation on bound member function expression
//1>error C3350: 'System::Windows::Forms::KeyPressEventHandler' : a delegate constructor expects 2 argument(s)
this->textBox9->KeyPress += gcnew System::Windows::Forms::KeyPressEventHandler(this, &AA::G1->SM_KeyPress);
G1 is an another class, i added these lines to use library.
#include "Genel.h"
using namespace Util;
private : Util::Genel^ G1;
Thank you very much...
|
|
|
|
|
I recreated your situation
Make sure you crete an instace that points to the class thats going to handle the event in this case HA
HandleAccessor^ HA;
this->textBox1->KeyPress += gcnew System::Windows::Forms::KeyPressEventHandler(HA,
&HandleAccessor::textBox2_KeyPress);
a programmer traped in a thugs body
|
|
|
|
|
It works!!! Thank you very much...
|
|
|
|
|
Thanks for looking at my question! I am a fairly new programmer, so please bear with me.
I am trying to make a program that takes the user-inputted values from 3 text boxes, adds them together, then displays the total as a label that I placed next to the boxes in real time-(as in the number updates automatically every time the number in one of the text boxes is changed). Also, how do I make sure the value that is inputted is only numbers?
Ok, here is what I have got so far. Obviously it doesn't work because I am asking this question.
north1, north2, and north3 are the three text boxes and northT is the label next to them. The rest is pretty easy to understand from the code.
private: System::Void northT_Click(System::Object^ sender, System::EventArgs^ e)
{
double nTotal = 0.0;
double n1 = 0.0;
double n2 = 0.0;
double n3 = 0.0;
do
{
n1 = Convert::ToDouble(north1->Text);
n2 = Convert::ToDouble(north2->Text);
n3 = Convert::ToDouble(north3->Text);
nTotal = n1 + n2 + n3;
northT->Text = nTotal.ToString();
} while(nTotal > 0);
}
Again, thanks for looking, and any help will be greatly appreciated.
|
|
|
|
|
Hi,
you're pretty close. Your question is clear, except for the "it doesn't work" which is too vague. You probably mean: I never got the sum to show at all, my program simply freezes.
AFAIK your main problem is this: you have a do-while loop inside the handler, so for positive sums it will never exit, hence the new sum also does not become visible.
Experiment: enter 0, 0, and -1
Throw away the do-while all together; the handler should calculate the sum only once each time your event fires (not sure what it is connected to).
Further improvements:
- either add a try-catch construct to deal with bad input, or start using double.TryParse
- to restrict user input, you could wire TextChanged handlers to the TextBoxes, but it is rather hard to deal with all the details (minus signs, plus signs, exponents, periods, comma's, and editing, copy/pasting, etc). The TryParse method basically takes care of it all.
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
|
|
|
|
|
Thanks for the help! I will experiment with the Double.TryParse() after I can get the intended effect from the rest of my program.
I figured out how to stop my program from freezing and keep the do_while, (I also did it without the do_while, but my assignment is to make the program using do_while), but I still do not have the intended effect.
northT (the label that displays the total) will update when I click on it, but I need it to update every time one of the values in the text boxes change.
Here is the updated version of my code.
private: System::Void northT_Click(System::Object^ sender, System::EventArgs^ e)
{
double nTotalIn = 0.0;
double nTotalFi = 0.0;
double n1 = 0.0;
double n2 = 0.0;
double n3 = 0.0;
do
{
nTotalIn = Convert::ToDouble(northT->Text);
n1 = Convert::ToDouble(north1->Text);
n2 = Convert::ToDouble(north2->Text);
n3 = Convert::ToDouble(north3->Text);
nTotalFi = n1 + n2 + n3;
northT->Text = nTotalFi.ToString();
} while(nTotalFi != nTotalIn);
}
|
|
|
|
|
Hi guys,
I have a question ya... minus a int64 with another int64.. below is my coding :-
System::Int64^ limit1;
System::Int64^ limit2;
System::Int64^ diff;
diff = limit1-limit2;
the limit1 and limit2 values are the count of the records in a database.
but the diff-limit1-limit2; is not working.
i am new to managed c++.kindly help me...
Regards,
Thilek
|
|
|
|
|
Either of these should work:
System::Int64 limit1 = 100;
System::Int64 limit2 = 25;
System::Int64 diff = limit1 - limit2;
System::Int64^ limit1 = gcnew System::Int64(100);
System::Int64^ limit2 = gcnew System::Int64(25);
System::Int64^ diff = gcnew System::Int64(*limit1 - *limit2);
System::Int64 is a value type, so if you want to use handles to a value type
(e.g. System::Int64^) then you need to create objects on the managed heap.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Don't use handles on value types.
David Anton
http://www.tangiblesoftwaresolutions.com
Convert C++ to C#, VB, or Java
Convert Java to C#, VB, or C++
Convert VB to C#, C++, Java, or Python
Convert C# to VB, C++, Java, or Python
|
|
|
|
|
Hi, a "FileNotFoundException" raised in my code during call "Activator::GetObject()" method. details as following:
Environment:
1. VS 2005 Pro - C++/CLI
2. Windows XP SP3
There are two "windows forms applications" in my application: 1) server, 2) client.
// Server side
there are two classes in server side: 1) Form1.cpp, 2)serverRemote which inherits from MarshalByRefObject.
//serverRemote.cpp, code in briefly
public ref class serverRemote: public System::MarshalByRefObject
{
public:
System::Void update()
{
}
}
//Form1.cpp, code in briefly
public ref class Form1 : public System::Windows::Forms::Form
{
public: ObjRef^ obj;
public: TcpChannel^ channel;
public: serverRemote^ rem;
System::Void server::Form1::button1_Click(System::Object^ sender, System::EventArgs^ e) {
channel = gcnew TcpChannel(9001);
ChannelServices::RegisterChannel(channel, false);
obj = RemotingServices::Marshal(rem, "TcpService");
button1->Enabled = false;
button2->Enabled = true;
}
System::Void server::Form1::button2_Click(System::Object^ sender, System::EventArgs^ e) {
RemotingServices::Unmarshal(obj);
RemotingServices::Disconnect(rem);
ChannelServices::UnregisterChannel(channel);
delete channel;
button1->Enabled = true;
button2->Enabled = false;
}
}
//client side
public ref class Form1 : public System::Windows::Forms::Form
{
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
server::serverRemote^ rmtObj = dynamic_cast<server::serverRemote^>(Activator::GetObject(Type::GetType("server.serverRemote, serverRemote", true), "tcp://localhost:9001/TcpService"));
rmtObj->update();
}
}
Each projects are complied perfectly. Then i running it in the debug mode.
1. click button1 of server, everything fine
2. click button1 of client, "FileNotFoundException was unhandled". It is said "Could not load file or assembly 'serverRemote' or one of its dependencies. The system cannot find the file specified."
(I guess might be something wrong in the Activator::GetObject() method or Type::GetType() method call, but i couldn't fix it. )
Could anyone help me? Thanks a lot in advance!
|
|
|
|
|
zkii wrote: The system cannot find the file specified."
Could you explain more specifically what sort of help you want from us? That error messages is perfectly clear to me.
|
|
|
|
|
Thanks very much for your reply.
I mean why the system cannot find the file specified? Could you please tell me what's wrong in my code?
|
|
|
|
|
zkii wrote: Could you please tell me what's wrong in my code?
Your code does not effect how the various .NET loading mechanisms work.
zkii wrote: I mean why the system cannot find the file specified?
Because the file is not located in any of the locations where the .NET system looks for it. Or if you are using one of the registration mechanisms you may have an error in your registration implementation. All of these aspects of the .NET system are well documented. Therefore your next step should be to start reading.
|
|
|
|
|
Of course i've already known what the problem is from the description of Visual Studio debug mechanisms, but i just cannot fix it. I won't post this message if I didn't read documents or searching on google or try to solve it by myself. Anyway, thanks for your suggestion.
|
|
|
|
|
zkii wrote: but i just cannot fix it.
What do you think we can do in a forum to help you diagnose the problem? We don't have access to your system to perform the diagnosis. Secondly there is no magical incantation we can chant that will fix the problem.
If you can't solve the problem the root cause of that is you don't understand the documentation. If you did, you would use the understanding to diagnose and fix the problem. Therefore my suggestion remains the same, read the documentation.
|
|
|
|
|
Hi, I am trying to make my application read fields from a string array (by reading from a .csv file), assign each single field to a new string and then cast it double. I am however having problems setting the delimiters in C+/CLI.
The code I previously wrote for C++ (reported at the end) was working file, but I can't find anywhere how to set similar delimiters using C++/CLI.
array<String^>^ Cell= gcnew array<String^>(100);
StreamReader^ sr = gcnew StreamReader( "INPUT.csv" );
while(sr->Peek() >= 0)
{
for(int i = 0; i<100; i++)
{
String^ Value0AsString= Cell[i++];
String^ Value1AsString= Cell[i++];
String^ Value2AsString= Cell[i++];
double Value0= double:: Parse( Value0AsString);
double Value1= double:: Parse( Value1AsString);
double Value2= double:: Parse( Value2AsString);
}
}
The delimiters I would like to use are the following (code in c++):
string Cell[100];
int i = 0;
ifstream INPUT ("INPUT.csv");
while (! INPUT.eof())
{
if ((i + 1) % 3 == 0) getline(INPUT, Cell[i++]);
else getline(INPUT, Cell[i++], '\,');
}
....rest of the code
Any advice is welcome!
|
|
|
|
|
You could just your regularexpressions and not worry with parsing it yourself.
a programmer traped in a thugs body
|
|
|
|
|
You are correct, the String.Split method is what you want. See the documentation[^] for an example of how to set up your delimiters in Managed C++.
Dybs
|
|
|
|
|
Hi Dybs, thanks for the reply. However I can't find any good example on the correct syntax for the String.Split method in C++/CLI...Any suggestion is welcome!
|
|
|
|
|