Add \brief comments to ActiveQt examples.
[qt:qtactiveqt.git] / src / activeqt / doc / src / examples / dotnet.qdoc
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the documentation of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:FDL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Free Documentation License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Free
19 ** Documentation License version 1.3 as published by the Free Software
20 ** Foundation and appearing in the file included in the packaging of
21 ** this file.  Please review the following information to ensure
22 ** the GNU Free Documentation License version 1.3 requirements
23 ** will be met: http://www.gnu.org/copyleft/fdl.html.
24 ** $QT_END_LICENSE$
25 **
26 ****************************************************************************/
27
28 /*!
29     \page activeqt-dotnet.html
30     \title Dot Net Example (ActiveQt)
31
32     \brief The Dot Net example demonstrates how Qt objects can be used in a
33     .NET environment, and how .NET objects can be used in a Qt
34     environment.
35
36     Contents:
37
38     \tableofcontents
39
40     \section1 Qt vs. .NET
41
42     Qt is a C++ library and is compiled into traditional, native
43     binaries that make full use of the performance provided by the
44     runtime environment.
45
46     One of the key concepts of .NET is the idea of "intermediate language
47     code" - the source code is compiled into a bytecode format, and at
48     runtime, that bytecode is executed in a virtual machine - the \e
49     {Common Language Runtime} (CLR).
50
51     Another key concept is that of \e {managed code}. This is essentially
52     intermediate language code written in such a way that the CLR can take
53     care of the memory management, i.e. the CLR will do automatic garbage
54     collection, so the application code does not need to explicitly free
55     the memory for unused objects.
56
57     The MS compilers for C# and VB.NET will only produce managed
58     code. Such programs cannot directly call normal, native functions
59     or classes. \footnote The .NET framework provides Platform Invocation
60     Services - P/Invoke - that enable managed code to call native C (not
61     C++) functions located in DLLs directly. The resulting application
62     then becomes partially unmanaged.\endfootnote
63
64     The MS C++ compiler for .NET on the other hand, can produce both
65     normal and managed code. To write a C++ class that can be compiled
66     into managed code, the developer must flag the class as managed using
67     the \c __gc keyword, and restrict the code to only use the subset of
68     C++ known as "Managed Extensions for C++", or MC++ for short. The
69     advantage is that MC++ code can freely call and use normal C++
70     functions and classes. And it also works the other way around: normal
71     C++ code can call managed functions and use managed classes (e.g. the
72     entire .NET framework class library), including managed functions and
73     classes implemented in C# or VB.NET. This feature of mixing managed
74     and normal C++ code immensely eases the interoperability with .NET,
75     and is by Microsoft referred to as the "It Just Works" (IJW) feature.
76
77     This document demonstrates two different ways of integrating normal
78     C++ code (that uses Qt) with managed .NET code. First, the manual way
79     is presented, which includes using a thin MC++ wrapper class around
80     the normal Qt/C++ class. Then, the automated way is presented, which
81     utilizes the ActiveQt framework as a generic bridge. The advantage of
82     the first method is that it gives the application developer full
83     control, while the second method requires less coding and relieves the
84     developer of dealing with the conversion between managed and normal
85     data objects.
86
87     The impatient reader, who right away wants to see a QPushButton
88     and a custom Qt widget (\l{activeqt/multiple}{QAxWidget2}) run in
89     a .NET GUI application is referred to the example directory of
90     ActiveQt. It contains the result of this walkthrough using both
91     C# and VB.NET, created with Visual Studio .NET (not 2003).
92     Load \c {examples/dotnet/walkthrough/csharp.csproj},
93     \c {examples/dotnet/walkthrough/vb.vbproj}
94     or \c {examples/dotnet/wrapper/wrapper.sln} into the IDE and run
95     the solution.
96
97     \b{Remark:} You will notice that in the generated code the following line is
98     commented out:
99
100     \snippet doc/src/snippets/code/doc_src_examples_activeqt_dotnet.qdoc 0
101
102     This line is regenerated without comment whenever you change the
103     dialog, in which case you have to comment it out again to be able
104     to run the project. This is a bug in the original version of
105     Visual Studio.NET, and is fixed in the 2003 edition.
106
107     \section1 Walkthrough: .NET interop with MC++ and IJW
108
109     Normal C++ classes and functions can be used from managed .NET code by
110     providing thin wrapper classes written in MC++. The wrapper class will
111     take care of forwarding the calls to the normal C++ functions or
112     methods, and converting parameter data as necessary. Since the wrapper
113     class is a managed class, it can be used without further ado in any
114     managed .NET application, whether written in C#, VB.NET, MC++ or other
115     managed programming language.
116
117     \snippet examples/activeqt/dotnet/wrapper/lib/worker.h 0
118
119     The Qt class has nothing unusual for Qt users, and as even the Qt
120     specialities like \c Q_PROPERTY, \c slots and \c signals are
121     implemented with straight C++ they don't cause any trouble when
122     compiling this class with any C++ compiler.
123
124     \snippet examples/activeqt/dotnet/wrapper/lib/networker.h 0
125
126     The .NET wrapper class uses keywords that are part of MC++ to indicate
127     that the class is managed/garbage collected (\c {__gc}), and that \c
128     StatusString should be accessible as a property in languages that
129     support this concept (\c {__property}).  We also declare an event
130     function \c statusStringChanged(String*) (\c {__event}), the
131     equivalent of the respective signal in the Qt class.
132
133     Before we can start implementing the wrapper class we need a way to
134     convert Qt's datatypes (and potentionally your own) into .NET
135     datatypes, e.g. \c QString objects need to be converted into objects
136     of type \c {String*}.
137
138     When operating on managed objects in normal C++ code, a little extra
139     care must be taken because of the CLR's garbage collection. A normal
140     pointer variable should not \footnote Indeed, the compiler will in
141     many cases disallow it. \endfootnote be used to refer to a managed
142     object. The reason is that the garbage collection can kick in at any
143     time and move the object to another place on the heap, leaving you
144     with an invalid pointer.
145
146     However, two methods are provided that solves this problem easily. The
147     first is to use a \e pinned pointer, i.e. declare the pointer variable
148     with the \c __pin keyword. This guarantees that the object pointed to
149     will not be moved by the garbage collector. It is recommended that
150     this method not be used to keep a references to managed objects for a
151     long time, since it will decrease the efficiency of the garbage
152     collector. The second way is to use the \c gcroot smartpointer
153     template type. This lets you create safe pointers to managed
154     objects. E.g. a variable of type \c gcroot<String> will always point
155     to the String object, even if it has been moved by the garbage
156     collector, and it can be used just like a normal pointer.
157
158     \snippet examples/activeqt/dotnet/wrapper/lib/tools.cpp 0
159     \codeline
160     \snippet examples/activeqt/dotnet/wrapper/lib/tools.cpp 1
161
162     The convertor functions can then be used in the wrapper class
163     implementation to call the functions in the native C++ class.
164
165     \snippet examples/activeqt/dotnet/wrapper/lib/networker.cpp 0
166     \codeline
167     \snippet examples/activeqt/dotnet/wrapper/lib/networker.cpp 1
168
169     The constructor and destructor simply create and destroy the Qt
170     object wrapped using the C++ operators \c new and \c delete.
171
172     \snippet examples/activeqt/dotnet/wrapper/lib/networker.cpp 2
173
174     The netWorker class delegates calls from the .NET code to the native
175     code. Although the transition between those two worlds implies a small
176     performance hit for each function call, and for the type conversion,
177     this should be negligible since we are anyway going to run within the
178     CLR.
179
180     \snippet examples/activeqt/dotnet/wrapper/lib/networker.cpp 3
181
182     The property setter calls the native Qt class before firing the
183     event using the \c __raise keyword.
184
185     This wrapper class can now be used in .NET code, e.g. using C++, C#,
186     Visual Basic or any other programming language available for .NET.
187
188     \snippet examples/activeqt/dotnet/wrapper/main.cs 0
189     \snippet examples/activeqt/dotnet/wrapper/main.cs 1
190     \snippet examples/activeqt/dotnet/wrapper/main.cs 2
191     \snippet examples/activeqt/dotnet/wrapper/main.cs 3
192
193     \section1 Walkthrough: .NET/COM Interop with ActiveQt
194
195     Fortunately .NET provides a generic wrapper for COM objects, the
196     \e {Runtime Callable Wrapper} (RCW). This RCW is a proxy for the
197     COM object and is generated by the CLR when a .NET Framework client
198     activates a COM object. This provides a generic way to reuse COM
199     objects in a .NET Framework project.
200
201     Making a QObject class into a COM object is easily achieved with
202     ActiveQt and demonstrated in the QAxServer examples (e.g., the
203     \l{activeqt/simple}{Simple} example). The walkthrough will use
204     the Qt classes implemented in those examples, so the first thing
205     to do is to make sure that those  examples have been built
206     correctly, e.g. by opening the
207     \l{qaxserver-demo-multiple.html}{demonstration pages} in Internet
208     Explorer to verify that the controls are functional.
209
210     \section2 Starting a Project
211
212     Start Visual Studio.NET, and create a new C# project for writing a
213     Windows application. This will present you with an empty form in
214     Visual Studio's dialog editor. You should see the toolbox, which
215     presents you with a number of available controls and objects in
216     different categories. If you right-click on the toolbox it allows
217     you to add new tabs. We will add the tab "Qt".
218
219     \section2 Importing Qt Widgets
220
221     The category only has a pointer tool by default, and we have to add
222     the Qt objects we want to use in our form. Right-click on the empty
223     space, and select "Customize". This opens a dialog that has two
224     tabs, "COM Components" and ".NET Framework Components". We used
225     ActiveQt to wrap QWidgets into COM objects, so we select the "COM
226     Components" page, and look for the classes we want to use, e.g.
227     "QPushButton" and "QAxWidget2".
228
229     When we select those widgets and close the dialog the two widgets
230     will now be available from the toolbox as grey squares with their
231     name next to it \footnote Icons could be added by modifying the
232     way the controls register themselves. \endfootnote.
233
234     \section2 Using Qt Widgets
235
236     We can now add an instance of QAxWidget2 and a QPushButton to
237     the form. Visual Studio will automatically generate the RCW for the
238     object servers. The QAxWidget2 instance takes most of the upper
239     part of the form, with the QPushButton in the lower right corner.
240
241     In the property editor of Visual Studio we can modify the properties
242     of our controls - QPushButton exposes the \c QWidget API and has many
243     properties, while QAxWidget2 has only the Visual Studio standard
244     properties in addition to its own property "lineWidth" in the
245     "Miscellaneous" category. The objects are named "axQPushButton1" and
246     "axQAxWidget21", and since especially the last name is a bit
247     confusing we rename the objects to "resetButton" and "circleWidget".
248
249     We can also change the Qt properties, e.g. set the "text" property
250     of the \c resetButton to "Reset", and the "lineWidth" property of the
251     \c circleWidget to 5. We can also put those objects into the layout
252     system that Visual Studio's dialog editor provides, e.g. by setting
253     the anchors of the \c circleWidget to "Left, Top, Right, Bottom", and
254     the anchors of the \c resetButton to "Bottom, Right".
255
256     Now we can compile and start the project, which will open a user
257     interface with our two Qt widgets. If we can resize the dialog,
258     the widgets will resize appropriately.
259
260     \section2 Handling Qt Signals
261
262     We will now implement event handlers for the widgets. Select the
263     \c circleWidget and select the "Events" page in the property
264     editor. The widget exposes events because the QAxWidget2 class has
265     the "StockEvents" attribute set in its class definition. We implement
266     the event handler \c circleClicked for the \c ClickEvent to increase
267     the line width by one for every click:
268
269     \snippet examples/activeqt/dotnet/walkthrough/Form1.cs 0
270
271     In general we can implement a default event handler by double
272     clicking on the widget in the form, but the default events for
273     our widgets are right now not defined.
274
275     We will also implement an event handler for the \c clicked signal
276     emitted by QPushButton. Add the event handler \c resetLineWidth to
277     the \c clicked event, and implement the generated function:
278
279     \snippet examples/activeqt/dotnet/walkthrough/Form1.cs 1
280
281     We reset the property to 1, and also call the \c setFocus() slot
282     to simulate the user style on Windows, where a button grabs focus
283     when you click it (so that you can click it again with the spacebar).
284
285     If we now compile and run the project we can click on the circle
286     widget to increase its line width, and press the reset button to
287     set the line width back to 1.
288
289     \section1 Summary
290
291     Using ActiveQt as a universal interoperability bridge between the
292     .NET world and the native world of Qt is very easy, and makes it
293     often  unnecessary to implement a lot of handwritten wrapper classes.
294     Instead, the QAxFactory implementation in the otherwise completely
295     cross-platform Qt project provides the glue that .NET needs to to
296     generate the RCW.
297
298     If this is not sufficient we can implement our own wrapper classes
299     thanks to the C++ extensions provided by Microsoft.
300
301     \section2 Limitations
302
303     All the limitations when using ActiveQt are implied when using this
304     technique to interoperate with .NET, e.g. the datatypes we can use
305     in the APIs can only be those supported by ActiveQt and COM. However,
306     since this includes subclasses of QObject and QWidget we can wrap
307     any of our datatypes into a QObject subclass to make its API
308     available to .NET. This has the positive side effect that the same
309     API is automatically available in
310     \l{http://qt.nokia.com/products/qsa/}{QSA}, the cross platform
311     scripting solution for Qt applications, and to COM clients in general.
312
313     When using the "IJW" method, in principle the only limitation is the
314     time required to write the wrapper classes and data type conversion
315     functions.
316
317     \section2 Performance Considerations
318
319     Every call from CLR bytecode to native code implies a small
320     performance hit, and necessary type conversions introduce an
321     additional delay with every layer that exists between the two
322     frameworks. Consequently every approach to mix .NET and native
323     code should try to minimize the communication necessary between
324     the different worlds.
325
326     As ActiveQt introduces three layers at once - the RCW, COM and finally
327     ActiveQt itself - the performance penalty when using the generic
328     Qt/ActiveQt/COM/RCW/.NET bridge is larger than when using a
329     hand-crafted IJW-wrapper class. The execution speed however is still
330     sufficient for connecting to and modifying interactive elements in a
331     user interface, and as soon as the benefit of using Qt and C++ to
332     implement and compile performance critical algorithms into native code
333     kicks in, ActiveQt becomes a valid choice for making even non-visual
334     parts of your application accessible to .NET.
335 */