MFC
Multitouch, MFC 10 und das Kontextmenü
Ein Anwender, der SpeedCommander auf seinem Tablet-PC einsetzt, hatte mir geschrieben, dass dort die Anzeige des Kontextmenüs nicht wie erwartet funktioniert. Eigentlich sollte das Kontextmenü erscheinen, wenn man den Stift etwas länger gedrückt hält. In SpeedCommander tut sich da aber nichts.
Die Fehlersuche ergab, dass die Anzeige des Kontextmenüs bis zur Version 13.20 noch funktionierte und der Fehler erst ab der Version 13.30 auftrat. Ein Blick in die Versionsgeschichte zeigte aber, dass es zwischen diesen beiden Versionen keine Änderungen in der Listenansicht gab, die zu diesem Problem hätten führen können.
Mit der Version 13.30 erfolgte allerdings auch der Umstieg von der MFC 9 (SP1) von Visual Studio 2008 zur MFC 10 von Visual Studio 2010. Eigentlich sollte man erwarten, dass eine neue MFC-Version keine Verhaltensänderung nach sich zieht; zumindestens nicht, wenn man neue Funktionen nicht bewusst aktiviert. Die neue Multitouch-Unterstützung der MFC 10 ist hier aber eine Ausnahme, denn sie ändert die Funktionalität eines Fensters auch ohne explizite Verwendung der neuen Multitouch-Funktionen.
Die Ursache des Problems fand sich in der Verarbeitung der Nachricht WM_TABLET_QUERYSYSTEMGESTURESTATUS in der CWnd::OnTabletQuerySystemGestureStatus. Nach Konvertierung der Bildschirmkoordinaten in Koordinaten des Fensters wird die virtuelle Funktion CWnd::GetGestureStatus aufgerufen, die immer den Wert TABLET_DISABLE_PRESSANDHOLD zurückgibt. Die MFC 10 deaktiviert also für jedes von CWnd abgeleitete Fenster die Möglichkeit, das Kontextmenü der rechten Maustaste durch längeres Drücken des Stiftes oder Fingers anzuzeigen. Das ist unabhängig davon, ob die Multitouch-Funktionen verwendet werden oder nicht.
Die eleganteste Fehlerbehebung ist natürlich die Beseitigung der eigentlichen Ursache, indem die Rückgabe von CWnd::GetGestureStatus einfach auf 0 geändert wird. Nach einer Neuerstellung der MFC ist das Verhalten dann für alle Fenster wieder so, wie es in früheren MFC-Versionen war. Multitouch-Erweiterungen für bestimmte Fenster lassen sich trotzdem einbauen, die Funktion ist ja überschreibbar. Leider hat sich Microsoft mit der MFC 10 dafür entschieden, die entsprechenden Make- und Definitionsdateien nicht mehr auszuliefern. Sofern man sich die Dateien für eine Neuerstellung der MFC also nicht selbst zusammenbastelt, bleibt nur die Möglichkeit, die Funktion CWnd::GetGestureStatus in allen eigenen Ableitungen von CWnd zu überschreiben und den Wert 0 zurückzugeben:
ULONG CMyWnd::GetGestureStatus(__in CPoint /*ptTouch*/) { return 0; }
Entsprechend des Umfangs der eigenen Anwendung und der Anzahl der Fenster mit eigenem Kontextmenü ist das natürlich ziemlich aufwendig. Aber es ist leider auch der einzige Weg, wenn man auf Tablet-PCs mit dem Kontextmenü arbeiten möchte. Einfacher für alle Betroffenen wäre es wohl, wenn Microsoft die nächste MFC-Version entsprechend anpassen würde.
MFC abgespeckt
Letzte Woche Montag ist das Service Pack 1 für Visual Studio 2008 erschienen. Wichtige Neuerungen für den C++-Entwickler sind sicherlich die Unterstützung von TR1 und das UI-Update für die MFC. Nach den Installationsproblemen mit dem im April veröffentlichten Feature Pack wollte ich eigentlich erst einmal die Erfahrungen anderer abwarten.
Daraus wurde dann doch nichts. Zu Testzwecken hatte ich mir ein VS 2008 in einer VM installiert und anschließend das SP1 eingespielt. Probleme gab es keine, die Microsoft-Entwickler haben aus dem Feature Pack-Dilemma gelernt und diesmal wieder ausreichend getestet.
Erfreulicherweise hat Microsoft auch das Konzept beibehalten, die bisherige MFC sowie die neuen UI-Klassen nicht zu verzahnen. Somit kann man die Einbindung der neuen Klassen durch Entfernen der entsprechenden Sektion im Makefile sehr einfach entfernen und die MFC weiter im bisherigen Umfang verwenden. Nach dem Löschen der nicht mehr benötigten Dateien hat man wieder ein schlankes und übersichtliches MFC-Verzeichnis.
Neben den neuen UI-Klassen gab es in der Standard-MFC nur kleinere Korrekturen. Die in afximpl.h definierten Konstanten CX_BORDER und CY_BORDER wurden nach AFX_CX_BORDER und AFX_CY_BORDER umbenannt. Bei einigen Zeigern fehlte bisher die Prüfung gegen NULL, das wurde mit dem SP1 auch behoben.
Nach den positiven Erfahrungen bei der VM-Installation habe ich das SP1 dann auch auf meinem Entwicklungsrechner eingespielt sowie C/C++-Laufzeit und MFC kompiliert. Die Anleitungen für die C/C++-Laufzeit sowie für die MFC sind weiter gültig, zusätzlich müssen für einen manifestlosen Einsatz die Linkerkommentare in appmodul.cpp
#pragma comment(linker, "/include:__forceMFCManifestRTM")
und crtdll.c
#pragma comment(linker, "/include:__forceCRTManifestRTM")
auskommentiert werden. Ansonsten beschwert sich der Linker beim Erstellen der CRT sowie beim Erstellen einer MFC-Anwendung über einen fehlenden Import. Bisher habe ich leider noch nicht herausgefunden, was diese beiden Linkerkommentare bewirken sollen. Die RTM-Version kam noch ohne diese aus.
Fehler in CListCtrl::SortGroups
Die MFC-Unterstützung für die ComCtl32.dll von Windows XP war ja lange ziemlich mager, und so habe ich mir damals meine eigenen Wrapper-Funktionen geschrieben. Die MFC9 von Visual Studio 2008 ist mittlerweile auf dem aktuellen Stand, und so habe ich meine Wrapper-Funktionen zugunsten der MFC-Funktionen entfernt.
Dabei ist mir aufgefallen, dass in der CListCtrl-Methode SortGroups die Parameter vertauscht sind. Die Implementation schaut so aus:
AFX_INLINE BOOL CListCtrl::SortGroups(PFNLVGROUPCOMPARE _pfnGroupCompare, LPVOID _plv) { ASSERT(::IsWindow(m_hWnd)); return (BOOL)::SendMessage(m_hWnd, LVM_SORTGROUPS, (WPARAM)(LPARAM)_plv, (LPARAM)_pfnGroupCompare ); }
während das API-Makro ListView_SortGroups aus der commctrl.h so lautet:
#define ListView_SortGroups(hwnd, _pfnGroupCompate, _plv) \ SNDMSG((hwnd), LVM_SORTGROUPS, (WPARAM)(_pfnGroupCompate), (LPARAM)(_plv))
Beim Aufruf von SortGroups bekommt die Listenansicht also vertauschte WPARAM und LPARAM-Parameter und macht entweder gar nichts oder stürzt ab.
Damit SortGroups richtig funktioniert, muss es in afxcmn3.inl wie folgt geändert werden:
AFX_INLINE BOOL CListCtrl::SortGroups(PFNLVGROUPCOMPARE _pfnGroupCompare, LPVOID _plv) { ASSERT(::IsWindow(m_hWnd)); return (BOOL)::SendMessage(m_hWnd, LVM_SORTGROUPS, (WPARAM)_pfnGroupCompare, (LPARAM)_plv ); }
Zu diesem Problem gibt es übrigens auch einen Connect-Eintrag. In diesem wird das Problem der vertauschten Parameter klar erläutert, aber Microsoft kann es ohne Demoprojekt oder Minidump nicht nachvollziehen…
Visual C++ 2008 Feature Pack Beta
Gestern abend hat Microsoft die erste Beta vom Visual C++ 2008 Feature Pack veröffentlicht. Das Paket ist 303 MiB groß und erfordert zur Installation ein englisches Visual Studio 2008. Die dazugehörige Dokumentation ist etwas kleiner (3.40 MiB) und lässt sich auch ohne Installation betrachten.
Mit der Installation des Feature Packs werden die CRT- und MFC-Verzeichnisse aktualisiert. Es empfiehlt sich daher, vor der Installation eine Kopie des aktuellen VS 2008-Installationsverzeichnisses anzulegen, damit man nach der Installation bei Bedarf zwischen beiden Versionen hin- und herschalten kann. Wer nach der Installation einen schwerwiegenden Fehler mit der Meldung bekommt, dass keine VS 2008-Installation gefunden werden konnte, der sollte vor der Installation des Patches die Installations-DVD von VS 2008 einlegen. Eine Aufforderung dazu gibt es nämlich nicht.
Mit dem Visual C++ 2008 Feature Pack verwandelt sich die MFC zu einem Monstrum. Das atlmfc\include-Verzeichnis wächst von 152 Dateien auf 334 Dateien an und im atlmfc\mfc\src-Verzeichnis befinden sich nach dem Update 437 Dateien (vorher 261). Die zu verteilende mfc90(u).dll wächst von 1.10 MiB auf 3.57 MiB an, was die Größe des Redistributionspakets mal eben locker verdreifacht.
Nun zu den guten Nachrichten. Die normalen MFC-Dateien sind bisher (noch?) nicht von den neuen BCG-Dateien abhängig. Wenn man in atlmfc\mfc\src\makefile die Sektion CONTROLBARS entfernt und die neuen Exporte in den mfc90(ud).def-Dateien löscht, dann kann die MFC immer noch ohne die BCG-Dateien erstellt werden. Zudem muss aus der atlmfc\mfc\src\mfcdll.rc noch die Zeile #include „afxribbon.rc“ auskommentiert werden, damit die Office 2007-Grafiken nicht eingebunden werden. Wenn das auch in Zukunft so bleibt, dann kann ich damit leben.
VS 2008: MFC selbst kompilieren
Gestern hatte ich darüber berichtet, wie man der WinSxS-Hölle entkommt und eine eigene Version der C/C++-Laufzeit kompiliert. Nun kompilieren wir uns noch eine MFC ohne Manifest und können in Zukunft die C/C++-Laufzeit sowie die MFC unseren Anwendungen beilegen, ohne uns mit Manifestproblemen herumquälen zu müssen.
1. Anpassen der Dateien
Die nötigen Änderungen an den MFC-Dateien halten sich in Grenzen. Zuerst schnappen wir uns die Datei atlmfc\include\MFCassem.h und kommentieren das Manifest ab Zeile 25 bis zum Ende aus. In atlmfc\include\afx.h ersetzen wir die Zeilen 81 bis 97 durch folgende:
#ifndef _UNICODE #ifdef _DEBUG #pragma comment(lib, "MyMfc90d.lib") #pragma comment(lib, "MyMfc90sd.lib") #else #pragma comment(lib, "MyMfc90.lib") #pragma comment(lib, "MyMfc90s.lib") #endif #else #ifdef _DEBUG #pragma comment(lib, "MyMfc90ud.lib") #pragma comment(lib, "MyMfc90sud.lib") #else #pragma comment(lib, "MyMfc90u.lib") #pragma comment(lib, "MyMfc90su.lib") #endif #endif
Damit legen wir fest, dass unsere Anwendungen dynamisch gegen die MyMfc90(u).dll gelinkt werden.
2. Vorbereitung der .DEF-Dateien
In atlmfc\src\mfc\intel und atlmfc\src\mfc\intel befinden sich jeweils vier .DEF-Dateien, deren Modulnamen ebenfalls angepasst werden müssen:
mfc90.def -> MyMfc90 mfc90d.def -> MyMfc90d mfc90u.def -> MyMfc90u mfc90ud.def -> MyMfc90ud
Im Gegensatz zur C/C++-Laufzeit werden aber nur die Modulnamen in den .def-Dateien angepasst, die Dateinamen selbst dürfen nicht geändert werden.
3. Anpassung des Makefiles
Die Änderung in der Datei atlmfc\src\atlmfc.mak beschränkt sich darauf, die Erstellung der statischen MFC sowie der WinForms-Komponenten auszuklammern. Dazu löschen wir in Zeile 123 die Einträge MFC_STATIC und MFCM_DLL.
4. Kompilieren
Nun kopieren wir unsere bereits erstellten Batchdateien mit den Umgebungsvariablen aus dem Ordner crt in den Ordner atlmfc\src. Zusätzlich erstellen wir in diesem Verzeichnis eine Datei makemfc_x86.bat mit dem Inhalt
nmake -f atlmfc.mak MFC LIBNAME=MyMfc90 PLATFORM=INTEL MP_BUILD=1
sowie makemfc_amd64.bat mit
nmake -f atlmfc.mak MFC LIBNAME=MyMfc90 PLATFORM=AMD64 MP_BUILD=1
Anschließend öffnen wir eine Eingabeaufforderung und starten
vcvars_x86.bat makemfc_x86.bat
sowie anschließend
vcvars_amd64.bat makemfc_amd64.bat
Nach ein paar Minuten sollte der Compiler seine Arbeit erledigt haben und wieder das Befehlsprompt erscheinen.
5. Kopieren der Lib-Dateien
Der letzte Schritt ist das Kopieren der lib-Dateien nach atlmfc\lib, damit der Linker diese später auch findet. Die Lib-Dateien für die 32-bit Version werden bei der MFC-Erstellung in atlmfc\lib\Intel abgelegt und müssen deshalb manuell nach atlmfc\lib kopiert werden. Die Lib-Dateien für die x64-Version landen dagegen direkt im richtigen Verzeichnis (atlmfc\lib\amd64).
Die MFC-Dlls finden wir in atlmfc\src\mfc\intel bzw. atlmfc\src\mfc\amd64. Zusammen mit den Dlls der C/C++-Laufzeit sowie den jeweiligen PDB-Dateien kopieren wir sie in einen Ordner, der in die PATH-Umgebungsvariable eingetragen wird. Somit ist sichergestellt, dass Visual Studio 2008 beim Debuggen auch alle nötigen Dateien findet.
6. Kontrolle
Zur Kontrolle erstellen wir uns ein Testprojekt und prüfen, ob gegen die richtigen Dateien gelinkt wird. Dazu lassen wir uns vom AppWizard eine einfache MFC-Anwendung erstellen und kompilieren diese. Mit Hilfe der Schnellansicht von SpeedCommander lässt sich leicht ermitteln, ob die Programmdatei an die richtigen Module gebunden wurden. Wenn es so ausschaut, dann ist alles in bester Ordnung:
Die gleiche Aktion führen wir noch einmal für die MyMfc90(ud).dll durch, diese sollten ebenfalls gegen die MyVcr90(d).dll gelinkt sein.
7. Letzte Worte
Zum Abschluss sei nochmals erwähnt, dass sich diese beiden Artikel wirklich nur an den nativen Entwickler richten, der vollständigen Einfluss auf die von ihm verwendeten Komponenten hat. Dazu gehört, dass alle Fremdkomponenten im Quellcode vorliegen und somit gegen die angepasste C/C++-Laufzeit bzw. die MFC kompiliert werden können. Verwendet man dagegen zusätzliche Managed Code-Erweiterungen oder fertige Libs/Dlls, die bereits gegen die originale MsVcr90.dll gelinkt sind, dann sollte man um die manifestlose Lösung einen großen Bogen machen.
2.7 MiB mehr für nichts
Pat Brenner hat im VC-Blog meine schlimmsten Befürchtungen bestätigt: Die Erweiterungen von MFCnext werden komplett in die MFCxx.dll gepackt, was deren Größe mal eben von 1.1 MiB auf 3.8 MiB ansteigen lässt. Einer der Vorteile der MFCxx.dll war immer, dass sie über die Jahre hinweg relativ schlank geblieben ist. All das ist Geschichte, stattdessen wird die MFC jetzt mit Klassen vollgestopft, welche wohl die wenigsten benötigen. Und am allerwenigsten diejenigen, die schon eine eigene UI-Bibliothek einsetzen.
Ich hoffe immer noch inständig, dass sich das unnützte Zeug beim Erstellen einer angepassten MFC-Version recht einfach ausblenden lassen wird. Sollte Microsoft es aber schaffen, MFC und MFCnext untrennbar miteinander zu verquicken, dann wird die MFC 9.0 meine letzte MFC-Version sein. Ich hatte eigentlich gedacht, dass ich mit dem Umstieg von VC6 auf VS 2008 nun längere Zeit nichts mehr mit MFC-Anpassungen zu tun haben und automatisch immer in den Genuss der neuesten Version kommen werde. Aber so kann man sich täuschen.
Weitere Infos zum MFC UI-Update
Im Codejock-Forum hat Kirk Stowell (der Chef von Codejock) ein paar interessante Infos zur ganzen Geschichte veröffentlicht, die ich euch nicht vorenthalten möchte. Demnach hat Microsoft schon vor einigen Jahren Codejock kontaktiert, um die MFC für Visual Studio 2005 etwas aufzupeppen. Es gab ein paar Gespräche, zu mehr führte es aber nicht.
Im März dieses Jahres ist Microsoft erneut mit Codejock in Kontakt getreten und hat Interesse daran geäußert, Codejocks MFC-Komponenten in die MFC von Visual Studio 2008 aufzunehmen. Das Budget für mögliche Lizenzgebühren sei aber nicht gerade hoch.
Im August ließ Microsoft wieder von sich hören. Man wollte mit Codejock über Erweiterungspläne der MFC diskutieren, als auch über die möglichen Auswirkungen auf die MFC-Produkte von Codejock. In diesen Gesprächen kam herüber, dass Microsoft für wenig Geld die MFC-Komponenten von BCGSoft lizenzieren wird und diese somit Teil der MFC werden sollen.
Kirk gab zu bedenken, dass sich diese Entscheidung als großer Fehler herausstellen könnte. Aus Erfahrung gäbe es einige Probleme mit den BCG-Komponenten, angefangen von der Stabilität bis hin zur recht schwachen Performance. Er wies Microsoft auch darauf hin, dass sich gerade deshalb viele BCG-Anwender für einen Wechsel zu den Produkten von Codejock entschieden hätten und schlug vor, dass Microsoft doch die Meinung einiger dieser Kunden einholen könnte. Der Vertrag mit BCGSoft war aber schon unterschrieben und Microsoft sah keine Notwendigkeit mehr, diese Sache weiter zu verfolgen.
Genau wie Kirk glaube ich auch, dass Microsoft eine ziemlich unglückliche Entscheidung getroffen hat. Die Performance-Probleme waren damals auch einer der Gründe für mich, vor vier Jahren zu Codejock zu wechseln. Ich kann mich noch gut daran erinnern, dass die Einbindung der BCGControlBar in FileSearch (SpeedCommander 9) den Start der Anwendung um knapp zwei Sekunden verzögerte. Also verzichtete ich damals in FileSearch auf die anpassbaren Menüs, stattdessen zeigte sich FileSearch nur mit normalen Menüs.
Gemeinsam mit Rainer haben wir damals auch die Aufrufgeschwindigkeit der frei downloadbaren Beispieldateien von Codejock und BCGSoft miteinander verglichen. Die von BCGSoft starteten alle merklich langsamer. Auf Rainers Rechner, der damals auch nicht gerade der schnellste war, wurde dies besonders deutlich.
Microsoft wird also einiges an Mühe aufwenden müssen, damit die MFCnext ein stabiles und performantes Produkt wird. Es ist als Entwickler immer schwer, sich in eine so umfangreiche Bibliothek einzuarbeiten. Mal schauen, wie Microsoft das meistern wird.
The Next Generation
In Barcelona findet in dieser Woche die TechEd Developers 2007 statt, also der richtige Zeitpunkt, um Großes zu verkünden. Die erste wichtige Info ist, dass Visual Studio 2008 bis zum Ende dieses Monats verfügbar sein wird und damit wohl allen MSDN-Abonnenten zur Verfügung gestellt wird.
Schon seit einiger Zeit laufen einem im Web Hinweise über den Weg, dass auch für die MFC einige Überraschungen zu erwarten sind. Microsoft hat nun die Katze aus dem Sack gelassen, und diese Katze ist wirklich fett. Die MFC bekommt ein vollständiges UI-Toolkit spendiert (genannt MFCnext), unter anderem mit
- Office 2007-Ribbon
- Erweiterte Docking-Funktionen
- Verschiedene Styles (Office 2003, Office 2007, …)
- Etliche neue UI-Elemente (Eigenschaftsseiten, Maskierbares Editierfeld, Farbpicker, …)
Der erste Release Candidate soll schon im Dezember veröffentlicht werden, die endgültige Freigabe ist für März 2008 geplant.
Auf den ersten Blick sieht das auch alles Klasse aus, mit dem zweiten sieht man aber bekanntlich besser. Und man stellt fest, dass dies alles ja schon seit Jahren zur Verfügung steht. Zwar nicht mit der MFC selbst, wohl aber mit den Toolkits anderer Hersteller (Codejock oder BCGSoft). Hier stellt sich nun die Frage, wie der Vergleich zwischen den neuen MFC-Erweiterungen und den etablierten Bibliotheken ausschauen wird, sowohl vom Umfang als auch von der Performance und der Codequalität. Auch wird interessant, wie die beiden Hersteller mit der Situation klarkommen, dass die von ihnen verkauften Funktionen nun plötzlich Bestandteil von Visual Studio sind und damit für jeden MFC-Anwender auch kostenfrei zur Verfügung stehen. Wenn sich Microsoft einmal entschließen sollte, jedem Windows einen vernünftigen Dateimanager beizulegen, dann hätte ich wohl ein ähnliches Problem.
Dank Jochen Kalmbach brauchen wir mit der Beantwortung dieser Fragen aber wohl nicht bis zum Dezember warten. In seiner Information zum geplanten MFC-Update verrät er nämlich, dass die meisten Controls von BCGSoft „portiert“ wurden. Wenn man sich mal die von ihm gemachten Fotos der Session anschaut und diese mal mit den Headerdateien der BCGControlBar Professional Edition vergleicht, dann entdeckt man auch erstaunlich viele Gemeinsamkeiten mit den BCG-Klassen. „Portiert“ heißt dann vermutlich eher „aufgekauft und umbenannt“. Aus Raider wird also Twix, sonst ändert sich nichts.
Und genau das ist für mich der Punkt, auch in Zukunft weiter auf Codejock zu setzen. Bis einschließlich SpeedCommander 9 habe ich ja bereits mit der BCGControlBar gearbeitet, mit SpeedCommander 10 erfolgte der Wechsel auf das Xtreme Toolkit Pro. Und diesen Wechsel habe ich bisher keine einzige Sekunde bereut. Nach meiner Erfahrung ist die Codejock-Bibliothek nämlich um einiges performanter und auch übersichtlicher und moderner aufgebaut. Das Klassenlayout der aktuellen BCGControlBar-Version hat dagegen noch erstaunlich viel Gemeinsamkeiten mit den ganz frühen Versionen, die ich noch verwendet habe. Das mag gut für die Abwärtskompatibilität sein, so ein altes Fundament hat aber leider auch Nachteile. Neue Sachen werden nämlich immer nur angebaut und irgendwann schwindet die Übersichtlichkeit.
Wer also schon mal schauen will, wie sich die neuen UI-Elemente in der Praxis anfühlen, der muss sich einfach nur die Testversion der BCGControlBar Professional Edition herunterladen. Auf der gleichen Seite gibt es auch bereits kompilierte Beispielanwendungen. Spannend wird sicher sein, wie die Zukunft der BCGControlBar ausschaut. Ich glaube kaum, dass BCGSoft damit noch viel Umsatz machen wird. Aber vermutlich wird der Scheck von Microsoft groß genug gewesen sein, um die Schmerzen einigermaßen in Grenzen zu halten. Weitaus schwieriger wird es dagegen für Codejock werden. Ich hoffe wirklich, dass sich die Jungs durch diese Ankündigung nicht entmutigen lassen und auch in Zukunft gute Umsätze haben. Es wäre nämlich äußerst schade, wenn Codejock dadurch auf der Strecke bleiben würde.
Erster Ausblick auf die MFC 9
Auf Channel 9 ist ein Video erschienen, in dem Bill Dunlap und Steve Teixeira über die zukünftige Strategie von Visual C++ erzählen. Im letzten Sommer gab es im Team intensive Überlegungen, ob die schon länger anhaltende Bevorzugung von Managed Code gegenüber nativen Code in Visual C++ richtig ist. Mit der Befragung verschiedener Anwender (Systemintegratoren, ISV) stellte sich heraus, dass trotz der .NET-Hysterie immer noch die meisten Anwendungen in nativem C++ programmiert werden. Die Entwicklung basiert auf riesengroßen Quellcodearchiven in C++, die nicht mal eben auf .NET angepasst werden können. Stattdessen muss der Code gepflegt werden, nicht selten enthält er auch einiges an geistigem Eigentum.
Mit dem kommenden Visual Studio 9 (Orcas) soll nun für die C++-Sparte wieder mehr Wert auf die Unterstützung von nativem Code gelegt werden. Dazu wird die Interoperabilität zwischen nativem Code und Managed Code weiter verbessert, speziell die Konvertierung von einzelnen Dateitypen. Zudem wird Orcas auch eine STL in Managed Code für die CLR enthalten. Die MFC wird endlich wieder auf einen aktuellen Stand gebracht und soll viele Neuerungen in Vista unterstützen.
Die ersten Ergebnisse lassen sich bereits in der neuen Orcas-CTP vom März begutachten. Spielten sich die Änderungen in der MFC in der Orcas-CTP vom Januar im Vergleich zu VS 2005 nur im namenstechnischen Bereich ab, so enthält die Orcas-CTP vom März viele Änderungen, die wichtigsten möchte ich hier kurz skizzieren.
Entwickler, die mit ihren Anwendungen noch Windows 9x und NT4 unterstützen, müssen sich vor dem Umstieg auf Orcas samt MFC 9 die Frage stellen, ob sie dies auch weiterhin tun möchten. Mit der MFC 9 werden nämlich alle Brücken zu Windows 9x/NT4 abgerissen, die Mindestvoraussetzung für eine MFC 9-Anwendung ist Windows 2000. Auch die ISAPI-Unterstützung wurde entfernt.
CWnd enthält Nachrichtenhandler für neuere Systemnachrichten, für diese wurden auch neue Message-Cracker eingeführt. CFrameWnd bietet Unterstützung für die aus Vista bekannten ausblendbaren Menüs, die erst beim Drücken der Alt-Taste eingeblendet werden. CPropertySheet unterstützt nun auch die neuen Aero-Assistenten.
Die UI-Elemente CListCtrl, CTreeCtrl, CHeaderCtrl, CProgressCtrl und CToolTipCtrl aus der ComCtl32.dll unterstützen nun alle bis einschließlich Vista vorhandene Nachrichten und Stile. Das bereits mit der Version 4.71 eingeführte Pager-Control wird nun auch endlich gekapselt.
Neu ist auch CNetAddressCtrl, welches ein Editierfeld für Netzwerkadressen inkl. ihrer Verifizierung kapselt. Die Registrierung der Fensterklasse erfolgt mit der Funktion InitNetworkAddressControl, welche erstaunlicherweise zur Shell32.dll gehört und nicht zur ComCtl32.dll. Daher findet man im Windows SDK für Vista auch keinen Verweis innerhalb der Windows Controls, stattdessen werden die entsprechenden Macros unter Windows Shell – Shell Reference – Shell Macros aufgeführt.
Die Klasse CFileDialog zum Anzeigen eines „Datei öffnen/speichern“-Dialogs kann nun auch die neuen Dateidialoge von Windows Vista anzeigen. Vista zeigt zwar unter Umständen die neuen Dialoge selbstständig, allerdings auch nur, wenn die Anwendung keine Hookfunktion für diese Dialoge einsetzt. Da die MFC für die Implementation von CFileDialog aber zwingend auf die Hookfunktion angewiesen ist, zeigen MFC-Anwendungen unter Vista immer nur die alten Dialoge. In der MFC 9 nutzt CFileDialog unter Vista die COM-Schnittstellen für die neuen Dateidialoge. Der Entwickler verwendet CFileDialog wie bisher, der Rest geschieht automatisch unter der Haube.
Es ist sehr erfreulich, dass man bei Microsoft wohl eingesehen hat, dass die meisten C++-Entwickler ihre Sprache und ihre Anwendungen in nativem Code nicht einfach aufgeben wollen und können. Wenn sich jetzt auch noch Orcas in VC6-Performance ohne ständiges Geflicker präsentieren und der ClassWizard ein Comeback erleben würde, dann könnte ich guten Gewissens auf Orcas umsteigen und den VC6 in seinen wohlverdienten Ruhestand schicken. Aber ich fürchte, dass dies trotz der guten Aussichten so schnell wohl nicht passieren wird.
Kein Fehler aufgetreten
Henrik hat festgestellt, dass SpeedEdit beim Öffnen einer leeren Datei mit der Erweiterung .url die Meldung „Kein Fehler aufgetreten.“ ausgibt. Beim Debuggen habe ich dann auch recht schnell den Grund dafür gefunden.
In der Funktion OpenDocumentFile des CDocManager-Objektes wird die Funktion AfxResolveShortcut aufgerufen, mit deren Hilfe Verknüpfungen aufgelöst werden sollen. AfxResolveShortcut verwendet dafür die Schnittstelle IShellLink und gibt im Erfolgsfall den aufgelösten Pfadnamen zurück. Bei einer leeren .url-Datei vermeldet IShellLink::Resolve zwar Erfolg, IShellLink::GetPath gibt aber einen leeren String zurück. AfxResolveShortcut meldet den Erfolg weiter und die MFC verwendet nun statt des Dateinamens für die .url-Datei den leeren String, um die Datei zu öffnen.
Abhilfe schafft die zusätzliche Prüfung auf einen leeren aufgelösten Pfadnamen in der Datei docmgr.cpp (Zeile 928):
if (AfxResolveShortcut(AfxGetMainWnd(), szPath, szLinkName, _MAX_PATH) && szLinkName[0]) { Checked::tcscpy_s(szPath, _countof(szPath), szLinkName); }