diff options
Diffstat (limited to 'doc/html/activeqt-dotnet.html')
-rw-r--r-- | doc/html/activeqt-dotnet.html | 459 |
1 files changed, 0 insertions, 459 deletions
diff --git a/doc/html/activeqt-dotnet.html b/doc/html/activeqt-dotnet.html deleted file mode 100644 index e61772f87..000000000 --- a/doc/html/activeqt-dotnet.html +++ /dev/null @@ -1,459 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> -<!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/extensions/activeqt/examples/dotnet/dotnet.doc:1 --> -<html> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> -<title>Walkthrough: Using TQt objects in Microsoft .NET</title> -<style type="text/css"><!-- -fn { margin-left: 1cm; text-indent: -1cm; } -a:link { color: #004faf; text-decoration: none } -a:visited { color: #672967; text-decoration: none } -body { background: #ffffff; color: black; } ---></style> -</head> -<body> - -<table border="0" cellpadding="0" cellspacing="0" width="100%"> -<tr bgcolor="#E5E5E5"> -<td valign=center> - <a href="index.html"> -<font color="#004faf">Home</font></a> - | <a href="classes.html"> -<font color="#004faf">All Classes</font></a> - | <a href="mainclasses.html"> -<font color="#004faf">Main Classes</font></a> - | <a href="annotated.html"> -<font color="#004faf">Annotated</font></a> - | <a href="groups.html"> -<font color="#004faf">Grouped Classes</font></a> - | <a href="functions.html"> -<font color="#004faf">Functions</font></a> -</td> -<td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>Walkthrough: Using TQt objects in Microsoft .NET</h1> - - - - -<!-- toc --> -<ul> -<li><a href="#1"> Introduction -</a> -<ul> -<li><a href="#1-1"> TQt vs .NET -</a> -</ul> -<li><a href="#2"> Walkthrough: .NET interop with MC++ and IJW -</a> -<li><a href="#3"> Walkthrough: .NET/COM Interop with ActiveTQt -</a> -<ul> -<li><a href="#3-1"> Starting a Project -</a> -<li><a href="#3-2"> Importing TQt Widgets -</a> -<li><a href="#3-3"> Using TQt Widgets -</a> -<li><a href="#3-4"> Handling TQt Signals -</a> -</ul> -<li><a href="#4"> Summary -</a> -<ul> -<li><a href="#4-1"> Limitations -</a> -<li><a href="#4-2"> Performance Considerations -</a> -</ul> -</ul> -<!-- endtoc --> - -<p> <h2> Introduction -</h2> -<a name="1"></a><p> In the following walkthrough we will show how TQt objects can be used -in a .NET environment, and how .NET objects can be used in a TQt -environment. -<p> <h3> TQt vs .NET -</h3> -<a name="1-1"></a><p> TQt is a C++ library and is compiled into traditional, native -binaries that make full use of the performance provided by the -runtime environment. -<p> One of the key concepts of .NET is the idea of "intermediate language -code" - the source code is compiled into a bytecode format, and at -runtime, that bytecode is executed in a virtual machine - the <em>Common Language Runtime</em> (CLR). -<p> Another key concept is that of <em>managed code</em>. This is essentially -intermediate language code written in such a way that the CLR can take -care of the memory management, i.e. the CLR will do automatic garbage -collection, so the application code does not need to explicitly free -the memory for unused objects. -<p> The MS compilers for C# and VB.NET will only produce managed -code. Such programs cannot directly call normal, native functions -or classes. <a href="#footnote1"><sup>(1)</sup></a><a name="footnote-call1"></a> -<p> The MS C++ compiler for .NET on the other hand, can produce both -normal and managed code. To write a C++ class that can be compiled -into managed code, the developer must flag the class as managed using -the <tt>__gc</tt> keyword, and restrict the code to only use the subset of -C++ known as "Managed Extensions for C++", or MC++ for short. The -advantage is that MC++ code can freely call and use normal C++ -functions and classes. And it also works the other way around: normal -C++ code can call managed functions and use managed classes (e.g. the -entire .NET framework class library), including managed functions and -classes implemented in C# or VB.NET. This feature of mixing managed -and normal C++ code immensely eases the interoperability with .NET, -and is by Microsoft referred to as the "It Just Works" (IJW) feature. -<p> This document demonstrates two different ways of integrating normal -C++ code (that uses TQt) with managed .NET code. First, the manual way -is presented, which includes using a thin MC++ wrapper class around -the normal TQt/C++ class. Then, the automated way is presented, which -utilizes the <a href="activentqt.html#ActiveTQt">ActiveTQt</a> framework as a generic bridge. The advantage of -the first method is that it gives the application developer full -control, while the second method requires less coding and relieves the -developer of dealing with the conversion between managed and normal -data objects. -<p> The impatient reader, who right away wants to see a <a href="ntqpushbutton.html">TQPushButton</a> and a -custom TQt widget (<a href="qaxserver-example-multiple.html">TQAxWidget2</a>) run in a .NET GUI application is referred to the example -directory of ActiveTQt. It contains the result of this walkthrough -using both C# and VB.NET, created with Visual Studio.NET (not 2003). -Load <tt>examples/dotnet/walkthrough/csharp.csproj</tt>, -<tt>examples/dotnet/walkthrough/vb.vbproj</tt> -<a href="#footnote2"><sup>(2)</sup></a><a name="footnote-call2"></a> -or <tt>examples/dotnet/wrapper/wrapper.sln</tt> into the IDE and run -the solution. -<p> <h2> Walkthrough: .NET interop with MC++ and IJW -</h2> -<a name="2"></a><p> Normal C++ classes and functions can be used from managed .NET code by -providing thin wrapper classes written in MC++. The wrapper class will -take care of forwarding the calls to the normal C++ functions or -methods, and converting parameter data as necessary. Since the wrapper -class is a managed class, it can be used without further ado in any -managed .NET application, whether written in C#, VB.NET, MC++ or other -managed programming language. -<p> - -<pre> // native TQt/C++ class - class Worker : public <a href="tqobject.html">TQObject</a> - { - <a href="metaobjects.html#TQ_OBJECT">TQ_OBJECT</a> - TQ_PROPERTY(TQString statusString READ statusString WRITE setStatusString) - public: - Worker(); - - <a href="tqstring.html">TQString</a> statusString() const; - - public slots: - void setStatusString(const <a href="tqstring.html">TQString</a> &string); - - signals: - void statusStringChanged(const <a href="tqstring.html">TQString</a> &string); - - private: - <a href="tqstring.html">TQString</a> status; - }; -</pre> -<p> The TQt class has nothing unusual for TQt users, and as even the TQt -specialities like <tt>TQ_PROPERTY</tt>, <tt>slots</tt> and <tt>signals</tt> are -implemented with straight C++ they don't cause any trouble when -compiling this class with any C++ compiler. -<p> - -<pre> class Worker; - - // .NET class - public __gc class netWorker - { - public: - netWorker(); - ~netWorker(); - - __property String *get_StatusString(); - __property void set_StatusString(String *string); - - __event void statusStringChanged(String *args); - - private: - Worker *workerObject; - }; -</pre> -<p> The .NET wrapper class uses keywords that are part of MC++ to indicate -that the class is managed/garbage collected (<tt>__gc</tt>), and that <tt>StatusString</tt> should be accessible as a property in languages that -support this concept (<tt>__property</tt>). We also declare an event -function <tt>statusStringChanged(String*)</tt> (<tt>__event</tt>), the -equivalent of the respective signal in the TQt class. -<p> Before we can start implementing the wrapper class we need a way to -convert TQt's datatypes (and potentionally your own) into .NET -datatypes, e.g. <a href="tqstring.html">TQString</a> objects need to be converted into objects -of type <tt>String*</tt>. -<p> When operating on managed objects in normal C++ code, a little extra -care must be taken because of the CLR's garbage collection. A normal -pointer variable should not <a href="#footnote3"><sup>(3)</sup></a><a name="footnote-call3"></a> be used to refer to a managed -object. The reason is that the garbage collection can kick in at any -time and move the object to another place on the heap, leaving you -with an invalid pointer. -<p> However, two methods are provided that solves this problem easily. The -first is to use a <em>pinned</em> pointer, i.e. declare the pointer variable -with the <tt>__pin</tt> keyword. This guarantees that the object pointed to -will not be moved by the garbage collector. It is recommended that -this method not be used to keep a references to managed objects for a -long time, since it will decrease the efficiency of the garbage -collector. The second way is to use the <tt>gcroot</tt> smartpointer -template type. This lets you create safe pointers to managed -objects. E.g. a variable of type <tt>gcroot<String></tt> will always point -to the String object, even if it has been moved by the garbage -collector, and it can be used just like a normal pointer. -<p> - -<pre> #include <<a href="tqstring-h.html">tqstring.h</a>> - - #using <mscorlib.dll> - #include <vcclr.h> - - using namespace System; - - String *TQStringToString(const <a href="tqstring.html">TQString</a> &tqstring) - { - <a name="x2467"></a> return new String(tqstring.<a href="tqstring.html#ucs2">ucs2</a>()); - } -</pre> -<p> <pre> TQString StringToTQString(String *string) - { - wchar_t __pin *chars = PtrToStringChars(string); - return TQString::fromUcs2(chars); - } -</pre> -<p> The convertor functions can then be used in the wrapper class -implementation to call the functions in the native C++ class. -<p> - -<pre> #include "networker.h" - #include "worker.h" - #include "tools.h" - - netWorker::netWorker() - { - workerObject = new Worker(); - } -</pre> -<p> <pre> netWorker::~netWorker() - { - delete workerObject; - } -</pre> -<p> The constructor and destructor simply create and destroy the TQt -object wrapped using the C++ operators <tt>new</tt> and <tt>delete</tt>. -<p> <pre> String *netWorker::get_StatusString() - { - return TQStringToString(workerObject->statusString()); - } -</pre> -<p> The netWorker class delegates calls from the .NET code to the native -code. Although the transition between those two worlds implies a small -performance hit for each function call, and for the type conversion, -this should be negligible since we are anyway going to run within the -CLR. -<p> <pre> void netWorker::set_StatusString(String *string) - { - workerObject->setStatusString(StringToTQString(string)); - __raise statusStringChanged(string); - } -</pre> -<p> The property setter calls the native TQt class before firing the -event using the <tt>__raise</tt> keyword. -<p> This wrapper class can now be used in .NET code, e.g. using C++, C#, -Visual Basic or any other programming language available for .NET. -<p> - -<pre> using System; - - namespace WrapperApp - { - class App - { - void Run() - { - netWorker worker = new netWorker(); - - worker.statusStringChanged += new netWorker.__Delegate_statusStringChanged(onStatusStringChanged); - - System.Console.Out.WriteLine(worker.StatusString); - - System.Console.Out.WriteLine("Working cycle begins..."); - worker.StatusString = "Working"; - worker.StatusString = "Lunch Break"; - worker.StatusString = "Working"; - worker.StatusString = "Idle"; - System.Console.Out.WriteLine("Working cycle ends..."); - } - - private void onStatusStringChanged(string str) - { - System.Console.Out.WriteLine(str); - } - - [STAThread] - static void Main(string[] args) - { - App app = new App(); - app.Run(); - } - } - } -</pre> -<p> <h2> Walkthrough: .NET/COM Interop with ActiveTQt -</h2> -<a name="3"></a><p> Fortunately .NET provides a generic wrapper for COM objects, the -<em>Runtime Callable Wrapper</em> (RCW). This RCW is a proxy for the -COM object and is generated by the CLR when a .NET Framework client -activates a COM object. This provides a generic way to reuse COM -objects in a .NET Framework project. -<p> Making a <a href="tqobject.html">TQObject</a> class into a COM object is easily achieved with -ActiveTQt and demonstrated in the <a href="qaxserver-examples.html">examples</a>. The walkthrough will use the TQt classes implemented -in those examples, so the first thing to do is to make sure that those -examples have been built correctly, e.g. by opening the <a href="qaxserver-demo-multiple.html">demonstration pages</a> in Internet -Explorer to verify that the controls are functional. -<p> <h3> Starting a Project -</h3> -<a name="3-1"></a><p> Start Visual Studio.NET, and create a new C# project for writing a -Windows application. This will present you with an empty form in -Visual Studio's dialog editor. You should see the toolbox, which -presents you with a number of available controls and objects in -different categories. If you right-click on the toolbox it allows -you to add new tabs. We will add the tab "TQt". -<p> <h3> Importing TQt Widgets -</h3> -<a name="3-2"></a><p> The category only has a pointer tool by default, and we have to add -the TQt objects we want to use in our form. Right-click on the empty -space, and select "Customize". This opens a dialog that has two -tabs, "COM Components" and ".NET Framework Components". We used -ActiveTQt to wrap TQWidgets into COM objects, so we select the "COM -Components" page, and look for the classes we want to use, e.g. -"TQPushButton" and "TQAxWidget2". -<p> When we select those widgets and close the dialog the two widgets -will now be available from the toolbox as grey squares with their -name next to it <a href="#footnote4"><sup>(4)</sup></a><a name="footnote-call4"></a> . -<p> <h3> Using TQt Widgets -</h3> -<a name="3-3"></a><p> We can now add an instance of TQAxWidget2 and a <a href="ntqpushbutton.html">TQPushButton</a> to -the form. Visual Studio will automatically generate the RCW for the -object servers. The TQAxWidget2 instance takes most of the upper -part of the form, with the TQPushButton in the lower right corner. -<p> In the property editor of Visual Studio we can modify the properties -of our controls - TQPushButton exposes the <a href="tqwidget.html">TQWidget</a> API and has many -properties, while TQAxWidget2 has only the Visual Studio standard -properties in addition to its own property "lineWidth" in the -"Miscellaneous" category. The objects are named "axTQPushButton1" and -"axTQAxWidget21", and since especially the last name is a bit -confusing we rename the objects to "resetButton" and "circleWidget". -<p> We can also change the TQt properties, e.g. set the "text" property -of the <tt>resetButton</tt> to "Reset", and the "lineWidth" property of the -<tt>circleWidget</tt> to 5. We can also put those objects into the layout -system that Visual Studio's dialog editor provides, e.g. by setting -the anchors of the <tt>circleWidget</tt> to "Left, Top, Right, Bottom", and -the anchors of the <tt>resetButton</tt> to "Bottom, Right". -<p> Now we can compile and start the project, which will open a user -interface with our two TQt widgets. If we can resize the dialog, -the widgets will resize appropriately. -<p> <h3> Handling TQt Signals -</h3> -<a name="3-4"></a><p> We will now implement event handlers for the widgets. Select the -<tt>circleWidget</tt> and select the "Events" page in the property -editor. The widget exposes events because the TQAxWidget2 class has -the "StockEvents" attribute set in its class definition. We implement -the event handler <tt>circleClicked</tt> for the <tt>ClickEvent</tt> to increase -the line width by one for every click: -<p> - -<pre> private void circleClicked(object sender, System.EventArgs e) - { - this.circleWidget.lineWidth++; - } -</pre> -<p> In general we can implement a default event handler by double -clicking on the widget in the form, but the default events for -our widgets are right now not defined. -<p> We will also implement an event handler for the <tt>clicked</tt> signal -emitted by <a href="ntqpushbutton.html">TQPushButton</a>. Add the event handler <tt>resetLineWidth</tt> to -the <tt>clicked</tt> event, and implement the generated function: -<p> <pre> private void resetLineWidth(object sender, System.EventArgs e) - { - this.circleWidget.lineWidth = 1; - this.resetButton.setFocus(); - } -</pre> -<p> We reset the property to 1, and also call the <tt>setFocus()</tt> slot -to simulate the user style on Windows, where a button grabs focus -when you click it (so that you can click it again with the spacebar). -<p> If we now compile and run the project we can click on the circle -widget to increase its line width, and press the reset button to -set the line width back to 1. -<p> <h2> Summary -</h2> -<a name="4"></a><p> Using ActiveTQt as a universal interoperability bridge between the -.NET world and the native world of TQt is very easy, and makes it -often unnecessary to implement a lot of handwritten wrapper classes. -Instead, the <a href="qaxfactory.html">TQAxFactory</a> implementation in the otherwise completely -cross-platform TQt project provides the glue that .NET needs to to -generate the RCW. -<p> If this is not sufficient we can implement our own wrapper classes -thanks to the C++ extensions provided by Microsoft. -<p> <h3> Limitations -</h3> -<a name="4-1"></a><p> All the limitations when using ActiveTQt are implied when using this -technique to interoperate with .NET, e.g. the datatypes we can use -in the APIs can only be those supported by ActiveTQt and COM. However, -since this includes subclasses of <a href="tqobject.html">TQObject</a> and <a href="tqwidget.html">TQWidget</a> we can wrap -any of our datatypes into a TQObject subclass to make its API -available to .NET. This has the positive side effect that the same -API is automatically available in <a href="http://www.trolltech.com/products/qsa">TQSA</a>, the cross platform -scripting solution for TQt applications, and to COM clients in general. -<p> When using the "IJW" method, in priciple the only limitation is the -time required to write the wrapper classes and data type conversion -functions. -<p> <h3> Performance Considerations -</h3> -<a name="4-2"></a><p> Every call from CLR bytecode to native code implies a small -performance hit, and necessary type conversions introduce an -additional delay with every layer that exists between the two -frameworks. Consequently every approach to mix .NET and native -code should try to minimize the communication necessary between -the different worlds. -<p> As ActiveTQt introduces three layers at once - the RCW, COM and finally -ActiveTQt itself - the performance penalty when using the generic -TQt/ActiveTQt/COM/RCW/.NET bridge is larger than when using a -hand-crafted IJW-wrapper class. The execution speed however is still -sufficient for connecting to and modifying interactive elements in a -user interface, and as soon as the benefit of using TQt and C++ to -implement and compile performance critical algorithms into native code -kicks in, ActiveTQt becomes a valid choice for making even non-visual -parts of your application accessible to .NET. -<p> -<hr> -<ol> <li><a name="footnote1"></a> -The .NET framework provides Platform Invocation -Services - P/Invoke - that enable managed code to call native C (not -C++) functions located in DLLs directly. The resulting application -then becomes partially unmanaged. <a href="#footnote-call1">Back...</a> <li><a name="footnote2"></a> - -You will notice that in the generated code the following line is -commented out: <pre> - ' VB is case insensitive, but our C++ controls are not. - ' Me.resetButton.enabled = True - </pre> - -This line is regenerated without comment whenever you change the -dialog, in which case you have to comment it out again to be able -to run the project. This is a bug in the original version of -Visual Studio.NET, and is fixed in the 2003 edition. - <a href="#footnote-call2">Back...</a> <li><a name="footnote3"></a> -Indeed, the compiler will in -many cases disallow it. <a href="#footnote-call3">Back...</a> <li><a name="footnote4"></a> -Icons could be added by modifying the -way the controls register themselves. <a href="#footnote-call4">Back...</a></ol> -</hr><p>See also <a href="qaxserver-examples.html">The TQAxServer Examples</a>. - -<!-- eof --> -<p><address><hr><div align=center> -<table width=100% cellspacing=0 border=0><tr> -<td>Copyright © 2007 -<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a> -<td align=right><div align=right>TQt 3.3.8</div> -</table></div></address></body> -</html> |