Über dieses Blog...
Tipps und Tricks, aber auch Kritik - breit gefächert von Technik bis hin zum Design, manchmal (oder immer öfter) auch Politik.
Momentaner Fokus: Android/Java, CalDAV, Windows 7 benutzbar machen
Feeds
Interessant gefunden? Mitlesen? Vollständige Beiträge per Feed.
Zur Weiterverarbeitung oder zum Einbauen für Ihre Homepage: CSV, JavaScript
Tag-Cloud
Durchsuchen
Kategorien
Archiv
| Mo | Di | Mi | Do | Fr | Sa | So |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 |
TYPO3: Sprachwechsler ohne Extension
Von e7 am 16.06.2011, 22:06 in der Kategorie Code-Snippets mit den Tags html javascript mehrsprachig typoscript sprache i18n typo3. Kompletten Eintrag zeigen
Sprachwechsel-Funktionalität in TYPO3, ohne eine eigene Extension zu verwenden. Code einfach als HTML-Contentelement platzieren oder ins Template klatschen, Sprachen anpassen (in den Arrays) und den noscript-Fallback nicht vergessen! Es wird unterstellt, dass die Sprache per Parameter &L=de und ähnlich gewechselt wird.
<script type="text/javascript">
<!--
function changeLanguage() {
var e = document.getElementById(„langswitch“);
var s = „"+document.location;
if (s.indexOf('&L=') != -1) {
s = s.substr(0, s.indexOf('&L=')+3)+e.value;
} else {
s += „&L="+e.value;
}
document.location = s;
}
var availLangCodes = new Array(„de", „cz“);
var availLangDescr = new Array(„Deutsch", „Czech“);
var curLang = „"+document.location;
if (curLang.indexOf('&L=') != -1) {
curLang = curLang.substr(curLang.indexOf('&L=')+3, 2);
} else {
curLang = availLangCodes[0];
}
document.write('<p><select id="langswitch“ onchange="changeLanguage();">');
for (var i = 0; i < availLangCodes.length; i++) {
document.write('<option value="'+availLangCodes[i]+'“ '+(curLang == availLangCodes[i] ? ' selected="selected"' : '')+'style="background-image: url(\'/typo3/gfx/flags/'+availLangCodes[i]+'.gif\'); background-repeat: no-repeat; background-position: 1px 50%; padding-left: 30px; „>'+availLangDescr[i]+'</option>');
}
document.write('</select></p>');
//-->
</script>
<noscript>
<p>
<a href="index.php?id=123&L=de"><img src="/typo3/gfx/flags/de.gif“ alt="DE"></a>
<a href="index.php?id=123&L=cz"><img src="/typo3/gfx/flags/cz.gif“ alt="CZ"></a>
</p>
</noscript>
Natürlich keine Garantie auf Funktionstauglichkeit, da innerhalb weniger Minuten zusammengeschustert und nicht ausführlich getestet, sieht aber ganz gut aus soweit :)
VB6: Laufzeitfehler 10 beheben
Von e7 am 22.02.2011, 15:20 in der Kategorie Code-Snippets mit den Tags bug redim, goto, 10, laufzeitfehler, runtime, error, ide, vb6, visual basic,. Kompletten Eintrag zeigen
In Visual Basic 6 habe ich wieder einen Workaround für einen bescheuerten Bug benötigt. Folgender Laufzeitfehler 10 (Runtime Error) tritt bei Redim auf:
Array ist unveränderlich oder momentan gesperrt
This array is fixed or temporarily locked
Bei Microsoft existiert dafür eine Beschreibung, die „triviale“ Lösung lautet:
Avoid using Exit For inside a With statement. A GoTo statement should be used instead.
NOTE: Be sure that the End With statement is executed. If the statement is not executed, you will receive the above error message.
Das heißt, man muss statt bspw. Exit For folgende Krücke verwenden — also jetzt als Alternative zum GoTo, was ja auch nicht gerade so toll ist, aber ebenfalls eine Lösung darstellt:
Dim outOfLoop As Boolean '<--
For I = 0 To UBound(allProperties)
With arrayName(I)
If .feld = gesuchterwert Then
treffer = I
outOfLoop = True '<--
End If
End With
If outOfLoop Then Exit For '<--
Next I
Interessant ist, dass der Fehler in der IDE nicht auftritt, sondern nur im compilierten Projekt; außerdem scheint man wohl den Code häufiger ausführen zu müssen, bis das Problem auftritt. Auf jeden Fall funktioniert ein ReDim problemlos, wenn ma darauf achtet, dass die Zeile „End With“ grundsätzlich ausgeführt wird.
Man kann sich auch Gedanken über die Architektur machen, die dem VB-Compiler zugrunde liegen muss. Bisher dachte ich, With ist nur eine Art Schreiberleichterung und wird vom Compiler zu normalem Code aufgelöst — scheinbar habe ich da falsch gedacht und er bastelt da noch einiges drum herum.
Visual Basic 6: Windows Media Player-Control (neue wmp.dll statt alte msdxm.ocx)
Von e7 am 17.12.2010, 23:41 in der Kategorie Code-Snippets mit den Tags abspielen nächstes ereignis endofstream starten problem kompatibel msdxm.ocx wmp.dll Windows Media Player vb6 visual basic. Kompletten Eintrag zeigen
Wie es für Microsoft üblich ist, fällt man immer wieder in die Kompatiblitätsfalle: in neuen Versionen ist kaum was kompatibel zum alten bzw. es funktioniert einfach aus rätselhaften Gründen nicht mehr.
Einer dieser Fälle ist die msdxm.ocx. Der gute, alte Windows Media Player, noch in der klassischen Ansicht. Die Datei ist unter Windows 7 nach wie vor vorhanden — und die Programme, die auf die Datei zurückgreifen, können diese nach wie vor verwenden. Nur die Visual Basic 6-IDE macht eine Ausnahme — die ist unter Windows 7 zu doof, das Control einzubinden. Die Abhilfe, die einem überall empfohlen wird: Nimm doch das neue WMP-Control.
Grundsätzlich ist das auch eine gute Idee — wenn es nur nicht so erstaunlich inkompatibel wäre. Erstens lege ich keinen Wert darauf, die Playlisten des Windows Media Players zu pflegen, andererseits brauch ich nicht ein Modell, das zwar ähnlich aussieht, aber in den entscheidenden Punkten abweicht. Und die alte msdxm.ocx hat wenigstens funktioniert und war nicht mit Bugs beladen. Ach ja, vom Aufwand, ganze Projekte auf ein neues Control umzustellen, ganz zu schweigen.
Ich hab mir dafür eine kleine Wrapper-Klasse geschrieben, die sich ähnlich dem alten Control verhält und keine größeren Änderungen am Projekt erfordert. Ihr wird eine Instanz eines der neuen Controls übergeben und simuliert das Interface des alten Players. Gewisse Funktionen (wie „Open“) müssen natürlich im Code umbenannt werden, da man diese Funktionsnamen nicht selbst verwenden kann — ansonsten klappt es eigentlich soweit.
Hier mal das grundlegende Modul basClassicWMP:
Option Explicit
Public Const mpStopped As Long = WMPLibCtl.WMPPlayState.wmppsStopped 'msdxm: 0
Public Const mpPaused As Long = WMPLibCtl.WMPPlayState.wmppsPaused 'msdxm: 1
Public Const mpPlaying As Long = WMPLibCtl.WMPPlayState.wmppsPlaying 'msdxm: 2
Public Const mpWaiting As Long = WMPLibCtl.WMPPlayState.wmppsWaiting 'msdxm: 3
Public Const mpClosed As Long = WMPLibCtl.WMPPlayState.wmppsMediaEnded 'msdxm: 8
Public ClassicWMP_TmrCounter As Long
Hauptsächlich ist das da, um die alten Konstanten wieder zu haben — somit kann man sich zumindest diese Arbeit sparen. Ganz nett ist noch die Variable, die eindeutige Control-Namen sicherstellen soll. Dummerweise ist es so, dass man — wenn ein Lied zu Ende gespielt wurde — in den ausgelösten Ereignissen nicht das nächste starten kann. Macht er einfach nicht — warum auch immer. Der Code dazu ist korrekt, da bin ich mir sicher — wenn man per Hand auf die Schaltfläche klickt, gehts nämlich. Scheinbar darf man keinen neuen Song/Video starten, bevor nicht das Ereignis wieder verlassen wurde.
In der folgenden Klasse gibt es dazu einen dreckigen Work-Around: Es wird ein Timer angelegt, der entsprechend aktiviert wird, wenn abgespielt werden soll — nach 10 ms greift er zu, genug Zeit also, um das Ereignis zu verlassen. „Multithreading“ rulz! Zurück zum Thema: das folgende ist nun die ClassicWMP.cls:
Option Explicit
Private WithEvents WMP As WindowsMediaPlayer
Private WithEvents TMR As VB.Timer
Public Event OpenStateChange(ByVal OldState As Long, ByVal NewState As Long)
Public Event EndOfStream(ByVal Result As Long)
Public Event PlayStateChange(ByVal OldState As Long, ByVal NewState As Long)
Public Event PositionChange(ByVal oldPosition As Double, ByVal newPosition As Double)
Public Event ScriptCommand(ByVal scType As String, ByVal Param As String)
Public Event Warning(ByVal WarningType As Long, ByVal Param As Long, ByVal Description As String)
Private OldState As Long
Property Get PlayState() As Long
PlayState = WMP.PlayState
End Property
Property Get CurrentPosition() As Double
CurrentPosition = WMP.Controls.CurrentPosition
End Property
Property Let CurrentPosition(ByVal newPosition As Double)
WMP.Controls.CurrentPosition = newPosition
End Property
Property Get SendErrorEvents() As Boolean
'Keine Funktion
End Property
Property Let SendErrorEvents(ByVal NewState As Boolean)
'Keine Funktion
End Property
Property Get FileName() As String
If WMP.currentMedia Is Nothing Then
FileName = vbNullString
Else
FileName = WMP.currentMedia.sourceURL
End If
End Property
Property Get Duration() As Double
If WMP.currentMedia Is Nothing Then
Duration = 0
Else
Duration = WMP.currentMedia.Duration
End If
End Sub
Sub Pause()
WMP.Controls.Pause
End Sub
Sub Play(Optional DirectStart As Boolean)
If DirectStart Then
'Direktstart auf ausdrücklichen Wunsch
TMR_Timer
Else
'Indirekt starten
TMR.Enabled = True
End If
End Sub
Private Sub TMR_Timer()
'Indirekt starten
TMR.Enabled = False
WMP.Controls.Play
End Sub
'"Stop“ geht nicht als Funktionsname, da Keyword
Sub StopPlay()
WMP.Controls.stop
End Sub
'"Open“ kann nicht als Funktionsname verwendet werden, da Keyword
Sub OpenFile(FN As String)
WMP.Close
WMP.URL = FN
End Sub
'----
Sub initWMP(Ctrl As WindowsMediaPlayer, DummyForm As Form)
'Controls initialisieren
Set WMP = Ctrl
WMP.settings.Autostart = False
'Timer anlegen
ClassicWMP_TmrCounter = ClassicWMP_TmrCounter + 1
Set TMR = DummyForm.Controls.Add(„VB.Timer", „classicwmp_timer_“ & ClassicWMP_TmrCounter, DummyForm)
TMR.Enabled = False
TMR.Interval = 10
End Sub
Private Sub WMP_OpenStateChange(ByVal NewState As Long)
'Weiterreichen
RaiseEvent OpenStateChange(-1, NewState)
End Sub
Private Sub WMP_PlayStateChange(ByVal NewState As Long)
'Unwichtige ignorieren
If (NewState = WMPLibCtl.WMPPlayState.wmppsTransitioning) Then
DoEvents
Exit Sub
'Workaround für nicht auslösendes EndOfStream-Ereignis
ElseIf (NewState = WMPLibCtl.WMPPlayState.wmppsMediaEnded) Then
RaiseEvent EndOfStream(-1)
Else
'Sonst weiterreichen
RaiseEvent PlayStateChange(OldState, NewState)
End If
'Merken
OldState = NewState
End Sub
Private Sub WMP_PositionChange(ByVal oldPosition As Double, ByVal newPosition As Double)
RaiseEvent PositionChange(oldPosition, newPosition)
End Sub
Private Sub WMP_ScriptCommand(ByVal scType As String, ByVal Param As String)
RaiseEvent ScriptCommand(scType, Param)
End Sub
Private Sub WMP_Warning(ByVal WarningType As Long, ByVal Param As Long, ByVal Description As String)
RaiseEvent Warning(WarningType, Param, Description)
End Sub
Verwendet wird die Klasse in einem Formular, indem man diese zuerst samt Ereignissen einbaut:
Public WithEvents MP As ClassicWMP
Damit ist sie fast wie ein Steuerelement nutzbar. Beispielsweise in Form_Load können wir nun die Variable mit einer neuen Instanz initialisieren:
Set MP = New ClassicWMP
MP.initWMP Me.WMP, Me
Dabei wird ein Objekt des neuen Mediaplayers (hier „WMP“ genannt) übergeben — und das Formular, um darauf einen Timer anlegen zu können, da ein new VB.Timer leider nicht funktioniert und auch CallBack über AddressOf nicht in einer Klasse funktioniert.
Die Klasse wrapt nun fleißig die wichtigsten Dinge hin und her — klar, der Funktionsumfang ist noch nicht ganz so hoch und auch auf die GUI muss man verzichten, aber das wichtigste ist gemacht. Möglicherweise bastel ich das ganze mal noch als Steuerelement, aber vorerst mal eher nicht.
Wichtig ist nur das Fazit, das man daraus zieht: Vertraue nie auf Microsoft-Technologien, irgendwann gehts einfach nicht mehr und es gibt keine Hilfe.
Android: Sensor verwenden - Helligkeit auslesen
Von e7 am 06.11.2010, 00:04 in der Kategorie Code-Snippets mit den Tags ambient licht hardware sensor java android. Kompletten Eintrag zeigen
Und wieder ein Traum zerplatzt: Da ja Android-Geräte häufig einen Helligkeitssensor verbaut haben, dachte ich — aus Entwicklersicht gesehen — an so etwas wie einen Belichtungsmesser für Fotografen, insbesondere um bspw. die Stärke eines Blitzes ausmessen zu können. Dummerweise reagiert bspw. mein Sensor nur ab Lichtschwankungen, die ungefähr eine Sekunde Mindestdauer haben. Bei Blitzen, die kürzer als 1/1000 und so sind, leider inakzeptabel.
Hier trotzdem mal der Code bzw. das Vorgehen:
import android.hardware.*;
Wichtig :)
public class TestActivity extends Activity implements SensorEventListener {
SensorManager sm;
TextView tv;
Wir benötigen einen SensorEventListener, wofür sich im Moment die Klasse anbietet, und etwas zum Anzeigen.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TextView(this);
setContentView(tv);
sm = (SensorManager)getSystemService(SENSOR_SERVICE);
}
Hier ist die Zeile mit dem SensorManager wichtig.
protected void onResume() {
super.onResume();
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_LIGHT), SensorManager.SENSOR_DELAY_FASTEST);
}
protected void onStop() {
super.onStop();
sm.unregisterListener(this);
}
Die Sensor-Events sollten aus Akkugründen nur bei aktivierter Anwendung verarbeitet werden, deshalb in onResume und onStop die entsprechenden Vorgänge. Möglicherweise ist es eine gute Idee, sm.getDefaultSensor vor dem Weiterreichen zu prüfen. Gibt die Funktion null zurück, gibt es nämlich keinen Sensor :)
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
tv.setText(„Aktuell: „+event.values[0]);
}
Auch hier sollte man aufpassen, dass event.values auch tatsächlich ein Element enthält, sonst schmiert's ab, aber generell funktioniert's so.
Ältere Einträge - Alle Nachrichten finden Sie im Archiv.
© 2001 - 2012 by e7o.de; powered by e7cms. XHTML Strict für gute Browser.