Tuesday, 5. February 2008Konvertieren von RTF in TXT files mittels WIN32-API
Heute hatte ich im Büro die Aufgabenstellung, eine RTF-Datei in PLaintext zu konvertieren.
Für solche Aufgabenstellungen gibt es natürlich unzählige Libraries im Internet, aber mittels des RichEdit-Controls funktioniert es auch direkt über Windows. Das Prinzip ist einfach: Ein verstecktes Richedit-Control als Fenster anlegen, RTF-Daten hineinladen, TXT-Daten herausschreiben, fertig. Ich habe mir eine kleine Funktion hierfür gebastelt. Wen's interessiert, es gibt sie hier. Sunday, 6. January 2008MySQL 5 Mit Visual Studio 6 kompilieren
Nachdem Visual Studio 6 das letzte brauchbare VS ist, erscheint es naheliegent, MySQL auch mit diesem zu kompilieren, damit man nicht extra nur für diesne Zweck VS7 oder höher installieren muss.
Mit ein paar Modifikationen des MySQL-Sourcecodes ist es möglich, MySQL mit nmake unter VS6 zu kompilieren: MySQL 5 mit Visual Studio 6 kompilieren Erstellen kann man die nmake Makefiles nach setzen des VC-Environments (VCVARS.BAT) mit:
Monday, 3. December 2007DELL Vostro 200 mit Debian aufsetzen
Der DELL Vostro 200 ist ein billiger PC ohne jegliche Ausstattung. Er ist dermaßen erbärmlich, dass er nicht einmal PS/2 Ports besitzt, weswegen auch eine USB-Tastatur mitgeliefert wird. Er eignet sich also wunderbar als dummer Server für diverse nicht sehr anspruchsvolle Aufgaben. Möchte man ihm ein ein Debian Linux Betriebssystem verpassen, stößt man leider auf einige Probleme:
Es erfordert daher etwas Handarbeit, den PC aufsetzen zu können. Als erstes muss man die richtige InstallationsCD besorgen. Hier bietet sich die Debian testing Netinstall-CD an, welche einen aktuellen 2.6.22er Kernel enthält: http://cdimage.debian.org/cdimage/daily-builds/daily/arch-latest/i386/iso-cd/debian-testing-i386-netinst.iso Startet man mit dieser Install-CD den Kernel jedoch normal, so gibt es Probleme mit unbehandelten IRQs. Man muss die Installation daher mit dem Parameter irqpoll starten.Am CD-Bootprompt: install irqpoll Nachdem die Installation einmal gestartet hat, kommt die nächste Ernüchterung: Die Netzwerkkarte wird nicht erkannt. Zu neu, wies scheint. Man benötigt also die aktuellen Treiber von Intel und muss diese für den Kernel kompilieren. Nachdem das Module Object Format der einzelnen Kernels untereinander nicht kompatibel zu sein scheint, braucht man entweder eine korrekt vorkompilierte Version für den eignesetzen Kernel 2.6.22-3 oder man muss es so wie ich machen: Temporär andere NIC rein (RTL8139D), damit installieren und das Kernelmodul nachtäglich builden, dann die neue NIC wieder raus. Damit einem dieses Ärgernis erspart bleibt, habe ich mal das von mir kompilierte Modul online gestellt, in der Hoffnung, dass man dann beim Setup nur noch das Modul von Diskette laden und mit insmod in den Kernel installieren muss (ALT+F2 für Konsole, ENTER, mountfloppy , insmod /floppy/e1000.ko , ALT+F1 zurück zur Installation).Das von mir vorkompilierte Kernel-Modul gibt's hier. Nach dem Neustart muss man den irqpoll Boot-Parameter wieder entfernen, scheinbar macht der nur beim CD-Booten Probleme:vi /boot/grub/menu.lst Um nun den aktuellen e1000 Treiber zu kompilieren und in den Kernel zu installieren sind folgende Schritte notwendig:
Damit sollte der Schrotthaufen dann hoffentlich endlich laufen. Sunday, 23. September 2007T-Mobile Internet (web'n'walk) mit externer IP
Web'n'walk von T-Mobile ist ansich ein praktischer mobiler Internetzugang.
Die Standardinstallation hat nur leider einen "Schönheitsfehler": Wählt man sich ins Internet ein, so bekommt man eine interne Klasse A-Adresse (10.x.x.x) zugeteilt anstatt einer externen IP. Alle VErbindungen auf die externe IP werden außerdem nicht durchgeschleift, sodass man praktisch vollständig gefirewalled ist. Das ist natürlich äußerst unpraktisch denn z.B. für Remoteadministration usw. ist eine externe IP doch recht praktisch. Glücklicherweise ist das Problem relativ einfach zu umgehen, indem man einfach den APN wechselt. Dies mann man entweder im web'n'walk Manager Tool bewerkstelligen, indem man einfach ein neues Profil anlegt und dort den APN von gprsinternet auf business.gprsinternet umstellt.Verwendet man eine DFÜ-Verbindung dafür (die einfach *99# am GPRS-Modem wählt), so muss man stattdessen die Modemeinstellungen ändern. Hierbei gibt man als zusätzlichen Init-String für das Modem an: +cgdconf=1,,"business.gprsinternet" .Damit wird dann der richtige APN gewählt und fortan ist man endlich auch über seine externe IP erreichbar. Thursday, 6. September 2007lseek unter cygwin
Unlängst musste ich in der Firma unsere Unix-Programme mittels Cygwin teilweise auf WIN32 portieren.
Nachdem ich es geschafft hatte, dass die Programme kompilieren versuchte ich ein Programm zu starten. Boom: malloc() fehler, zu wenig SPeicherplatz. Eine Analyse des MAskenhandlercodes ergab allerdings, dass die Fehlermeldung ein Folgefehler von einem misslungenen lseek() Aufruf war.Der Maskenhandler wurde vor 20 Jahren unter Unix programmiert. Es wurde für den Seek-Modus nicht eine der Konstanten aus unistd.h verwendet, sondern der numerische Wert direkt angegeben.Ansich kein Fehler. Daher wurde die unistd.h auch nicht #include t, der Compiler bindet lseek() dann implizit.Allerdings lieferte unter Cygwin das lseek() dann immer EINVAL .Der Parameterwert stimmte aber. Schließlich habe ich dann folgendes Experiment gemacht: Einmal ein Programm, in welchem lseek() implizit gebunden wird und einmal habe ich die unistd.h inkludiert. Siehe da, mit unistd.h funktioniert das Kommando, ohne die include-Datei nicht. Ein weiterer Versuch zeigte, dass bereits die Deklaration der Funktion ausreicht, damit es funktioniert, nur beim implizit binden trat immer EINVAL auf.Das machte mich natürlich etwas stutzig, sodass ich dann den Assember-Code der beiden Funktionsaufrufe verglichen habe:
Bei impliziter Bindung wird also offensichtlich lseek64 der Cygwin-DLL mit einem Parameter zu wenig aufgerufen: Implizite Bindung: lseek64(hFile, 0, 2); Mit Deklaration: lseek64(hFile, 0, 0, 2); Daher also der Fehler. Ob das nun ein Compilerbug ist oder böse Absicht kann ich nicht sagen. Auf der Cygwin-Mailingliste habe ich nur bei einem ähnlichen Fall den lapidaren Kommentar gefunden, dass es unsauber ist, die Header-Datei nicht zu inkludieren. Das mag schon stimmen, allerdings sehe ich die fehlerhafte implizite Bindung trotzdem als Bug an. Sunday, 24. June 2007Erste Erfahrungen mit Windows Vista und Windows Live OneCare
Gestern hatte ich das zweifelhafte Vergnügen bei jemandem einen Windows XP-Rechner auf einen neuen Windows Vista - Rehcner zu überspielen. Der Kunde hat sich neben Windows Vista auch noch Windows Live OneCare dazugekauft (44 EUR), in der Annahme, dass diese neue Virenschutz- und Sicherheitslösung von Microsoft ja eigentlich perfekt mit Vista zusammenspielen müsste, da vom selben Hersteller.
Der Plan war, zuerst OneCare als Firewall- und Virenschutzlösung zu installieren, anschließend den Internetzugang einzurichten (nun durch OneCare geschützt) und danach die entsprechende Software zu installieren. Doch das Vorhaben scheiterte bereits daran, dass sich OneCare ohne Internetverbindung nicht installieren lässt. Es lädt sich scheinbar bei der Installation selbst aus dem Internet, was das Konzept einer Firewall irgendwie ad absurdum führt. Außerdem frage ich mich, wozu man eine CD kauft, wenn dann erst wieder alles heruntergeladen wird. Also gut, Planänderung: 1) Internetzugang installieren Der Kunde besitzt ADSL von der Telekom, welches bekannterweise als PPTP VPN-Verbindung eingerichtet werden muss. Freundlicherweise bietet Vista bereits einen Assistenten zur Einrichtung von Internetverbindungen an. Dort hat man aber nur die Wahl zwischen PPPOE und Dialup. PPTP? - Gibt's nicht. Auch der Versucht, einen erstellten PPPOE-Zugang nachträglich übe die Eigenschaften auf PPTP umzustellen scheitert. Gut, also am anderen Rechner erstmal die Installationsanleitung der Telekom herunterladen. Dort steht dann beschrieben, wie vorzugehen ist. Man muss in der Systemsteuerung /Netzwerk links in der Aufgabenleiste eine bestimmte Aufgabe wählen, damit man dann endlich zu dem von XP her bekannten ASsitenten zum Einrichten einer VPN-Verbindung kommt. Doch auch dieser Versuch scheitert vorerst. Vista meckert, dass es nicht auf den Zielhost verbinden kann. Na gut, also mal WIN+R / cmd (Wie man im Startmenü sonst auf "Ausführen..." kommt habe ich noch nicht herausgefunden) und mal den anderne Host pingen.. Gut, geht. Also mittels telnet versuchen, auf den VPN-Port zu verbinden. Telnet? Kennt Vista nicht. Aus irgendeinem unerklärlichen Grund ist der telnet-Client standardmäßig deaktiviert. Also wieder ins Intenret und nachschaun, wie man telnet aktiviert. Irgendwie hab ichs dann doch noch geschafft, die DSL-Verbindung zum Laufen zu bekommen. Also weiter zu Schritt 2: 2) Windows OneCare installieren Nachdem OneCare sich nun heruntergeladen und installiert ist, muss man neustarten (auch in diesem Punkt scheint es also bei Vista wenig Verbesserungen zu geben). Nach dem Neustart ersertzt OneCare die Windows-STandardfirewall und lässt einen ein paar Applikationszugriffsregeln erstellen. Zum Abschließen der Installation ist wieder Internetzugang erforderlich. Nur dumm, dass der jetzt schon wieder nicht mehr funktioniert. Scheinbar blokciert die OneCare-Firewall den Internetzugang mal standardmäßig, den es aber zur Fertigstellen der Installation braucht. Sehr sinnvoll. Der Versuch, die Firewall temporär zu deaktivieren scheitert, da OneCare die Firewallstufe ständig selbstständig wieder auf "eingeschränkt" hochsetzt. Nach dem manuellen Freischalten von VPN-Verbindungen in OneCare kann man dann endlich wieder ins Internet. Erinnert irgendein ein wenig an Symandre... 3) Windows OneCare freischalten Gut, die Installation lässt sich nun also abschließen. Nun ist bei OneCare noch ein 1-Jahres-Abo enthalten, welches man mittels Aktivierung aktivieren muss. Hierzu braucht man ein Windows Live-Konto. Es genügt angeblich auch der Hotmail-Account, den man auch für Live freischalten kann. Gibt man seinen hotmail-Account an, wird man dazu genötigt, diesen für Live freizuschalten weil ohne Account gibt's nix. Klickt man allerdings auf dne Button, um sich freizuschalten, wird einem gesagt, man möge die Anweisungen auf der sich nun öffnenden Website befolgen. Man kommt hier allerdings nur auf die Seite http://get.live.com/betas/home, wo man Betaversionen herunterladen kann. Keine Anweisungen zum Aktivieren des Live-Kontos. Möchte man ein neues Live-Konto erstellen kommt man auf dieselbe Seite. Das Ganze scheint also noch in der Betaphase zu stecken, wird aber schon verkauft?? Ich habe keine Möglichkeit gefunden, das gekaufte Abonnement freizuschalten, somit bleibt Windows-Defender vorzeitig mal in der 90 Tage Trial-Phase. OneCare-Installation also quasi gescheitert. 4) REINER SCT - PC-Chipkartenleser cyberJack einrichten Für das Onlinebanking benötigt der Kunde den genannten Kartenleser. Beim Hersteller gibt es sogar schon Vista-Treiber dafür. Also Treiber installiert (und sich - wie man es bei Vista ja ohnehin schon kennt - durch 100.000 Sicherheitsabfragen (Wollen Sie wirklich..??) durchquälen) und den Versuch gestartet, sich mittels der Java-Applikation der Bank mithilfe des Chipkartenleser anmelden. Geht nicht - Kartenleser konnte nicht gefunden werden. Eine Recherche ergab, dass man im Internet Epxlorer den sogenannten "geschützten Modus" deaktivieren muss, damit Java dann auf den Kartenleser zugreifen kann. Anschließend musst e man dann noch die Firmware des Kartenlesers aktualisieren, dann hat es endlich funktioniert. Schwere Geburt. 5) Software installieren Gut, nun musste noch die entsprechende Anwendersoftware installiert werden. Man möchte meinen, dass das auf einem 3GhZ Dualcore-System mit 3GB RAM ja eine Kleinigkeit sein sollte. Nur leider war dem nicht so. Die zu installierenden Softwarepakete benutzten der Standard-Installer Macrovision Installshield. Gut, Installation gestartet, Installshield bleibt bei 0% scheinbar hängen. 2 Minuten gewartet.. Tut sich nix. Task gekillt, nochmal versucht. Geht nicht.. Vista neu gestartet, nochmal versucht, geht nicht. Dann kam mir die Idee, dass IS evtl. vor der Installation einen Systemwiederherstellungspunkt anlegt, bevor es fortfährt. Der Verdacht erhärtete sich dadurch, dass die Festplatte die ganze Zeit ziemlich herumratterte. Und nachdme Vista ja ein sehr behäbiges System ist, wäre es natürlich möglich, dass die Erstellung eines Wiederherstellungspunkts ganz einfach ewig dauert. Gemäß dem Motto "Gut Ding braucht eben Weile" habe ich also sicher über 4 Minuten gewartet, ehe die Installation dann endlich begann. Und das bei jeder Installshield-Installation. Sehr zeitsparend, genau dafür kauft man sich ein neues System... Ein Update der installierten Software quittierte den Installationsversuch dann mit nicht ausreichenden Rechten. Also Update in einen Ordner herunterladen, dort hinwechseln, rechte Maustaste - "Als Administrator ausführen". Dann wieder 5 Minuten warten und siehe da, es funktionierte. Die Altdatenübernahme gestaltete sich anschließend dafür halbwegs problemlos. Der Kunde hatte hierfür ein USB-Überspielkabel von Hama gekauft (bietet im Prinzip dieselben Features wie der "Übertragen der Einstellungen" - Assistent von XP). Dieses Kabel hatte im Menü auch einen Modus für das Überspielen über eine LAN-Verbindung (geht ja doch etwas shcnelelr als USB) drinnen, aber wie dieser funktionieren sollte entzog sich meiner Kenntnis, sodass wir dann der Einfachheit halber das Ganze über USB überspielten. Fazit: Was eine einfache Überspielaktion hätte sein sollen entwickelte sich zu einem regelrechten Chaos. Vista ist meiner Ansicht nach alles Andere als ausgereift und Benutzerfreundlich sondern erschwert einem die Bedienung mit zahlreichen Sicherheitsabfragen, lästigen Features und Inkompatibilitäten. Etwas überspitzt formuliert: Ein Unix-Terminal ist von der Bedienung her ein Traum dagegen. Das Ganze wirkt irgendwie noch sehr unausgereift und Microsofft hat sich mehr Mühe denn je gegeben, ihre Funktionen gut vor dem Anwender zu verstecken, damit man das System auch ja nicht selbst administrieren kann. Ich werde keine Support mehr für Vista geben, denn mal abegesehen von den technsichen Problemen (Speicherfresser, schlechter Bootloader, DRM (oder wie es so schön nun genannt wird: "customer enablement"), ...) scheint es auch aus reiner Anwendersicht alles Andere als Benutzerfreundlich zu sein. Also: Finger weg von Vista! Sunday, 29. April 2007Qt GPL-Version mit Visual Studio 6
Zum Entwickeln von Plattformunabhängigen GUIs gibt es mehrere Toolkits auf dem Markt, welche alle ihre Vor- und Nachteile haben.
In einem meiner vorherigen Blog-Einträge habe ich ja schon über die Vorzüge von GTK geschrieben. Nichtsdestotrotz hat GTK auch einige Nachteile, u.A. zeichnet es alle seine Widgets selbst und man hat somit nich den Look&Feel der Zielplattform. Das war nur einer der Gründe, warum bei uns in der Firma beschlossen wurde, für diesen Zweck trotz entsprechender Lizenzkosten das QT-Toolkit der Firma Trolltech einzusetzen. Ein großer Nachteil von QT ist sicherlich, dass es leider C++ only ist, und damit keine schöne C-API bietet, so wie die WIN32 API, was das Programmieren damit natürlich etwas verkompliziert. Es soll allerdings nicht unerwähnt bleiben, dass es eine libqtc gibt, welche ein C-Binding für QT darstellt. Aufgrund des Designs von QT ist das Programmieren mittels des Bindings aber leider nicht wirklich so viel einfacher (vergleicht man es mit der relativ gut programmierbaren WIN32-API) und nachdem es sich um ein binding handelt hat man damit natürlich nur noch mehr overhead. Sonst läuft die Bibliothek jedoch ziemlich stabil und ist man bereit, für die Multiplattformfähigkeit etwas mehr Haupspeicher zu opfern (ca. 6 MB verschlingen alleine die DLLs!), ist es gegenüber speicherfressenden Java-basierenden Toolkits oder instabileren Toolkits wie WxWidgets immer noch eine gute Wahl. Wie allgemein bekannt sein dürfte, gibt es auch eine GPL-Version des Toolkits. Nachdem man natürlich nicht die Katze im Sack kaufen will, kann man damit zuerst einmal nach Herzenslust damit programmieren und erst wenn man sein Produkt kommerziell vertreibt eine Lizenz kaufen. Die GPL-Version hat jedoch für die WIN32-Entwicklung einen entscheidenen Nachteil: Sie funktioniert standardmäßig nur mit dem MinGW environment, welches nicht nur fettere Executables produziert als der Microsoft C compiler, sondern auch keine komfortable IDE bietet, wie Visual Studio 6.0. Für kommerzielle Kunden wird natürlich eine visual Studio Integration angeboten. Allerdings wird auch hier neuerdings nur noch Visual Studio .NET unterstützt, welches für den praktischen Gebrauch meines Erachtens nach nicht zu gebrauchen ist. Ich habe mir daher die Mühe gemacht, mehrere Patches zusammenzusuchen, die eine Integration in VS 6 ermöglichen und selber eine Workspace-Template gebaut und auch einige kleinere Sourcecode-Patches für QT geschrieben, damit das Erstellen von VS 6 Projekten reibungslos funktioniert. Die einzelnen Patches aufzuzählen würde hier zuviel Platz einnehmen, sie sind aber in der Anleitung innerhalb des ZIP-Pakets beschrieben. In der Langanleitung steht, woher die ursprünglichen Patches sind und welche Teile davon verwendet wurden, bzw. welche Patches ovn mir hinzugefügt wurden. Nachdem das Ganze doch etwas komplexer ist, habe ich eine kleine Batchdatei geschrieben, die das Patches automatisch übernehmen sollte. Es werden die QT-Sources hierfür benötigt, man kann sich also auf eine mehrstündige Kompilierorgie gefasst machen (am besten über Nacht rennen lassen). Das Paket gibt es hier. Bei Fragen oder Anregungen einfach einen Kommetar hinterlassen (sollte jetzt endlich wieder funktionieren). Wednesday, 4. April 2007Bash: Alle Tage in einem Datumsbereich ausgeben
Nur weil ich es heute in der Arbeit gebraucht habe, aber auf die Schnelle keine brauchbare Lösung gefunden habe: Mit GNUdate funktioniert das Ganze relativ einfach:
Sonst muss man die Datumskalkulationen selbst durchführen. Hierfür gibt es ein ganz praktisches Script: http://www.unix.com/showthread.php?s=&postid=16559 Thursday, 29. March 2007Die Sache mit den verflixten #defines
Oft entstehen Probleme in Programmen aufgrund von ungenügender Kenntnis einer Programmiersprache.
Dieses Problem tritt vermehrt natürlich dann auf, wenn mehrere LEute an einem PRogramm arbeiten. So ein Problem stellte sich unlängst bei uns in der Firma: Für unsere Softwareprodukte haben wir ein eigenes Window-Management System entwickelt, welches die Terminal-Ausgabe über verschiedene Messages, die über ein eigenes RPC-System zum Client gesendet werden, auf eine GUI umsetzt, welche die entsprechenden Controls dann anzeigt. Somit gibt es auch eine Funktion, mit welcher man sich für verschiedene Events registrieren kann, um den Netzwerktraffic-Overhead möglichst gering zu halten. Die jeweiligen Events werden dann zum Client geschickt. Die Events sind logischerweise als Flags definiert, welche man setzen kann. Irgendwer hat das Window-Management System dann um ein neues Event, und damit um ein neues Flag, nennen wir es FLAGx, erweitert. Folgende #defines wurden verwendet:
Und jetzt die Rätselfrage: Was hat der Programmierer, der FLAGx deklariert hat hier falsch verstanden? Bitte als Comment posten Thursday, 15. March 2007Einfärben von ListBox und ListView controls
Die Aufgabenstellung selbst erscheint relativ simpel: Man möchte in einer ListBox bzw. in einem ListView einen Eintrag mit einer Hintergrundfarbe hinterlegen, um diesen z.B. besonders hervorzuheben.
Leider unterscheiden sich die Methoden hierfür bei ListBox und ListView erheblich. Beim ListView ist das Ganze relativ einfach zu lösen: Das ListView sendet eine WM_NOTIFY Message an den Parent-Dialog, der das Control beinhaltet. Als lParam erhält man eine LPNMLISTVIEW Struktur, welche im hdr Member wiederum einen Member code enthält, welcher den eigentlichen Notification code angibt. Für das ListView ist hier für uns der Code NM_CUSTOMDRAW interessant. Durch Erhalt der Message ist sichergestellt, dass es sich bei der in lParam an uns übergebene Struktur um eine NMLVCUSTOMDRAW Struktur handelt. In deren Member nmcd befindet sich die zur Message zugehörige Struktur NMCUSTOMDRAW , welche wiederum den Member dwDrawStage beinhaltet, der uns über den aktuellen Zeichnungsstatus informiert. Erhalten wir hier die Nachricht CDDS_PREPAINT , wissen wir, dass das Zeichnen des ListViews gerade beginnt. An dieser Stelle müssen wir nun unser Interesse an den Notifications für die einzelnen Items der Liste anmelden. Das geht ganz einfach mit folgendem Kommando:SetWindowLong (hWnd, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW); Mit besagtem Kommando teilen wir dem Notifier unsere Antwort mit, die da eben lautet CDRF_NOTIFYITEMDRAW .Nun können wir den Drawstage pro Item mit der Nachricht CDDS_ITEMPREPAINT dispatchen.An dieser Stelle können wir nun auf den Zeichenprozess einfluss nehmen, indem wir die Members de rStruktur in lParam entsprechend modifizieren und den Notifier diese Änderung zur Kenntnis bringen. Hier ein Beispiel, welches den Text rot färbt: lplvcd->clrText = RGB(255,0,0); Den kompletten Source zur besseren Übersicht gibt's hier Bei der ListBox ist das Ganze leider nicht ganz so einfach. Diese bietet nämlich leider keinen so bequemen WM_NOTIFY -Mechanismus. Stattdessen muss man sich hier mit einem owner-Drawn control aushelfen, was natürlich einiges an Arbeit mit sich bringt. Daher sollte man als Style für das Control LBS_OWNERDRAWFIXED verwenden. Ein LBS_HASSTRINGS könnte sich auch als nützlich erweisen.Bei einem Owner-Drawn control erhält der Parent eine WM_DRAWITEM Notification, welche entpsrechend behandelt werden muss.Als lParam erhält man ein LPDRAWITEMSTRUCT , welches den Member itemAction hat. Interessant sind hierbei die Actions ODA_SELECT und ODA_DRAWENTIRE .Ein Zeichnen des ListBox-Eintrags im entsprehcenden Style erreicht man hier mittels Modifikation des device contexts, welcher sich im hDC Member des DRAWITEMSTRUCT s befinder.Je nach itemState Member sollte man die Vordergrund- und Hintergrundfarbe des Eintrags entsprechend setzen. Um die Systemfarben zu ermitteln, empfiehlt sich der Einsatz der Funktion GetSysColor .Mit FillRect die Auswahlmarkierung erzeugen und mit TextOut schließlich den Text zeichnen. Also ein relativ hoher Aufwand, um nur die Farbe des Textes zu ändern.Ein Codebeispiel gibt's wie immer hier. Tuesday, 16. January 2007MessageBox mit Mauscursor auf default button
Ich bin unlängst vor dem Problem gestanden, dass ich eine Software, welche sich über ein Diktiergerät
steuern lässt (im Prinzip ein USB HID mit Zusatzknöpfen), entsprechend erweitern sollte, sodass der Mauscursor auch in Dialogen entsprechend immer auf dem Default-Knopf platziert wird. Das bietet den Vorteil, dass man beim schnellen Arbeiten z.B. bei der Frage, ob man ein Diktat speichern will, nur noch die linke Maustaste drücken muss, um zu bestätigen, und nicht jedesmal mit der Trackpad-Kugel hinfahren muss. In selbst definierten Dialogen geht das ja relativ einfach mit SetCursorPos . Was aber macht man bei Standard Windows-Dialoge, welche man mit MessageBox generiert? Hier hat man ja normalerweise keinen Einfluss auf die Gestaltung des Dialogs. Aufmerksame Leser meines Blogs werden sich an meinen Artikel zur Anpassung von Standarddialogen erinnern, wo diese Problematik ja schon einmal besprochen wurde. Windows bietet ja glücklicherweise die Möglichkeit, mittels SetWindowsHookEx und einer CBTProc-Funktion die Erstellung von Messageboxes zu hooken und damit auch zu beeinflussen.Konstruiert man also nun so einen Hook, kann man die HCBT_ACTIVATE Notification abfangen. Zu diesem Zeitpunkt sind bereits alle Controls positioniert und gesetzt. Daher kann man dann mittels GetWindowLong mit dem GWL_STYLE Parameter abfragen, welcher Button default ist. Um das Ganze für alle möglichen Buttons in einer Schleife realisieren zu können, muss man die IDs der einzelnen Buttons wissen:
Es reicht also, zwischen IDOK und IDNO zu loopen.Interessanterweise kann sich die Position des MessageBox-Fensters auch nach HCBT_ACTIVATE noch ändern, sodass man mittels SetWindowPos die Fensterposition auf eine marginal andere Position als die aktuelle ändern muss, damit das Fenster dort bleibt, wo es ist.Dann einfach mit SetCursorPos den Mauscursor auf das Default-Button platzieren und fertig.Das Sourcecode dafür gibt es hier Saturday, 9. December 2006Win32 API Tutorial
Beim Herumstöbern im Netz bin ich auf eine gute Seite mit nützlichen Win32-Codesnippets gestoßen, die ich dem geneigten Leser dieses Blogs nicht vorenthalten möchte: Win32 tutorial
Tuesday, 14. November 2006COM Interface von C aus ansprechen
Ich habe ja schon bereits vor einiger Zeit erklärt, wie man COM-Interfaces von reinem C aus über die VTable eines COM-Objekts richtig anspricht. Allerdings gibt es natürlich manchmal das Problem, dass keine C-Style Deklaration des Interfaces vorliegt. Beim Surfen durch das Netz bin ich hier auf einen interessantes Artikel gestoßen, der gut erklärt, wie man nun COM-Interfaces von C aus anspricht: COM-Interfaces von C aus ansprechen
Saturday, 4. November 2006Bluetooth CrackThierry Zoller und Kevin Finistere haben auf der Hack.lu-Konferenz beeindruckend bewiesen, dass es mit der Sicherheit in Bluetooth-Geräten nicht weit her ist. Sie zeigten eine Demonstration mit dem Windows-Tool BTCrack. Bluetooth-PIN und Linkkey wurden nach dem „Handshake“ in fast Echtzeit gecrackt. Friday, 20. October 2006Größe eines struct members ohne Instanzierung ermitteln
Manchmal steht man vor dem Problem, die Größe eines einzelnen Eintrags einer Struktur wissen möchte, ohne die Struktur vorher instanzieren zu müssen, beispielsweise, um die Größe einer anderen Struktur entsprechend anzupassen.
Folgendes Beispiel soll dies verdeutlichen:
Natürlich funktioniert dieses Beispiel nicht, weil der sizeof() Operator nur auf "instanzierte" Strukturen angewandt werden kann, nicht auf die Typendefinition an sich. Was kann man in diesem Fall also tun? Eine Funktion zur Auflösung zu schreiben fällt aus, da die Größe ja schon zur Compilezeit feststehen muss. Nach einiger Überlegung kommt man dann zur eigentlich trivialen Lösung des Problems: Wenn der Compiler unbedingt eine "Instanz" haben will, dann soll er sie doch mittels eines Typecasts haben. Also erstellt man einfach einen Pointer auf die Struktur an Adresse 0, und verwendet dann wie gewohnt den sizeof()- Operator. Folgendes Makro bewerkstelligt die Aufgabe:
Die Definition von Struct2 auf dem obrigen Beispiel würde dann also folgendermaßen funktionieren:
« vorige Seite
(Seite 2 von 8, insgesamt 107 Einträge)
» nächste Seite
|
SucheBlog abonnierenTop ReferrerVerwaltung des Blog |