FAQ: 'Microsoft Visual C++' (18.12.2004)

Inhaltsverzeichnis


Folgende Autoren haben an diesem FAQ mitgewirkt

Name EMail Homepage
Kurt Antreich MTSIS@Microsoft.com http://www.microsoft.com
Thomas Aschauer taschaue@cosy.sbg.ac.at
Olivier Braun olivier.braun@tu-berlin.de
Karl Donaubauer admin@donkarl.com http://www.donkarl.com
Jörg Friebel joerg.friebel@picturebox.de http://www.picturebox.de
Jens Geyer jgx@vsx.net
Dirk Hedderich hedderich@gmx.net
Manni Heumann manni.heumann@gmx.de
Maximilian Hänel max_haenel@smjh.de
Andreas Kaiser ryuash@cs.tu-berlin.de
Thomas Klocker klockertom@gmx.net
Michael Krafzik developer@netzzentrale.de
Martin Richter martin.richter@grutzeck.de
Alexander Sailer Alexander.Sailer@de.bosch.com
Eberhard Schefold ebab@gmx.de
Dieter Smode dietersmode@web.de http://www.mpdvc.de
Andre Stille stille@socon.com
Albert Weinert mail@albert-weinert.de http://www.awn-design.de
Carsten Witte carsten.witte@gmx.de http://www.carsti.de
Stefan Zehe szehe@t-online.de

Inhaltsverzeichnis


1  Grundsätzliches zu diesem FAQ

1.1  Über dieses FAQ [URL]

Die Visual C++-FAQ ist eine Sammlung häufig gestellter Fragen zu Visual C++ und ihrer Antworten aus dem Newsforum microsoft.public.de.vc der Microsoft Corp.

Obwohl versucht wird, offensichtliche inhaltliche Fehler aufzufinden, kann nicht gewährleistet werden, daß die in dieser FAQ angebotenen Informationen fehlerfrei sind. Jegliche Haftung durch die Autoren sowie jedwede mit der FAQ im Zusammenhang stehende Person oder Organisation wird ausgeschlossen. Die Erwähnung oder Besprechung von Produkten oder Firmen stellen keine Empfehlung dar.

Diese FAQ enthält Verweise (Links) zu Websites anderer Unternehmen, Organisationen oder zu privaten Anbietern. Für Inhalt, Aktualität, Qualität, Verwendbarkeit, Vollständigkeit dieser verlinkten Websites kann keinerlei Haftung oder Gewähr übernommen werden. Dies gilt insbesondere auch für die Quelle der dort angebotenen Informationen und die eventuell bestehenden Rechte Dritter. Für die Websites Dritter wird jegliche Verantwortung ausdrücklich abgelehnt.

Copyright © Albert Weinert 1999-2001, Dieter Smode 2002

Dieses Dokument ist durch internationale Urheberrechte geschützt. Es wird ausdrücklich genehmigt, die Visual C++-FAQ in Gesamtheit in schriftlicher oder elektronischer Form zu kopieren und Dritten zugänglich zu machen, vorausgesetzt, daß hierfür in keiner Form Gebühren erhoben werden.

Im FAQ erwähnte Markennamen, Warenzeichen und sonstige geschützte Begriffe und Bezeichnungen werden hiermit uneingeschränkt anerkannt, ohne daß eine ausdrückliche Erwähnung oder Kennzeichnung im Einzelfall erfolgt.

Verweise:

microsoft.public.de.vc

Autoren:

Albert Weinert, Dieter Smode

1.2  Bezugsquelle der Microsoft Visual C++® FAQ [URL]

Die Visual C++ FAQ ist über das Internet unter der Adresse http://www.mpdvc.de zu beziehen. Es gibt ein Download Archiv welches die kompletten FAQ zur lokalen Nutzung enthält.

Verweise:

Bezugsquelle Microsoft Visual C++ FAQ
Visual C++ FAQ (HTML)
Visual C++ FAQ (PDF)

Autoren:

Albert Weinert, Dieter Smode

1.3  Beiträge zu den Visual C++ FAQ [URL]

Diese FAQ lebt von den Beiträgen ihrer Leser. Die Aufgabe des Redakteurs besteht nicht in der Initiierung und Erstellung von Artikeln, sondern in deren redaktioneller Aufarbeitung und eingeschränkt in deren inhaltlicher Prüfung.

Jeder Leser kann und soll(!) an den FAQ-Redakteur neue Artikel, erweiterte Informationen zu bestehenden Artikeln und Fehlerkorrekturen senden. Da es Sinn dieser FAQ ist, das Datenaufkommen in den Newsforen auf das notwendige Maß zu beschränken, soll bei Einbringung neuer Artikel insbesondere berücksichtigt werden, daß es sich um ein Thema handeln soll, das durch mehrfache Behandlung diesem Anspruch genügt.

Artikelbeiträge werden im Allgemeinen unter Angabe des Initiators angeboten, diese Kennzeichnung kann auf Wunsch unterbleiben. Ein Anspruch auf solche Kennzeichnung besteht jedoch nicht. Eine namentliche Kennzeichnung bedeutet nicht, daß die benannte Person diesen Artikel wörtlich verfaßt hat.

Der Redakteur der FAQ steht im Allgemeinen nicht für die Beantwortung programmiertechnischer Fragen zur Verfügung. Bitte wenden Sie sich an die namentlich genannten Personen oder an die Microsoft-Newsforen, wenn Sie inhaltliche Fragen zu einem Beitrag haben.

Beiträge, Korrekturen und/oder Beitragsvorschläge können per E-Mail an den Redakteur der FAQ gesendet werden.

Verweise:

Eine Frage/Antwort zum FAQ beitragen bzw. ergänzen

Autoren:

Albert Weinert

1.4  Kann ich die Autoren direkt etwas fragen? [URL]

Dies kann nicht so pauschal beantwortet werden. Natürlich ist von jedem Autor, sofern er es möchte, die e-Mail Adresse in der FAQ mit angegeben. Primär dient diese jedoch bei Fehlern in der entsprechenden Antwort, oder für kurze Nachfragen zur der Antwort, den Autor zu kontaktieren. Nicht um ihnen weitere Fragen zu stellen, die sie in ihrer Freizeit mal eben beantworten sollen.

Es bleibt den Autoren selbst überlassen auf solche Fragen einzugehen oder sie einfach zu ignorieren. Der größere Teil der Autoren wird solche Fragen nicht beantworten. Als Fragesteller sollte man diese Einstellung respektieren.

Für die Beantwortung von Fragen stehen die Newsforen zu Verfügung. Dort ist die Chance das jemand die Frage beantworten kann ohnehin viel höher. Bitte nutzt diesen Weg!

Verweise:

microsoft.public.de.vc

Autoren:

Albert Weinert

1.5  Was bedeutet dieses [URL] neben jeder Überschrift? [URL]

Hier handelt es sich um einen Link, der auf den Beitrag selbst verweist. Mit dem Internet Explorer und Netscape kann man die URL mit Rechtsklick "Verknüpfung kopieren" bzw. "Copy Shortcut" (oder so ähnlich) ins Clipboard übernehmen und dann einfach in eine Newsgroup-Antwort kopiert werden.

Wenn der Browser diese Methode nicht unterstützt: Ein Klick darauf kopiert die URL des Artikels in die Adreßzeile des Browsers und kann dann von dort einfach kopiert.

Autoren:

Dieter Smode

Inhaltsverzeichnis


2  Neue und aktualisierte Beiträge

2.1  Geänderte Beiträge [URL]

18.12.2004
7.26 Wie kann ich den Fehlercode von GetLastError in einen Fehlerstring umwandeln?

27.07.2004
3.4 Wo sind die aktuellen ServicePacks rund um Microsoft Visual C++ erhältlich?
3.10 Erkennen der ServicePack-Version für Visual Studio 6.0

22.06.2004
Links aktualisiert

2.2  Neue Beiträge [URL]

26.07.2004
3.10 Erkennen der ServicePack-Version für Visual Studio 6.0

25.07.2004
6.6 Umgang mit float und double
HOWTO: Fließkommadarstellung und Problembehandlung

Inhaltsverzeichnis


3  Allgemeine Fragen zu Visual C++ (VC)

3.1  Welche Version von Visual C++ ist aktuell? [URL]

Für die aktuellen Betriebssysteme ist dies die Version 7.1 (auch als Visual Studio .NET 2003 bzw. Visual C++ .NET 2003 bekannt). VC 7.1 gibt als als einzelne Version zu kaufen, oder als Paket - genannt Visual Studio - in verschiedenen Varianten.

Sollten Sie noch Software für DOS oder Windows 3.x entwickeln müssen, kann die Version 1.52c verwendet werden.

Verweise:

Entwicklerprodukte/MSDN

Autoren:

Albert Weinert, Dieter Smode

3.2  Wo liegen die Unterschiede zwischen den verschiedenen Editionen? [URL]

Eine detailierte Beschreibung der Unterschiede zwischen den einzelnen Editionen ist auf der Homepage von Microsoft zu finden.

Verweise:

Entwicklerprodukte
Microsoft Schulprodukte

Autoren:

Albert Weinert, Dieter Smode

3.3  Darf ich Programme, welche mit der Schulversionen erstellt worden sind, kommerziell vertreiben? [URL]

Nein. Es darf keine Gewinnabzielungsabsicht bestehen.

Aber man kann zu den normalen Updatepreisen auf die kommerziellen Versionen updaten.

Verweise:

Microsoft Lizenzen für Schüler, Studierende und Lehrkräfte

Autoren:

Albert Weinert, Dieter Smode

3.4  Wo sind die aktuellen ServicePacks rund um Microsoft Visual C++ erhältlich? [URL]

ServicePacks gibt es leider nicht für einzelnene Programme aus dem VisualStudio Paketen. Es gibt zwar abgespeckte Version für Visual Basic Anwender, als Visual C++ Anwender muß man leider immer die komplette Version runterladen.

Für das Visual Studio 6.0 ist das ServicePack 6 das letzte erschienene SP.

Wenn Sie mit Visual Studio 97 (5.0) arbeiteten das ist auch ein ServicePack 3 das letzte erschienene SP.

Von vielen anderen Microsoft Produkten die zur Entwicklung gebraucht werden gibt es auch neue Versionen. Diese sind hier auch aufgeführt.

Verweise:

Übersicht über die Microsoft ServicePacks (Deutsch)
Übersicht über die Microsoft ServicePacks (Englisch)
Service Pack 3a für SQL-Server 2000 bzw. MSDE (s. hierzu auch INF: So identifizieren Sie die MSI-Datei, die für eine bestehende MSDE-Installation verwendet wurde)
Runtime Komponenten für Visual C++ 6.0 Applikationen
Comctl32 Redistributables 5.80.2614.3600 (WinNT und Win9x)
Jet 4.0 Service Pack 8
Acc97: Neuere Version der Microsoft Jet 3.5
MDAC: Microsoft Data Access Components (2.1 SP2, 2.5, 2.5 SP1, 2.6, 2.7, 2.8)
Windows NT4 Security Rollup Package
Visual Studio® Installer 1.1
Microsoft XML Core Services 4.0 SP2 und weitere XML-Downloads (früher Microsoft XML Parser)
Windows Template Library 7.0
Redistributables for Platform SDK

Autoren:

Albert Weinert, Dieter Smode

3.5  Kann ich mit Visual C++ Software für Window CE entwickeln? [URL]

Ja, dies ist möglich. Dazu benötigen Sie die Windows eMbedded Visual Tools, die sind kostenlos und können im Internet runterladen oder auf CD bestellt werden.

Windows eMbedded Visual Tools brauchen kein installierte Visual Studio, so wie es bei den Vorgängerversionen der Fall war.

Verweise:

Microsoft eMbedded Visual C++ 4.0
MSDN: Windows Embedded Developer Support Center

Autoren:

Albert Weinert

3.6  Welche Version von Visual C++ kann für die DOS-Entwicklung eingesetzt werden? [URL]

Die letzte hierfür einsetzbare Version ist V 1.52c. MSDN-Abonnenten können diese Version über "Subscriber Downloads" herunterladen.

Autoren:

Dieter Smode

3.7  Brauche ich eine Quellcodeverwaltung? [URL]

Unbedingt erforderlich ist eine Quellcodeverwaltung nicht. Aber sie hat eindeutige Vorteile! Auch wenn man als Einzelkämpfer programmiert, hat die Quellcodeverwaltung ihre Berechtigung. Bei der Softwareentwicklung in Gruppen sollte sie allerdings zur Pflicht werden. Mit ihrer Hilfe kann man Änderungen am Code relativ einfach nachvollziehen, da die ganze Entstehungsgeschichte des Codes letztlich in der Quellcodeverwaltung enthalten ist und mit einem Diff-Utility (z. B. Windiff) verfolgt werden kann. Wenn also etwas nicht mehr funktioniert, ist es relativ einfach, die Änderungen zwischen einer noch funktionierenden Version und der nicht mehr funktionierenden Version nachzuvollziehen. Wer hier immer den kompletten Code liest oder grundsätzlich den Debugger anwirft, macht sich das Leben unnötig schwer.

Die meisten Quellcodeverwaltungen erlauben darüber hinaus, bestimmte Versionen zu kennzeichnen und diese Versionen auch wieder komplett abzurufen, d. h. man kann eine vor geraumer Zeit ausgelieferte Version wieder komplett reproduzieren, wobei hier auch darauf zu achten ist, daß nicht nur der Sourcecode hier eine Rolle spielt, sondern auch die Version der eingesetzten Tools einen Einfluß auf die Gesamtsoftware haben können und daher ggf. auch in die Quellcodeverwaltung gehören (in der Regel können Quellcodeverwaltungen auch mit Binärdateien umgehen).

Ab und an kommt es darüber hinaus vor, daß ein Modul in leicht unterschiedlichen Varianten gepflegt werden muß. Das wird durch Verzweigen (Branch) häufig unterstützt. Es kommt auch vor, daß solche Verzweigungen letztlich wieder in gemeinsamen Code münden. Bei diesem Zusammenführen (Merge) kann die Quellcodeverwaltung ebenfalls helfen.

Ein weiterer gewichtiger Grund für den Einsatz einer Quellcodeverwaltung ist die Wiederverwendbarkeit von Code. In der Praxis wird das häufig so gemacht, daß die entsprechenden Module einfach kopiert werden, so daß schlußendlich etliche Kopien entstehen, die mitunter unabhängig voneinander geändert werden, so daß sich letztlich keiner mehr damit auskennt. Bei diesem Verfahren ist es äußerst mühsam, wenn einmal eine generelle Änderung an einem Modul vorgenommen werden muß. Eine zweite Variante für die Wiederverwendbarkeit besteht darin, bestimmte Codeteile in einem Verzeichnis zu halten und von den verschiedenen Projekten darauf zuzugreifen. Dabei handelt man sich den Nachteil ein, daß jede Änderung stets für alle betroffenen Projekte gilt.

Die dritte Variante besteht darin, sich bei der Wiederverwendbarkeit von der Quellcodeverwaltung unterstützen zu lassen. Hier kann man die gemeinsam genutzten Module innerhalb der Quellcodeverwaltung bereitstellen. Auch hier existiert zunächst nur eine Kopie des Codes. Allerdings wird jede Änderung automatisch dokumentiert und man kann im Bedarfsfall die gemeinsame Nutzung wieder aufgeben oder einen neuen Zweig anlegen.

Visual SourceSafe ist die Quellcodeverwaltung von Microsoft (diese liegt zumindest der Enterprise-Version von VisualStudio bei, ist aber auch einzeln erhältlich). Während es bei Quellcodeverwaltungen anderer Hersteller immer wieder Probleme bei der Integration in VisualStudio gibt, ist SourceSafe recht gut integriert. Der Zusatzaufwand durch die Quellcodeverwaltung besteht im wesentlichen darin, daß man zu bearbeitende Module auschecken und sich daran gewöhnen muß, diese auch wieder einzuchecken, wenn ein sinnvoller Änderungsstand erreicht ist. Wichtig ist natürlich auch, speziell beim Einchecken die durchgeführten Änderungen auch noch einmal kurz zu beschreiben und so die verschiedenen Versionen zu kennzeichnen.

Autoren:

Dieter Smode

3.8  Was gehört in die Quellcodeverwaltung? [URL]

Die Antwort ist relativ einfach: alles, was nicht von der Entwicklungsumgebung aus vorhandenen Informationen neu generiert werden kann. Im MSDN-Artikel "INFO: Which Visual C++ Files to Add to Source-Code Control" (156513) gibt Microsoft dazu einige Hinweise.

Allerdings sollte man sich entsprechend den eigenen Erfordernissen Gedanken machen, was evtl. noch zusätzlich in die Quellcodeverwaltung gehört. Ist man beispielsweise darauf angewiesen, bestimmte Programmversionen wieder herstellen zu können, dann sollten auch Fremdlibraries etc. in die Quellcodeverwaltung aufgenommen werden. Denn die beste Versionsverwaltung hilft nicht, wenn sich beim Erzeugen der Software herausstellt, daß ein inzwischen aktualisiertes Fremdtool zu den alten Sourcen nicht mehr kompatibel ist.

Verweise:

INFO: Which Visual C++ Files to Add to Source-Code Control

Autoren:

Dieter Smode

3.9  Voraussetzungen für VisualStudio .NET 2003 [URL]

VisualStudio .NET 2003 kann unter den nachfolgend genannten Betriebssysteme installiert werden:

  1. Microsoft Windows Server 2003
  2. Windows XP Professional
  3. Windows XP Home Edition (da die Home Edition keinen Internet Information Server enthält, können hier keine Webservices erzeugt werden)
  4. Windows 2000 Professional
  5. Windows 2000 Server

Mit VisualStudio .NET 2003 lassen sich Programme für folgende Zielbetriebssysteme erstellen:

  1. Microsoft Windows .NET Server 2003
  2. Windows XP Professional
  3. Windows XP Home Edition
  4. Windows 2000 (Service Pack 2 wird empfohlen)
  5. Windows Millennium Edition (Windows Me)
  6. Windows 98
  7. Microsoft Windows NT 4.0 (Service Pack 6a erforderlich)

Das im Produkt enthaltene VC++ trägt die Versionsnummer 7.1 (VisualStudio .NET 2002 enthält VC++ V 7.0).

Autoren:

Dieter Smode

3.10  Erkennen der ServicePack-Version für Visual Studio 6.0 [URL]

Die installierte ServicePack-Version kann man an der Version der Datei c1xx.dll (in <Installationspfad>\VC98\Bin) erkennen:

SP3: 12.0.8472.0
SP4: 12.0.8867.0
SP5: 12.0.8964.0
SP6: 12.0.9782.0

Alternativ kann man auch in die Registry schauen (geht möglicherweise erst ab SP3):

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\6.0\ServicePacks

Verweise:

How To Tell That a Visual Studio Service Pack Is Installed
INFO: How to Determine If Visual Studio 6.0 Service Pack 3, 4, or 5 Is Installed
INFO: Visual Studio 6.0 Service Packs, What, Where, Why

Autoren:

Carsten Witte, Alexander Sailer, Andre Stille, Martin Richter, Dieter Smode

Inhaltsverzeichnis


4  Graphical User Interface (GUI)

4.1  Wie können mehrzeilige ToolTips erzeugt werden? [URL]

Nun das ist leider so ohne weiteres nicht möglich, wenn es sich um Tooltips handelt, die die MFC selbst darstellt. Wenn es um eigene Tooltips geht so ist es ganz einfach, man muss nur \n in den Text mit einbauen. Desweiteren ist es nötig die Breite des ToolTips einzustellen. Dies geht mit  CToolTipCtrl::SetMaxTipWidth(int iWidth );

Wenn es sich um die Standard Tooltips handelt wird es schwierig. Im CFrameWnd gibt es eine Routine die auf TTN_NEEDTEXT reagiert (genaugenommen auf TTN_NEEDTEXTA und TTN_NEEDTEXTW). Diese lädt den entsprechenden Resource-String zu der ID und führt AfxExtractSubString(strTipText, szFullText, 1, '\n'); durch. Diese Funktion behandelt strTipText als String der durch mehrere '\n' getrennt ist und lädt einfach den zweiten Teilstring.

Wie man aber sieht heißt das, dass die zweite Zeile der dritte Teilstring wäre, da das selbe Trennzeichen verwendet wird... Also bleibt nichts anderes übrig als TTN_NEEDTEXT in dem CFrameWnd zu überschreiben und entsprechend der MFC Source selbst zu implementieren. Nur nimmst man nicht AfxExtractSubString(), sondern strchr(strTipText,'\n')+1 als Funktion um den Teilstring zu ermitteln.

Autoren:

Martin Richter

4.2  Warum klappt meine ComboBox im DropDown-Stil in einem Dialog nicht auf? [URL]

Beim Erstellen einer ComboBox in einem Dialog Template muss auch die Größe mit angegeben werden, die die ComboBox haben soll, wenn Sie denn aufgeklappt wird. Dies kann auf zwei Methoden geschehen.

Methode 1: ComboBox aus der Werkzeugleiste einfach durch einen Mausklick einsetzen. Anschließend auf den "DropDown"-Schalter klicken und nun die gewünschte Größe einstellen.

Methode 2: Combox durch Ziehen eines Rechteckes auf dem Dialog einsetzen. In diesem Fall wird die Größe gleich korrekt bestimmt. Nachträgliche Änderung der Größe erfolgt dann wieder durch anklicken des "DropDown"-Schalters.

Anmerkung: Die Größe einer ComboBox mit dem Stil CBS_DROPDOWN und CBS_DROPDOWNLIST im NICHT aufgeklappten Zustand kann beim Erzeugen nicht verändert werden. Diese Größe bestimmt Windows automatisch. Die Größe die bei CreateWindow/CreateWindowEx angegeben wird ist immer die Größe des Control im aufgeklappten Zustand. Nachdem ein gültiger Windowshandle auf die ComboBox existiert kann mit CComboBox::SetItemHeight die Höhe der Items bzw. des Editfelds der ComboBox verändert werden.

Autoren:

Martin Richter

4.3  Wie kann ich mit den MFC ein Control in einem Dialog sichtbar/unsichtbar machen? [URL]

Dies ist relativ einfach.

Mit

GetDlgItem( IDC_DES_ITEMS)->ShowWindow( SW_HIDE ) ;

macht man es unsichtbar, und mit

GetDlgItem( IDC_DES_ITEMS)->ShowWindow( SW_SHOW ) ;

wieder sichtbar. Nun wird man jedoch auf den Effekt stoßen das ein Tastaturkürzel trotz unsichbaren Controls weiterhin funktioniert. Um das zu unterbinden muß man das Control auch noch Disablen.

GetDlgItem( IDC_DES_ITEMS)->ShowWindow( SW_HIDE ) ;
GetDlgItem( IDC_DES_ITEMS)->EnableWindow( FALSE ) ;

Hat das Control um Moment des Disablen den Focus so wird die Tab-Taste bis zum nächsten anklicken nicht funktionieren. Dazu ist es notwendig zu testen ob das Control den Focus hat und bei Bedarf ein ein anderes zu Focussieren. Hier ein komplettes Beispiel um ein Control zu verstecken, hier als Funktion eine Dialoges.

void CDlgDocument::HideControl(int IDC)
{
    CWnd* pWnd = GetDlgItem(IDC);
    if (GetFocus() == pWnd) {
        if (CWnd* pFWnd = GetNextDlgTabItem(pWnd)) pFWnd->SetFocus();
    }
    pWnd->EnableWindow(FALSE);
    pWnd->ShowWindow(SW_HIDE);
}

Autoren:

Alexander Sailer, Martin Richter , Eberhard Schefold, Albert Weinert, Jens Geyer

4.4  Wie kann ich Popups- bzw. Context-Menüs realisieren? [URL]

Dies ist gar nicht so schwierig, dazu gibt die TrackPopupMenu() Funktion. Ruft man diese auf wird das Menü als Context-Menü dargestellt.

Die Anforderung eines Context-Menü kommt vom Betriebssystem wenn man die rechte Maustaste bzw. die Context-Menü Taste auf der Tastatur drückt. Wichtig ist das man nicht direkt die rechte Maustaste abfragt sondern die Nachricht WM_CONTEXTMENU , sonst bekommt man das drücken der Tastatur nicht mit!

void CXView::OnContextMenu(CWnd* pWnd, CPoint point)
{
 // Falls point -1,-1 dann haben wir eine Tastatur Aktion
 if (point.x==-1 && point.y==-1) {
  /* Wenn das Menü über die Tastatur aufgerufen wird, so sollte
   * man ein dem Context passende Position des Menüs festlegen
   * sonst wird es immer in der linken oberen Ecke dargstellt.
   * GetMyItemRectForContextMenu() wird hier als Beispiel eingesetzt
   * und ist keine Windows Funktion. Die muss selbst geschrieben werden! */

  CRect  rect;
  GetMyItemRectForContextMenu (rect);

  // Mitte verwenden
  point.x = (rect.left+rect.right)/2;
  point.y = (rect.top+rect.bottom)/2;
     ClientToScreen (&point);
 }
 // Ab hier dann die eigentliche Erstellung des Menüs
 // Ein entsprechendes Menü laden, dem Context entsprechend
 CMenu menu, *menuTrackPopup;
 if (!menu.LoadMenu (m_uiContextMenu)) return;

 /* Das erste Menü aus dem Popmenü auswählen um TrackPopupmen
  * aufzurufen. Das Menü kann auch mit CreatePopupMenu() erstellt
  * werden werden, dann müssen die Menüpunkte mit InsertMenu()
  * oder AppenMenu() hinzugefügt werden. */

   menuTrackPopup = menu.GetSubMenu(0);
   menuTrackPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, GetParentFrame ());
   menu.DestroyMenu();
}

Noch ein wichtiger Punkt ist das man nicht das eigene Fenster über sondern eins der übergeordneteten CFrameWnds übergibt, sonst funktioniert die Nachrichtbehandlung nicht Ordnungsgemäß. Hat man kein übergeordnetes FrameWindow bzw. keine entsprechende Nachrichtenbehandlung wie bei den MFC, so kann man mit dem Flag TPM_RETURNCMD auch veranlassen das ::TrackPopupMenu () den entsprechenden Menüpunkt als Rückgabewert liefert. Die Programmausführung hält dann natürlich solange an!

Verweise:

MSDN: CMenu::TrackPopupMenu()
MSDN: ::TrackPopupMenu()

Autoren:

Albert Weinert, Martin Richter

4.5  Warum erscheinen Zeilenumbrüche in mehrzeiligen Edit-Controls nicht? [URL]

Zunächst sollte überprüft werden, ob der Stil ES_MULTILINE wirklich gesetzt ist.

Der Zeilenumbruch selbst muß durch ein CR (\r) und ein LF (\n) vorgenommen werden. Anderenfalls wird nur ein kleiner Block statt des Zeilenumbruchs angezeigt.

Beispiel (m_edMultiline ist eine Membervariable für das Edit-Control):

DWORD dwStyle = m_edMultiline.GetStyle();
ASSERT((dwStyle & ES_MULTILINE) == ES_MULTILINE);
m_edMultiline.SetWindowText(_T("Jedes\r\nWort\r\neine\r\nZeile..."));

    

Autoren:

Dieter Smode, Carsten Witte

4.6  Wie kann ich ein beliebiges Steuerelement in der Toolbar darstellen? [URL]

Vorausgesetzt das m_wndToolBar ein CToolBar Objekt ist, IDC_COMBO_PLACEHOLDER ist ein "Dummy"-Button in der Toolbar, m_ComboBox mit der ID IDC_MY_COMBO ist ein ComboBox Objekt, erstellen Sie eine ComboBox in der Toolbar folgendermaßen:

//Symbolleiste wurde erzeugt......

 int   iPos  = 0;
 int   cx    = 100; //Breite der ComboBox
 int   cy    = 200; //Höhe der aufgeklappten ComboBox
 CRect rect  = NULL;

 while(m_wndToolBar.GetItemID(iPos) != IDC_COMBO_PLACEHOLDER)
     iPos++;

 m_wndToolBar.SetButtonInfo(iPos, IDC_MY_COMBO, TBBS_SEPARATOR, cx);

 m_wndToolBar.GetItemRect(iPos, &rect);
 rect.top    = 0;
 rect.bottom = rect.top + cy;

 if (!m_ComboBox.Create(
   CBS_DROPDOWN|CBS_AUTOHSCROLL|WS_VISIBLE|WS_TABSTOP,
   rect, &m_wndToolBar, IDC_MY_COMBO))
 {
     TRACE0("Konnte ComboBox in der Toolbar nicht erstellen\n");
     return FALSE;
 }

Dies funktioniert natürlich auch mit anderen Steuerelementen, jedoch werden dort ein paar kleine Änderungen bezüglich Höhe (cy), Breite (cx) und dem Create-Aufruf notwendig sein.

Autoren:

Thomas Klocker

4.7  Wie kann ich die Hintergrundfarbe eines Steuerelements ändern? [URL]

Hierzu kann die Windows-Nachricht WM_CTLCOLOR verwendet werden. Diese Nachricht wird normalerweise an das Parentwindow des Controls versendet. Da dies manchmal unhandlich ist, bietet MFC ab V 4.0 Message Reflection an. In diesem Fall kann die oben genannte Nachricht auch vom Steuerelement selbst bearbeitet werden. Mehr hierzu findet sich in TN062 im MSDN.

Verweise:

TN062: Message Reflection for Windows Controls

Autoren:

Dieter Smode

Inhaltsverzeichnis


5  Datenbanken

5.1  Wie komme ich an die Microsoft Data Engine (MSDE)? [URL]

Man kann Sie im Internet bestellen, oder direkt runterladen. Die Bestellung ist jedoch anzuraten da auf der CD mehr Administrationstools enthalten sind.

Verweise:

MSDE for Visual Studio 6.0
MSDE 1.0 und SQL Server 7.0 Service Pack 4
MSDE 1.0 und SQL Server 7.0 Security Update for Service Pack 4
MSDE 2000 for Developers Using Visual Studio .NET Service Pack 3a (volle Version mit Service Pack)
SQL Server 2000 Service Pack 3a (auch für MSDE)

Autoren:

Albert Weinert

Inhaltsverzeichnis


6  Datentypen

6.1  Wie kann ich separierte Strings mit einer einfachen Funktion aufspalten? [URL]

Es kommt immer wieder vor das Teile eines Strings zurückgegeben werden sollen, der durch bestimmte Trennzeichen aufgebaut wurde. Verwendet wird dies z.B. im CFileDialog bei dem die Filter-Strings durch '|' getrennt werden. Ebenfalls werden die Texte Tooltips von den Menü-Texten, die in der Statuszeile angezeigt werden durch ein '\n' getrennt. Die MFC verwendet dazu die undokumentierte Funktion BOOL AFXAPI AfxExtractSubString(CString& rString, LPCTSTR lpszFullString, int iSubString, TCHAR chSep = '\n'). Leider hat Sie den kleinen Nachteil, das nur CString's als Argument angenommen werden. Zudem ist Sie ja wie gesagt undokumentiert, allerdings public in der AFXWIN.H deklariert.

Ich habe mir diese Funktion etwas umgeschrieben und habe das Eingangsargument auf LPCTSTR geändert. Dadurch kann jeder SubString zurückgegeben werden. Interessant sind auch Schachtelungen der Strings, so gibt ExtractSubString(ExtractSubString("1|2|3\n4|5|6\n7|8|9",1,'\n'),1,'|') den CString Wert mit dem Inhalt "5" zurück.

CString ExtractSubString(LPCTSTR lpszFullString, int iSubString, TCHAR chSep)
{
 CString rString;

 // Wenn nichts da leeren String zurück
 if (lpszFullString == NULL)
  return rString;

 while (iSubString--)
 {
  // Siche nächsten delimiter
  lpszFullString = _tcschr(lpszFullString, chSep);
  if (lpszFullString == NULL)
   // Nichts mehr da also leeres Ergebnis
   return rString;
  lpszFullString++;
 }

 // Ende errechnen
 LPCTSTR lpchEnd = _tcschr(lpszFullString, chSep);
 size_t nLen = (lpchEnd == NULL) ? _tcslen(lpszFullString) : (size_t)(lpchEnd - lpszFullString);
 ASSERT(nLen > = 0);
 // Daten kopieren
 memcpy(rString.GetBufferSetLength(nLen), lpszFullString, nLen*sizeof(TCHAR));
 return rString;
}

Autoren:

Martin Richter

6.2  Kann ich die CString-Klasse auch ohne die MFC verwenden? [URL]

Vor Visual Studio .NET leider nicht. Als Alternative kann z. B. die Klasse CStdString benutzt werden.

Ab Visual Studio .NET liegt "CString" als Template-Klasse (s. CStringT) in der ATL vor. Die MFC-Klasse CString ist dann nur noch ein typedef in afxstr.h.

Verweise:

CStdString-Klasse
CStringT-Klasse

Autoren:

Carsten Witte

6.3  \n aus einer Zeichenkette in einen Zeilenumbruch umwandeln [URL]

Q: Ich habe einen String, wie zum Beispiel "Eine\nneue\nZeile" und moechte, dass auch wirklich Zeilenumbrüche ausgegeben werden...

A: CString::Replace ("\\n", "\n");
Das gilt dementsprechend auch für Tabulatoren "\t" und alle anderen Sonderzeichen.

Autoren:

Carsten Witte

6.4  Wie konvertiere ich einen CString in einen char* ? [URL]

Kommt darauf an. Wird der char* nur für einen lesenden Zugriff benötigt (z.B. bei der Ausgabe mit printf() oder bei der Übergabe an eine Funktion, die einen LPCTSTR erwartet, wie SetWindowText(), dann muss man nichts weiter tun als eine Typecast auf den entsprechenden Typ  zu vollziehen.

    CString csText;
    csText = _T("Albert");
    printf(_T("Mein Name ist %s"), static_cast<LPCTSTR>(csText));

Braucht man den char* aber, um schreibend auf den CString zuzugreifen, z.B. um eine der Funktionen aus <string.h > , wie strcpy() zu nutzen, dann wird die Sache ein klein wenig komplizierter. In einem solchen Fall muss man den CString explizit auffordern, einem einen char* zu geben. Dabei muss auch angegeben werden, wie groß der Speicherbereich sein soll, auf den der char* zeigt. Beispiel: Benötigt wird ein char*, mit Platz für 100 Zeichen, auf den schreibend zugegriffen werden soll:

    CString csText;
    LPTSTR  szText= csText.GetBuffer (100);
    _tcscpy (szText, _T("Hallo Welt!"));
    csText.ReleaseBuffer();

Der CString csText enthält jetzt "Hallo Welt". Wird der Gültigkeitsbereich von csText beendet, dann wird auch der Speicher wieder freigeben. Jedoch verwaltet der CString seine Länge nach einem Aufruf von GetBuffer() nicht mehr selbst. Ein abschließender Aufruf von CString::ReleaseBuffer() gibt die Kontrolle wieder an CString zurück, ermittelt die Länge des im Puffer befindlichen Strings mit strlen/wcslen und setzt diese Länge für die CString-Instanz. Außerdem wird der enthaltene String mit einem \0-Zeichen terminiert.

Verweise:

MSDN: CString::ReleaseBuffer()
MSDN: CString::GetBuffer()

Autoren:

Manni Heumann, Carsten Witte , Albert Weinert

6.5  Wie konvertiere ich eine Zahl in einen String und umgekehrt? [URL]

Die folgenden Beispiele konvertieren eine Integer in einen String und dann wieder zurück in eine Integer. Alle Beispiele sind so geschrieben, dass sie mit allen Zeichensatzeinstellungen (Unicode, MBCS) funktionieren.

Die Variante mit Hilfe des Typecasts "(TCHAR)" ist keine Konvertierung. Hier wird nur dafür gesorgt, daß die in iValue enthaltene Zahl anders interpretiert wird. Wenn man sich diese Variante im Debugger anschaut, wird man feststellen, dass sowohl iValue als auch cSign anschließend die Zahl 42 enthalten.

int iValue= 42;

// Warnung: keine Umwandlung, sondern eine andere Interpretation
// des Wertes, man erhält das Zeichen '*'
TCHAR cSign= (TCHAR) iValue;
ASSERT(cSign == _T('*'));

// Konvertierung int -> String: als Ergebnis steht im String: "42"
CString csBuffy;
csBuffy.Format(_T("%d"), iValue);
ASSERT(csBuffy == _T("42"));
// Und jetzt nochmal mit den von der Runtime Library bereitgestellten Funktion
TCHAR acBuffer[20];
_stprintf(acBuffer, _T("%d"), iValue);
ASSERT(_tcscmp(acBuffer, _T("42")) == 0);

// Und nun wieder zurück in eine Zahl:
iValue = 0;
iValue = _ttoi((LPCTSTR) csBuffy);
ASSERT(iValue == 42);
// oder mit _stscanf
iValue = 0;
_stscanf(acBuffer, _T("%d"), &iValue);	
ASSERT(iValue == 42);

Die Konvertierung anderer Zahlen erfolgt analog mit den entsprechenden Formatcodes bzw. Funktionen (s. unten).

Verweise:

MSDN: CString::Format()
MSDN: _stprintf (sprintf)
MSDN: _stscanf (sscanf)
MSDN: _tstof, _ttoi, _ttoi64, _ttol (atof, atoi, _atoi64, atol)
MSDN: _tcstod (strtod)
MSDN: _tcstol (strtol)
MSDN: _tcstoul (strtoul)

Autoren:

Carsten Witte, Dieter Smode

6.6  Umgang mit float und double [URL]

Bei Verwendung der Datentypen float und double kommt es immer wieder zu Irritationen, weil z. B. Vergleiche mit Konstanten nicht funktionieren oder Rechenergebnisse "ungenau" sind. Da mit Integer-Datentypen diese Probleme nicht auftreten (mal von einem Overflow abgesehen, wenn der maximal darzustellende Wertebereich durch eine Rechenoperation überschritten wird), stellt sich die Frage, warum das so ist und wie solche Probleme gegebenenfalls zu vermeiden sind.

Generell werden die in C/C++ realisierten Fließkomma-Datentypen durch Darstellungen im Speicher repräsentiert, die eine endliche Länge haben (bei float 4 Bytes, bei double 8 Bytes). Es ist damit unmittelbar einsehbar, daß Zahlen wie 1/3 in diesem Speicherformat gar nicht genau abgebildet werden können. Allein deshalb sind Fehler beim Vergleich oder beim Rechnen mit solchen Zahlen nicht zu vermeiden.

Ein weiteres Problem besteht darin, daß die interne Darstellung von Zahlen nicht so erfolgt, wie man sich das vielleicht vorstellt. Zahlen, die sich im "normalen" Leben problemlos darstellen lassen, sind in dem von den C/C++-Fließkommaformat nicht exakt abbildbar. Nähere Informationen dazu finden sich im Artikel HOWTO: Fließkommadarstellung und Problembehandlung.

Schließlich kommt es durch Rechenoperationen mit Datentypen, die nur mit endlicher Genauigkeit dargestellt werden können, zu weiteren Fehlern. Dies kann schnell zu relativ großen Fehlern führen. Aus diesem Grund sind float und double für kaufmännische Berechnungen nur sehr bedingt geeignet (wenn man sich der Folgen genau bewußt ist). Man kann das sehr schnell sehen, wenn man z. B. mal die Mehrwertsteuerberechnung in einer Rechnung betrachtet. Ein Verfahren könnte für jeden Einzelposten den jeweiligen MwSt-Betrag ausrechnen und diese zum Schluß addieren. Ein anderes Verfahren addiert zunächst mal alle Beträge mit dem gleichen MwSt-Satz auf und berechnet die MwSt erst zum Schluß. Beide Verfahren führen schon bei einigen Posten zu Abweichungen.

Bei technisch-wissenschaftlichen Berechnungsverfahren werden mitunter Fehlerabschätzungen durchgeführt, um Aussagen über die Genauigkeit eines Rechenergebnisses machen zu können.

Die numerische Mathematik spricht im Falle von Fließkommazahlen von sicheren und unsicheren Stellen einer Zahl. Es gibt auch Regeln für die Ermittlung der Höchstzahl sicherer Stellen bei Rechenoperationen:

  1. Bei Addition und Subtraktion ergeben sich maximal so viele sichere Stellen, wie die Zahl mit der kleineren Anzahl an sicheren Stellen besaß.
  2. Bei Multiplikation und Division besitzt das Ergebnis mindestens zwei sichere Stellen weniger, als die Zahl mit der kleinsten Anzahl sicherer Stellen und höchstens gleich viele sichere Stellen.

Verweise:

HOWTO: Fließkommadarstellung und Problembehandlung

Autoren:

Dieter Smode

Inhaltsverzeichnis


7  Weitere Techniken

7.1  Wie kann ich ein Word, Excel, HTML oder was auch immer für ein Dokument starten? [URL]

Um z.B. eine Word, Excel oder HTML-Datei vom eigenen Programm zu starten, so das direkt auch die entsprechende Anwendung geöffnet wird, benutzt man die ShellExecute() funktion.

Beispiel:

HINSTANCE hInstance= ShellExecute(GetSafeHwnd(),
                     "open",
                     "DateiName.html",
                     NULL,
                     NULL,
                     SW_SHOWNORMAL);

Autoren:

Carsten Witte

7.2  Wie kann ich ein Verzeichnis auslesen? [URL]

Dazu gibt es mehrere Möglichkeiten.

Möglichkeit 1:

WIN32_FIND_DATA w32fd;
HANDLE hFind= FindFirstFile("C:\\*.*", &w32fd);
if (hFind == INVALID_HANDLE_VALUE) return;
do {
    cout << w32fd.cFileName << endl;
}
while (FindNextFile(hFind, &w32fd));
FindClose(hFind);

Möglichkeit 2: Ein Ansatz mit den MFC

Die Klasse CFileFind ist genau dazu da:

CFileFind finder;
BOOL bWorking = finder.FindFile("*.*");
while (bWorking) {
    bWorking = finder.FindNextFile();
    if (!finder.IsDirectory())
        cout << (LPCTSTR) finder.GetFileName() << endl;
}

Wie man sieht gibt es auch Methoden wie IsDirectory (), die die gefundene Datei auf bestimmte Attribute prüfen.

Verweise:

MSDN: CFileFind

Autoren:

Carsten Witte, Manni Heumann

7.3  Wie erhalte ich den kompletten Pfad, aus dem das aktuelle Programm gestartet wurde? [URL]

Über die Funktion GetModuleFileName() kann der Name des aktuellen Modules/DLL/EXE Datei ermittelt werden. Wird als hModule Wert der Parameter NULL übergeben, so wird der Pfad der ausführbaren Datei des aktuellen Prozesses returniert.

CString GetApplicationDirectory()
{
   TCHAR szPathName[_MAX_PATH];
   ::GetModuleFileName(NULL, szPathName, _MAX_PATH);
   LPTSTR pszFileName = _tcsrchr(szPathName, '\\') + 1;
   *pszFileName = '\0'; return szPathName;
}

Autoren:

Martin Richter

7.4  Wie führe ich einen cls(), _clearscreen() bzw. clrscr() in einer Windows-Konsolen Anwendung durch? [URL]

Es gibt keine direkte Funktion um einen Bildschirm in einer Console-Anwendung zu löschen. Dies ist nur über diverse API Funktionen möglich.
Nachstehend ein Auszug aus dem MSDN Artikel: Q99261 "HOWTO: Performing Clear Screen (CLS) in a Console Application".

Weitergehende Informationen zu diesem Thema inkl. einem kompletten Programm aus dem auch dieser Code entnommen ist findet sich im MSDN Beispiel: "Console: Demonstration of the Console Functions"

/* Standard error macro for reporting API errors */
#define PERR(bSuccess, api){if(!(bSuccess)) printf("%s:Error %d from %s \
    on line %d\n", __FILE__, GetLastError(), api, __LINE__);}

void cls( HANDLE hConsole )
{
    COORD coordScreen = { 0, 0 };    /* here's where we'll home the
                                        cursor */
    BOOL bSuccess;
    DWORD cCharsWritten;
    CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
    DWORD dwConSize;                 /* number of character cells in
                                        the current buffer */

    /* get the number of character cells in the current buffer */

    bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
    PERR( bSuccess, "GetConsoleScreenBufferInfo" );
    dwConSize = csbi.dwSize.X * csbi.dwSize.Y;

    /* fill the entire screen with blanks */

    bSuccess = FillConsoleOutputCharacter( hConsole, (TCHAR) ' ',
       dwConSize, coordScreen, &cCharsWritten );
    PERR( bSuccess, "FillConsoleOutputCharacter" );

    /* get the current text attribute */

    bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
    PERR( bSuccess, "ConsoleScreenBufferInfo" );

    /* now set the buffer's attributes accordingly */

    bSuccess = FillConsoleOutputAttribute( hConsole, csbi.wAttributes,
       dwConSize, coordScreen, &cCharsWritten );
    PERR( bSuccess, "FillConsoleOutputAttribute" );

    /* put the cursor at (0, 0) */

    bSuccess = SetConsoleCursorPosition( hConsole, coordScreen );
    PERR( bSuccess, "SetConsoleCursorPosition" );
    return;
}

Verweise:

HOWTO: Performing Clear Screen (CLS) in a Console Application (MSDN Q99261)
Console: Demonstration of the Console Functions

Autoren:

Martin Richter

7.5  Wie kann ich eine EMail aus einem Programm versenden? [URL]

Es gibt mehrere Möglichkeiten eine EMail aus dem eigenen Programm zu versenden. Die beiden gebräuchlisten sind: SMTP (Simple Mail Transfer Protokoll) und MAPI (Mail Application Programming Interface).

Während für MAPI ein s.g. MAPI-Client (ein Programm welches die e-Mail Funktion über MAPI zu Verfügung stellt) auf dem entsprechenden Rechner installiert sein muss (z.B. Outlook Express) ist dies bei SMTP nicht nötig. Dafür ist man bei SMTP auf einen SMTP-Server im Internet angewiesen, dieser sollte von Benutzer eingestellt werden können.

Bei SMTP muss man sich desweiteren mit Protokoll und dem Format an sich auseinandersetzten, das Format ist in RFC 822 definiert. Das Protokolle wir in RFC 821 beschrieben. Dafür ist SMTP Plattformunabhängig.

Für MAPI gibt es noch einen Scriptfähigen Aufsatz mit dem Namen CDO (Collaboration Data Objects), dies ist ein COM-Basierender Ansatz um EMails aus Programmen zu verschicken.

Beispiel Programme dazu gibt es im Internet Bereich auf der CodeGuru Webseite, dort den Unterpunkt EMail.

Verweise:

CodeGuru: Internet Programmierung
RFC 821
RFC 822
MSDN: MAPI Programmer's Reference
MSDN: CDO Programmer's Reference

Autoren:

Albert Weinert

7.6  Wie kann ich verhindern, dass mehrere Instanzen meines Programms gestartet werden? [URL]

Zum Beispiel mit einer (einem?) Mutex in InitInstance():

HANDLE hMutex =  CreateMutex   (NULL, TRUE, "unverwechselbarer String");
bool found=false;
if(GetLastError() == ERROR_ALREADY_EXISTS)
 found = true;
if(hMutex)
 ReleaseMutex (hMutex);
if (found)
{
     AfxMessageBox("Bitte starten Sie immer nur eine Instanz.");
    return FALSE;
}

Verweise:

Joseph Newcomer: Avoiding Multiple Instances of an Application

Autoren:

Manni Heumann

7.7  Wie bekomme ich die Applikation mit der eine Datei verknüpft ist? [URL]

Wie bekomme ich die Applikation mit der eine Datei verknüpft ist?

Das Problem bei der API Funktion FindExecutable ist, daß diese eine bestehende Datei benötigt. Ich habe diese Funktion so erweitert, daß in dem Temporären Verzeichnis des Systems eine Dummy-Datei erzeugt wird, welche nach der Überprüfung wieder gelöscht wird.

Funktionsparameter:


HINSTANCE FindExecutableEx(CString strFileExt, CString &
strExe)
{
  CString strTmpFile(""), strNewFileName("");
  char szTempPath[_MAX_PATH];
  char drive[_MAX_DRIVE];
  char dir[_MAX_DIR];
  char fname[_MAX_FNAME];
  char ext[_MAX_EXT];
  DWORD dwLen(0);
  CFile oFile;
  HINSTANCE hInst(0);

  //Temporären Pfad holen<
  dwLen = GetTempPath(_MAX_PATH, szTempPath);
  ASSERT(dwLen);
  ASSERT(dwLen  < = _MAX_PATH);

  //Temporären File erzeugen und Umbenennen der Extension
  //Mit überprüfung, ob File bereits existiert

  do{
    //Temporäre Datei erzeugen
    VERIFY(GetTempFileName(szTempPath, "tmp", 0, strTmpFile.GetBuffer(_MAX_PATH)));
    strTmpFile.ReleaseBuffer();

    //Dateiname für Umbenennung erzeugen
    _tsplitpath( strTmpFile, drive, dir, fname, ext );
    strNewFileName.Format("%s\\%s\\%s.%s", drive, dir, fname, strFileExt);

    //Prüfen ob neuer Dateiname existiert
    if(OpenFile(strNewFileName, &of, OF_EXIST) == HFILE_ERROR){
      bFileExist = FALSE;             //Datei existiert nicht
    }
    else{
      bFileExist = TRUE;              //Datei existiert bereits
      VERIFY(DeleteFile(strTmpFile)); //Datei löschen
    }
  } while (bFileExist);

  //Temporäre Datei umbenennen
  _tsplitpath( strTmpFile, drive, dir, fname, ext );
  strNewFileName.Format("%s\\%s\\%s.%s", drive, dir, fname, strFileExt);
  oFile.Rename(strTmpFile, strNewFileName);

  //Nach Exe suchen
  hInst = ::FindExecutable((LPCTSTR)strNewFileName, "", strExe.GetBuffer(_MAX_PATH));
  strExe.ReleaseBuffer();

  //Datei löschen
  VERIFY(DeleteFile(strNewFileName));

  return hInst;
}

Ab Windows 2000 und Windows 98, bzw. ab dem Internet Explorer 5.0 gibt es auch die Möglichkeit AssocQueryString () zu verwenden. Genaueres zur Anwendung findet sich im MSDN.

Verweise:

MSDN: FindExecutable()
MSDN: GetTempFileName()
MSDN: AssocQueryString()

Autoren:

Alexander Sailer, Carsten Witte

7.8  Wie kann ich ein Programm in mehreren Sprachen erstellen? [URL]

Es gibt sicher mehrere Techniken, die es erlauben, ein mehrsprachiges Programm zu entwickeln. Insbesondere kommt es darauf an, ob die Sprachumschaltung zur Laufzeit erfolgen muß, was eher selten wirklich der Fall ist und oft auch relativ aufwendige Eingriffe in die Software erfordert (es muß beispielsweise alles, was bereits sichtbar ist, entsprechend der gewählten Sprache aktualisiert werden), oder ob die Spracheinstellung für die gesamte Laufzeit bzw. nur bei der Installation vorgenommen wird.

Im wesentlichen kann man heute folgende Techniken beobachten:

  1. Verwendung mehrsprachiger String-Ressourcen (oder einer externen Datei, welche die sprachspezifischen Texte enthält) und Austausch der Texte z. B. beim Laden von (sprachneutralen) Dialogen.

    Dieses relativ einfache Verfahren hat eigentlich nur Nachteile: es ist nicht einsetzbar, wenn z. B. auch Bitmaps usw. an die jeweilige Sprache anzupassen sind. Weiterer Nachteil: für alle Texte ist z. B. in Dialogen soviel Platz zu reservieren, daß auch der längste Text noch Platz findet (wer schon mal eine englische Version auf Französisch oder Finnisch umgestellt hat, wird das nachempfinden können). Das führt dazu, daß kompakte Dialoge nicht möglich sind. Solche Dialoge sehen in der Regel - gelinde gesagt - etwas merkwürdig aus.

  2. Man kann die von Microsoft vorgesehene Mehrsprachigkeit der Ressourcen ausnutzen, hat also für die meisten Ressourcen mehrere sprachspezifische Versionen.

    Das hat den Vorteil, daß man alle Ressourcentypen anpassen und beispielsweise Dialoge auf die jeweilige Sprache hin optimieren kann. Nachteilig ist, daß viele Ressourcen und viele Sprachen zu einer Größenexplosion der Ressourcendateien und damit auch des Programms führt. Das Ganze wird dann schnell unübersichtlich. Außerdem muß bei jeder kleinsten Änderung das Programm neu kompiliert und ausgeliefert werden.

    Der Artikel INFO: Resource Language Loading Order beschreibt, in welcher Reihenfolge die verschiedenen Windows-Versionen die Ressourcen laden.

  3. Das flexibelste Verfahren besteht in der Bereitstellung von Ressourcen-DLLs, d. h. für jede Sprache gibt es eine DLL, welche die Ressourcen für eine einzige Sprache enthält.

    Es ist dann relativ flexibel möglich, Sprachversionen zu ergänzen oder zu überarbeiten, da nur die entsprechende Sprachen-DLL ausgetauscht bzw. ausgeliefert werden muß. Dieses Vorgehen unterstützt in der Regel auch die Verwendung spezieller Übersetzungssoftware, welche die Ressourcen direkt aus der DLL lädt und die mit mehrsprachigen Ressourcen häufig nicht zurechtkommt. Ein kleiner, aber zu vernachlässigender Nachteil besteht darin, daß die Software die richtige DLL für das Laden der Ressourcen verwenden muß.

Martin Richter hat zu den Ressourcen-DLLs einen ausführlichen Artikel mit Beispielen und Tipps geschrieben, so daß dieses Lokalisierungsverfahren von unerfahreneren Programmierern einfach verwendet werden kann. Die Verweise enthalten noch einige weitere Links auf Informationen zu dieser Thematik.

Verweise:

HOWTO: Multilinguale Programme mit VC für Dummies
Beispielprojekt mit Ressourcen-DLLs
INFO: Resource Language Loading Order
HOWTO: Create Localized Resource DLLs for MFC Application
HOWTO: #include the Localized MFC Resources in an EXE or DLL
HOWTO: Localize Application Resources with Foundation Classes
Microsoft Global Development and Computing Portal

Autoren:

Kurt Antreich, Dieter Smode

7.9  Elementfunktionen als Win32-Callback verwenden [URL]

Symptom: Ich will eine Elementfunktion einer meiner Klassen als Callback-Funktion für Win32 verwenden. Obwohl ich genau die angegebene Signatur verwendet habe, bekomme ich vom Compiler Fehlermeldungen.

Beispiel:

class CCallbackTestDlg : public CDialog
{
    // Construction
    public:
    CCallbackTestDlg(CWnd* pParent = NULL); // standard constructor
    // ...

    // Implementation
    protected:
    BOOL CALLBACK MeineTolleChildProc(
        HWND hwnd, // handle to child window
        LPARAM lParam // application-defined value
    );
    // ...
};

BOOL CALLBACK CCallbackTestDlg::MeineTolleChildProc(
        HWND hwnd, // handle to child window
        LPARAM lParam // application-defined value
    )
{
    // ...
    return TRUE;
}

BOOL CCallbackTestDlg::OnInitDialog()
{
    // ...

   ::EnumChildWindows(
            GetSafeHwnd(), // handle to parent window
            MeineTolleChildProc, // hier die Angabe der Callback-Funktion
            0 // application-defined value
       );
}

Bei dieser Angabe der Callback-Funktion gibt mir der Compiler folgenden Fehler (Visual Studio 6.0)

CallbackTestDlg.cpp(95) : error C2664: 'EnumChildWindows':
    cannot convert parameter 2 from 'int (struct HWND__ *,long)' to 'int (__stdcall *)(struct HWND__ *,long)'
    None of the functions with this name in scope match the target type

obwohl die Funktion scheinbar genau der für EnumChildWindows benötigten Signatur entspricht.

Erklärung: Elementfunktion besitzen immer einen „unsichtbaren” impliziten this-Zeiger; daher paßt die Signatur nicht. Wenn man's sich recht überlegt, kann es ja auch nicht funktionieren, denn wenn Windows eine Callback-Funktion anspringt, woher soll es wissen, für welche Instanz der Klasse?

Lösung: Man kann eine statische Elementfunktion verwenden:

    static BOOL CALLBACK MeineTolleChildProc(
        HWND hwnd, // handle to child window
        LPARAM lParam // application-defined value
    );

Wenn man in der Callback-Funktion nicht auf andere nicht-statische Elemente der Klasse zurückgreifen muß, ist dies bereits die Lösung. Meist reicht das aber nicht aus. Hilfe bietet der Parameter, den Win32 für die meisten Callback-Funktionen anbietet, oft ein LPARAM oder LPVOID, der weitergegeben wird und den die Anwendung für eigene Zwecke benutzen kann. In diesem Fall übergeben wir einen this-Zeiger auf die eigene Instanz. Die bei dieser Lösung notwendigen unschönen Typumwandlungen reduzieren wir mit folgender relativ eleganten Lösung auf ein Minimum; dabei wird eine rohe statische Hilfsfunktion als technischer Callback verwendet, welche die Typumwandlung leistet und die eigentliche nicht-statische Arbeitsfunktion aufruft.

BOOL CALLBACK MeineTolleChildProc(
    HWND hwnd, // handle to child window
    // der Applikations-spezifische Wert ist bereits für den this-Zeiger verbraten
    // und bringt somit nichts mehr; wird daher weggelassen
);  // Beachte: nicht-statisch!

static BOOL CALLBACK MeineTolleRoheChildProc(
    HWND hwnd, // handle to child window
    LPARAM lParam // application-defined value
)
{
    return reinterpret_cast< CCallbackTestDlg* >( lParam)->MeineTolleChildProc( hwnd );
}

// ...

::EnumChildWindows( GetSafeHwnd(), MeineTolleRoheChildProc, reinterpret_cast< LPARAM >( this ) );

In der eigentlichen Arbeitsfunktion MeineTolleChildProc kann somit ganz normal auf alle Elemente der Klasse zugegriffen werden.

Autoren:

Eberhard Schefold

7.10  Wie kann ich feststellen ob ein COM Port in meinem Rechner verfügbar ist? [URL]

/***************************************************************************
   METHOD     : IsPortAvailable
   AUTHOR     : Sailer Alexander
   DESCRIPTION: Prüft ob ein serieller Port vorhanden ist und wenn ja, ob dieser dann auch verfügbar ist.

--------------------------------------------------------------------------
   GLOBALS  : None
   RET VALUE: int   -1 - Port nicht vorhanden
                     0 - Port vorhanden aber nicht verfügbar
                     1 - Port vorhanden und verfügbar
   PARMS    :
     I - int nPortNumber

--------------------------------------------------------------------------
   HISTORY  :
      14.04.2000 - 06:00

***************************************************************************/
int CCOMPortsDlg::IsPortAvailable(int nPortNumber)
{
  CString strPort("");
  HANDLE  hPort = NULL;
  int nSize(0), nPort(0);
  DWORD dwErr(0);

  // Abprüfen des Ports auf Verfügbarkeit
  strPort.Format("\\\\.\\COM%d",, nPortNumber);
  hPort = CreateFile (strPort,        // Pointer to the name of the port
                      GENERIC_READ | GENERIC_WRITE,
                                      // Access (read-write) mode
                      0,              // Share mode
                      NULL,           // Pointer to the security attribute
                      OPEN_EXISTING,  // How to open the serial port
                      0,              // Port attributes
                      NULL);          // Handle to port with attribute to copy

  if (hPort == INVALID_HANDLE_VALUE)  // Invalid Porthandle, port NOT available
  {
    dwErr = GetLastError();
    if (dwErr == ERROR_ACCESS_DENIED || dwErr == ERROR_GEN_FAILURE)
      return 0;   // Port exists but not available
    else
      return -1;  //Port not exists
  }
  else // Valid PortHandle
  {
    CloseHandle(hPort); // Port wieder freimachen
    return true;  // Port exists
  }
}

Autoren:

Alexander Sailer, Thomas Aschauer

7.11  Wie kann man ein Programm "Remote" Debuggen? [URL]

Remote Debuggen ist die Möglichkeit das eigene Programm von einem anderen Rechner aus debuggen kann. Vorteil ist z.B. das die Systemumgebung nicht durch durch Komponenten, als Beispiel die Entwicklungsumgebung, verfälscht wird.

Martin Richter hat dazu einen ausführlichen Newsbeitrag geschrieben der Online im Netz steht. Folge einfach dem Verweis.

Verweise:

HOWTO: RemoteDebugging for Dummies

7.12  Wie finde ich heraus welches Betriebssystem gerade läuft? [URL]

Dazu gibt es die Funktion GetVersionEx(), mit dieser ist es möglich sich die Struktur OSVERSIONINFO zurückgeben zu lassen. Mit der Auswertung dieser kann man jede Windows Version feststellen. In den MSDN befindet sich auch ein ausführliches Beispiel dazu.

Verweise:

MSDN: OSVERSIONINFO
MSDN: GetVersionEx()
MSDN: Getting the System Version (Quellcode Beispiel)

Autoren:

Albert Weinert

7.13  Wie kann ich eine Datei zeilenweise einlesen? [URL]

Oft passiert es dass man eine Datei zeilenweise einlesen oder auch beschreiben will. Dies ist natürlich auch mit der CFile-Klasse möglich, jedoch ist dies Vergleichweise aufwendig. Für solche Standardaufgaben stellt die MFC eine einfachere Klasse zu Verfügung.

Die CStdioFile-Klasse bietet dazu zwei Methoden an ReadString() und WriteString(). Damit ist es möglich Dateien zeilenweise einzulesen.

Bis auf ein paar Ausnahmen steht mit CStdioFile alle Methoden der CFile-Klasse zu Verfügung.

ReadString hat allerdings einen Bug. Dazu müssen folgende Bedingungen alle erfüllt sein:

  1. die letzte Zeile enthält kein '\n' Zeichen
  2. die Länge der letzten Zeile ist ein Vielfaches von 128

In diesem Fall gibt ReadString fälschlicherweise FALSE zurück. Dieser Bug kann allerdings leicht umgangen werden, wenn zusätzlich geprüft wird, ob die gelesene Zeile leer ist oder nicht, also z. B.:

CString sZeile;
CStdioFile fDatei;
...
while( fDatei.ReadString(sZeile) || (! sZeile.IsEmpty()))
{ ... }

Verweise:

MSDN: CStdioFile-Klasse

Autoren:

Albert Weinert, Jens Geyer

7.14  Wie kann ich Outlook, Excel, Word usw. von meinem Programm aus steuern? [URL]

Die beste Methode dies mit "Automation", früher auch als OLE-Automation bekannt. Diese basiert auf COM und sehr viele der heutigen Programme, auch Office, können so gesteuert werden. Einen ausführlichen Artikel gibt es dazu in den MSDN.

Im Normalfall können alle Objekte die auch mit Visual Basic for Applikation (VBA) innerhalb der Anwendungen benutzt werden, auch von extern angesteuert werden. Somit ist eine vollständige Kontrolle der Software möglich.

In der Knowledge-Base von Microsoft gibt es eine Menge HOWTO-Artikel die auch auf spezielle Anforderungen eingehen. Einfach mal danach suchen.

Verweise:

MSDN: Automating Microsoft Office 97 and Microsoft Office 2000

7.15  Wie kann ich eine eigene Messageloop implementieren? [URL]

Ab und zu ist es notwendig eine eigene Nachrichtenschleife (Messageloop) zu implementieren. Mögliche Gründe sind:

In einer reinen Win32-Umgebung sieht die Lösung folgendermaßen aus:

MSG msg;

while( ::PeekMessage( &msg, NULL, NULL, NULL, PM_NOREMOVE ) )
{ 
  if (::GetMessage( &msg, NULL, 0, 0 ) == -1)
  {
    // handle the error and possibly exit
  }
  else
  {
    ::TranslateMessage(&msg); 
    ::DispatchMessage(&msg); 
  }
}

Im Prinzip könnte man diese Version auch für MFC-Programme verwenden, allerdings verliert man dann einige Spezialitäten des Messageroutings (z. B. die Reaktion auf Messages mit PreTranslateMessage und die Idle-Verarbeitung). Deshalb verwendet man in einer MFC-Anwendung

MSG msg;

while( ::PeekMessage( &msg, NULL, NULL, NULL, PM_NOREMOVE ) )
  ::AfxGetThread()->PumpMessage();

PumpMessage enthält neben der Win32-Lösung noch die für MFC-Applikationen notwendigen Spezialitäten (s. CWinThread::PumpMessage() in thrdcore.cpp).

Beide Varianten bearbeiten alle zum Zeitpunkt des Aufrufs vorliegenden Messages. Danach wird die Loop verlassen. Ist das nicht erwünscht, muß das Ganze entsprechend den Erfordernissen umgebaut werden. Allerdings sollte dann darauf geachtet werden, daß diese Nachrichtenschleife bei Auftreten von WM_QUIT verlassen werden muß (PumpMessage gibt dann FALSE zurück).

Verweise:

PumpMessage
Idle Loop Processing
GetMessage
PeekMessage

Autoren:

Dieter Smode

7.16  Wie kann ich andere Bitmap-Formate als .bmp anzeigen?  [URL]

Wenn Bitmapformate außer .bmp benötigt werden, hilft ::LoadBitmap bzw. ::LoadImage nicht weiter. Allerdings stellt Windows mit der API-Funktion ::OleLoadPicture eine Möglichkeit zur Verfügung, diverse Formate (JPEG, GIF, WMF, ICO etc.) zu laden. Die Funktion liefert ein IPicture-Interface, welches genutzt werden kann, das geladene Grafikformat auf den übergebenen DC zu zeichnen (IPicture::Render).

Für MFC-Anwender gibt es unter Code Project eine erweiterte Bitmapklasse (CEnBitmap), die ::OleLoadPicture/IPicture kapselt (CEnBitmap::LoadImage), die sich aber ansonsten wie CBitmap verhält.

Das folgende Beispiel zeigt das Laden eines Bildes mit LoadPicture und die Ausgabe mit DrawPicture:

LPPICTURE pPicture;
long lWidth, lHeight;
int iWidth, iHeight;

BOOL LoadPicture(LPCTSTR pszFileName)
{
  //datei öffnen
  HANDLE hFile = CreateFile(pszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);

  if(INVALID_HANDLE_VALUE == hFile)
   return FALSE;

  //datei größe ermitteln
  DWORD dwFileSize = GetFileSize(hFile, NULL);

  //speicher in größe der datei allokieren
  HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
  LPVOID  pvData  = GlobalLock(hGlobal);

  //datei lesen u. im speicher behalten
  DWORD dwBytesRead = 0;
  BOOL  bRead       = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);

  if(!bRead)
   return FALSE;

  GlobalUnlock(hGlobal);
  CloseHandle(hFile);

  //IStream* aus dem speicher erzeugen
  LPSTREAM pstm = NULL;
  HRESULT  hr   = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);

  //IPicture vom bild erzeugen
  if(pPicture)
      pPicture->Release();

  hr = OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID*)&pPicture);
  pstm->Release();

  //breite u. höhe vom bild holen
  pPicture->get_Width(&lWidth);
  pPicture->get_Height(&lHeight);

  HDC hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);

  //in Pixel konvertieren
  iWidth = (lWidth  * GetDeviceCaps(hdc, LOGPIXELSX)) / 2540;
  iHeight = (lHeight * GetDeviceCaps(hdc, LOGPIXELSY)) / 2540;

  return TRUE;
}

BOOL DrawPicture(HWND hwnd, HDC hdc)
{
  if(pPicture) //wenn bild geladen
  {
   RECT rc;
   GetClientRect(hwnd, &rc);

   //Bild anzeigen mittels Render
   pPicture->Render(hdc, 0, 0, iWidth, iHeight, 0, lHeight, lWidth, -lHeight, &rc);

   return TRUE;
  }

  return FALSE;
}

Verweise:

CEnBitmap von Code Project
OleLoadPicture
IPicture
Displaying a JPG in your MFC Application (Paul DiLascia)

Autoren:

Dieter Smode, Thomas Klocker

7.17  Wie kann ich in eine MessageBox formatiert ausgeben?  [URL]

Es ist häufig lästig, zunächst einen String zu formatieren und ihn dann in einer MessageBox anzuzeigen. Der folgende Code zeigt, wie man eine printf nachempfundene formatierte Ausgabe realisieren kann:

int MessageBoxPrintf(HWND hWnd, TCHAR * szCaption, UINT nType, TCHAR * szFormat, ...)
{
    TCHAR szBuffer [1024] = _T("");
    va_list pArgList;
		
    va_start(pArgList, szFormat);

    if (szFormat != NULL)
    {
      _vsntprintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), szFormat, pArgList);
    }
    
    va_end(pArgList);

    return MessageBox(hWnd, szBuffer, szCaption, nType);
}
		

Wird MFC verwendet, empfiehlt es sich statt MessageBox die Funktion AfxMessageBox aufzurufen:

int MessageBoxPrintf(UINT nType, TCHAR * szFormat, ...)
{
    TCHAR szBuffer [1024] = _T("");
    va_list pArgList;

    va_start(pArgList, szFormat);

    if (szFormat != NULL)
    {
      _vsntprintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), szFormat, pArgList);
    }

    va_end(pArgList);

    return AfxMessageBox(szBuffer, nType);
}
		

Autoren:

Thomas Klocker

7.18  Wie füge ich Versionsinformationen ein und wie frage ich diese ab?  [URL]

Die Versionsinformation wird in einer Versionsressource im Code untergebracht. Hierzu sind zunächst die Ressourcen zu öffnen. In der Ressourcenansicht wird dann über den Menüpunkt "Einfügen ..." (VS 6) oder "Ressource hinzufügen ..." (VS.NET) ein Dialog geöffnet, der u. a. das Einfügen einer Versionsressource ermöglicht. Dies Ressource muß dann nur noch ausgefüllt werden.

Der Inhalt der Ressource kann über den Windows-Explorer abgefragt werden, indem zur entsprechenden Datei die Dateieigenschaften geöffnet werden. In diesem Dialog existiert dann eine eigene Seite "Version".

Für die programmtechnische Abfrage existieren eigene API-Funktionen. Mit den Funktionen GetFileVersionInfoSize, GetFileVersionInfo und VerQueryValue lassen sich die Einträge der Versionsressource abfragen. Paul DiLascia hat hierfür eine Klasse CModuleVersion im Microsoft System Journal beschrieben.

Verweise:

Version Information
CModuleVersion

Autoren:

Dieter Smode

7.19  Wie ergänze ich mein aktuelles Projekt um die Darstellung des XP-Theme-Stils?  [URL]

Hierzu findet sich bei "Code Project" eine Anleitung mit Beispielcode.

Verweise:

Add Windows XP Theme Style to your current projects

Autoren:

Carsten Witte

7.20  Wie verhindere ich bei einer MDI-Anwendung, dass automatisch ein leeres Fenster geöffnet wird?  [URL]

In der von CWinApp abgeleiteten Applikationsklasse befindet sich in InitInstance der Code, welcher die Befehlszeilenparameter bearbeitet und z. B. eine dort übergebene Datei öffnet. Die notwendigen Änderungen sind im folgenden Codeschnipsel fett dargestellt:

...
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew)
{
  cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
}

// Verteilung der in der Befehlszeile angegebenen Befehle
if (!ProcessShellCommand(cmdInfo))
  return FALSE;
...

Wird beim Untersuchen der Befehlszeile keine spezielle Option gefunden (Öffnen einer Datei, Drucken einer Datei), wird automatisch angenommen, dass eine neue Datei zu öffnen ist. Diese Einstellung ändert die obige Einfügung so, dass keine Datei geöffnet wird.

Hinweis: es sollte vermieden werden, cmdInfo.m_nShellCommand ohne Prüfung auf den von ParseCommandLine gesetzten Wert zu ändern, da anderenfalls z. B. das Drucken einer registrierten Datei durch Fallenlassen auf einen Drucker bzw. das Öffnen einer Datei durch Fallenlassen auf die Applikation nicht mehr funktionieren!

Verweise:

CCommandLineInfo::m_nShellCommand

Autoren:

Dieter Smode

7.21  Was bedeutet "Nicht abgefangene Ausnahme in ..." im Ausgabefenster des Debuggers?  [URL]

Diese Meldung kann im allgemeinen ignoriert werden. Leider wurde diese Meldung für die deutsche Version von Visual Studio schlecht übersetzt.

Tritt bei laufendem Debugger eine Exception auf, bekommt der Debugger diese angeboten, bevor die Applikation die Exception sieht. Im Englischen wurde das mit "first chance exception" sehr treffend bezeichnet. Im Deutschen ist dann leider "Nicht abgefangene Ausnahme in ..." dabei herausgekommen.

Ignoriert der Debugger diese Exception (das ist die Standardeinstellung), bekommt die Applikation die Exception und kann sie ggf. fangen. Wird die Exception auch von der Applikation ignoriert (hier würde die Release-Version dann abstürzen), bekommt der Debugger die Exception ein weiteres Mal angeboten ("second chance exception"). In der Regel hält der Debugger dann an und man kann sich das Problem anschauen.

Ob eine so signalisierte Exception, die dann von der Applikation behandelt wurde, schwerwiegend ist oder nicht, läßt sich nicht so einfach entscheiden. Es kann ein problematischer Fehler im Programm oder in den genutzten DLLs etc. vorhanden sein. Es kann aber auch sein, daß die Exception gewollt eingesetzt wurde und daher völlig unschädlich ist. In der Regel wird sich dies an der Funktion der Software zeigen.

Verweise:

INFO: First and Second Chance Exception Handling

Autoren:

Dieter Smode

7.22  Kann ich eine Release-Version debuggen?  [URL]

Mit zwei Änderungen an den Einstellungen der Release-Version kann der Debugger eingesetzt werden:

  1. VC 6.0: Auf der Registerkarte "C/C++" (Kategorie Allgemein) in der Combobox "Debug-Info" die Einstellung "Programmdatenbank" wählen.
    VC 7.x: In den Eigenschaftsseiten für das Projekt unter "C/C++ -> Allgemein" unter "Debuginformationsformat" die Einstellung "Programmdatenbank (/Zi)" wählen.
  2. VC 6.0: Auf der Registerkarte "Linker" (Kategorie Allgemein) die Checkbox "Debug-Info generieren" anhaken.
    VC 7.x: In den Eigenschaftsseiten für das Projekt unter "Linker -> Debuggen" unter "Debuginfo generieren" die Einstellung "Ja (/DEBUG)" wählen.

Anschließend muß das Projekt nochmal komplett neu erzeugt werden. Danach kann der Debugger genutzt werden.

Allerdings gibt es ein paar Einschränkungen. Es kann nicht in Code debuggt werden, der nicht im Rahmen des Projekts erzeugt wurde. Weiterhin springt der Debugger teilweise ziemlich merkwürdig im Code herum. Dies liegt daran, daß der Release-Code in der Regel mit Optimierungen übersetzt wird. Diese können natürlich abgeschaltet werden. Allerdings verschwinden bestimmte Fehler dann gegebenenfalls, weil sich Codeteile verschieben.

Es gibt einige häufig gemachte Fehler, die sich beim Übergang von Debug- zu Release-Versionen bemerkbar machen. Microsoft hat hierfür einige Tips veröffentlicht, die bei der Behebung hilfreich sein können.

Verweise:

Common Problems When Creating a Release Build

Autoren:

Dieter Smode

7.23  Verwendung von .obj- und .lib-Dateien anderer Entwicklungsumgebungen [URL]

Völlig unproblematisch funktionieren .obj- und .lib-Dateien nur dann, wenn die verwendete Entwicklungsumgebung diese Dateien im gleichen Format erzeugt, wie VisualStudio.

Reiner C-Code oder mit extern "C" geklammerter C++-Code kann in der Regel dann übernommen werden, wenn die Dateien im COFF-Format vorliegen.

Im Falle von C++ wird es komplizierter, selbst wenn die Dateien im COFF-Format erzeugt werden. C++ verwendet nämlich das Name Mangling, um z. B. überladene Funktionen unterscheidbar zu machen. Wenn die andere Entwicklungsumgebung nicht die gleichen Konventionen für das Name Mangling verwendet, kommt es beim Linken zu Fehlern.

Möglicherweise sind in den Dateien auch Referenzen auf andere Libraries enthalten, die so in VisualStudio nicht exisitieren. Beim Linken muß dann Zugriff auf diese Libraries bestehen.

Die beste Strategie bei Einbindung von Code aus verschiedenen Entwicklungsumgebungen ist die Verwendung von DLLs (mit oder ohne Importlibraries).

Unten findet sich ein Link, der beschreibt, wie z. B. das Format einer Library festgestellt bzw. aus einer .lib eine DLL gemacht werden kann

Verweise:

How to convert VC+ .lib file to Borland and vice versa?
HOWTO: Create 32-bit Import Libraries Without .OBJs or Source

Autoren:

Dieter Smode

7.24  Wie setze ich den Cursor in einem Edit-Control an eine beliebige Position? [URL]

Zum Setzen des Cursors bedient man sich der Technik, den Text zu selektieren, bzw. die Selektion zu entfernen. Dies kann über mehrere Arten implementiert werden.

MFC:

//Zeiger auf Control holen
CEdit* pEdt = ((CEdit*)GetDlgItem(IDC_MYEDIT));
ASSERT(pEdt);

//Position der Selektion (alles selektieren)
int nPos = -1;

//Selektion von Position 0 bis gewählte Position setzen
pEdt->SetSel(0,nPos);

//Selektion entfernen, dass Cursor am Ende stehen bleibt 
pEdt->SetSel(-1,0);

API:

//Zeiger auf Control holen
HWND hWndEdit = ::GetDlgItem(this->m_hWnd, IDC_MYEDIT);

//Position der Selektion (alles selektieren)
int nPos = -1;

//Selektion von Position 0 bis gewählte Position setzen
::SendMessage(hWndEdit, EM_SETSEL, 0, nPos);

//Selektion entfernen, dass Cursor am Ende stehen bleibt 
::SendMessage(hWndEdit, EM_SETSEL, -1, 0);

Anmerkung: Die Position des Cursors kann nur gesetzt werden, wenn das Editfeld den Focus hat. Den Focus setzt man in einem Dialog am einfachsten mit CDialog::GotoDlgCtrl und Konsorten.

Autoren:

Alexander Sailer

7.25  Wie kann ich einen Screenshot erstellen und als Bitmap ins Clipboard kopieren bzw. in eine Datei speichern?  [URL]

Eine Lösung hierzu findet sich z. B. beim MVP-Kollegen Joseph Newcomer unter Screen Capture to the Clipboard.

Unter Writing a window image to a BMP file findet sich die Lösung für das Speichern in einer Datei. Copying a bitmap to clipboard zeigt, wie eine Bitmap ins Clipboard kopiert werden kann.

Verweise:

Screen Capture to the Clipboard
Writing a window image to a BMP file
Copying a bitmap to clipboard

Autoren:

Thomas Klocker, Dieter Smode

7.26  Wie kann ich den Fehlercode von GetLastError in einen Fehlerstring umwandeln?  [URL]

Die Umwandlung kann mit der API-Funktion FormatMessage erreicht werden, wobei auch die Sprache des Fehlerstrings angegeben werden kann:

DWORD dwError = GetLastError();
HLOCAL hlocal = NULL;

BOOL fOk = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
                         NULL,
                         dwError,
                         MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
                         (PTSTR)&hlocal,
                         0,
                         NULL);

if(!fOk)
{
   // Netzwerkbezogener Fehler
   HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);

   if(hDll != NULL)
   {
        FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM,
                      hDll,
                      dwError,
                      MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
                      (PTSTR) &hlocal,
                      0,
                      NULL);

        FreeLibrary(hDll);
   }
}

if(hlocal != NULL)
{
    MessageBox(hwnd, (LPCTSTR)LocalLock(hlocal), TEXT("My App"), MB_ICONERROR);
    LocalFree(hlocal);
}

Benötigt man den letzten Fehlercode bzw. die Fehlermeldung während des Debuggens, erhält man diese durch Eingabe von @Err bzw. @Err,hr im Watch- bzw. QuickWatch-Fenster.

Verweise:

FormatMessage

Autoren:

Thomas Klocker, Andreas Kaiser

7.27  Wie kann ich beim Drucken mit MFC die Seitengröße mit korrigierten Randeinstellungen ermitteln?  [URL]

////////////////////////////////////////////////////////////////////////////
/
// GetPrintPageMetrics
//  print Helper functions, that returns full physical pagesize
//  corrected margins (incomming in 1/10mm) in device units.
//   rMarginIn (in) - margins to use in 1/10mm
//   prMarginOut (out) - Adjusted to LP
//  Returnvalue:
//   pageRect (out)  - in LP
//

#if defined(__AFX_H__)

CRect GetPrinterPageMetrics(CDC *pDC, const CRect &rMarginIn, CRect *prMarginOut)
{
  // Allow user to set page format
  CRect rect;
	
  // Start by getting the dimensions of the unprintable part of the
  // page (in device units). GETPRINTINGOFFSET will tell us the left
  // and upper unprintable area.
  rect.left = pDC->GetDeviceCaps(PHYSICALOFFSETX);
  rect.top  = pDC->GetDeviceCaps(PHYSICALOFFSETY);
	
  // To get the right and lower unprintable area, we need to take
  // the entire width and height of the paper (GETPHYSPAGESIZE) and
  // subtract everything else.
  CSize sPageSize(pDC->GetDeviceCaps(PHYSICALWIDTH),
                  pDC->GetDeviceCaps(PHYSICALHEIGHT));
  rect.right  = sPageSize.cx                   // total paper width
                 - pDC->GetDeviceCaps(HORZRES) // printable width
                 - rect.left;                  // left unprtable margin
  rect.bottom = sPageSize.cy                   // total paper height
                 - pDC->GetDeviceCaps(VERTRES) // printable ht
                 - rect.top;                   // top unprtable margin
								 
  // At this point, rect contains the widths of the
  // unprintable regions on all four sides of the page in device units.
  // Convert the Hi-Metric/10 margin values from the Page Setup dialog
  // to device units and subtract the unprintable part we just
  // calculated. Save the results back in rect.
  // (254 == # of Hi-Metric/10 units in an inch)
  CSize size(pDC->GetDeviceCaps(LOGPIXELSX),    // dpi in X direction
             pDC->GetDeviceCaps(LOGPIXELSY));   // dpi in Y direction
  rect.left   = MulDiv(rMarginIn.left, size.cx, 254) - rect.left;
  rect.top    = MulDiv(rMarginIn.top, size.cy, 254) - rect.top;
  rect.right  = MulDiv(rMarginIn.right, size.cx, 254) - rect.right;
  rect.bottom = MulDiv(rMarginIn.bottom, size.cy, 254) - rect.bottom;

  // rect now contains the values used to shrink the printable
  // area of the page. Could check rect here for negative values
  // to prevent setting margins outside the printable area of the page.
  // Convert to logical units and we're done!
  CRect rMarginOut(max(0,rect.left),
        max(0,rect.top),
        max(0,rect.right),
        max(0,rect.bottom));
  // Convert into logical points
  pDC->DPtoLP(&(CSize &)rMarginOut.TopLeft());
  pDC->DPtoLP(&(CSize &)rMarginOut.BottomRight());
  
  // Ergebnis kopieren wenn gewünscht
  if (prMarginOut)
    *prMarginOut = rMarginOut;
  
  // Get pagesize
  CRect rPage(0,0,pDC->GetDeviceCaps(HORZRES),pDC->GetDeviceCaps(VERTRES));
  pDC->DPtoLP(&rPage);

  // Reserve room for margins and headers
  rPage.left   += rMarginOut.left;
  rPage.top    += rMarginOut.top;
  rPage.right  -= rMarginOut.right;
  rPage.bottom -= rMarginOut.bottom;

  return rPage;
}

#endif

Hinweis:
Es hilft sehr, beim Drucken auf Hilfsfunktionen - wie die obige - zurückzugreifen, in diesen Hilfsfunktionen die notwendigen Berechnungen durchzuführen und ein für die gewählten Ausgabefunktionen passendes Ergebnis zurückzugeben.

Verweise:

CDC::GetDeviceCaps
GetDeviceCaps

Autoren:

Martin Richter

7.28  Wie binde ich Libraries einfach in ein Projekt ein?  [URL]

Wer kennt nicht Linker-Fehler wie:

EditView.obj : error LNK2019: unresolved external symbol
_GetFileVersionInfoSizeA@8 referenced in function "public: virtual int
__thiscall CEditorApp::InitInstance(void)"
(?InitInstance@CEditorApp@@UAEHXZ)

Man hat einfach vergessen, die entsprechende Library in den Linker-Einstellungen des Projektes mit anzugeben.

Bei größeren Projekten kann das ganz schon umfangreich werden, zumdem muss man dies für jede Konfiguration (Debug/Release/Unicode etc.) vornehmen. Das ganze kann man ziemlich intelligent umgehen, in dem man einfach die entsprechende Library im C/C++ Code anfordert. Dies erreicht man durch ein #pragma Statement. In diesem Fall z.B.:

#pragma comment(lib,"version")

Dies eignet sich besonders für kleine Code Snipletts, die man in einem Shared-Code Pool hält. Man shared die entsprechenden Dateien aus einem VSS Verzeichnis in sein Projekt. Die Projekt-Einstellungen müssen nicht geändert werden selbst wenn dieses Code Segment Libraries benötigt, die im Projekt noch nicht eingebunden wurden. Dies erleichert das Wiederverwenden von Sourcecode.

Verweise:

#pragma comment
Pragma Directives

Autoren:

Martin Richter

Inhaltsverzeichnis


8  Installation und Verteilung eigener Programme?

8.1  Welche kostenlosen Installationsprogramme gibt es? [URL]

Mit Windows 2000® wurde der "Microsoft Windows Installer" entwickelt. Dieser kann auch auch auf Systemen mit Windows 95, Windows 98 und Windows NT 4.0 installiert werden. Um darauf basierende Installationen zu erstellen, kann der Visual Studio installer verwendet werden. Dieser ist über die Microsoft-Website erhältlich (wie auch der Microsoft Windows Installer selbst).

Den Freeware-Installer "Inno Setup " von Jordan Russell kann man - samt Sourcecode (allerdings Delphi) - bekommen.

Desweiteren gibt es noch den Install Creator von ClickTeam.

NullSoft stellt den NSIS der Allgemeinheit zu Verfügung, sogar inkl. Sourcecode (C++).

Verweise:

Inno Setup
Visual Studio® Installer 1.1
Install Creator
NSIS

Autoren:

Michael Krafzik, Dirk Hedderich, Stefan Zehe

8.2  Welche kommerziellen Installationsprogramme existieren? [URL]

Eines der bekanntesten Installationsprogramme ist InstallShield. Eine eingeschränkte Version liegt Microsoft Visual C++® ab der Professional-Edition bei.

Als Alternative hat sich Wise Install etabliert:

Verweise:

InstallShield
Wise Install

Autoren:

Michael Krafzik

8.3  Welche der Dateien, die Visual C++ beiliegen, darf ich weitergeben? [URL]

Es sind zu viele, um sie alle hier aufzuzählen (wenn man Sourcecode mit einbezieht, viele tausend Dateien). Jeder Kopie von Visual C++ liegt ein Text (redist.txt) bei, in dem diese Dateien aufgeführt werden.

Einige der häufig weitergegebenen Dateien sind:

mfc42.dll
mfc42deu.dll
msvcrt40.dll
msvcrt.dll
msvcp60.dll

Es ist speziell darauf zu achten, daß die Debugversionen der MFC-DLLs nicht weitergegeben werden dürfen.

Verweise:

Redistributing Microsoft Visual C++ 6.0 Applications
Comctl32 Redistributables 5.80.2614.3600 (WinNT und Win9x)
Runtime Komponenten für Visual C++ 6.0 Applikationen
Redistributables for Platform SDK

Autoren:

Michael Krafzik, Albert Weinert

Inhaltsverzeichnis


9  Integrated Development Enviroment (IDE)

9.1  Die automatische Vervollständigung von Anweisungen funktioniert plötzlich nicht mehr. Was kann ich tun? [URL]

Die Intellisense Technologie scheint ein wenig empfindlich und auch ein wenig buggy zu sein. Das Problem kann mehrere Ursachen haben:

Visual Studio hat sich verschluckt und ist über einen seiner Bugs gestolpert. Abhilfe schafft hier oft, den Arbeitsbereich zu schließen und die Datei meinprojekt.ncb zu löschen. Dann lädt man den Arbeitsbereich wieder. Die gelöschte Datei wird automatisch wieder erstellt.

Hilft dies nicht weiter, können zusätzlich auch die Dateien meinprojekt.clw und meinprojekt.opt (vorher sichern) gelöscht werden. Die Datei meinprojekt.clw wird wieder neu aufgebaut, wenn der Klassenassistenz das erste Mal wieder aufgerufen wird (es erscheint ein Dialog). In meinprojekt.opt befinden sich z. B. die Ordnereinstellungen der Klassenansicht aber auch andere Einstellungen (Breakpoints etc.). Diese gehen durch Löschen der Datei unwiderruflich verloren.

Intellisense ist teilweise extrem kontextsensitiv. Funktioniert die automatische Vervollständigung nicht mehr, kann das auch ein Hinweis auf Syntax-Fehler und insbesondere Klammerfehler im vorangehenden Code sein.
(einfaches) Beispiel:

  void foo()
  {
   CString cs;
 }
 cs.

Hier wird jetzt nichts mehr angezeigt. Hat man also einmal eine Klammer zuviel zugemacht, kann sich das schon bei der Eingabe des Codes rächen.

Wenn das Problem häufiger auftritt, könnte sich ein Blick auf VisualAssist durchaus lohnen.

Verweise:

INFO: Limitations of IntelliSense in Visual C++ 6.0
VisualAssist

Autoren:

Manni Heumann, Dieter Smode

9.2  Anzeigen der Hilfe nicht möglich! [URL]

Nach der Installation von Visual C++ 6.0 bzw. Visual Studio 6.0 ist das Anzeigen der Hilfe nicht möglich. Stattdessen kommt eine Meldung: Anzeigen der Hilfe nicht möglich. Eine benötigte Komponente fehlt.

Die Lösung ist ganz einfach, es muss die Vshelp.dll im System mit Regsvr32 registriert werden. Danach sollte es wieder funktioniert.

Verweise:

MSDN: MSDN Library Unable to Display Help from Within Visual Studio Programs

Autoren:

Albert Weinert

9.3  Gibt es Erweiterungen für das Visual Studio? [URL]

Die Benutzeroberfläche von Visual Studio kann durch sogenannte Add-Ins funktionell erweitert werden. Während es jederzeit möglich ist, eigene Add-Ins zu implementieren, gibt es bereits zahlreiche sehr nützliche Tools von diversen Fremdanbietern. Einige interessante Add-Ins wollen wir hier kurz vorstellen:

Verweise:

MSDN: Add-ins for the Visual C++ Developer Studio
Wenn man selbst Add-Ins für Visual C++ erstellen möchte, so ist dies ein guter Start.
VisualAssist
erweitert die Intellisense-Funktionen um eine erweiterte automatische Vervollständingung (Makros werden ebenso erkannt, wie Namensbereiche), ermöglicht das Navigieren zu Symbol Deklarationen auch ohne Browser-Informationen, bietet nützliche Navigationshilfen, bietet eine automatische Korrektur der Groß-Kleinschreibung, ermöglicht farbige Ausdrucke und, und, und. Dieses Add-In kann 30 Tage lang kostenlos getestet werden. Nach Ablauf dieser 30 Tage (oder auch schon früher) kann VA gegen eine Gebühr von 79 US-$ erworben werden.
WndTabs
Bietet nützliche Fenster und Datei Management Funktionen. Zu den augenscheinlichsten dürften allerdings die sogennanten "Window-Tabs" zählen. Dabei wird für jedes offene Fenster ein Reiter in die Visual Studio IDE eingefügt, was ein schnelles Navigieren durch den Fenster Dschungel ermöglicht. Die standard Version ist kostenlos. Die Erweiterte Version schlägt mit 10 US-$ zu Buche.
Project Line Counter
Wer wissen will, aus wie vielen Zeilen Code sein Projekt besteht, und darüber hinaus daran interessiert ist, wie viele Zeilen davon als Kommentare respektive Leerzeilen eingehen, sollte sich dieses kostenlose Add-In näher ansehen.

Autoren:

Maximilian Hänel, Olivier Braun

9.4  Wie viele Zeilen hat mein Code? [URL]

Auch diese Frage ist zu beantworten, einfach zählen! Nunja, damit es nicht so schwer wird gibt es auch ein Add-In dafür.

Verweise:

Project Line Counter
Wer wissen will, aus wie vielen Zeilen Code sein Projekt besteht, und darüber hinaus daran interessiert ist, wie viele Zeilen davon als Kommentare respektive Leerzeilen eingehen, sollte sich dieses kostenlose Add-In näher ansehen.

9.5  Welche MSDN-Version läuft mit meiner Visual Studio Version? [URL]

Für Visual Studio V 6.0 ist die MSDN vom Oktober 2001 die letzte Version, die in die IDE integriert werden kann. Alle MSDN-Versionen ab Januar 2002 können nur noch in Visual Studio .NET integriert werden.

Es spricht nichts dagegen, die Oktober-2001-MSDN parallel zu einer neueren Version zu installieren, wenn beide Versionen benötigt werden.

Zum besseren Umgang mit MSDN ist der Leitfaden von Carsten Witte sehr zu empfehlen.

Verweise:

HOWTO: Suchen und Finden im MSDN

Autoren:

Dieter Smode

Inhaltsverzeichnis


10  Buchempfehlungen

10.1  Hinweise [URL]

Diese Buch- und Zeitschriftenempfehlungen sind aus den Newsgroups entnommen und es wird versucht, diese Liste aktuell zu halten.

Die Kommentare sind die von den Autoren der Newsbeiträge. Der Link auf dem Buchtitel geht zu www.amazon.de . Hier sind weitere Rezensionen.

Sollte bei einem Buch kein Link vorhanden sein, so ist dieses Buch nicht mehr zubekommen. Dann hilft nur der Versuch es gebraucht zu erwerben.

Die Reihenfolge der Bücher ist zufällig. D. h. ein oben stehendes Buch muss nicht besser oder schlechter sein.

Verweise:

www.amazon.de

Autoren:

Albert Weinert

10.2  C++ [URL]

Verweise:

Zusammenstellung von C++-Literatur
Hier findet man einige Bücher zum Thema C++, die teilweise auch hier im FAQ aufgeführt sind.
Das Einmaleins der C-Programmierung (nicht mehr lieferbar)
von Ulrich Cuber, deutsch, Taschenbuch - 416 Seiten (Dezember 1997) Econ TB Vlg., München; ISBN: 3612281577; 13,95 €

Kommentar:
Das Buch vermittelt die Basics von C eigentlich ganz gut, ist aber wirklich nur für den Newbie gedacht.
Thinking in C++: Introduction to Standard C++, Volume One, Second Edition (englisch)
von Bruce Eckel, englisch Taschenbuch - 814 Seiten (15. April 2000) Prentice Hall ; ISBN: 0139798099; 44,90 €

Kommentar:
Als Einführung zu C++ gibt es auch "Thinking in C++" ist zwar auf Englisch und sehr gut, dafür aber gratis downloadbar in allen möglichen Formaten

Kommentar:
Ist sehr zu empfehlen. Geht nicht auf VC ein

Kommentar:
richtet sich vor allem an Umsteiger von C nach C++, bietet aber auch dem Einsteiger in C++ viel interessantes.
In C++ denken (nicht mehr lieferbar)
von Bruce Eckel, deutsch Gebundene Ausgabe - 640 Seiten (1998) Markt u. Technik, Haar; ISBN: 3-82729-567-X; ca. 39,95 €

Kommentar:
Dies ist die Deutsche Ausgabe von Thinking in C++. Es richtet sich vor allem an Umsteiger von C nach C++, bietet aber auch dem Einsteiger in C++ viel interessantes. Allerdings ist die mir vorliegende 2., revidierte Auflage grausam zu lesen, weil der Verlag scheinbar kein Geld für einen vernünftigen Übersetzer ausgeben wollte.
Thinking in C++ (online, englisch)
von Bruce Eckel

Kommentar:
Dies ist die Online Ausgabe von Thinking in C++.

Kommentar:
Bruce bietet auch den bisher nicht veröffentlichten Band 2 online an.
Die C++ Programmiersprache
von Bjarne Stroustrup, Gebundene Ausgabe - 1108 Seiten (Mai 2000) Addison-Wesley; ISBN: 382731660X; 49,95 €

Kommentar:
Wirklich ein Muß!! Unbedingt auf die 4. Ausgabe achten. Aber kleine Einschränkung: Nicht für Neueinsteiger, sondern nur für Umsteiger gedacht.

Kommentar:
Falls du C++ noch nicht kannst, würde ich folgendes Buch empfehlen, ich habe es selber
C++ Programmieren mit Stil. Eine systematische Einführung (nicht mehr lieferbar)
von Wolfgang Strasser Taschenbuch (1997) dpunkt-Verlag, Heidelberg; ISBN: 3-92099-369-1 25,05 €

Kommentar:
Und ich kann mich diesem Tipp nur anschließen. Den Strasser für C++ und die Gregory für die Windows-Programmierung mit den MFC.
Objektorientiertes Programmieren in C++
von Nicolai Josuttis Gebundene Ausgabe (2001; 2. aktualisierte und überarbeitete Auflage) Addison Wesley; ISBN: 3-8273-1771-1; 39,95 €

Kommentar:
Falls du C++ noch nicht kannst, würde ich dir dieses Buch empfehlen, ich habe es selber
C/C++ Referenz
von Petra Nootz, Franz Morick; Gebundene Ausgabe - 480 Seiten (2001) Franzis, Feldkirchen; ISBN: 3-77236-356-3; 39,95 €

Kommentar:
Falls du C++ noch nicht kannst, würde ich dir dieses Buch empfehlen, ich habe es selber
C++ Einführung und professionelle Programmierung mit CD-ROM
von Ulrich Breymann; Taschenbuch - 714 Seiten (2003; 7. überarbeitete Auflage) Hanser Fachbuch; ISBN: 3-446-22330-4; 39,90 €

Kommentar:
Ersteres hat mir C++ eigentlich recht gut erklärt (hatte ein wenig C-Erfahrung unter Linux)
Effektiv C++ programmieren. 50 Möglichkeiten zur Verbesserung Ihrer Programme
von Scott Meyers; Gebundene Ausgabe - 304 Seiten (Dezember 1997) Addison-Wesley; ISBN: 3827313058; 29,95 €

Kommentar:
Das Buch wendet sich zwar in erster Linie an den erfahreneren Programmierer, aber auch Einsteiger werden hier bereits den einen oder anderen nützlichen Tip finden. Auch wer glaubt, die Sprache C++ gut zu kennen, wird dem Buch in der Regel noch neue Erkenntnisse entnehmen können.
Mehr Effektiv C++ programmieren. 35 neue Wege zur Verbesserung Ihrer Programme und Entwürfe
von Scott Meyers; Gebundene Ausgabe - 328 Seiten (Dezember 1997) Addison-Wesley; ISBN: 3827312752; 29,95 €

Kommentar:
Weitere nützliche Erkenntnisse rund um C++.

10.3  Programmieren allgemein [URL]

Verweise:

Code Complete: A Practical Handbook of Software Construction
von Steve McConnell; englisch; Taschenbuch - 752 Seiten (März 1993) Microsoft Press; ISBN: 1-55615-484-4; 39,00 €

Kommentar:
In diesem Buch wird sprachunabhängig beschrieben, was man zu einem guten Programmierstil braucht. In englisch hab ich das Buch noch nicht gelesen
Code Complete: deutsch (nicht mehr lieferbar)
von Steve McConnell; Gebundene Ausgabe - Microsoft Press, ISBN: 3-86063-333-3; ca. 45,50 €

Kommentar:
In diesem Buch wird sprachunabhängig beschrieben, was man zu einem guten Programmierstil braucht. Dieses Buch ist leider vergriffen, aber wer es irgendwo in einem Antiquaritat sieht sollte es sich sofort mitnehmen.
Professional Software Development
von Steve McConnell; englisch; 208 Seiten (2003) Addison-Wesley; ISBN: 0321193679; 28,84 €

10.4  Visual C++ [URL]

Verweise:

Visual C++ 6.0, mit CD-ROM. Für Einsteiger und Fortgeschrittene
von Hans-Jürgen Scheibl, deutsch, Gebundene Ausgabe - 953 Seiten (1999) Carl Hanser, Mch.; ISBN: 3-44619-548-3; 49,90 €

Kommentar:
ist ein gutes Buch wie man in C++ programmiert.
Visual C++ .NET, mit CD-ROM. Für Einsteiger und Fortgeschrittene
von Hans-Jürgen Scheibl, deutsch, Gebundene Ausgabe - 1100 Seiten (2003) Carl Hanser, Mch.; ISBN: 3-44622-329-0; 49,90 €
Visual C++ 6 in 21 Tagen
von Davis Chapman, Gebundene Ausgabe - 840 Seiten (1998) Markt u. Technik, Haar; ISBN: 3-82722-035-1; 44,95 €

Kommentar:
Naja, es stimmt schon, dass man nach diesem Buch nicht all zu viel kann! Aber wenn man schon etwas Programmieren kann und mit C, besser C++, schon etwas vertraut ist, bietet dieses Buch doch zumindest einen brauchbaren Einstieg, sozusagen ein Schnupperkurs.

Kommentar (zur Version 5):
Dieses Buch ist für Leute, welche sich über die Grundfunktionen der MFC und die grundlegenden Möglichkeiten der GUI ein Bild machen möchten. Als 'ersten' Einstieg für ein paar Samples in die MFC kann es Dir hilfreich sein, stößt aber mit sehr schnell an Grenzen.

Kommentar:
für den Einstieg in VC++ kann ich dieses Buch empfehlen. Dort wird eine Menge über die Bedienung des Visual Studios erklärt. Beispiele gibts auch viele und alles ist nochmal komplett auf der CD. Die CD hat ebenfalls eine ganz gute Stichwortsuche, ebenfalls alle Sourcecodes.
Visual C++ .NET in 21 Tagen
von Davis Chapman, Gebundene Ausgabe - 880 Seiten (2002) Markt u. Technik, Haar; ISBN: 3-82726-320-4; 44,95 €
Sams Teach Yourself C++ in 21 Days Complete Compiler Edition (englisch)
von Jesse Liberty; Taschenbuch - 640 Seiten (31. Dezember 2001) Sams; ISBN: 0672322072; 56,65 € Einsteiger

Kommentar:
Geht auf die IDE von VC ein und erklärt dir alles Schritt für Schritt, enthält auch eine "Introductory-Edition" von VC.
C++ in 21 Tagen. Schritt für Schritt zum Programmierprofi
von Jesse Liberty; Taschenbuch - 1008 Seiten (1999) Markt u. Technik; ISBN: 3827256240; 44,95 € Einsteiger
Programming Microsoft Visual C++, Fifth Edition
von David J. Kruglinski, George Shepherd, Scot Wingo; Taschenbuch - 1150 Seiten (August 1998) Microsoft Press; ISBN: 1-57231-857-0; 56,00 €
Programming Microsoft Visual C++ .NET, Sixth Edition
von George Shepherd, David J. Kruglinski; Gebunden - 1038 Seiten (2002) Microsoft Press; ISBN: 0735615497; 70,35 €
Inside Visual C++ 6.0
von David Kruglinski, Scot Wingo, George Sheperd; Gebundene Ausgabe - 1200 Seiten (1998) Microsoft Press, München; ISBN: 3-86063-461-5; 49,90 €

Kommentar:
Ich habe "Inside Visual C++ Version 5" von MS Press durchgearbeitet. Ging hauptsächlich auf die grundlegenden Möglichkeiten der Microsoft Foundation Classes ein, behandelte aber auch ein paar tiefgreifendere Themen wie Speicherverwaltung und TCP/IP-Programmierung.

Kommentar
Ich empfehle für die ersten Schritte in Windows Programmierung. erschlägt alle Themen und baut gut auf
Inside Visual C++ .NET
von David Kruglinski, Scot Wingo, George Sheperd; Gebundene Ausgabe - 950 Seiten (2002) Microsoft Press, München; ISBN: 3-86063-678-2; 49,90 €
Jetzt lerne ich Visual C++ 6
von Dirk Louis; Taschenbuch - 548 Seiten (1999) Markt u. Technik, Haar; ISBN: 3-82725-519-8; 24,95 €

Kommentar:
ist ein gutes Buch
Jetzt lerne ich Visual C++.NET. Windows-GUI-Programmierung mit Visual C++ .NET und den MFC
von Dirk Louis; Taschenbuch - 504 Seiten (2002) Markt u. Technik, Haar; ISBN: 3-82726-200-3; 24,95 €
Visual C++ - Das Kompendium
von Viktor Toth, Dirk Louis; Gebundene Ausgabe - 1261 Seiten (2000) Markt u. Technik, Haar; ISBN: 3-8272-5669-0; 49,95 €

Kommentar:
ist ein gutes Buch
Visual C++ für Dummies. Gegen den täglichen Frust mit Visual C++
von Michael Hyman, Bob Arnson; Taschenbuch - 444 Seiten (1999) MITP, Bonn; ISBN: 3-82662-862-4; 25,51 €; Einsteiger

Kommentar:
Hab ich selbst nicht gelesen, soll aber ganz gut sein
Visual C++ .NET for Dummies
von Michael Hyman, Bob Arnson; Taschenbuch - 432 Seiten (2001) John Wiley & Sons Inc.; ISBN: 0764508687; 28,06 €; Einsteiger

10.5  Windows-API [URL]

Verweise:

Windows Programmierung: Das Entwicklerhandbuch zur Win32-API
von Charles Petzold, Gebundene Ausgabe (1999) Microsoft Press, München; ISBN: 3-86063-487-9; 59,90 €

Kommentar:
Programmierung in reinem C mit Hilfe der API-Befehle.
Programming Applications for Microsoft Windows
von Jeffrey Richter. Gebundene Ausgabe - 1056 Seiten (September 1999) Microsoft Press; ISBN: 1-57231-996-8; 67,00 €

Kommentar:
Da lernst Du einiges über die WinAPI

10.6  MFC [URL]

Verweise:

Windows Programmierung mit MFC
von Jeff Prosise, Gebundene Ausgabe (1999) Microsoft Press, München; ISBN: 3-86063-434-8; ca. 65,96 €

Dieses Buch ist auch nicht mehr erhältlich. Jedoch auch gebraucht ist das Buch sein Geld wert. Die englische Version ist unter dem Titel Programming Windows With MFC lieferbar (Gebundene Ausgabe - 1376 Seiten (Mai 1999) Microsoft Press; ISBN: 1572316950; 65,34 €)

Kommentar:
Ich kann Buch nur empfehlen. Dafür sind C++ Kenntnisse erforderlich und werden vorausgesetzt.

Kommentar:
Der Preis ist frech, aber meiner Meinung nach lohnt es sich

Kommentar:
Es ist sehr lang (über 1200 Seiten), aber man findet einige Details und tiefergehende Informationen, die in anderen Büchern so ausführlich nicht behandelt werden. Im Prinzip stehen diese Informationen auch irgendwo in der MSDN. Aber das ist halt Geschmackssache, ob man so etwas in einem Buch am Stück lesen will, oder lieber die MSDN durchsucht. Die Beispiele sind sehr gut kommentiert.

Kommentar:
Ich finde das Buch sehr gut. Es geht auf Details ein, die in anderen Büchern fehlen, z. B. werden Makros entschlüsselt, statt sie einem nur um die Ohren zu hauen. Meiner Meinung nach ist es sowohl als Lehrbuch als auch als Nachschlagewerk zu benutzen.

Kommentar:
das Buch ist das Beste was ich am Markt entdecken konnte. Gibt auf viele Fragen antworten, wo andere Bücher schweigen.
Visual C++ 6.0. Windows-Programmierung mit den MFC (nicht mehr lieferbar)
von Frank Budszuhn, Thomas Reichel; Gebundene Ausgabe - 656 Seiten (1999) Addison-Wesley, München; ISBN: 3-82731-394-5; 39,95 €

Kommentar:
Das Buch ist für Anfänger bzw. als Einführung weniger geeignet.
Visual C++ - Programmierung mit den MFC (für V 6.0 und .NET)
von Frank Budszuhn; Gebundene Ausgabe - 690 Seiten (2002) Addison-Wesley, München; ISBN: 3-82731-869-6; 44,95 €
Using Visual C++ 6 (Special Edition)
von Kate Gregory Taschenbuch - 858 Seiten (August 1998) Que; ISBN: 0-78971-539-2; 37,42 €

Kommentar:
"Visual C++ 5 Special Edition" Und ich kann mich diesem Tipp nur anschließen. Den Strasser für C++ und die Gregory für die Windows-Programmierung mit den MFC.
Using Visual C++ .NET (Special Edition)
von Kate Gregory Taschenbuch - 784 Seiten (2002) Que; ISBN: 0-78972-466-9; 46,77 €
The MFC Answer Book, Solutions for effective Visual C++ Applications
von Eugène Kain; englisch; Taschenbuch - 704 Seiten (1999) Addison Wesley Publishing Company; ISBN: 0-20118-537-7; 46,77 €

Kommentar:
Der Inhalt des Buches befaßt sich mit Themen, die in Standardwerken selten vorkommen. So ist z.B. beschrieben, wie man einen UpdateCommandHandler in eine Dialog- und Formviewklasse einbaut. Kurz mit vielen Themen, die ständig in den Newgroups gefragt werden. Aus diesem Grund rechtfertigt sich auch der Preis.

10.7  STL und Templates [URL]

Verweise:

The C++ Standard Library
von Nicolai M. Josuttis; Gebundene Ausgabe - 912 Seiten (13. September 1999) Addison Wesley; 73,51 €

Kommentar:
Die STL Bibel schlechthin
C++ Templates
von David Vandervoorde und Nicolai M. Josuttis; Gebundene Ausgabe - 293 Seiten (1. November 2002) Addison Wesley; 51,45 €

Inhaltsverzeichnis


11  Wo gibt es weitere Informationen?

11.1  Deutschsprachige Visual C++ und C++ Newsgruppen [URL]

Verweise:

microsoft.public.de.vc
microsoft.public.de.german.entwickler.dotnet.vc
de.comp.lang.iso-c++
de.comp.os.ms-windows.programmer

Autoren:

Michael Krafzik, Albert Weinert , Alexander Sailer

11.2  Englischsprachige Visual C++ und C++ Newsgruppen [URL]

Verweise:

microsoft.public.vc
microsoft.public.vc.3rdparty
microsoft.public.vc.activex.templatelib
microsoft.public.vc.atl
microsoft.public.vc.database
microsoft.public.vc.debugger
microsoft.public.vc.etk
microsoft.public.vc.events
microsoft.public.vc.ide-general
microsoft.public.vc.language
microsoft.public.vc.online_help
microsoft.public.vc.project_mgt
microsoft.public.vc.res_editing
microsoft.public.vc.source_editing
microsoft.public.vc.stl
microsoft.public.vc.utilities
microsoft.public.vc.yellowpages
microsoft.public.dotnet.languages.vc
microsoft.public.dotnet.languages.vc.libraries
comp.lang.c++
comp.lang.c++.moderated

Autoren:

Michael Krafzik, Albert Weinert

11.3  Englischsprachige Visual C++ Newsgruppen - MFC [URL]

Verweise:

comp.os.ms-windows.programmer.tools.mfc
microsoft.public.vc.mfc
microsoft.public.vc.mfc.docview
microsoft.public.vc.mfcole

Autoren:

Michael Krafzik

11.4  Englischsprachige Visual C++ Newsgruppen - Macintosh [URL]

Verweise:

microsoft.public.vc.language.macintosh
microsoft.public.vc.mfc.macintosh

Autoren:

Michael Krafzik

11.5  Visual C++ Newsgruppen in anderen Sprachen [URL]

Verweise:

han.comp.devtools.vc++
microsoft.public.ae.arabic.vc
microsoft.public.es.vc
microsoft.public.fr.vc
microsoft.public.il.hebrew.vc
microsoft.public.kr.vc
microsoft.public.ru.vc
es.comp.lenguajes.c++
japan.comp.lang.visual-c++
it.comp.lang.c++
fr.comp.lang.c++

Autoren:

Michael Krafzik, Albert Weinert

11.6  Gibt es Online Kurse? [URL]

Ja, es gibt einige Tutorials. Unten finden sich direkte Links auf solche Kurse sowie weitere Links, die auf eine Zusammenstellung von Tutorials zum Thema C/C++ verweisen.

Verweise:

Einführungskurse in die C/C++ und MFC Programmierung
Einführung in MS VISUAL C++ (MFC)
Zusammenstellung von Tutorials zu C++
Zusammenstellung von Tutorials zu C

Autoren:

Albert Weinert, Carsten Witte

11.7  Gibt es weitere FAQs? [URL]

Ja, natürlich ist dies nicht die einzige FAQ zum Thema Visual C++

Verweise:

MFC FAQ
Die FAQ ist auch auf den MSDN-Medien in der Version 5.6 noch enthalten:

MSDN Library - October 2001
  Backgrounders
    Visual Tools
      Microsoft Visual C++
        Visual C++/MFC Frequently Asked Questions
MVP Visual C++ FAQ (Englisch)
Die FAQ der englischsprachigen VC MVP

Autoren:

Olivier Braun

11.8  Leitfaden zur Nutzung von MSDN [URL]

Carsten Witte hat ein HOWTO zur effizienten MSDN-Nutzung beigesteuert, welches insbesondere dem Anfänger nützliche Tips gibt, wie man an die gewünschten Informationen kommt.

Welche MSDN-Version mit welcher Entwicklungsumgebung kompatibel ist, kann hier nachgelesen werden.

Verweise:

HOWTO: Suchen und Finden im MSDN
Welche MSDN-Version läuft mit meiner Visual Studio Version?

Autoren:

Carsten Witte

Inhaltsverzeichnis


12  Tipps für die Newsgroups

12.1  Erst schauen, dann Fragen [URL]

Was vor dem Stellen einer Frage erwartet wird:

Weitere Quellen, die du evtl. nutzen könntest:

Es erwartet niemand, dass du alles von alleine findest, was in den o.a. Quellen steht. Du solltest aber bei einer Anfrage in der NG angeben, was du bereits versucht hast oder welche Quellen du erfolglos konsultiert hast. Selbst wenn du dabei etwas "Einfaches" übersehen haben solltest, wird dir keiner böse sein, weil du dir zumindest erkennbar Mühe gegeben hast.

Verweise:

Google-Groups durchsuchen
Microsoft Support Knowledge Base - Deutsch
MSDN: Library
Google: microsoft.public.de.vc

Autoren:

Karl Donaubauer, Albert Weinert

12.2  Betreff richtig verwenden [URL]

Ein richtig formulierter Betreff (subject) wird eher eine Antwort erhalten als z.B. ein genereller Schrei nach Hilfe oder ein Titel wie "Problem", "Anfänger". Der Betreff sollte kurz und informativ die Thematik deines Beitrages vermitteln. Ein Betreff, aus dem man das Thema erahnen kann, hilft v.a. auch beim Suchen in der langen Liste der Beiträge.

Autoren:

Karl Donaubauer

12.3  Unnötige Rückfragen vermeiden [URL]

Versuche präzise Angaben zu deinem Problem zu machen.
Damit ersparst du Antwort-Willigen lästige Rückfragen und bekommst eher passende Antworten.

Erwähne unbedingt die verwendete Visual-C++-Version in deinem Posting. Ebenso das Betriebssystem und andere Hard- oder Softwaredaten, die irgendeine Rolle im Zusammenhang mit dem Problem spielen könnten.

Wenn du von Visual C++ oder dem Betriebssystem eine Fehlermeldung bekommst, dann zitiere diese Meldung exakt in deiner Anfrage und gib auch die Fehlernummer an. Jedoch füge die Fehlermeldung nicht als Bildschirmkopie an.

Wenn du einen Fehler in deinem Quelltext vermutest, dann zitiere die in Frage kommenden Abschnitte im Text deiner Anfrage.

Schreib auch kurz dazu, welchen Kenntnisstand du im Zusammenhang mit der angefragten Thematik hast. z.B. ob du dich mit MFC, COM, DAO, OLE DB oder SQL gut auskennst oder nicht.

Autoren:

Karl Donaubauer

12.4  Nur 1 Thema pro Beitrag [URL]

Stelle pro Beitrag nur eine Frage oder mehrere verwandte Fragen zum selben Thema. Für Fragen zu einer anderen Thematik schreibe einen weiteren Beitrag.

Der Diskussionsfaden und die NG insgesamt ist dadurch übersichtlicher und effizienter.

Autoren:

Karl Donaubauer

12.5  Richtig zitieren [URL]

Bitte zitiere in deiner Antwort die wichtigen Teile des Beitrages, auf den du antwortest. Übernimm aber nicht einfach den Text der Frage zu 100% (machen die meisten Newsreader automatisch), sondern beschränke dich auf den Teil, der zum Verständnis der Antwort absolut notwendig ist. Das spart uns allen (Download-) Zeit und erhöht v.a. die Lesbarkeit. Wichtig ist das Zitieren auch deshalb, weil andere NG-Teilnehmer evtl. den Beitrag, auf den du antwortest, noch nicht oder nicht mehr sehen können

Verweise:

Wie zitiere ich im Usenet?

Autoren:

Karl Donaubauer

12.6  Frage und Antwort in der Newsgroup [URL]

Bitte frage nicht nach einer Antwort in Form einer Email und schicke keine Emails direkt an Leute, die an den NG-Diskussionen teilnehmen, außer es wird ausdrücklich so vereinbart. Viele Leute haben weder Zeit noch Lust, individuelle Fragen per Email zu beantworten. Zudem geht eine solche Diskussion für die Allgemeinheit verloren, entspricht also nicht dem Zweck der NGs.

Zum Abschluss einer Diskussion kann es sehr aufschlussreich für alle Mitlesenden sein, wenn du schreibst, ob die Sache geklappt hat und wie. Dies gilt insbesondere falls Du das Probleme mit einer mail Email geschickten Nachricht gelöst hast.

Autoren:

Karl Donaubauer

12.7  Realnamen verwenden [URL]

Verwende im 'von' deiner Beiträge deinen echten Vor- und Nachnamen, wenn nicht anders möglich einen Firmennamen und dann in der Signatur deinen vollen Namen.

'Lustige' oder 'coole' Pseudonyme sind in Chatrooms üblich, nicht aber in technischen Diskussionsforen. Viele Teilnehmer haben negative Erfahrungen mit Pseudonym-Nutzern.

Du wirst mit deinem Realnamen eher ernst genommen und für die anderen Teilnehmer ist es angenehmer und effizienter, da Leute in der Masse der Teilnehmer wiederzuerkennen sind.

Autoren:

Karl Donaubauer

12.8  Keine Dateien, HTML, Visitenkarten oder sonstiges [URL]

Die beiden Newsgrouppen sind - wie die meisten NGs - reine Text-Gruppen. Bitte schicke auf keinen Fall Dateien in diese Gruppen. Für Dateien gibt es eigene NGs wie z. B. de.alt.dateien.misc Du kannst Dateien dorthin schicken und in der Visual-C++-NG einen Hinweis darauf geben oder sie per Email an jemanden senden, der das ausdrücklich möchte.

Verwende auch bitte generell kein HTML in Newsgroups, sondern nur ASCII-Text. Es gibt viele Newsreader, die HTML nicht lesen können.

Ebenso sind angehängte Visitenkarten (vCards) in den NGs unbeliebt.

Verweise:

de.alt.dateien.misc

Autoren:

Karl Donaubauer

12.9  Warum kriege ich keine Antwort? [URL]

Das kann viele Ursachen haben.
Wichtig ist erst mal, dass du dir im Klaren darüber bist, dass NGs auf Freiwilligkeit beruhen. Keiner wird für eine Antwort bezahlt, du bezahlst nix für Antworten. Deshalb hast du keinerlei "Anspruch" auf eine Antwort.

Ein Grund für mangelnde Antworten kann sein, dass du diese Tips hier nicht beachtet hast, z.B. unverständlich formuliert hast, ein nichtssagendes Betreff verwendet hast etc. Geh dann diese Tips hier wie eine Checkliste durch und frage dich, ob du einen Fehler gemacht hast. Nach einigen Tagen des Wartens kannst du deine Frage (besser formuliert) noch einmal stellen.

Ein weiterer Grund kann sein, dass einfach niemand eine gute Antwort geben kann, weil dein Problem zu spezifisch oder schwierig ist. Weiter kann es noch an technischen Problemen im Internet liegen.

Autoren:

Karl Donaubauer

12.10  Abkürzungen, Emoticons und Smilies [URL]

In den Newsgroup werden oft Abkürzungen verwenden, ein ausührliche Auflistunge gibt es auf der Homepage von Carsten Witte.

Zu den Smilies gibt es auch eine Beschreibung im Internet

Verweise:

Smilies
Carsti's Kurzschlüsse

Autoren:

Albert Weinert

12.11  Was bedeutet eigentlich MVP? [URL]

MVP heist Most Valuable Professionals. Sprich die Newsgroupsteilnehmer mit dem besten Nährwert :). Das MVP-Programm ist eine Initiative von Microsoft die besonderes aktive, kompentete Newsgroupsteilnehmer auszeichnet! Der Titel wird von Microsoft verliehen. Weitere Informationen dazu gibt es auf der entsprechenden Internetseite.

Verweise:

Microsoft: Microsoft Most Valuable Professionals (MVPs)

Autoren:

Albert Weinert

12.12  Und warum soll ich mich an all' das halten? [URL]

Diese Frage ist vor lange Zeit schon in den Newsgroups beantwortet worden. Lest einfach selbst nach. Folgt dem Link!

Verweise:

Warum soll ich mich an die Regeln halten?

12.13  Die aktuelle Microsoft Netikette [URL]

Auch Microsoft hat sich Gedanken über die Netikette in den Newsgroups gemacht (s. nachfolgender Link).

Verweise:

Microsoft Netikette

12.14  Fragen erfolgreich stellen[URL]

Nachfolgend ein Link, der Tipps zum erfolgreichen Stellen von Fragen in Online-Medien gibt (leider nur in Englisch und Französisch).

Verweise:

Wie man Fragen richtig stellt
Tipps zum Fragen in Newsgroups (Englisch/Französisch)

Autoren:

Jens Geyer, Dieter Smode

Inhaltsverzeichnis


Impressum