Programmieren in C und C++: Unterschied zwischen den Versionen

Aus GoPalWiki
Wechseln zu: Navigation, Suche
K (Voraussetzungen)
K (Textersetzung - „z.B.“ durch „z. B.“)
 
(23 dazwischenliegende Versionen von 4 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
[[Kategorie:Entwicklung]]
+
Ziel dieser Seite  ist, unabhängig der gewählten Programmierumgebung die zur Verfügung stehende API verstehen und kleine Programme entwickeln, die auf dem GoPal PNAs lauffähig sind.
 +
== Voraussetzungen  ==
 +
*Aus den [[Programmierumgebungen für C und C++]] sollte man sich eine herausgesucht und funktionsfähig installiert haben.
 +
*Dies hier ist kein grundlegender C/C++-Kurs. Man sollte also schon C/C++-Kenntnisse z. B. auf Desktop-PC unter Windows, Linux oder sonstigen Betriebssystemen gesammelt haben. Um diese Grundlagen zuerst auf dem Desktop-PC zu erwerben, eignen sich folgende Tutorien:
 +
**http://www.cpp-tutor.de/
 +
**http://www.rzbt.haw-hamburg.de/dankert/ccontent.html
 +
**http://ladedu.com/cpp/
 +
**http://www2.its.strath.ac.uk/courses/c/ (in Englisch)
 +
**http://www.aasted.org/GC/c-tut.php (in Englisch)
 +
**http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html (in Englisch)
 +
== Rund um das 'Hallo Welt'  ==
 +
Nach dem Motto ''Keep it simple!'' (Halte es einfach!) ist der erste Schritt eines Entwicklers häufig ein erstes eigenes Programm zu schreiben, um die Funktionsfähigkeit der Toolchain, der gesamten Entwicklungsumgebung, zu prüfen. Also muss ein dann selbst geschriebenes Programm her, das ein Lebenszeichen von sich gibt. Das Lebenszeichen ist dann häufig die Ausgabe einer Zeichenkette ''Hallo Welt!'' auf dem Bildschirm des Target-Device (Zielgerät). In unserem Fall also soll solch eine Zeichenkette auf dem Bildschirm des GoPal-Gerätes erscheinen.
  
= Voraussetzungen =
+
Ein solches Basis-Programm dann später um sinnvolle Funktionen zu erweitern, stellen sich Entwickler immer gaaaaaanz trivial vor. Ist es ja auch, wenn man weiß wie.
  
* Aus den [[Programmierumgebungen für C und C++]] sollte man sich eine herausgesucht und funktionsfähig installiert haben.
+
Aber Schritt für Schritt... Bleiben wir vorerst beim ''Hallo Welt!''.
* Dies hier ist kein grundlegender C/C++-Kurs. Man sollte also schon C/C++-Kenntnisse z.B. auf DesktopPC unter Windows, Linux oder sonstigen Betriesbssystemen gesammelt haben.
+
=== Das geschenkte 'Hallo Welt' von Microsoft  ===
 +
Je nach verwendeter Entwicklungsumgebung kommt bei dem ''Hello World''-Programm, das die Entwicklungsumgebung erzeugt, anderer Source Code heraus und andere Standardbibliotheken werden verwendet. Daher gehen wir hier nochmals auf die einzelnen Entwicklungsumgebungen ein.
 +
==== Microsoft eMbedded Visual C++ ====
 +
Im Hilfe-Menu unter ''About...'' steht etwas von Version 4.00.1610.0. Ich beschreibe hier die englische Version. Ich benutze einfach das Standard SDK (Pocket PC2003), das bei der Installation dabei war. Unter der Verwendung eines anderen nachinstallierten SDKs sind ähnliche Schritte durchzuführen, jedoch mögen die Menu/Punkte dann natürlich ein wenig anders lauten.
 +
# Im ''File''-Menu unter ''New'' wählt man da Tab ''Projects'' aus.
 +
# Wir erstellen eine ''WCE Pocket PC 2003 Application'' mit '''Project name''' ''HelloWorld''. Dabei dürfte die Standardeinstellung unter '''Location''' zu ''C:\Program Files\Microsoft eMbedded C++ 4.0\Common\EVC\MyProjects\HelloWorld'' erweitert werden.
 +
# Ein neuer Arbeitsbereich wird mittels ausgewähltem ''Create new workspace'' angelegt und als '''CPU''' wählen wir mindestens, dass ''Win32 (WCE ARMV4)'' unterstützt wird.<br />Streng genommen handelt es sich hier nicht um eine ausgewählte CPU, sondern um ein Instruction Set. Die CPU muss dieses Instruction Set beherrschen, damit das spätere Kompilat darauf laufen kann.
 +
# Abschließend hier ''OK'' auswählen.
 +
# Jetzt nochmals ''A typical Hello World application'' auswählen und noch mit ''Finish'' bestätigen. Und nochmal ''OK''...  
 +
# Im ''FileView'' den Baum expandieren und unter ''Source Files'' die Datei ''HelloWorld.cpp'' öffnen.<br />Und schon sehen wir in der Datei, dass die ''Aygshell'' verwendet werden soll.
 +
Wurde als CPU auch der Emulator ausgewählt, so kann man durchaus mal testen, dass im Emulator das Programm funktioniert. Oben nicht die Auswahl des Emulators vergessen!
 +
<gallery widths=262px heights=438px>
 +
Image:HelloWorld Emulator.jpg|Das Hello World im Emulator mit Aygshell.dll
 +
Image:HelloWorld Aygshell SamsungOmnia i900 1.jpg|Die gleichen Sourcen unter ARMV4 instruction set kompiliert. Auf dem Samsung Omnia i900 läuft alles.
 +
</gallery>
  
= Ziel dieser Seite =
+
<gallery widths=400px heights=240px>
 +
Image:HelloWorld Aygshell SamsungOmnia i900 2.jpg|Die gleichen Sourcen unter ARMV4 instruction set kompiliert. Auf dem Samsung Omnia i900 läuft alles. Auch in Landscape mode...
 +
Image:HelloWorld noAygshell E3210M10.jpg|Die gleichen Sourcen unter ARMV4 instruction set kompiliert. Mindestens eine Aygshell.dll fehlt auf dem GoPal E3210 M10
 +
</gallery>
  
* Unabhängig der gewählten Programmierumgebung die zur Verfügung stehende API verstehen und kleine Programme entwickeln, die auf dem GoPal lauffähig sind.
+
Man kann es auch, so wie es ist, für das ARMV4 Instruction Set kompilieren und wenn man einen PDA oder Windows Mobile Phone besitzt, die daraus erhaltene HelloWorld.exe mal laufen lassen. Im Visual Studio oben nicht die Auswahl von ''Win32 (WCE ARMV4) Release'' vergessen. Übertragen des HelloWorld.exe mehr oder weniger umständlich per direktem Deploy auf das Device, per Active Sync oder sonstwie SD card und dann aufs Target Device.  
  
= Rund um das 'Hallo Welt' =
+
Probiert man dieses HelloWorld.exe nach dem Kompilieren auf einem unmodifizierten GoPal-Gerät aus, kommt nur eine Fehlermeldung, dass irgendwelche Dateien oder Libraries nicht gefunden werden konnten. Und wir stecken mitten im Problem der reduzierten [[Windows Embedded#Lizenz|Core Runtime License im Vergleich zur Professional Runtime License]] oder des reduzierten API sets. Irreführend ist hier die Meldung, dass das ''HelloWorld'' selbst nicht gefunden werden kann. Wer sich mal wieder die Fehlermeldung ausgedacht hat?&nbsp;:-)
  
Nach dem Motto ''Keep it simple!'' (Halte es einfach!) ist der erste Schritt eines Entwicklers häufig ein erstes eigenes Programm zu schreiben, um die Funktionsfähigkeit der Toolchain, der gesamten Entwicklungsumgebung, zu prüfen. Also muss ein dann selbstgeschriebenes Programm her, das ein Lebenszeichen von sich gibt. Das Lebenszeichen ist dann häufig die Ausgabe einer Zeichenkette ''Hallo Welt!'' auf dem Bildschirm des Target-Device (Zielgerät). In unserem Fall also soll solch eine Zeichenkette auf dem Bildschirm des GoPal-Gerätes erscheinen.
+
Und da wir nicht mit der [[Windows Embedded#Dynamic_Linked_Libraries_nachinstallieren|Aygshell rumschummeln]] wollen, kommt jetzt die Frage auf, wie wir doch zu einem ''HelloWorld.exe'' kommen, das läuft.  
  
Ein solches Basis-Programm dann später um sinnvolle Funktionen zu erweitern, stellen sich Entwickler immer gaaaaaanz trivial vor. Ist es ja auch, wenn man weiß wie.
+
Was muss ich also ändern, damit es auf dem GoPal-Gerät auch ohne Microsoft Aygshell.dll und ohne DLLs von Dritten läuft?
  
Aber Schritt für Schritt... Bleiben wir vorerst beim ''Hallo Welt!''.
+
So und los geht's...  
 +
[[Image:GoPal HelloWorld wo aygshell.jpg|mini|left|500px|Angepasstes HelloWorld.exe, so dass Aygshell nicht verwendet wird auf E3210 M10.]]
 +
{{Absatz}}
  
== Das geschenkte 'Hallo Welt' von Microsoft ==
+
Aus dem HelloWorld.cpp sind die folgenden Zeilen auszukommentieren oder zu löschen:
  
Je nach verwendeter Entwicklungsumgebung kommt bei dem ''Hello World''-Programm, das die Entwicklungsumgebung erzeugt, anderer Source Code heraus und andere Standardbibliotheken werden verwendet. Daher gehen wir hier nochmals auf die einzelnen Entwicklungsumgebungen ein.
+
  // #include &lt;aygshell.h&gt;
 
 
=== Microsoft eMbedded Visual C++ ===
 
 
 
Im Hilfe-Menu unter ''About...'' steht etwas von Version 4.00.1610.0. Ich beschreibe hier die englische Version. Ich benutze einfach das Standard SDK (Pocket PC2003), das bei der Installation dabei war. Unter der Verwendung eines anderen nachinstallierten SDKs sind ähnliche Schritte durchzuführen, jedoch mögen die Menu/Punkte dann natürlich ein wenig anders lauten.
 
 
 
# Im ''File''-Menu unter ''New'' wählt man da Tab ''Projects'' aus.
 
# Wir erstellen eine ''WCE Pocket PC 2003 Application'' mit '''Project name''' ''HelloWorld''. Dabei dürfte die Standardeinstellung unter '''Location''' zu ''C:\Program Files\Microsoft eMbedded C++ 4.0\Common\EVC\MyProjects\HelloWorld'' erweitert werden.
 
# Ein neuer Arbeitsbereich wird mittels ausgewähltem ''Create new workspace'' angelegt und als '''CPU''' wählen wir mindestens, dass ''Win32 (WCE ARMV4)'' unterstützt wird.
 
 
 
Streng genommen handelt es sich hier nicht um eine ausgewählte CPU, sondern um ein Instruction Set. Die CPU muss dieses Instruction Set beherrschen, damit das spätere Kompilat darauf laufen kann.
 
 
 
Abschließend hier ''OK'' auswählen.
 
 
 
Jetzt nochmals ''A typical Hello World application'' auswählen und noch mit ''Finish'' bestätigen. Und nochmal ''OK''...
 
 
 
Im ''FileView'' den Baum expandieren und unter ''Source Files'' die Datei ''HelloWorld.cpp'' öffnen.
 
 
 
Und schon sehen wir in der Datei, dass die ''Aygshell'' verwendet werden soll.
 
 
 
Wurde als CPU auch der Emulator ausgewählt, so kann man durchaus mal testen, dass im Emulator das Programm funktioniert. Oben nicht die Auswahl des Emulators vergessen!
 
 
 
----
 
 
 
{||
 
|[[Bild:HelloWorld_Emulator.jpg|Das Hello World im Emulator mit Aygshell.dll]]
 
|[[Bild:HelloWorld_Aygshell_SamsungOmnia_i900_1.jpg|Die gleichen Sourcen unter ARMV4 instruction set kompiliert. Auf dem Samsung Omnia i900 läuft alles.]]
 
|-
 
|''Das Hello World im Emulator mit Aygshell.dll''
 
|''Die gleichen Sourcen unter ARMV4 instruction set kompiliert. Auf dem Samsung Omnia i900 läuft alles''
 
|-
 
|[[Bild:HelloWorld_Aygshell_SamsungOmnia_i900_2.jpg|Die gleichen Sourcen unter ARMV4 instruction set kompiliert. Auf dem Samsung Omnia i900 läuft alles. Auch in Landscape mode...]]
 
|[[Bild:HelloWorld_noAygshell_E3210M10.jpg|Die gleichen Sourcen unter ARMV4 instruction set kompiliert. Mindestens eine Aygshell.dll fehlt auf dem GoPal E3210 M10]]
 
|-
 
|''Die gleichen Sourcen unter ARMV4 instruction set kompiliert. Auf dem Samsung Omnia i900 läuft alles. Auch in Landscape mode...''
 
|''Die gleichen Sourcen unter ARMV4 instruction set kompiliert. Mindestens eine Aygshell.dll fehlt auf dem GoPal E3210 M10''
 
|}
 
 
 
----
 
 
 
Man kann es auch, so wie es ist, für das ARMV4 Instruction Set kompilieren und wenn man einen PDA oder Windows Mobile Phone besitzt, die daraus erhaltene HelloWorld.exe mal laufen lassen. Im Visual Studio oben nicht die Auswahl von ''Win32 (WCE ARMV4) Release'' vergessen. Übertragen des HelloWorld.exe mehr oder weniger umständlich per direktem Deploy auf das Device, per Active Sync oder sonstwie SD card und dann aufs Target Device.
 
 
 
Probiert man dieses HelloWorld.exe nach kompilieren auf einem unmodifizierten GoPal-Gerät aus, kommt nur eine Fehlermeldung, dass irgendwelche Dateien oder Libraries nicht gefunden werden konnten. Und wir stecken mitten im Problem der reduzierten [[Windows Embedded#Lizenz|Core Runtime License im Vergleich zur Professional Runtime License]] oder des reduzierten API sets. Irreführend ist hier die Meldung dass das ''HelloWorld'' selbst nicht gefunden werden kann. Wer sich mal wieder die Fehlermeldung ausgedacht hat? :-)
 
 
 
Und da wir nicht mit der [[Windows Embedded#Dynamic Linked Libraries nachinstallieren|Aygshell rumschummeln]] wollen, kommt jetzt die Frage auf, wie wir doch zu einem ''HelloWorld.exe'' kommen, das läuft.
 
 
 
Was muss ich also ändern, damit es auf dem GoPal-Gerät auch ohne Microsoft Aygshell.dll und ohne DLLs von Dritten läuft?
 
 
 
So und los geht's...
 
 
 
----
 
 
 
{|
 
|[[Bild:GoPal HelloWorld wo aygshell.jpg|Angepasstes HelloWorld.exe, so dass Aygshell nicht verwendet wird auf E3210 M10.]]
 
|-
 
|''Angepasstes HelloWorld.exe, so dass Aygshell nicht verwendet wird auf E3210 M10''
 
|}
 
 
 
----
 
 
 
Aus dem HelloWorld.cpp sind die folgenden Zeilen auszukommentieren oder zu löschen:
 
 
 
  // #include <aygshell.h>
 
 
  // HWND g_hwndCB; // The command bar handle
 
  // HWND g_hwndCB; // The command bar handle
 
  // static SHACTIVATEINFO s_sai;
 
  // static SHACTIVATEINFO s_sai;
Zeile 96: Zeile 64:
 
         RECT rcMenuBar;
 
         RECT rcMenuBar;
 
  &nbsp;
 
  &nbsp;
         GetWindowRect(hWnd, &rc);
+
         GetWindowRect(hWnd, &amp;rc);
         GetWindowRect(g_hwndCB, &rcMenuBar);
+
         GetWindowRect(g_hwndCB, &amp;rcMenuBar);
 
         rc.bottom -= (rcMenuBar.bottom - rcMenuBar.top);
 
         rc.bottom -= (rcMenuBar.bottom - rcMenuBar.top);
 
  &nbsp;
 
  &nbsp;
Zeile 111: Zeile 79:
 
  /*        g_hwndCB = CreateRpCommandBar(hWnd);
 
  /*        g_hwndCB = CreateRpCommandBar(hWnd);
 
             // Initialize the shell activate info structure
 
             // Initialize the shell activate info structure
             memset (&s_sai, 0, sizeof (s_sai));
+
             memset (&amp;s_sai, 0, sizeof (s_sai));
 
             s_sai.cbSize = sizeof (s_sai);
 
             s_sai.cbSize = sizeof (s_sai);
 
  */
 
  */
  
 
  // CommandBar_Destroy(g_hwndCB);
 
  // CommandBar_Destroy(g_hwndCB);
  // SHHandleWMActivate(hWnd, wParam, lParam, &s_sai, FALSE);
+
  // SHHandleWMActivate(hWnd, wParam, lParam, &amp;s_sai, FALSE);
  // SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai);
+
  // SHHandleWMSettingChange(hWnd, wParam, lParam, &amp;s_sai);
  
 
  /* HWND CreateRpCommandBar(HWND hwnd)
 
  /* HWND CreateRpCommandBar(HWND hwnd)
Zeile 123: Zeile 91:
 
         SHMENUBARINFO mbi;
 
         SHMENUBARINFO mbi;
 
  &nbsp;
 
  &nbsp;
         memset(&mbi, 0, sizeof(SHMENUBARINFO));
+
         memset(&amp;mbi, 0, sizeof(SHMENUBARINFO));
 
         mbi.cbSize    = sizeof(SHMENUBARINFO);
 
         mbi.cbSize    = sizeof(SHMENUBARINFO);
 
         mbi.hwndParent = hwnd;
 
         mbi.hwndParent = hwnd;
Zeile 131: Zeile 99:
 
         mbi.cBmpImages = 0;
 
         mbi.cBmpImages = 0;
 
  &nbsp;
 
  &nbsp;
         if (!SHCreateMenuBar(&mbi))  
+
         if (!SHCreateMenuBar(&amp;mbi))  
 
                 return NULL;
 
                 return NULL;
 
  &nbsp;
 
  &nbsp;
Zeile 149: Zeile 117:
 
                         shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
 
                         shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
 
                         shidi.hDlg = hDlg;
 
                         shidi.hDlg = hDlg;
                         SHInitDialog(&shidi);
+
                         SHInitDialog(&amp;shidi);
 
                         return TRUE;  
 
                         return TRUE;  
 
  &nbsp;
 
  &nbsp;
Zeile 164: Zeile 132:
 
  */
 
  */
  
Um die Möglichkeit zu schaffen, das Programm auch ohne ''OK''-Button oder schließen des Fensters zu verlassen, fügen wir noch eine Zeile ein. Unser ''Hello World'' läuft nämlich jetzt im Vollbildmodus ohne Fensterdekoration.
+
Um die Möglichkeit zu schaffen, das Programm auch ohne ''OK''-Button oder schließen des Fensters zu verlassen, fügen wir noch eine Zeile ein. Unser ''Hello World'' läuft nämlich jetzt im Vollbildmodus ohne Fensterdekoration.  
  
Vor der Zeile
+
Vor der Zeile  
  
 
  case WM_DESTROY:
 
  case WM_DESTROY:
  
fügen wir noch folgendes ein
+
fügen wir noch folgendes ein  
  
 
  case WM_LBUTTONDOWN:
 
  case WM_LBUTTONDOWN:
  
Das sieht also dann in etwa so aus:
+
Das sieht also dann in etwa so aus:  
  
 
  case WM_LBUTTONDOWN:
 
  case WM_LBUTTONDOWN:
Zeile 182: Zeile 150:
 
     break;
 
     break;
  
Das CommandBar_Destroy hatten wir vorher gerade frisch auskommentiert.
+
Das CommandBar_Destroy hatten wir vorher gerade frisch auskommentiert.  
  
Der WM_LBUTTONDOWN sorgt dafür, dass jetzt beim Berühren des Touchscreen an beliebiger Position das ''Hello World'' beendet wird.
+
Der WM_LBUTTONDOWN sorgt dafür, dass jetzt beim Berühren des Touchscreen an beliebiger Position das ''Hello World'' beendet wird.  
  
Und siehe da: Die Aygshell wird nicht benötigt. Die Befehle, Konstanten, etc., die in unserem Beispiel mit SH... beginnen, sind diejenigen, die in der Aygshell enthalten sind. Daher wurden solche Absätze und Zeilen, die solche Aygshell Anteile besaßen, einfach wie oben beschrieben entfernt.
+
Und siehe da: Die Aygshell wird nicht benötigt. Die Befehle, Konstanten, etc., die in unserem Beispiel mit SH... beginnen, sind diejenigen, die in der Aygshell enthalten sind. Daher wurden solche Absätze und Zeilen, die solche Aygshell Anteile besaßen, einfach wie oben beschrieben entfernt.  
  
Das so erhaltene Programm kann als Basis für die weiteren Eigenentwicklungen verwendet werden.
+
Das so erhaltene Programm kann als Basis für die weiteren Eigenentwicklungen verwendet werden.  
  
Viel Spaß beim Ausprobieren...
+
Viel Spaß beim Ausprobieren...  
  
Obwohl hier Microsoft verwendet wurde: Entwicklungsumgebung etc. war kostenlos! Es läuft und man kann eigentlich alles daraus bauen, wenn man noch rausbekommt wie... GoPal-gerätespezifische Fragen bitte an [[Fragen zur Programmierung]]
+
Obwohl hier Microsoft verwendet wurde: Entwicklungsumgebung etc. war kostenlos! Es läuft und man kann eigentlich alles daraus bauen, wenn man noch rausbekommt wie... GoPal-gerätespezifische Fragen bitte an [[Fragen zur Programmierung]]  
  
So böse ist Microsoft zumindest hier also gar nicht: Hallo non-Microsoftler! Willkommen auf der dunklen Seite... Come to the dark side... We have cookies! :-)
+
So böse ist Microsoft zumindest hier also gar nicht: Hallo non-Microsoftler! Willkommen auf der dunklen Seite... Come to the dark side... We have cookies!&nbsp;:-)
  
=== Microsoft Visual Studio 2005 mit Smart Devices ===
+
==== Microsoft Visual Studio 2005 mit Smart Devices ====
  
Visual Studio 2005 bietet natürlich eine integrierte Entwicklungsumgebung (IDE), die deutlich moderner und komfortabler als das eMbedded Visual C++ ist. Als echter vi, sed, awk und ed User ist das zwar Nebensache, aber wir wollen ja auch den nicht Gurus oder gerade diesen Gurus auch ein wenig Komfort zuteil werden lassen.
+
Visual Studio 2005 bietet natürlich eine integrierte Entwicklungsumgebung (IDE), die deutlich moderner und komfortabler als das eMbedded Visual C++ ist. Als echter vi, sed, awk und ed User ist das zwar Nebensache, aber wir wollen ja auch den nicht Gurus oder gerade diesen Gurus auch ein wenig Komfort zuteil werden lassen.  
  
Gehen wir von Standard ''Hello World'' des Visual Studio 2005 aus und versuchen es auf den abgespeckten GoPal-Geräten zum Laufen zu überreden, so sind noch ein paar andere Hürden zu nehmen. Auch wenn manches ähnlich aussieht...
+
Gehen wir von Standard ''Hello World'' des Visual Studio 2005 aus und versuchen es auf den abgespeckten GoPal-Geräten zum Laufen zu überreden, so sind noch ein paar andere Hürden zu nehmen. Auch wenn manches ähnlich aussieht...  
  
Also nochmal das Ganze:
+
Also nochmal das Ganze:  
 +
=== 'Hallo Welt' von Anfang an  ===
 +
Von einem leeren Zustand etwas neu zu entwickeln wird auch als Entwicklung ''from scratch'' bezeichnet.
 +
; In C++ mit Hilfe der WTL
 +
Der folgende Ansatz funktioniert in allen Entwicklungsumgebungen gleichermaßen, da man ja überall von einem ''leeren Editor'' ausgehen kann. Die Menü-Bezeichnungen kommen von der englischen Version eines Visual Studio 2005 und können in anderen Entwicklungsumgebungen variieren.
  
== 'Hallo Welt' von Anfang an ==
+
In diesem Abschnitt wird die [http://sourceforge.net/projects/wtl/ WTL] in der Version 8.0 eingesetzt.
 +
 
 +
Die Windows Template Library (WTL) ist eine C++ library für die Entwicklung von Windows-Applikationen und Benutzerschnittstellen-Komponenten. Diese Bibliothek erweitert die Microsoft eigene ATL (Active Template Library) und stellt eine Menge von Klassen zur Verfügung wie Kontroll-Elemente, Dialoge, Fensterklassen, GDI Objekte, und sogar noch mehr.
 +
 
 +
Die WTL ist Open Source Software und muss natürlich erst mal installiert werden.
 +
 
 +
Voraussetzung ist auch hier ein installiertes [http://www.microsoft.com/downloads/details.aspx?familyid=FA1A3D66-3F61-4DDC-9510-AE450E2318C3&displaylang=en Standard SDK für Windows CE 5.0].
 +
 
 +
File -&gt; New -&gt; Project -&gt; Visual C++ -&gt; Smart Device -&gt; Win32 Smart Device Project
 +
 
 +
Name eingeben (z.&#x202f;B. HelloWelt), Location auswählen (z.&#x202f;B. c:\proj ), danach OK klicken.
 +
 
 +
Es erscheint nun der Win32 Smart Device Project Wizard bei dem folgende Einstellungen vorgenommen werden müssen:
 +
*Platforms -&gt; Pocket PC 2003 entfernen, STANDARDSDK_500 hinzufügen
 +
*Application Settings -&gt; Application type: Windows application auswählen
 +
*Application Settings -&gt; Additional options: Empty project aktivieren
 +
Danach Finish klicken.
 +
 
 +
Wir haben nun ein geeignetes leeres Projekt.
 +
 
 +
Zum sinnvollen Arbeiten brauchen wir allerdings eine C++ Datei:
 +
 
 +
Im Solution-Explorer, rechter Mausclick auf Source-Files -&gt; Add -&gt; New Item -&gt; Code -&gt; C++ File (.cpp)
 +
 
 +
Name: HalloWelt.cpp eintragen und Add klicken.
 +
 
 +
Include und library Pfade für [http://sourceforge.net/projects/wtl/ WTL 8.0] entweder global oder für das Project setzen (beides z.&#x202f;B. c:\wtl80\include) und folgenden Code in HalloWelt.cpp einfügen.
 +
 
 +
#include &lt;atlbase.h&gt;
 +
#include &lt;atlapp.h&gt;
 +
&nbsp;
 +
extern CAppModule _Module;
 +
&nbsp;
 +
#include &lt;atlgdi.h&gt;
 +
#include &lt;atlmisc.h&gt;
 +
&nbsp;
 +
CAppModule _Module;
 +
&nbsp;
 +
class CMainWindow&nbsp;: public CWindowImpl&lt;CMainWindow , CWindow , CWinTraits&lt;WS_VISIBLE&gt; &gt;
 +
{
 +
        // Message map is used to map Windows messages to handlers.
 +
        BEGIN_MSG_MAP(CMainWindow)
 +
                MESSAGE_HANDLER(WM_PAINT, OnPaint)
 +
                MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
 +
                MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
 +
        END_MSG_MAP()
 +
&nbsp;
 +
        LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&amp; bHandled)
 +
        {
 +
                CPaintDC dc(m_hWnd);
 +
                CRect rect;
 +
                GetClientRect(rect);
 +
                dc.DrawText(_T("Hello, Wtl!"), -1, rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER);
 +
                return 0;
 +
        }
 +
&nbsp;
 +
        LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&amp; bHandled)
 +
        {
 +
                PostMessage(WM_CLOSE);
 +
                return 0;
 +
        }
 +
&nbsp;
 +
        LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&amp; bHandled)
 +
        {
 +
                PostQuitMessage(0);
 +
                return 0;
 +
        }
 +
};
 +
&nbsp;
 +
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int) {
 +
        // Init module.
 +
        _Module.Init(0, hInstance, 0);
 +
        // Create main window.
 +
        CMainWindow wnd;
 +
        wnd.Create(NULL, CWindow::rcDefault, _T("Hello, Welt!"));
 +
        wnd.ShowWindow(SW_SHOW);
 +
        // Run message loop.
 +
        CMessageLoop loop;
 +
        int res = loop.Run();
 +
        // Terminate.
 +
        _Module.Term();
 +
        return res;
 +
}
  
New -> Project -> ... -> leeres Projekt
+
Und damit geht es mit der WTL...  
  
Von einem leeren Zustand etwas neu zu entwickeln wird auch als Entwicklung ''from scratch'' bezeichnet.
+
[[Category:Entwicklung]]

Aktuelle Version vom 24. Mai 2021, 01:42 Uhr

Ziel dieser Seite ist, unabhängig der gewählten Programmierumgebung die zur Verfügung stehende API verstehen und kleine Programme entwickeln, die auf dem GoPal PNAs lauffähig sind.

Voraussetzungen

Rund um das 'Hallo Welt'

Nach dem Motto Keep it simple! (Halte es einfach!) ist der erste Schritt eines Entwicklers häufig ein erstes eigenes Programm zu schreiben, um die Funktionsfähigkeit der Toolchain, der gesamten Entwicklungsumgebung, zu prüfen. Also muss ein dann selbst geschriebenes Programm her, das ein Lebenszeichen von sich gibt. Das Lebenszeichen ist dann häufig die Ausgabe einer Zeichenkette Hallo Welt! auf dem Bildschirm des Target-Device (Zielgerät). In unserem Fall also soll solch eine Zeichenkette auf dem Bildschirm des GoPal-Gerätes erscheinen.

Ein solches Basis-Programm dann später um sinnvolle Funktionen zu erweitern, stellen sich Entwickler immer gaaaaaanz trivial vor. Ist es ja auch, wenn man weiß wie.

Aber Schritt für Schritt... Bleiben wir vorerst beim Hallo Welt!.

Das geschenkte 'Hallo Welt' von Microsoft

Je nach verwendeter Entwicklungsumgebung kommt bei dem Hello World-Programm, das die Entwicklungsumgebung erzeugt, anderer Source Code heraus und andere Standardbibliotheken werden verwendet. Daher gehen wir hier nochmals auf die einzelnen Entwicklungsumgebungen ein.

Microsoft eMbedded Visual C++

Im Hilfe-Menu unter About... steht etwas von Version 4.00.1610.0. Ich beschreibe hier die englische Version. Ich benutze einfach das Standard SDK (Pocket PC2003), das bei der Installation dabei war. Unter der Verwendung eines anderen nachinstallierten SDKs sind ähnliche Schritte durchzuführen, jedoch mögen die Menu/Punkte dann natürlich ein wenig anders lauten.

  1. Im File-Menu unter New wählt man da Tab Projects aus.
  2. Wir erstellen eine WCE Pocket PC 2003 Application mit Project name HelloWorld. Dabei dürfte die Standardeinstellung unter Location zu C:\Program Files\Microsoft eMbedded C++ 4.0\Common\EVC\MyProjects\HelloWorld erweitert werden.
  3. Ein neuer Arbeitsbereich wird mittels ausgewähltem Create new workspace angelegt und als CPU wählen wir mindestens, dass Win32 (WCE ARMV4) unterstützt wird.
    Streng genommen handelt es sich hier nicht um eine ausgewählte CPU, sondern um ein Instruction Set. Die CPU muss dieses Instruction Set beherrschen, damit das spätere Kompilat darauf laufen kann.
  4. Abschließend hier OK auswählen.
  5. Jetzt nochmals A typical Hello World application auswählen und noch mit Finish bestätigen. Und nochmal OK...
  6. Im FileView den Baum expandieren und unter Source Files die Datei HelloWorld.cpp öffnen.
    Und schon sehen wir in der Datei, dass die Aygshell verwendet werden soll.

Wurde als CPU auch der Emulator ausgewählt, so kann man durchaus mal testen, dass im Emulator das Programm funktioniert. Oben nicht die Auswahl des Emulators vergessen!

Man kann es auch, so wie es ist, für das ARMV4 Instruction Set kompilieren und wenn man einen PDA oder Windows Mobile Phone besitzt, die daraus erhaltene HelloWorld.exe mal laufen lassen. Im Visual Studio oben nicht die Auswahl von Win32 (WCE ARMV4) Release vergessen. Übertragen des HelloWorld.exe mehr oder weniger umständlich per direktem Deploy auf das Device, per Active Sync oder sonstwie SD card und dann aufs Target Device.

Probiert man dieses HelloWorld.exe nach dem Kompilieren auf einem unmodifizierten GoPal-Gerät aus, kommt nur eine Fehlermeldung, dass irgendwelche Dateien oder Libraries nicht gefunden werden konnten. Und wir stecken mitten im Problem der reduzierten Core Runtime License im Vergleich zur Professional Runtime License oder des reduzierten API sets. Irreführend ist hier die Meldung, dass das HelloWorld selbst nicht gefunden werden kann. Wer sich mal wieder die Fehlermeldung ausgedacht hat? :-)

Und da wir nicht mit der Aygshell rumschummeln wollen, kommt jetzt die Frage auf, wie wir doch zu einem HelloWorld.exe kommen, das läuft.

Was muss ich also ändern, damit es auf dem GoPal-Gerät auch ohne Microsoft Aygshell.dll und ohne DLLs von Dritten läuft?

So und los geht's...

Angepasstes HelloWorld.exe, so dass Aygshell nicht verwendet wird auf E3210 M10.

Aus dem HelloWorld.cpp sind die folgenden Zeilen auszukommentieren oder zu löschen:

// #include <aygshell.h>
// HWND				g_hwndCB;					// The command bar handle
// static SHACTIVATEINFO s_sai;
// LRESULT CALLBACK	About			(HWND, UINT, WPARAM, LPARAM);
// HWND				CreateRpCommandBar(HWND);
//When the main window is created using CW_USEDEFAULT the height of the menubar (if one
// is created is not taken into account). So we resize the window after creating it
// if a menubar is present
/*	if (g_hwndCB)
   {
       RECT rc;
       RECT rcMenuBar;
 
       GetWindowRect(hWnd, &rc);
       GetWindowRect(g_hwndCB, &rcMenuBar);
       rc.bottom -= (rcMenuBar.bottom - rcMenuBar.top);
 
       MoveWindow(hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, FALSE);
   }
*/
/*    case IDM_HELP_ABOUT:
          DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
          break;
*/
/*         g_hwndCB = CreateRpCommandBar(hWnd);
           // Initialize the shell activate info structure
           memset (&s_sai, 0, sizeof (s_sai));
           s_sai.cbSize = sizeof (s_sai);
*/
//			CommandBar_Destroy(g_hwndCB);
//			SHHandleWMActivate(hWnd, wParam, lParam, &s_sai, FALSE);
//			SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai);
/* HWND CreateRpCommandBar(HWND hwnd)
{
       SHMENUBARINFO mbi;
 
       memset(&mbi, 0, sizeof(SHMENUBARINFO));
       mbi.cbSize     = sizeof(SHMENUBARINFO);
       mbi.hwndParent = hwnd;
       mbi.nToolBarId = IDM_MENU;
       mbi.hInstRes   = g_hInst;
       mbi.nBmpId     = 0;
       mbi.cBmpImages = 0;
 
       if (!SHCreateMenuBar(&mbi)) 
               return NULL;
 
       return mbi.hwndMB;
}
// Mesage handler for the About box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
       SHINITDLGINFO shidi;
 
       switch (message)
       {
                case WM_INITDIALOG:
                       // Create a Done button and size it.  
                       shidi.dwMask = SHIDIM_FLAGS;
                       shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
                       shidi.hDlg = hDlg;
                       SHInitDialog(&shidi);
                       return TRUE; 
 
                case WM_COMMAND:
                       if (LOWORD(wParam) == IDOK)
                       {
                               EndDialog(hDlg, LOWORD(wParam));
                               return TRUE;
                       }
                       break;
       }
   return FALSE;
}
*/

Um die Möglichkeit zu schaffen, das Programm auch ohne OK-Button oder schließen des Fensters zu verlassen, fügen wir noch eine Zeile ein. Unser Hello World läuft nämlich jetzt im Vollbildmodus ohne Fensterdekoration.

Vor der Zeile

case WM_DESTROY:

fügen wir noch folgendes ein

case WM_LBUTTONDOWN:

Das sieht also dann in etwa so aus:

case WM_LBUTTONDOWN:
case WM_DESTROY:
// CommandBar_Destroy(g_hwndCB);
   PostQuitMessage(0);
   break;

Das CommandBar_Destroy hatten wir vorher gerade frisch auskommentiert.

Der WM_LBUTTONDOWN sorgt dafür, dass jetzt beim Berühren des Touchscreen an beliebiger Position das Hello World beendet wird.

Und siehe da: Die Aygshell wird nicht benötigt. Die Befehle, Konstanten, etc., die in unserem Beispiel mit SH... beginnen, sind diejenigen, die in der Aygshell enthalten sind. Daher wurden solche Absätze und Zeilen, die solche Aygshell Anteile besaßen, einfach wie oben beschrieben entfernt.

Das so erhaltene Programm kann als Basis für die weiteren Eigenentwicklungen verwendet werden.

Viel Spaß beim Ausprobieren...

Obwohl hier Microsoft verwendet wurde: Entwicklungsumgebung etc. war kostenlos! Es läuft und man kann eigentlich alles daraus bauen, wenn man noch rausbekommt wie... GoPal-gerätespezifische Fragen bitte an Fragen zur Programmierung

So böse ist Microsoft zumindest hier also gar nicht: Hallo non-Microsoftler! Willkommen auf der dunklen Seite... Come to the dark side... We have cookies! :-)

Microsoft Visual Studio 2005 mit Smart Devices

Visual Studio 2005 bietet natürlich eine integrierte Entwicklungsumgebung (IDE), die deutlich moderner und komfortabler als das eMbedded Visual C++ ist. Als echter vi, sed, awk und ed User ist das zwar Nebensache, aber wir wollen ja auch den nicht Gurus oder gerade diesen Gurus auch ein wenig Komfort zuteil werden lassen.

Gehen wir von Standard Hello World des Visual Studio 2005 aus und versuchen es auf den abgespeckten GoPal-Geräten zum Laufen zu überreden, so sind noch ein paar andere Hürden zu nehmen. Auch wenn manches ähnlich aussieht...

Also nochmal das Ganze:

'Hallo Welt' von Anfang an

Von einem leeren Zustand etwas neu zu entwickeln wird auch als Entwicklung from scratch bezeichnet.

In C++ mit Hilfe der WTL

Der folgende Ansatz funktioniert in allen Entwicklungsumgebungen gleichermaßen, da man ja überall von einem leeren Editor ausgehen kann. Die Menü-Bezeichnungen kommen von der englischen Version eines Visual Studio 2005 und können in anderen Entwicklungsumgebungen variieren.

In diesem Abschnitt wird die WTL in der Version 8.0 eingesetzt.

Die Windows Template Library (WTL) ist eine C++ library für die Entwicklung von Windows-Applikationen und Benutzerschnittstellen-Komponenten. Diese Bibliothek erweitert die Microsoft eigene ATL (Active Template Library) und stellt eine Menge von Klassen zur Verfügung wie Kontroll-Elemente, Dialoge, Fensterklassen, GDI Objekte, und sogar noch mehr.

Die WTL ist Open Source Software und muss natürlich erst mal installiert werden.

Voraussetzung ist auch hier ein installiertes Standard SDK für Windows CE 5.0.

File -> New -> Project -> Visual C++ -> Smart Device -> Win32 Smart Device Project

Name eingeben (z. B. HelloWelt), Location auswählen (z. B. c:\proj ), danach OK klicken.

Es erscheint nun der Win32 Smart Device Project Wizard bei dem folgende Einstellungen vorgenommen werden müssen:

  • Platforms -> Pocket PC 2003 entfernen, STANDARDSDK_500 hinzufügen
  • Application Settings -> Application type: Windows application auswählen
  • Application Settings -> Additional options: Empty project aktivieren

Danach Finish klicken.

Wir haben nun ein geeignetes leeres Projekt.

Zum sinnvollen Arbeiten brauchen wir allerdings eine C++ Datei:

Im Solution-Explorer, rechter Mausclick auf Source-Files -> Add -> New Item -> Code -> C++ File (.cpp)

Name: HalloWelt.cpp eintragen und Add klicken.

Include und library Pfade für WTL 8.0 entweder global oder für das Project setzen (beides z. B. c:\wtl80\include) und folgenden Code in HalloWelt.cpp einfügen.

#include <atlbase.h>
#include <atlapp.h> 
 
extern CAppModule _Module; 
 
#include <atlgdi.h> 
#include <atlmisc.h> 
 
CAppModule _Module; 
 
class CMainWindow : public CWindowImpl<CMainWindow , CWindow , CWinTraits<WS_VISIBLE> > 
{ 
       // Message map is used to map Windows messages to handlers. 
       BEGIN_MSG_MAP(CMainWindow) 
               MESSAGE_HANDLER(WM_PAINT, OnPaint)
               MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
               MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 
       END_MSG_MAP() 
 
       LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 
       { 
               CPaintDC dc(m_hWnd); 
               CRect rect; 
               GetClientRect(rect); 
               dc.DrawText(_T("Hello, Wtl!"), -1, rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER); 
               return 0; 
       } 
 
       LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 
       { 
               PostMessage(WM_CLOSE); 
               return 0; 
       } 
 
       LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 
       { 
               PostQuitMessage(0); 
               return 0; 
       } 
}; 
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int) { 
       // Init module. 
       _Module.Init(0, hInstance, 0); 
       // Create main window. 
       CMainWindow wnd; 
       wnd.Create(NULL, CWindow::rcDefault, _T("Hello, Welt!")); 
       wnd.ShowWindow(SW_SHOW); 
       // Run message loop. 
       CMessageLoop loop; 
       int res = loop.Run(); 
       // Terminate. 
       _Module.Term(); 
       return res; 
}

Und damit geht es mit der WTL...