Thursday, 15. September 2005Splash screen
Heute möchte ich die Programmierung eines Splash-screens unter WIN32 näher beleuchten.
Kennt sicher jeder: Die schönen Grafiken, die während des Ladeprozesses eines Programms am Schirm erscheinen, z.B. beim Starten von Visual Studio. Im Prinzip handelt es sich hierbei einfach um ein TOPMOST - Fenster, welches eine Grafik beinhaltet, auf der idealerweise auch dynamisch die Versionsinformation über das Programm angezeigt wird. Die Grafik wird beim Starten entweder nach dem Ladevorgang oder nach einer festgelegten Zeitspanne (z.B. 2 Sekunden) ausgeblendet. Wie geht man sowas nun an? Grundsätzlich muss man die WM_PAINT Nachricht eines neuen, leeren Fensters dispatchen. Dieses Fenster wird in der Größe nun an die Größe des zu ladenden Splash-screen Bitmaps angepasst (im unteren Beispiel befindet sich das in der Ressourcen als IDB_SPLASH ) und das Fenster anschließend zentriert.Nun kopiert man das Bitmap in den DC des Fensters. So weit, so gut! Nun wäre es aber noch interessant die Versionsinformationen auszugeben. Hierzu kann man ja praktischerweise gleich meine QueryResource - Klasse verwenden. Zuerst muss nun der Font und die Schriftgröße, sowie die Schriftfarbe bestimmt werden. Anschließend wird der Text an die angegebene Position innerhalb des Bitmaps gezeichnet. Das war's im Prinzip mit dem Zeichnen. Nun sollte man noch dafür sorgen, dass der Splashscreen bei entsprechenden Aktionen verschwindet, z.B. beim Klicken oder nach Ablauf einer bestimmten Zeit. Um den Splashscreen nach einer bestimmten Zeitspanne verschwinden zu lassen, installiert man am Besten einen Timer in der Initialisierungsroutine des Fensters ( WM_CREATE ) mittels der SetTimer Funktion.Idealerweise lassen wir den Aufrufer der Dialoprozedur selbst das Timeout angeben. Der an die Dialogbox übergebene Wert befindet sich bei einem Standard-Fenster innerhalb der in lParam übergebenen Struktur CREATESTRUCT und zwar im Member lpCreateParams .Dieser Parameter wird als letzter Parameter beim Erstellen des Fensters der CreateWindowEx - Funktion übergeben.Beim Erstellen des Fensters macht es Sinn, den Flag WS_EX_TOPMOST als Windowstyle anzugeben, damit das Fenster zu oberst erscheint.Im untenstehenden Codeschnipsel befindet sich nun eine fertige, von mir entwickelte Splash-screen Lösung. Ich habe alle Stellen im Code mit dem Kommentar EDITME gekennzeichnet, welche entsprechend angepasst gehören, um die Routine für seine eigenen Zwecke weiterverwenden zu können. Außerdem wird hier meine QueryResource - Klasse zum Auslesen der Versionsinfos verwendet, diese wird als ggf. auch benötigt.Ansonsten: Viel Spaß damit! Wenn's Fragen dazu geben sollte, einfach als Kommentar posten Sunday, 11. September 2005Autorun von Webseiten
Eine häufige Problemstellung: Man stellt eine WerbeCD zusammen mit Seiten im HTML-Format zur bequemen Navigation.
Nun möchte man auch gleich eine passende Autorun-Funktion dafür haben. Autorun dürfte Jedem bekannt sein: Einfach eine autorun.inf - Datei anlegen und dort einen kleinen Dreizeiler reinschreiben:
Die erste Idee, die Einem in den Sinn kommt, ist, warum nicht einfach die Startseite beim open= angeben? Also z.B.: open=index.htm Der Windows 2000+ Benutzer wird er ausprobieren und zufrieden lächeln - Funktioniert! Tja, aaaaber leider erst ab den Shell Common Controls 5.0, also erst ab Win2k. Besitzen von Win 9x/NT 4 kommen nicht in den Genuss eines praktischen Autostarts. Um auch diese OS-Versionen zu unterstützen braucht man also einen kleinen launcher, der die angegebene HTML-Seite im Standard-Browser startet. Hierfür gibt es im Internet diverse Freeware-Applikationen, die sich aber für kommerzielle Massen-Distribution aufgrund der verwendeten Lizenz evtl. nicht eignen. Aus diesem Grund starten wir mal wieder VC++ und basteln uns kurzerhand unseren eigenen Starter, den wir dann nach Belieben verwenden können: Der Grundansatz ist, einfach zu prüfen, mit welchem Startprogramm die übergebene Datei verknüft ist, und dieses wird dann mit Datei+Pfad als Parameter gestartet. Dieses Konzept hat auch noch den Vorteil, dass unsere kleine Applikation universell einsetzbar ist für alle Dateitypen, nicht nur .html Dateien. Wenn man das nachstehende Programm kompiliert sollte man mittels geeignetem Makefile eine 16k kleine .exe erhalten. Diese würde sich mit UPX oder anderen EXEpackern auf ~3k herunterkomprimieren lassen, allerdings wird das dann lizenztechnisch wieder problematisch.. Genug geschwafelt, hier ist das kleine Programm: Es nimmt als Parameter ein zu strtendes file. Wird nichts übergeben, wird versucht, die index.html zu starten. Friday, 9. September 2005Minimalgröße eines Fensters setzen
Wenn man einen resizable Dialog erstellt, dann ist man natürlich daran interessiert,
dass sich die Dialog-Controls entsprechend an die aktuelle Fenstergröße anpassen und der neu entstehende Raum im Dialogfeld nicht ungenutzt bleibt. Dummerweise ist dies garnicht so einfach, da es von der WIN32-API nativ keine Docking bzw. Anchoring-Unterstützung gibt. Man muss einfach die WM_SIZE Nachricht dispatchen und dort die controls (=child windows) entsprechend neu zeichnen. Dies ist insofern ärgerlich, als dass es eine ziemliche Herumfitzelei ist, und sobald man etwas am Form-design ändert, funktioniert der Code möglicherweise schon nicht mehr. Daher haben sich einige Programmierer daran gemacht, Klassen zur Lösung dieses Problems zu schreiben. Dummerweise sind die meisten erhältlichen Klassen aber für die MFCs. Wenn man diesen Ballast aber nicht mit seiner Applikation herumschleppen möchte, und sich ohnehin, wie ich etwa, nicht so recht mit der etwas chaotischen MFC anfreunden mag, sucht man relativ lange, bis man etwas Brauchbares findet. Ich bin beim Stöbern im Netz auf eine brauchbare Klasse gestoßen, die klein, aber trotzdem praktisch und einfach aufgebaut ist. Grundsätzlich werden darin zwar auch MFC Debug-Makros verwendet, aber die kann man ja ohne Bedenken löschen. Sonst funktioniert die Klasse eigentlich problemlos mit plain-WIN32. Hier ist sie:http://www.codeguru.com/Cpp/W-D/dislog/resizabledialogs/article.php/c5001/ Ich habe sie übrigens selbst für mich auch noch etwas optimiert, damit das Flackern beim Resizen nicht ganz so stark ist. Der Trick besteht darin, statt SetWindowPos lieber die Funktion DeferWindowPos zu verwenden. Für nähere Erläuterungen zur Funktionsweise mitte dem Link zur MSDN folgen.Wenn man nun die Controls entsprechend dockt, bleibt immer noch das Problem, dass man die Form kleiner machen kann, als sie in ihrem Initialzustand war, und das sieht dann doch ziemlich merkwürdig aus, wenn die Controls gegenseitig überlappen. Daher sollte man idealerweise die Fensterminimalgröße auf die Anfangsgröße limitieren. Damit man diese nicht hartcodieren muss, bedient man sich einfach einer static-Variable, die den Initialzustand des Fensters speichert, somit ist man auch hier flexibel. Hier mein Code hierfür: Wednesday, 7. September 2005Size grip in Fenstern
Heute gibt's einen Artikel über die Lösung eines eigentlich trivialen Problems:
Seit Win2k, wenn ich richtig informiert bin, gibt es ja die Möglichkeit, einen sg. "size grip" in der unteren, rechten Ecke eines Fensters anzuzeigen, um zu verdeutlichen, dass es sich dort schön resizen lässt. Das schaut nett aus und vergrößert auch etwas die Fläche, in der der Maus-cursor zum Resize-cursor wird. Seinen eigenen Fenstern diesen Style zu geben ist aber garnicht so trivial.. Im Prinzip müssen v.A. 3 Dinge beachtet werden: 1) Das Ding gehört gezeichnet. Dies wird in WM_PAINT erledigt.2) Beim Ändern der Fenstergröße muss der Grip auch gelöscht werden, damit er beim neu zeichnen nicht "verschmiert". Das erledigen wir in WM_SIZING , also noch, bevor die Größenänderung passiert ist.3) Dem Grip muss auch eine Funktionalität zugeordnet werden, sodass der Cursor entsprechend zum Resize-cursor wird, wenn sich die Maus auf dem Grip befindet. Hierfür tracen wir das Maus-Event in WM_NCHITTEST Beim Zeichnen des Grips muss zusätzlich darauf geachtet werden, dass dieser im maximierten Fensterzustand nicht gezeichnert wird. Ich habe in folgendem Codeschnipsel die oben genannten Punkte zusammengefasst, wie man sie in der Window-Dispatcherroutine zu behandeln hat, um den gewünschten Effekt zu erzielen. Viel Spaß! UTF8 - Decoding unter WIN32
Heute gibt es mal eine Lösung zu einem relativ trivialen Problem, welches aber oft unnötigerweise durch Zuhilfenahme zusätzlicher, externer Bibliotheken gelöst wird:
Die UTF-8 Konvertierung. Windows verwaltet intern alles durch seine wchars, welche 16bit zur Darstellung eines Zeichens benötigen. Die Konvertierung von UTF-8 in die derzeit benutzte system-locale führt daher auch über WideChars: Zuer konvertiert man mit MultiByteToWideChar UTF-8 auf wchar und anschließend mittels WideCharToMultiByte auf die aktuelle locale. Mit dieser Kombination lassen sich natürlich auch andere Zeichensätze bequem konvertieren. Im Folgenden eine kleine C++ Beispielfunktion, die einen basic_string UTF8-decodiert. In C funktioniert's natürlich dementsprechend noch einfacher, das kann sich aber dann ohnehin Jeder selbst basteln: Saturday, 3. September 2005Versionsinformationen auslesen
Oft implementiert man in seine Applikation einen About-Dialog, in dem man sich nicht nur selbst verewigt, sondern auch die Programmversion usw. anzeigt.
Hardcodet man nun diese Information, so hat man hier unnötige Doppelgleisigkeiten, da man die Versionsnummer normalerweise ja schon in der Versioninfo-Resource angibt. Bei einem Programmupdate müsste man dann immer 2 Werte ändern, was man häufig vergisst. Die Idee ist daher naheliegend, dass man sich für seinen About-Dialog gleich die Versionsinformationen aus der Versioninfo-Resource extrahiert. Unglücklicherweise ist dies weniger trivial, als man viell. ursprünglich annehmen möchte. Generell sollte man sich hierfür die Hilfe zur VerQueryValue-Funktion ansehen. Hier sind auch die Strings beschrieben, die man aus der Versioninfo auslesen kann. Nachdem für die Benutzung dieser Funktion jedoch einige Vorarbeiten notwendig sind, ist es praktisch, die Versionsabfrage in eine Klasse zu kapseln, welche im Konstruktor die Extraktion der Resourcen zur weiteren Verwendung durch VerQueryValue übernimmt und im Destruktor den Speicher wieder frei gibt.Ich habe daher eine kleine Klasse implementiert, die diese Aufgabe übernimmt: Diese lässt sich relativ bequem dann in der Window-Procedure the About-Dialogs einsetzen:
(Seite 1 von 1, insgesamt 6 Einträge)
|
SucheBlog abonnierenTop ReferrerVerwaltung des Blog |