Wednesday, 1. March 2006Defekte Windows 2k Registry reparieren
Ab und zu kann es vorkommen, dass die Registry beschädigt wird. Erkennen tut man dies beim Start von Windows an einer Fehlermeldung, die besagt, dass eine der Dateien in
%SYSTEMROOT%\SYSTEM32\CONFIG beschädigt ist, z.B. C:\WINNT\SYSTEM32\CONFIG\SYSTEM In diesem Fall wird empfohlen, die Reperaturkonsole zu verwenden, um die beschädigte Registrierung von der Notfalldiskette oder aus der letzen Sicherung wiederherzustellen. Meistens hat man jedoch keine aktuelle Sicherung parat und die letzte als funktionierend bekannte Konfiguration funktioniert genausowenig. In diesem Fall kann man eigentlich nur noch die ursprüngliche Registry aus dem %SYSTEMROOT%\REPAIR - Verzeichnis wiederherstellen. Danach hat man jedoch meist die Registry vom Zeitpunkt der Windows-Installation und damit kommt diese Aktion einem neu aufsetzen gleich, denn die ganzen Anwendungen gehören alle neu installiert und überhaupt.. In diesem Fall kann man gleich neu aufsetzen. Diese Lösung eignet sich bestenfalls noch dazu, das System wieder in Gang zu bringen, um noch eventuelle Daten sichern zu können.Was man also brauchen würde ist ein Programm, welches die Konsistenz der Registry überprüft und diese gegebenenfalls repariert, also etwas wie chkdsk , nur für die Registry.Microsoft hat tatsächlich so ein Tool geschrieben, welches, wie ich heute festgestellt habe, durchaus gute Dienste leistet. Es nennt sich bezeichnenderweise chkreg.exe und kann hier von Microsoft bezogen werden. Allerdings benötigt man hierfür wieder den Genuine Advantage-Schwachsinn, was einfach nur nervt. Daher besser gleich von hier direkt herunterladen.Das Tool wurde mittels der Native API entwickelt und benötigt daher einen laufenden NT-Kernel, damit es eingesetzt werden kann. Um das Tool auf einem druch eine zerstörte Registry nicht lauffähigen System laufen zu lassen, benötigt man daher den Windows Setup-Diskettensatz, um einen lauffähigen NT-Kernel als Basis zu haben. Also: Setup-Diskettensatz herunterladen, 6 Disketten erstellen, chkreg.exe herunterladen, starten und vom Installscript auf Diskette 6 des Installationsdiskettensatzes schreiben lassen und danach mit den Setup-Disketten booten. Am Setup-Schirm mit der Frage, ob Windows installiert werden soll, oder ob man eine bestehende Installation [R]eparieren will, R drücken und über das zu reparierende System rennen lassen. Danach sollte die Registry wieder funktionsfähig sein. PS.: In meinen Tests funktionierte das Erstellen der bootdisketten mit dem standardmäßig ausgeführten Tool MAKEBT.EXE nicht. Dieses Tool blieb einfach ohne Ausgabe stehen. Als Behelf habe ich während das Tool in einer DOS-Box stehen blieb in einem zweiten Fenster die Kommandozeile geöffnet (WIN+R/cmd/OK) und bin in das Verzeichnis gewechselt, wohin die Bootdisketten entpackt wurden (%TEMP%\ISR000.TMP oder so ähnlich). In diesem Verzeichnsi gibt es auch ein 2. Tool namens MAKEBT32.EXE . Dieses Tool funktioniert ordnungsgemäß. Nach dem Erstellen der Disketten, kann man das hängende MAKEBT.EXE Fenster killen und die entpackten Dateien verschwinden wieder.Chello wird schnellerTuesday, 31. January 2006Vorsicht vor defektem F-Prot update!
Nachdem mir heute nun der zweite Fall zu Ohren gekommen ist, hier eine kurze Warnung:
Am 28.01.2006 wurde ein F-Prot Update ausgesandt, welches einen Definitionsfehler enthielt, der in der standard - Windowsdatei userinit.exe , welche normalerweise in %winroot%\system32 liegt, den Virus W32/feebs.Y erkennt. Nachdem die Datei nicht desinfiziert werden kann, wird sie von F-Prot gelöscht. Das hat leider zur Folge, dass man sich nicht mehr in Windows anmelden kann (Nach dem Einloggen wird man sofort wieder abgemeldet, statt dass die Benutzeroberfläche erscheint).Es wurde noch am selbten Tag ein Update veröffentlich, welches den Definitionsfehler behebt. Siehe diesen Thread bei gulli.com. Man sollte also ein F-Prot-Update machen, falls man unglücklicherweise die defekte Definition-DAtei eingespielt hat und überprüfen, ob die userinit.exe sich noch im system32 -Ordner befindet und diese ggf. von der Windows XP-CD bzw. aus den Servicepack-Files wieder restoren, falls F-Prot bereits zugeschlagen hat.Thursday, 8. December 2005Bitmap files und deren Aufbau
Nachdem ich bei meinem derzeitigen Projekt hier in Mexiko mit Bitmap-Files arbeiten muss, habe ich im Internet nach ein paar Informationen zum Aufbau des unkomprimierten BMP-Formats gesucht. Und anderem bin ich auch ziemlich oft auf folgende Methode gestoßen, um den Speicherplatzverbrauch eines Bitmaps zu errechnen:
Erscheint eigentlich irgendwie logisch, oder? biBitCount ist die Auflösung des Bitmaps (meistens 24bit, also 3 Bytes, manchmal aber auf 32bit wobei dann das letzte Byte Reserved und somit immer 0 ist).Dementsprechend habe ich meinen Zielpuffer auch ge malloc() t und brav das Bild entsprechend hineingeschrieben, also einfach Zeile für Zeile die 24bit-Werte in den Buffer reingestopft.Zu meiner großen Überraschung enthielt das geschriebene Bitmap immer einen scheußlichen Querstreifen mitten durchs Bild. Ich habe lange herumgegrübelt und getestet, um rauszufinden, woher der Streifen kommt... Bis ich schließlich auf folgenden Microsoft-Artikel gestoßen bin, der mir endlich Klarheit verschafft hat: http://support.microsoft.com/kb/81498/en-us Der springende Punkt ist, dass Bitmap-Scanlines DWORD-Aligned sind Das bedeutet, man kann die Größe incht mit oben gezeigter Formel berechnen, so wie das viele Programmierer im Internet fälschlicherweise gemacht haben. Stattdessen muss man die auf der M$-Seite angegebene Formel verwenden:
Außerdem sollte man darauf achten, dass man nicht vergisst, DeleteObject() zu machen, nachdem man mit CreateCompatibleBitmap() ein Bitmap angelegt hat.Soweit zum Thema Bitmaps... Wednesday, 16. November 2005Interessantes neues Blog
Habe heute einen Link zu einem interessanten, relativ neuen Blog bekommen, den ich hier nur weiterempfehlen kann:
http://www.hexblog.com/ Beinhaltet interessante Artikel rund um das Debuggen mit IDA Pro. Sunday, 13. November 2005Zugriff auf COM-Funktionen mittels plain-C
Alles begann damit, dass ich mir in den Kopf gesetzt habe, das Windows Adressbuch auszulesen, um Telefonnummern für mein Miranda WebSMS - Adressbuch zu sammeln.
Durch kurzes Suchen bin ich dann auch recht schnell auf die Funktion WABOpen gestoßen, um gleich darauf aufzuschrecken: Oh, was haben wie denn da? COM? Hilfe! Nachdem ich am liebsten in plain C entwickle hat mich das zurückgegebene Interface gleich etwas verunsichert. Sieht verdächtig nach C++ aus. Ein näherer Blick auf das Interface hat diesen Verdacht noch verhärtet. Also habe ich nach Alternativen gesucht, aber die einzige Möglichkeit, das Adressbuch auszulesen ist über COM. Na gut, dann muss das Teil aber über C auch ansprechbar sein, schließlich baut die ganze WIN32-API darauf auf. Daher habe ich mich etwas über COM schlau gemacht. Wo ist der beste Ort hierfür? Klar, in Raymond Chens Weblog The Old New Thing. Ich habe auch gleich eine kurze Erklärung des COM Interfaces gefunden, was meinen Verdacht, dass das Zeugs doch mittels C ansprechbar ist, bestätigt hat. Na juhu, dann auf ans Werk! Die Beispiele, die man zum Windows-Adressbuch im Internet so findet sind leider so gut wie alle C++. Und in C++ kann man die COM-Interfaces wie Klassen ansprechen, mittels iInterface->Function(Param1, Param2, ...) Wer das jedoch in C versucht, wird schnell feststellen, dass die COM-Struktur nicht einfach direkt Function-Pointer auf die entsprechenden Funktionen enthält und das damit auf dieselbe Weise auch in C funktioniert. Viel mehr baut COM die C++ Klassenfunktionalität mithilfe von sogenannten VTABLEs nach. Diese enthalten die entsprechenden Function Pointer auf die Startadressen der jeweiligen Funktionen . Die Funktionen ihrerseits bekommen als ersten Parameter den aus C++ bekannten this-pointer mit übergeben. In C++ wird dies entsprechend automatisch aufgelöst, in C muss man jedoch manuell auf dien vTable zugreifen. Um das Ganze kurz zu fassen, wie man nun auf COM-Funktionen in C zugreift, zeige ich das Ganze anhand der Funktion IAddrBook::GetPAB :
Also ein C einfach die Funktion innerhalb des Strukturmembers lpVtbl suchen und als ersten PArameter das Interface mitübergeben. Das ist alles. Tuesday, 1. November 2005Windows Standarddialoge anpassen
Auch wenn es darüber schon etliche Artikel im Netz gibt, möchte ich hier dennoch eine Technik präsentieren, wie man Standarddialoge, wie z.B. die MessageBox - Dialoge modifizieren und für seine Zwecke anpassen kann.
Das Ganze hat folgenden Hintergrund: Ich habe in der Arbeit ein Programm geschrieben, welches eine Erfolgsmeldung ausgibt, wenn es abgeschlossen ist: "Generierung erfolgreich abgeschlossen" [OK] Nun wollte der Programmauftraggeber aber auch die Möglichkeit haben, die generierte Datei aus diesem Dialog heraus zu öffnen, also selbigen Dialog, nur neben dem [OK] sollte ein [Datei öffnen] stehen. Nun gibt es mehrere Ansätze, das Problem zu Lösen. 1) Der naheliegendste Ansatz: OK - Dialog im Resource-Editor nachbauen, entsprechendes Icon reinladen und Dialog entsprechend umgestalten. Dies bringt allerdings den Nachteil einer zusätzlichen Resource und sollte sich der Standard-Dialog einmal ändern, hat man immer noch seinen fix definierten Dialog 2) Statt als Resource würde sich der Dialog auch "on the fly" nachbauen. Raymond Chen beschreibt dies recht gut in seinem Blog. 3) Man nutzt die bestehende Dialogbox und baut sie nach seinen Wünschen um. Ich habe mich hier für Ansatz 3 entschieden, da er meines Erachtens nach die einfachste Möglichkeit darstellt und sicherstellt, dass immer die Standard-Dialogbox von Windows verwendet wird. Um also oben genannte Dialogbox zu realisieren, verwende ich einfach eine OK/Abbrechen ( MB_OKCANCEL ) Dialogbox. Diese hat bereits 2 Buttons und ich brauche somit eigentlich nur den Abbrechen-Button neu beschriften.Um dies zu erreichen, muss man einen WindowHook setzen, um in das System eingreifen zu können. Dies geschieht mittels der Funktion SetWindowsHookEx .Von allen möglichen Hook-Möglichkeiten nehmen wir hier den WH_CBT , da dieser am wenigsten Overhead generiert und unsere Hook-Procedure damit möglichst wenig oft in Anspruch nimmt (siehe auch CBTProc ).In der Hook-Procedure müssen wir darauf achten, immer mittels CallNextHookEx an den nächsten Haken weiterzugeben.Der Rest sollte dann ansich nur noch eine Formalität sein: SetDlgItemText ((HWND)wParam, IDCANCEL, pszText); Das funktioniert zwar soweit ganz gut, kann jedoch je nach Text und verwendeter Windows-Sprachversion schnell ins Auge gehen. Die Sache hat nämlich einen Haken: Die Größe der Buttons und deren Ausrichtung wird schon bei der Erstellung die Dialogbox kalkuliert und ist dementsprechend an den originalen Texten der Buttons ausgerichtet. Im Englischen ist der Text "Abort" z.B. denkbar kurz, sodass man keinen vernünftigen Text auf diesem Button unterbringt. Die einzige Abhilfe hier scheint zu sein, dass man die Buttons selbst nochmals neu ausrichtet. Zur Berechnung der Buttongröße kann man die Defaultgröße des verwendeten Fonts heranziehen. Das wäre: LOWORD(GetDialogBaseUnits()) Daraus lässt sich dann ungefähr eine Buttongröße berechnen. Sehr genau ist dies aber leider nicht, da der verwendete Font meistens keine gleichmäßige Zeichengröße besitzt. Dennoch geht es sich meistens mit der unten gezeigten Methode gut aus. Nach der Größenberechnung des 2. Buttons werden die beiden Knöpfe kurzerhand verschoben. Und das war's dann auch schon. Minutenlange Wartezeit beim Öffnen von Arbeitplatz
Ich habe mich heute zufällig an ein ganz interessantes Problem erinnert, welches sich vor 1 1/2 Monaten bei einem Kunden zugetragen hat:
Dieser hatte das Problem, dass er nach dem Doppelklick auf das "Arbeitsplatz" - Symbol in Windows etliche Minuten (!) warten musste, bis endlich die Laufwerke erschienen. Der Kunde berichtete außerdem, dass er das System schon mehrfach neu installiert hatte, das Problem aber immer wieder nach einiger Zeit von selbst auftrat. Also habe ich das Ereignisprotokoll seiner Windows-Installation durchforstet und bin dabei auf den Eintrag: "Der Server "{A1F4E726-8CF1-11D1-BF92-0060081ED811}" konnte innerhalb des angegebenen Zeitabschnitts mit DCOM nicht registriert werden." Also mal in der Registry geforscht, was sich hinter dieser CLSID verbirgt. Siehe da, es ist der WIA-Dienst. WIA steht für Windows Image Acquisition und ist der Windows-Bilderfassungsdienst. Stellt sich die Frage, warum gerade dieser Dienst sich anscheinend nicht mit DCOM registrieren kann. Nach einigem Herumsuchen im Internet konnte ich das Problem schließlich auf seinen Scanner zurückführen: Er besitzt einen Scanner von HP (Precision Scan, wenn ich mich jetzt richtig erinnere) und der Treiber dieses Scanners scheint die WIA teilweise zu blockieren, insbesondere, wenn der Scanner abgeschaltet ist. Der Grund, dass der Arbeitsplatz so lange blockiert ist, dass dieser normalerweise einen Ordner für "Scanner und Kameras" enthält, welcher wiederum vom WIA-Dienst abhängt. Nach einiger Suche im Internet habe ich dann schließlich doch noch die Problemlösung gefunden: Folgender Registry-Key gehört entfernt: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\ Der Artikel, dem ich diese nützliche Information entnehmen konnte, ist hier zu finden (letzter Eintrag). Sunday, 23. October 2005Prüfen, ob die HTML-Help installiert ist
In heutigen Applikationen möchte man die Online-Hilfe oft nicht im klassischen
WINHELP-Format realisieren, sondern als neue HTML-Help. Wenn man sich die Microsoft-Dokumentation zur HTML Help anschaut, so ist diese aber eher etwas verwirrend, was den Aufruf aus der Applikation heraus betrifft. Zwar hat sich MS bemüht, den Umstieg von Winhelp möglichst einfach zu gestalten, indem das HtmlHelp() - Kommando dem WinHelp() Kommando syntaktisch gleicht, das Ganze ist aber trotzdem nicht einfach zu implementieren, denn insbesondere das Errorhandling scheint etwas kompliziert zu sein: Zuallererst benötigt man den HTMLhelp-Library und header files, welche im HTML-Help Workshop integriert sind, welcher hier erhältlich ist. Als nächstes kopiert man die library und das header-file ins Lib- bzw. Include-Verzeichnis von Visual Studio. Wer glaubt, damit wäre es getan, irrt leider. Zur korrekten Verwendung von HTML Help muss auch noch die Struktur HH_LAST_ERROR definiert werden, da diese scheinbar nicht in der htmlhelp.h definiert wurde.Nun stellt sich das nächste Problem: Wie findet man überhaupt heraus, ob HTML-Help überhaupt installiert ist? Unter Win 95 bzw. NT 4.0 kann man standardmäßig nicht von einer installierten HTML-Help ausgehen, da diese Betriebssystemversionen standardmäßig noch keinen IE4 oder höher beinhalten, welcher als erstes HTML-Help einführt. Führt man seine Applikation auf einem dieser Zielsysteme aus, so kommt eine Fehlermeldung, die besagt, dass eine DLL nicht gefunden werden konnte. Um den Benutzer nicht durch solch kryptische Meldungen zu verunsichern, sollte man also auf Vorhandensein der HTML-Help prüfen und, falls nicht vorhanden, den Benutzer darauf hinweisen, dass IE 4.0 oder höher zu installieren ist (Übrigens scheint das Ganze mit 100%iger Sicherheit nur bei einer Vollinstallation des IE mitinstalliert zu werden). Die Identifikation von HTML-Help funktioniert nur mittels des Prüfens auf Vorhandensein der CLSID {ADB880A6-D8FF-11CF-9377-00AA003B7A11} .Sollte die HTML-Help nun zwar vorhanden sein, aber nicht gestartet werden können, so ist die entsprechende Fehlermeldung auszulesen und dem Benutzer auszugeben. Auch dies ist leider kein allzu einfaches Unterfangen, da der Fehlerstring, anders als bei normalen C-Funktionen vom Typ BSTR ist. Um das Handling dieses Wide-character strings zu vereinfachen, verwenden wir, falls C++ zum Einsatz kommt, die Klasse _bstr_t, welche die Speicherverwaltung und Stringkonvertierung für die Ausgabe für uns übernimmt. Ich habe hier die wichtigsten Funktionen zusammengefasst, die benötigt werden, um die HTML-Help ordnungsgemäß verwenden zu können. Am Einfachsten ruft man sie beim Erhalt der WM_HELP-Nachricht in seiner Window-Dispatcher procedure auf, um sie beim Druck auf F1 anzeigen zu können. Hier nun mein Code-snippet: 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ß!
« vorige Seite
(Seite 4 von 8, insgesamt 107 Einträge)
» nächste Seite
|
SucheBlog abonnierenTop ReferrerVerwaltung des Blog |