Monthly Archives: October 2009

ListBoxItem Template…

Wir haben hier für die ListBox ein eigenes Template gemacht, dass eben alle ListBoxen bei uns in der Anwendung gleich aussehen… dabei haben wir einfach das Beispiel aus der MSDN verwendet: ListBoxItem ControlTemplate Example

Eigentlich sollte man ja meinen, dass dies Beispiel zumindest einigermaßen funktioniert… leider weit gefehlt…

Das Problem ist: Sobald wir ein eigenes DataTemplate für spezielle Daten gemacht haben, hat ein Klick auf ein Element nur dann reagiert, wenn entweder genau auf den Rahmen des Items geklickt wurde oder genau auf den Text:
ListBoxItem

Es ist also relativ schwer z.B. das “!” genau zu treffen…wir haben ewig gesucht, bis wir endlich den Grund gefunden haben… (dank Franks Unterstützung haben wir es mittels Snoop und der Event-Ansicht gefunden): Der Border in dem ControlTemplate hat keine Hintergundfarbe. Somit ist der Border “durchsichtig” (bzw. “x:Null”), was dazu führt, dass ein Klick auf den Border nicht vom Border verarbeitet wird, sondern vom darunterliegenden Scroll-Container… und der macht natürlich hier nichts damit…
Hier ist auch ein Beispielprojekt (VS2008), damit man es mal selber probieren kann.

Für uns jetzt mal die Lösung: Wir setzen einfach die Hintergrundfarbe des Borders des ControlTemplates auf “Transparent”, dann wirken sich jetzt überall die Klicks auf die ListBox aus… danke an Hendrik für diesen Hinweis!

VS2010 Beta 2 – jetzt öffentlich verfügbar!

Seit einigen Tagen konnte ja schon MSDN Abonenten die Beta von Visual Studio 2010 runterladen. Ab sofort ist es auch als öffentlichen Download verfügbar:
Microsoft Visual Studio 2010 Ultimate Beta 2 – ISO

Und wer sich gleich noch über die Neuerungen in der MFC informieren will (ja die gibt es!), kann sich hier ein Video anschauen:
Pat Brenner: Visual Studio 2010 – MFC and Windows 7

vcredist für VS2008 – ATL security update

Wer unbedingt gegen die DLL-Version der CRT/MFC linken will/muss, der steht seit dem ATL-Security-Update vor dem Problem, dass neu übersetze Projekte jetzt zwangsläufig die neue CRT-Version im Manifest eingetragen hat. Dieses verhalten wurde von MS einfach so eingeführt, ohne dies zu kommunizieren. Dies hat natürlich zu etwas Kritik geführt. Aber “Security” rechtfertigt ja alles.
Bisher wurde nach einem Update von VS2008 (also z.B. durch das Feature-Pack oder durch den SP1) im Manifest immer noch die Versionsnummer der RTM-Version eingetragen. Deshalb war es auch jetzt sehr verwirrend, dass plötzlich eine neue Version eingetragen wird, ohne dass man irgend etwas am Projekt geändert hat. Bisher war es nötig, dass man als Define ein “_BIND_TO_CURRENT_CRT_VERSION=1” setzt. Erst dann wurde die aktuelle auf dem Enticklungsrechner verwendete Version eingetragen.

Aber nun ist es nunmal anders und wir sind entweder gezwungen das Security-Update von VS2008 nicht einzuspielen (was ich aktuell als einzige Lösung hier im Automatisierungs-Bereich habe, wenn man auch alte Systeme updaten muss) oder auf neuen Systemen das passende vcredist zu installieren.

Update (2011-04-13): Es gibt schon wieder ein Hotfix:
Siehe: MS11-025: Description of the security update for Visual C++ 2008 SP1 Redistributable Package: April 12, 2011
Update (2011-06-11): Es gibt schon wieder ein Hotfix:
Siehe: MS11-025: Description of the security update for Visual C++ 2008 SP1 Redistributable Package: June 14, 2011

Nur jetzt ist wieder die Frage: Welches ist denn nun die “richtige” vcredist…
Hier die Auflistung der aktuell verfügbaren Versionen:

Wer ganz sicher gehen will, der sollte ab sofort nur noch das oberste installieren!

CurrentItem einer ObservableCollection ermitteln/ändern

In letzter Zeit mach ich mehr mit WPF rum. Hierbei spielt ja das MVVM-Pattern eine große Rolle. Darin werden für änderbare Listen oft eine “ObservableCollection” verwendet. Diese informiert alle beteiligten darüber, wenn ein Element gelöscht oder hinzugefügt wurde. Auch unterstützt es dabei das Feature eines “CurrentItems”. Nur konnte ich dieses bisher nie über irgendwelche Methoden aus dem View-Model heraus ansprechen… immer nur durch WPF-Elemente war dies möglich. So hat z.B. eine ListBox das Property “IsSyncronizedWithCurrentItem“. Damit werden Änderungen am “CurrentItem” durch andere Controls (z.B. durch andere ListBoxen) automatisch auch in alle “angeschlossenen” übernommen.
Nur aus meinem ViewModel war es mir noch nicht gelungen das “CurrentItem” zu setzen (z.B. nach Button-Klick), da ich keine Methode oder Property finden könnte.
Jetzt hab ich es endlich gefunden wie man auf das “CurrentItem” zugreift: Man muss sich zuerst die “DefaultView” der Collection holen. Dann kann man auch die Position des aktuelle Items ändern.
z.B. um das “CurrentItem” zu setzen:

var dv = CollectionViewSource.GetDefaultView(viewModel.MeineCollection);
dv.MoveCurrentTo(viewModel.MeineCollection[1]);

oder um das CurrentItem auszulesen:

var dv = CollectionViewSource.GetDefaultView(this.List);
MessageBox.Show(dv.CurrentItem.ToString());

Hier gibt es auch ein kleines Beispielprojekt: WPF_CurrentItem.zip

Windows 7 installiert…

Nachdem ich auf meinen Wohnzimmer-Rechner schon vor einigen Wochen von Mac OSX auf Windows 7 Ultimate umgestiegen bin, hab ich das ganze vor zwei Tagen auf mit meinem Hauptrechner gemacht. Hier hatte ich vorher Vista 64 Ultimate drauf. Da ich mit der Partitionierung nicht ganz zufrieden war, hab ich mich entschieden alles neu zu installieren und das Ding ganz Platt zu machen.
Zuerst habe ich mit Acronis TrueImage Home 2010 eine Sicherung gemacht und dann die Windows 7 Ultimate x64 installation gestartet. Ich muss sagen: Die Installation hat ca. 25 min. gedauert und er hat alle Hardware in meinem Rechner erkannt (RAID, Soundekarte (die kannte Vista nicht), usw.).

Alles im allem muss ich sagen, dass ich sehr zufrieden bin. Leider musste ich dann natürlich wieder alles installieren, was man so braucht… und die Daten wieder rüberkopieren.

Also, ich kann es nur empfehlen auf Windows 7 umzusteigen. Es macht einen schönen und performanten Eindruck.

Jetzt dürft ihr auch gerne zu meiner Windows 7 HouseParty kommen 😉

GetWindowText und WM_GETTEXT

Es soll ja tatsächlich Leute geben, die den Unterschied der beiden Funktionsweisen noch nicht kennen. Liest man die MSDN-Dokumentation, so kann man erkennen, dass GetWindowText nur zuverlässig für den eigenen Prozess funktioniert. Die Begründung findet man dann bei “The Old New Thing“.

Und damit es jeder auch selber nachvollziehen kann, dass GetWindowText wirklicht nicht zuverlässig für andere Prozesse geht, hab ich hier ein kleines Beispielprogramm:
http://blog.kalmbachnet.de/files/GetWindowText.zip

Wie man aus dem verwiesenen Blog-Eintrag erkennen kann, verwendet intern “GetWindowText” nur WM_GETTEXT, wenn es ein Fenster im eigenen Prozess ist. Sonst wird ein “secret-buffer” verwendet. Ein WM_GETTEXT wird nicht gesendet!

Die ZIP-Datei besteht aus zwei Projekten (Release-EXEn liegen auch drin, damit man es nicht mal mehr selber übersetzen muss).
1. TargetApp: Dieses Wizard erzeugte Fenster-Programm verarbeitet selber die WM_GETTEXT Message und gibt als String “Booga!” zurück. Durch Aufruf von “Help|About…” kann man nachweisen, dass “GetWindowText” hier den String “Booga!” zurück gibt. Es verwendet also WM_GETTEXT um den Text zu erhalten.

2. SpyApp: Dieses Wizard erzeugte Fenster-Programm mach nach Aufruf von “Help|About…”: Es ermittelt das Fenster-Handle des TargetApp durch den Klassennamen (TARGETAPP). Dann kommt der eigentlich Aufruf zu “GetWindowText”. Der zurückgegebene Text wird dann in einer MessageBox angezeigt.

Und dreimal dürft Ihr Raten, was das für ein Text ist 😉 (nein, es ist nicht “Booga!”).

PS: Auch durch den Aufruf von diversen anderen Funktionen wie AttachThreadInput und GetFocus ändert sich an dem verhalten nichts, dass GetWindowText nicht WM_GETTEXT verwendet.

PPS: Wer sich für den Auslöser dieses Posting interessiert, der kann es hier nachlesen:
aktives Control ermitteln
Dort behauptet der Poster, dass “GetWindowText” intern WM_GETTEXT sendet. Und das stimmt natürlich nur für den eigenen Prozess, nicht aber für externe (in diesem Thread geht es nur um externe Prozesse).

[ADD: 2009-10-11]
PPPS: Wer sich wundert, warum im Source-Code der SpyApp sowas komisches wie “AttachThreadInput” aufgerufen wird, der sollte einfach nur den obigen Thread lesen… dieser Aufruf ist einfach sinnlos und kann getrost entfernt werden; ein anderer behauptet in dem Thread, dass es “unbedingt notwendig” ist, damit das “GetWindowText” intern ein WM_GETTEXT verwendet (was es ja für externe Prozesse nicht tut, wie das Beispiel ja schön zeigt).