Das verschollene Scribble Tutorial…

Immer wieder merke ich, dass man bei vielen Anfragen in den Foren auf den Klassiker verweisen müsste:
Das Scribble Tutorial.

Dieses Tutorial ist offiziell über die MSDN Suche im Internet nicht mehr zu finden. Egal wie man auf den MS-Seiten sucht. Interessant ist, dass es noch genug KB-Artikel gibt die auf dieses Tutorial verweisen. Der Sample Code ist noch vorhanden. Nur das Tutorial ist nicht einfach zu finden.

Aber es existiert noch in einem Ast der MSDN, die die VC++ 6.0 Dokumentation beinhaltet.:
http://msdn2.microsoft.com/en-us/library/aa716528(VS.60).aspx

Leider ist dieser Ast mit der globalen Suchfunktion nicht erreichbar und auch nicht entsprechend indiziert.
Meiner Meinung nach, hätte dieses Tutorial schon längst angepasst werden müssen, weil sich die Wizards komplett seit VS.NET 2002 geändert haben.

BTW: Leider befürchte ich, dass auch dieser VC++ 6.0 Ast der MSDN irgendwann verschwinden wird.

VS-Tipps & Tricks: Gruppieren von Tastaturbefehlen

Als Entwickler hat man schon viele Tastaturkürzel im Kopf. Viele sind jedoch nicht vordefiniert, also denkt man sich was eigenes aus. Dennoch gibt es Befehle, die man nicht so häufig benutzt und gerne auf der Tastatur ausführen möchte. Man vergisst dennoch, das Kürzel oder sogar wo man einfach den Menübefehl findet.

Oft ging es mir so, mit den Befehlen aus Visual Source Safe. Irgendwann habe ich für alle VSS-Befehle dann mal Kürzel angelegt. Aber keine 1 Tastenbefehle, sondern eine Sequenz.
Alle VSS-Befehle fangen bei mir mit Alt+V an. Dann folgt simpel und einfach der Befehl den ich VSS geben möchte:

  • Alt+V, O – Check out
  • Alt+V, I – Check in
  • Alt+V, H – Show history
  • Alt+V, E – Start VSS Explorer
  • Alt+V, U – Undo Checkout
  • Alt+V, G – Get lastest version
  • Alt+V, P – Show properties

So habe ich mit bestimmten Tastatursequenzen mir bestimmte Aufgabengruppen geschaffen, die einfach mit der ersten Sequenz die Gruppe definiert und mit der zweiten Taste, sinnvoll und einfach den Befehl auslöst. Die Lernphase ist extrem niedrig und man behält hunderte von Sequenzen im Kopf, weil man einfach weiß was man machen will.

Gleiches lohnt sich mit vielen netten Features aus Visual Assist (bei mir Alt+A) Gruppe. Oder auch für den Dialogeditor, dem man einfach bestehende Befehle einfachere und zusätzliche Tastaturkürzel gibt. Oder man erzeugt sich eine Gruppe von erweiterten Navigationsbefehlen (nächste Block, nächste Funktion etc.). Die Outlining Befehle sind ja schon unter Strg+M zusammengefasst, allerdings finde ich hier die Assoziationen für den zweiten Buchstaben nicht ganz so gut.
Es gibt noch viele wirklich gute Funktionen im Editor des Visual Studios, leider sind viele unerreichbar, weil die Tastaturbefehle abstrus sind oder gar nicht definiert sind. Es lohnt sich hier selbst auf Erkundungstour zu gehen.

SetFocus versus WM_NEXTDLGCTL

Die meisten Entwickler verwenden SetFocus um in einem Dialog gezielt den Eingabefokus zu versetzen. Aber es gibt ein Problem, dem SetFocus nicht gerecht wird: der Default Button.
Der Default Button wird durch WM_SETDEFID bzw. CDialog::SetDefID gesetzt. SetFocus berücksicht das interne Konzept des Default Buttons nicht.

Wenn man mit der Tab-Taste durch einen Dialog springt und einen Button erwischt, dann wird dieser automatisch zum Default Button. Normalerweise ist das der OK-Schalter, er verliert dann den dicken Rahmen. Drückt man die Eingabe-Taste, dann wird nun der neue Schalter ausgelöst und nicht der OK-Schalter.
Landet der Fokus von einem Button dann bei einem Edit Control, dann wird der OK-Schalter wieder der Default Button und man kann mit der Eingabe-Taste den Dialog beenden.

Wenn nun SetFocus verwendet wird durch eine interne Funktion, dann wird dieser Mechanismus des Dialoges umgangen. Der Default-Button wird evtl. nicht korrekt gesetzt. Es kann sogar soweit kommen, dass es zwei Default-Schalter oder gar keinen mehr gibt. SetFocus führt immer zu Problemen wenn das neue Control oder das bisherige Control, welches den Fokus hatte, ein Button ist. Nur wenn beide Controls keine Button sind kann SetFocus gefahrlos verwendet werden.

Korrekt funktioniert das Ganze nur, wenn statt SetFocus, WM_NEXTDLGCTL verwendet wird, oder die entsprechenden MFC Funktionen, CDialog::NextDlgCtrl bzw. CDialog::GotoDlgCtrl verwendet werden.
Die Nachricht WM_NEXTDLGCTL wird auch intern durch die DefDialogProc behandelt und normalerweise durch IsDialogMessage erzeugt.
Gefahrlos ist auch die Verwendung von SetFocus in WM_INITDIALOG bzw. CDialog::OnInitDialog Handlern, die dann normalerweise mit FALSE, verlassen werden. Nach dieser Funktion sorgt der Dialog Handler, für die korrekte Behandlung der Default Buttons.

Fazit: Man sollte also innerhalb von Dialogen ganz auf SetFocus verzichten sondern nur WM_NEXTDLGCTL  bzw.  CDialog::NextDlgCtrl und CDialog::GotoDlgCtrl verwenden. Konsequenterweise sollte man dann auch in OnInitDialog Handlern auf SetFocus verzichten. ❗

Besonderheiten bei der Ausgabe über Excel via ODBC

Man sollte tunlichst darauf achten, dass bei Excel Export über ODBC alle Spalten mit einem möglichst exakten Datentyp erzeugt werden. D.h. der Faulheit halber sollte man nicht jede Spalte mit dem Typ TEXT erzeugen, sondern eben DOUBLE, NUMERIC, BIT, DATETIME etc. verwenden, die Excel auch unterstützt. In diesem Fall werden nur die TEXT-Daten mit einem Apostroph versehen. (siehe dieser Blogbeitrag)

Lästig ist, dass Excel es nicht schafft DATETIME, DATE und TIME Spalten standardmäßig auch korrekt anzuzeigen. DATETIME-Spalten werden zwar korrekt mit Datum und Uhrzeit befüllt. Das Anzeigeformat wird aber so dämlich gewählt, dass nur das Datum sichtbar ist. Für DATE-Spalten geht das in Ordnung. Bei TIME-Spalten wird sogar noch einfach das Tagesdatum „hinzugedacht“, obwohl nur der Zeitwert übertragen wurde. D.h. man sieht ein Tagesdatum aber nicht die Zeit. Die Zeit wird nur sichtbar beim Ändern des Formtes der Zellen, oder wenn man die Daten einzeln anklickt und in der Bearbeitungsleiste betrachtet.

Trickreich ist auch die Ausgabe in ein DATETIME Feld, wenn man ein Textfeld bindet. In diesem Fall muss zwingend das Format JJJJ-MM-TT für die Ausgabe verwendet werden.

Ein weitere Trick besteht darin, die Spalten zusätzlich mit der Option NULL anzulegen:
CREATE TABLE [Data] ([Field1] TEXT NULL, [Field2] DOUBLE NULL)
andernfalls braucht man sich nicht wundern, wenn es eine Exception gibt beim Speichern eines leeren Strings.

Wann Message Reflection nicht funktioniert!

TN062: Message Reflection for Windows Controls beschreibt die vielen schönen Möglichkeiten der Message Reflection.

Aber es gibt eine wichtige Voraussetzung, dass da ganze funktioniert:
Das Parent Window muss auch ein Fenster sein, das mit der MFC erzeugt wurde, oder durch die MFC gesubclassed sein.

Die Reflektion geschieht immer nur durch das Parent Fenster. Wenn dort also eine WM_CTLCOLOR Nachricht das Parent erreicht, dann wird die Nachricht an das Fenster, dass es gesendet weitergeleitet, wenn es eben über einen entsprechenden Reflektion Eintrag für WM_CTLCOLOR verfügt. Das ganze wird erledigt durch die Funktion CWnd::ReflectLastMessage, die die entsprechenden Funktion  CWnd::SendChildNotifyLastMsg im eigentlichen Control wieder aufruft. Diese Funktion ruft wiederum CWnd::OnChildNotify auf, die dann die Reflection Einträge in der Message Map sucht. Ist das Parent nun kein MFC Fenster kann auch niemand die Nachrichten an das sende Fenster zurückleiten.

Hat man also ein Fenster hat, dass durch pure Win32 API Funktionen erzeugt wurde und auch nicht durch die MFC gesubclassed wurde und in diesem Fenster wird ein MFC Fenster als Child erzeugt, dann erreichen dieses Child keine Nachrichten durch die Reflektion.

Eigentümliche Quotes beim Erzeugen einer Excel Datei mit ODBC

Eigentümlicher Effekt:
Ich erzeuge eine Excel Tabelle mit ODBC. Dann füge ich einige Zeilen in die Tabelle ein.

Wenn ich diese Tabelle mit Excel öffne sieht alles gut aus.
Betrachte ich die einzelnen Zellen jedoch näher, dann erscheint in der Bearbeitungsleiste für den Wert der Zelle immer ein zusätzliches einzelnes Anführungszeichen ‚ vor jeder Zelle. Die Zellen werden jedoch in der Ansicht korrekt angezeigt und auch in Formeln korrekt verwendet.

Ich binde die Daten ganz normal mit RFX_Text. Und der nColumnType wurde als Default-Wert mit SQL_VARCHAR angegeben.

Nach dem Lesen von einigen Artikeln bin ich letzten Endes darauf gekommen, dass dieses führende Quote ein internes Zeichen für Excel ist, dass es sich um eine Textzelle handelt.
Die Spaltenwerte werden ganz normal und korrekt weiterhin angezeigt.
Es scheint so, dass man das Ganze ignorieren kann. 😕

Siehe auch diesen guten Beitrag, der viele nützliche Excel Links bzgl. Automation und ADO enthält: http://groups.google.de/group/microsoft.public.vb.database.ado/browse_frm/thread/c3504ad88cc713ce

VS-Tipps & Tricks: Schnelles Navigieren im Class View

Wenn man in Dialogen und Klassen über den Class View Variablen oder Funktionen hinzufügen will, dann ist dies oft mit mühsamen Rollen und suchen der Funktionen und Klassen verbunden.
Ganz besonders wenn man auch noch viele Namespaces verwendet.

Es gibt eine Funktion, der normalerweise kein Hotkey zugeordnet ist: View.SynchronizeClassView.

Der Name deutet es ja schon an, der Class View wird mit dem aktuellen Kontext synchronisiert.  Am Besten man weißt dieser Funktionen eine guten Hotkey zu und probiert die Funktion aus. Ich verwende hier Alt+A, S.

Diese Funktion zeigt den Class View an (auch wenn diese Tab-Seite aktuelle nicht aktiv ist), weiterhin wird sofort die aktuelle Klasse oder Funktion im Class View angezeigt, in dessen Kontext man sich aktuell befindet. Längeres Navigieren erübrigt sich.