Alles was mit Programmierung zu tun hat.

[vb.net] MDIchild Problem beim ändern der .text-Eigenschaft. Wird in .size nicht übernommen.

Das ist jetzt ein wenig kompliziert zu erklären. Ich bin auch nur darauf gestoßen weil die Software multilingual ist und ich Texte zur Laufzeit ändern muss.

Damit das Problem auftritt muss die Anwendung eine MDI Anwendung sein. Ändern wir nun zur Laufzeit im MDIchild z.B. den Text von Button1 (Me.Button1.Text = „Bla Bla“) dann funktioniert das auch wunderbar. Das Problem dabei ist das sich die Werte von Me.Button1.Size. nicht verändern. Das heißt der Button-Text ändert sich zwar, aber die Size-Eigenschaften nicht.

Das ist insofern ein Problem als das ich ja meist 2 Buttons habe. „Ok“ und „Abbrechen“ oder was auch immer. Nun ändere ich den Text im rechten Button und er wird dadurch kleiner oder größer (autosize = on). Damit das ganze trotzdem weiterhin schick aussieht, muss der linke Button nun so verschoben werden das der Abstand zwischen Button1 und Button2 wieder normal groß ist. Und genau hier brauche ich den neuen Me.Button1.Size.Width-Wert. Der aber immer noch der alte ist.

Die einzige Lösung die ich gefunden habe ist das die Texte der zu ändernden Elemente schon geändert werden müssen noch bevor man in der MDIform das Child öffnet. Dann werden die Werte auch schon beim Laden des Childs geändert. Achso, das Problem ist nicht immer. In der Form-Resize Funktion z.B. ändern sich die Werte ordnungsgemäß. Beim Load allerdings nicht.

Ich denke das Problem werden nur sehr wenige haben, wer ändert schon zur Laufzeit die Texte in Elementen. Aber vielleicht der ein oder andere schon.
Das wäre also eine mögliche Lösung. Hast du noch eine andere, bessere? Dann schreib doch bitte einen Kommentar und zeige uns deine Lösung. Danke.

[VB.NET] Datagridview – Schriftfarbe oder Hintergrundfarbe einer einzelnen Zelle ändern

Problem des Tages heute: Eine einzelne Zelle in einem Datagridview farbig ändern. Egal ob Schriftfarbe oder Hintergrundfarbe.

Schon mal versucht? Geht gar nicht so einfach. Das habe ich auch ganz schnell rausgefunden. Es gibt zwar die Style Eigenschaften, wenn man sich die Zelle mit Me.Datagridview1.Rows(0).Style… vorknöpft. Doch bewirkt eine Änderung hier nicht viel. Erst die letzte bzw. erste neue Zelle wird damit eingefärbt. Nicht aber die Zelle die man eigentlich einfärben möchte.

Und so habe ich heute stundenlang hin und her experimentiert, Google befragt, mich durch etliche Foren belesen, kuriose Klassen ausprobiert… und es am Ende doch selbst gemacht.

Leider ist es ein sehr mühsamer Weg, wenn man einer einzigen besch*** Zelle sagen will „Mache mal den Text Rot!“. Denn man muss das komplette Datagridview manuell anlegen. Ich arbeite ja generell ohne Databindings. Ja, fragt mich nicht warum, ich mache es halt :-) Nur war es bis dato einfach zu sagen Me.Datagridview1.Rows.Add(„Text 1“, „Text 2“, 1, 2, 3, etc.)

Jetzt wird das ganze nicht mehr so einfach. Jetzt müssen wir jede Zelle wirklich einzeln anlegen, denn nur so können wir auf die konkreten Zelleigenschaften zugreifen und auch setzen.
Ok, wie geht es konkret.

Dim DGVRow As New DataGridViewRow 
Dim Cell As DataGridViewCell 

'Eine normale Zelle 
Cell = New DataGridViewTextBoxCell 
Cell.Value = "Ein Text zum Testen" 
DGVRow.Cells.Add(Cell) 

'Eine Zelle mit rotem Text 
Cell = New DataGridViewTextBoxCell 
Cell.Value = "Ein roter Text zum Testen" 
Cell.Style.ForeColor = Color.Red 
DGVRow.Cells.Add(Cell) 

Me.Datagridview1.Rows.Add(DGVRow) 

Was machen wir hier? Wir definieren eine einzelne Datagridview-Zelle und weisen dieser alle nötigen Werte zu. Im Normalfall einfach nur den Value. Aber man kann ihr jetzt auch eine Schriftfarbe zuweisen oder eine Hintergrundfarbe, Schriftart und alles weitere.
Dann packen wir die Zelle in einen Datagridview-Row (DGVRow) und können Sie danach neu Formatieren und neu Belegen, mit der nächsten Zelle. Die dann auch wieder in das Row-Element… bis alle Zellen für ein Row voll sind. Das vollständige DGVRow weisen wir letztendlich dem Me.Datagridview.Row.Add zu. Fertig…

… mit einer Zeile. Das müssen wir jetzt für alle Zeilen machen die dem Datagridview hinzugefügt werden sollen. Daher ist meine Empfehlung das ganze einer Funktion zuzuweisen oder noch besser einer Class. Das hier soll ja nur zur Orientierung dienen wie es funktioniert.

Sehr umständlich, aber funktioniert. Und das ohne fremde Klasse. ;-)

Update: Ich korrigiere. Auch mit Me.Datagridview1.Rows(0).Cells(0).Style.ForeColor = … lässt sich die Schriftfarbe verändern. Nur warum es mal funktioniert und mal nicht… das muss ich noch ergründen. Als einfach ausprobieren. Wenn es so funktioniert, dann kann man sich den komplizierteren Weg oben sparen.

Einen schönen Programmierer Tag!

Hi,

heute mal nur schnell eine Schlagzeile. Was aber nicht heißt das sie unwichtig ist! Denn heute ist Programmers Day (Tag der Programmierer). :-) Ein sehr wichtiger Feiertag (leider kein offizieller… hätte gern frei heute)!

Wer sich jetzt fragt wann denn der Tag der Programmierer im Jahr ist… na ganz einfach… am 256ten Tag im Jahr ;-) Warum 256? Weil man mit einem (8bit) Byte genau 256 verschiede Werte/Zustände (0 und 1) erstellen kann.

Die Zahl ist die Grundzahl eines jeden Programmierers. Wenn ein Programmierer auch sonst nix kann, diese Zahl muss er kennen… sonst ist es kein Programmierer :-)

Ins Leben gerufen wurde der Programmers Day von Valentin Balt im Jahr 2002. Er hat sogar versucht das Russland diesen Tag als offiziellen Feiertag anerkennt. Und?… Seid dem Jahr 2009 gilt der Programmers Day als offizieller Feiertag in Russland. … Ich bin begeistert. :-)

 

Also liebe Programmierer all around the world: Happy Programmers Day!! And less bugs in the next year! ;-)

[VB.NET] NotifyIcon mit Transparenz

Hallo,

heute mal ein kleiner Codeschnipsel zum Thema NotifyIcon mit Transparenz.

Ich habe nicht rausgefunden wie man normal ein *.ico mit Transparenz hinbekommen. Zumindest hat es mein Programm nicht unterstützt. Also habe ich mir einen kleinen Code gebastelt der ein bisschen rumtrickst. :-) Damit kann man auch noch sicher andere Sachen basteln.

Funktionieren tut es ganz einfach. In meinem Fall habe ich eine ImageList die diverse Bilder beinhaltet. Daraus suche ich einfach eines raus und lasse es als NotifyIcon setzen.

Die Sub dazu sieht dann so aus. Muss natürlich noch mit dem Programmstart ausgeführt werden.


    ' sets a new icon from the imagelist. because of the transparens
    Sub createNotifyIcon()
        Try
            Dim img As Bitmap = Me.ImageList1.Images(1)
            Dim hIcon As IntPtr = img.GetHicon()
            Dim icn As Icon = Drawing.Icon.FromHandle(hIcon)
            Me.NotifyIcon1.Icon = icn
            icn = Nothing
            hIcon = Nothing
            img = Nothing
        Catch exc As Exception
            'ups, error... hope the icon is still there...
        End Try
    End Sub

Ist Technorati wieder zurück? Endlich kann ich wieder eintragen, ohne Connection-Timeout.

Ohh, was ist da los? Ist Technorati wieder zurück? Ist da endlich mal jemand aufgewacht? Neuer Server? Neue Internetleitung? Vorbei die Timout-Zeit?

Unglaublich, aber wahr… ich konnte gerade 3 Seiten Problemlos und ohne 100 Verbindungsunterbrechungen wegen Timeout, bei Technorati eintragen. Ich hatte ja erst vor kurzem darüber geschrieben (siehe Technorati Timout Problem) das es schon seid Monaten nicht mehr möglich ist bei Technorati eine Webseite einzutragen. Einfach weil man es irgendwann leid war das es nach der hundersten Verbindungsunterbrechung, weil der Server von Technorati beim Eintragen (und nur da), einen Timeout hatte, wieder auf „Noch mal versuchen“ zu klicken.

Und jetzt scheint es auf einmal wieder zu gehen! Oder ist das nur ein Zeitfenster und ich habe gerade Glück?? Keine Ahnung, aber falls dem so ist… tragt schnell eure Seiten ein, solange es möglich ist!!! ;-)

Auch die Mails mit dem Verifizierungscode kamen sofort an. Ich hoffe die werden auch schnell gecheckt… bevor das Glück wieder vorbei ist. *bibber*

Bug in WordPress XMLRPC wp.uploadfile – Dateiupload funktioniert nicht!

Gerade habe ich einen Bug in der XMLRPC-Schnittstelle von WordPress gefunden. Anscheinen nutzt diese Funktion aber wohl kaum jemand, wenn es noch keinem Aufgefallen ist. Ich habe aber genau diese Klasse kopiert und in einem anderen Projekt verwendet, um es mir mal einfacher zu machen. :-)

Der Bug befindet sich in der wp.uploadFile aka mw_newMediaObject Funktion. Mit dieser Funktion können Dateien über die XMLRPC-Schnittstelle in den Blog geladen werden.
Das Problem, es funktioniert nur nicht wirklich. Die Daten müssen per base64_encode codiert werden. Hab ich auch brav gemacht, nur werden sie im Blog nicht wieder decodiert und damit genau so gespeichert wie sie übertragen werden. Das kann jedoch nicht funktionieren.

Also habe ich mich auf die Suche gemacht und den Fehler gefunden. Die XMLRPC Klasse von WordPress (class-IXR.php) erkennt auf der Client-Seite Base64-Codierte Strings nicht. Ich habe im Netz auch keine Möglichkeit gefunden wie man prüfen kann ob ein String im Base64-Format vorliegt. Daher habe ich zu einer anderen Möglichkeit gegriffen den Bug zu fixen.

Wir gehen mal wieder in den Code. Achtung: Wenn diese Änderung im Blog selbst vorgenommen wird, wird es beim nächsten Update überschrieben!
Als erstes nehmen wir uns ca. Zeile 35 vor. Hier sollte folgendes stehen:


foreach ($this->data as $key => $value) {
     $this->data[$key] = new IXR_Value($value);
}

Das ändern wir in:


foreach ($this->data as $key => $value) {
     if($key == "bits") $this->data[$key] = new IXR_Value($value, "base64");
     else $this->data[$key] = new IXR_Value($value);
}

Soweit ich gesehen habe gibt es den „bits“ Parameter nur ein mal in der Schnittstelle. Und zwar genau dort wo der Base64-String unserer Datei drin ist. Also sagen wir „Wenn Parameter ‚bits‘ ist, dann ist es Base64. Und schon schalten wir die automatische – und falsche – Erkennung des Variablen-Types aus und sagen gleich das es Base64 ist.

Dann gehen wir noch zu einem anderen Bug. Der ist ca. in Zeile 114. Die Originalzeile heißt:


     case 'date':
     case 'base64':
          return $this->data->getXml();
          break;

Das gibt einen Fehler. Die Funktion getXml() gibt es unter $this->data nicht und wäre auch Schwachsinn.  Die Zeilen müssen wie folgt aussehen:


     case 'date':
          return $this->data->getXml();
          break;
     case 'base64':
          return '<base64>'.$this->data.'</base64>';
          break;

So, jetzt sollte es funktionieren.

Wie gesagt, wenn ihr die Klasse kopiert habt und in einem anderen Projekt verwendet, dann ist es ok. Wenn ihr es im WordPress selbst ändert dann wird es beim nächsten Update überschrieben.

[WordPress] FTP Daten für automatische Updates festlesen

Da wir heute gerade schon mal beim Thema waren. Hier gleich noch ein Beitrag zu den automatischen Updates. Normalerweise fragt WordPress immer nach den FTP Daten um die Updates zu installieren. Man kann diese jedoch auch in der wp-config.php selbst (und fest) vorgeben. Dann müssen sie einerseits nicht mehr ständig eingegeben werden und es verringert auch das Sicherheitsrisiko (sagen jedenfalls die Experten :-) ).

Also wp-config.php öffnen und irgendwo – am besten nach den SQL Daten – die folgenden Parameter eintragen (und konfigurieren natürlich).

define('FTP_HOST', 'musterdomain.de');
define('FTP_USER', 'ftp_user');
define('FTP_PASS', 'ftp_paswort'); 

Die folgenden Zeilen müssen nicht angegeben werden. Wenn Du weißt was Du tust, dann kannst Du auch hier eigene Einstellungen vornehmen.

 
define('FTP_SSL', true); //SSL Verschlüsselter Upload
define('FTP_BASE', '...'); //Root Verzeichnis der WordPress Installation
define('FTP_CONTENT_DIR', '...'); //wp-content Verzeichnis
define('FTP_PLUGIN_DIR', '...'); //wp-plugin Verzeichnis
define('FS_METHOD', 'direct'); //FTP Methode

[WordPress] Automatisches Update funktioniert nicht

Ich habe schon seid einer Weile ein Problem mit meinen automatischen Updates im WordPress. Er bricht das Update gleich mit der Fehlermeldung: „Das Verzeichnis „wp-content“ konnte nicht gefunden werden.“ ab.

Dazu muss ich sagen das ich auf einen Webspace umgezogen bin und nun alles irgendwie in einem Root Verzeichnis, in verschiedenen Unterverzeichnissen, liegt. Das ganze wird über einen FTP Zugang gemanaged.

Schnelle Abhilfe schafft man sich indem man WordPress einfach den richtigen Pfad vorgibt. Dann weiß WordPress wieder wohin mit den Daten und alles ist schick ;-)
Dazu einfach den folgenden Code in die wp-config.php einfügen, irgendwo.

putenv('TMPDIR=' . ini_get('upload_tmp_dir'));

Speichern, hochladen und alles sollte wieder laufen.

[Magento] Pflichtfelder bei der Registrierung ändern

Da sind wir mal wieder beim Magento-Shopsystem. Ich kann nicht sagen das ich von dem System sehr begeistert bin. Um da durchzusteigen muss man Magento studiert haben. Aber egal.

Das Problem heute: Wie ändere ich Pflichtfelder bei der Registrierung.

Aktueller Fall ist das nur der Vorname, Nachname, E-Mail und Passwort.

Magento Version: 1.4.1.1

Als erstes nehmen wir uns die Registrierungsform vor. Die ist unter „/app/design/frontend/base/default/template/checkout/onepage/billing.phtml„.
Hier suchen wir alle Felder die wir nicht als Pflichtfelder haben wollen und entfernen in der entsprechenden Zeile erst einmal die „<em>*</em>„. Dann noch im Formularfeld selbst den CSS-Code in ändern.
Wenn man Pflichtfelder hinzufügen möchte, dann natürlich andersrum.
Das war es in der Datei auch schon.
Bei der Postleitzahl ist noch eine änderung ganz unten vorzunehmen. Aus der Zeile:

var billingRegionUpdater = new RegionUpdater('billing:country_id', 'billing:region', 'billing:region_id', countryRegions, undefined, ''billing: postcode');

machen wir

var billingRegionUpdater = new RegionUpdater('billing:country_id', 'billing:region', 'billing:region_id', countryRegions, undefined, '');

Das gleiche muss auch in der Datei „/app/design/frontend/base/default/template/checkout/onepage/shipping.phtml“ gemacht werden.

Jetzt müssen wir die Prüfung durch PHP deaktivieren, für die Nicht-Pflichtfelder. Das passiert in der „/app/code/core/Mage/Customer/Model/Address/Abstract.php“. Ganz unten die Prüfungen auskommentieren die nicht erfolgen sollen.

Das sollte es gewesen sein. Bei mir funktioniert es :-)

[PHP] Dateiupload und Dateidownload

Jeder macht das eine und einige machen auch das andere. Die Rede ist vom Hoch- und Runterladen von Dateien im Internet. Jeder kann etwas herunter laden. Ob die Bedienungsanleitung, im PDF-Format, für den Fernseher oder ein schickes Bildchen als Bildschirmhintergrund oder oder oder… die Möglichkeiten sind schier unbegrenzt. Auf der anderen Seite gibt es natürlich auch I-Net Nutzer die auch Dinge hochladen.

Hier möchte ich kurz erklären wie man es als PHP Programmierer lösen kann. Viele Wege führen bekanntlich nach Rom. Hier mein Weg.
Als erstes der Upload. Hier brauchen wir natürlich überhaupt erst einmal eine HTML-Form mit einem Dateifeld. In seiner einfachsten Form würde das so aussehen:



Hier kann der User dann seine Datei auswählen und die Form abschicken. Damit wird, in diesem Fall, die Datei erneut aufgerufen und die Formulardaten mit übergeben. Sprich die Dateidaten. Diese können nun mit PHP erfasst und ausgewertet werden.


if(!empty($_FILES["file"]["name"])) {
	$UploadFolder = "./uploads/";

	//Dateinamen auf ungueltige Zeichen pruefen
	$Dateiname = preg_replace('/[^a-z0-9.-_]/', '', strtolower($_FILES["file"]["name"]));

	//Existiert die Datei auch noch nicht
	if(!file_exists($UploadFolder.$Dateiname)) {
		//An die richtige Stelle kopieren
		move_uploaded_file($_FILES['file']['tmp_name'], $UploadFolder.$Dateiname);
		if(!file_exists($UploadFolder.$Dateiname)) {
			echo "Datei konnte nicht hochgeladen werden. Bitte wenden Sie sich an einen Administrator.";
		} else {
			//Datei ist hochgeladen
		}
	} else {
		echo "Es existiert bereits eine Datei mit diesem Dateinamen. Bitte bennenen Sie die Datei um.";
	}
}

So. Damit haben wir die Datei hochgeladen und in dem Ordner „Uploads“ abgelegt. Das ist natürlich nicht alles. Jeder muss hier seinen eigenen Weg gehen.
Der Dateiname muss z.B. irgendwo (Datenbank) gespeichert werden, damit sich das System später daran „erinnert“. Aber für den Upload selbst reicht das.

Kommen wir zum 2. Teil. Dem Download der Datei.

Ein User hat jetzt eine Bedienungsanleitung auf einer Webseite hochgeladen und für andere Benutzer zum Download zur Verfügung gestellt. Jetzt kommt ein anderer User und möchte die Datei downloaden.

Als Programmierer wäre es das einfachste einfach einen Link zu veröffentlichen der auf die Datei, im Dateisystem, zeigt. Das hätte aber den Nachteil das dieser Link kopiert werden könnte und jeder die Datei einfach herunterladen kann. Schlecht wenn das vielleicht eigentlich nur registrierte Mitglieder dürfen sollen.
Also muss eine andere Lösung her. Hier wieder mein Weg nach Rom ;-)


$UploadFolder = "./uploads/"; //Name des Ordners mit der Downloaddatei
$FileName = "musterdatei.pdf"; //Name der Downloaddatei

header("Content-Type: ".$mimeType);
header("Content-Length: ".filesize($UploadFolder.$FileName));
header("Content-Disposition: attachment; filename="".$FileName.""");
readfile($UploadFolder.$FileName);
exit;

Ja, das war es schon ;-) Aber es ist etwas komplizierter als es auf den ersten Blick scheint. Ich denke die ersten beiden Variablen sind klar. Der Content-Type beschreibt die Datei. Ob es ein Bild, PDF, Word-Dokument oder sonst was ist. Am besten ist hier diesen beim Upload gleich mit zu speichern. Denn das ist der einzige Zeitpunkt wo Du den Content Type „geliefert“ bekommst. Sonst könnte man ihn noch über die Dateierweiterung rausbekommen.

Content-Length ist die Länge der Datei. Vorsicht, nicht wirklich die Größe. Da 1 Zeichen aber einem Byte entspricht – wie praktisch – können wir einfach die Dateigröße in Byte (!) angeben. ;-)

Bei Content-Disposition wird einfach gesagt Dateianhang und den Dateinamen. Hier muss nicht der Originale Dateiname angegeben werden, es könnte auch ein fiktiver angegeben werden.

Und zu guter letzt noch mit readfile die Datei einlesen und gleichzeitig ausgeben.

Ganz wichtig ist hier noch das vor diesem Code keine Ausgabe an den Browser gemacht werden darf. Am besten ist es für den Download eine eigene Datei zu erstellen und vor diesem Code nur das nötigste zu tun. Zum Beispiel checken ob der User, der den Download starten möchte, auch die Berechtigung hat oder die Variablen aus einer Datenbank auslesen. Aber keinerlei ausgaben an den Browser machen, sonst erscheinen ganz viele komische Zeichen im Browser ;-)