Nun habe ich die CDs mit meinen alten Programmen ausgegraben, um kleine lustige Scherzfunktionen wiederzufinden, die ich irgendwann mal in einer Anwendung verwendet hatte.
Kurzer Hinweis: Scherze sind nur dann witzig, wenn sie in einem bestimmten Zusammenhang geschehen (z.B. "Hier bitte NICHT drücken" oder "Drücken Sie bloß nicht auf Nein!") oder überraschend passieren (z.B. Das CD-Laufwerk öffnet sich - "Legen Sie jetzt 20 € zum Bezahlen der Shareware in das Laufwerk und quittieren Sie den Vorgang mit Ok")
Außerdem sollten Scherze zeitlich begrenzt sein und nach kurzer Zeit ohne Schaden aufhören....
Die folgenden Funktionen könnten für Scherzprogramme genutzt werden:
(Die Implementierung in verschiedenen Programmiersprachen funktioniert vom Prinzip meist ähnlich, sodass meist nur eine Sprache in den Beispielen verwendet wurde - es sind nur englische Versionen verfügbar).
Beispiel: .Net / [C#]
Objekt: System.Windows.Forms.Control.Cursor
Diese Eigenschaft kann nicht nur gelesen, sondern auch gesetzt werden.
Code:
int screen_width = Screen.PrimaryScreen.Bounds.Width; int screen_height = Screen.PrimaryScreen.Bounds.Height; Random rnd = new Random(); for (int z=0;z<20;z++) { Cursor.Position = new Point(rnd.Next(0, screen_width), rnd.Next(0, screen_height)); Application.DoEvents(); Thread.Sleep (550); }
(Delphi) Beispiel herunterladen [200 kB]
Die Funktion BlockInput ermöglicht das Blockieren von Mausbewegungen oder Tastatureingaben.
DLL: user32.dll
Hinweis: Unter Windows Vista benötigt das Programm Adminrechte, um die Funktion aktivieren zu können.
Die Blockade kann mittels STRG+ALT+ENTF deaktiviert werden (<->DisableTaskMgr ?).
Code:
[Delphi:]
procedure TForm1.Block (); var DLLHandle: THandle; FuncPtr: TFarProc; BI: function(Block: BOOL): BOOL; stdcall; begin DLLHandle := LoadLibrary('user32.dll'); FuncPtr := GetProcAddress(DLLHandle, 'BlockInput'); if FuncPtr <> nil then begin @BI :=GetProcAddress(DLLHandle, PChar('BlockInput')) ; BI(true); // Maus + Tastatur sperren Sleep (6501); BI(false); //Maus + Tastatur wieder freigeben end; FreeLibrary(DLLHandle); end;
Ein nicht mehr vorhandenes Bildschirmsignal weckt die Befürchtung, dass etwas passiert, das nicht gesehen wird.
Der Monitor kann beispielsweise mittels Engeriesparmodus ausgeschaltet werden.
Code:
[Delphi:]
for i := 0 to 16 do begin SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, 2); Sleep (400); // 6400 ms end; //Energiesparmodus (re-)aktivieren SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, -1); //Energiesparmodus deaktivieren (Monitor wieder einschalten)
(Visual Basic) Beispiel herunterladen [10,1 kB]
Immer wieder überraschend ist das unerwartete Bedienen des CD-Laufwerkes. Dieses kann von Programmen geöffnet oder geschlossen werden.
DLL: winmm.dll
Einstiegspunkt: mciSendStringA
Befehl:
Öffnen: "set cdaudio door open"
Schließen: "set cdaudio door closed"
Code:
[C#:]
[DllImport("winmm.dll", EntryPoint="mciSendStringA", CharSet=CharSet.Ansi)] protected static extern int mciSendString (string mciCommand, StringBuilder returnValue, int returnLength, IntPtr callback); static void open () { mciSendString ("set cdaudio door open", null, 0, IntPtr.Zero); } static void close() { mciSendString ("set cdaudio door closed", null, 0, IntPtr.Zero); }
[Basic]
Private Declare Function mcisendString Lib "winmm.DLL" Alias _ "mciSendStringA" (ByVal lpstrCommand As String, ByVal _ lpstrReturnString As String, ByVal wReturnLength As Integer, _ ByVal hCallack As Integer) As Long Sub open () Call mcisendString("Set CDAudio Door Open", 0&, 0, 0) 'Open Wait End Sub Sub close () Call mcisendString("Set CDAudio Door Closed", 0&, 0, 0) 'Closed Wait End Sub
(c#) Download des Beispiels "Demo-WindowsForms-Net" [17,2 kB]
Beispiel: .Net / [C#]
Eigenschaft: System.Windows.Forms.Form.Opacity
Die Eigenschaft Opacity bestimmt den Grad der Durchsichtigkeit eines .Net Forms (Fensters) in Prozent.
Code:
[C#:]
//Fenster 100%-sichtbar this.Opacity = 1; //Fenster ab- und aufblenden for (int h=0;h<2;h++) { for (int j=100;j>20;j--) { this.Opacity -= 0.01; Application.DoEvents(); Thread.Sleep (40); //alle 40 ms } for (int j=20;j<100;j++) { this.Opacity += 0.01; Application.DoEvents(); Thread.Sleep (60); //alle 60 ms } } //Fenster 100%-sichtbar this.Opacity = 1;
Mit dieser Eigenschaft kann ein WindowsForm transparent gemacht werden.
Beispiel: .Net / [C#]
Eigenschaft: System.Windows.Forms.Form.TransparencyKey
Die Eigenschaft TransparencyKey bestimmt eine Farbe auf einem .Net-Form (Fenster), an dessen Auftreten das Form durchsichtig wird.
Wenn der FormBorderStyle auf None gesetzt wird, ist es so möglich, nicht rechteckige Fenster zu erstellen.
Code [C#]:
Der TransparencyKey kann als Eigenschaft eines WindowsForms gesetzt werden:
this.TransparencyKey = Color.Pink;
Überall, wo nun pinke Farbe auf dem Form auftritt, wird es durchsichtig sein. Falls die Farbe nicht am Rand gesetzt ist, bekommt das Form "Löcher".
(c++) Download des Beispiels "ControlHandles" [65,2 kB]
Glauben Sie, dass es jedes Fenster unter Windows fernbedient werden kann? Bzw. denken Sie, dass ein Programm Text aus einer anderen Anwendung auslesen kann?
Dieses Beispiel verdeutlicht den Umgang mit Handles am Beispiel von Notepad.
Beispiel: C++
DLL: user32.dll
genutztes Verfahren: Ereignisse an Windows-Nachrichtenschleife senden
Hilfreiche Tools: Microsoft Spy++
andere Handles können kontrolliert und gelesen werden
Im Prinzip besitzt jedes Objekt (Fenster, Button,...) unter Windows ein Handle, mit dem es angesprochen werden kann. Dieses Handle besitzt einen Klassennamen, Windowstext und kann Meldungen empfangen bzw. produzieren.
HWND <handlename> = NULL;
Diese Objekte können allerdings auch "von außerhalb" von anderen Programmen gesucht und gefunden sowie anschließend kontrolliert werden.
a) EnumWindows-Prozedur
//Suchen eines Fensters mit bestimmter ProzessID BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM param) { HWND found_hwnd; DWORD id = GetWindowThreadProcessId(hwnd, NULL); if (id == (DWORD)param) { //found found_hwnd=hwnd; return false; } return true; } BOOL OtherProcedure () { [...] ::EnumWindows(&EnumWindowsProc, pi.dwThreadId); [...] }
In diesem Fall wäre found_hwnd das gefundene Handle.
b) FindWindow
Es ist auch möglich Handles über die Funktion FindWindow zu finden.
Diese Funktion sucht nach einem Klassen- (class name) oder Window-Namen (Titel/Aufschrift):
HWND hIam = FindWindow(_T("Notepad"),0); //suche nach einem Handle mit dem Klassennamen "Notepad" HWND hIam = FindWindow(0,_T("Speichern unter")); //suche nach einem Handle mt dem Windownamen (Titel) "Speichern unter"
c) FindWindowEx
Die Handles, die dem übergeordneten (Parent-)Handle untergeordnet sind (Child), können über die Funktion FindWindowEx nach Klassen-/Windowsnamen gesucht werden.
Suche im Handle hParent nach dem (ersten) Handle mit dem Klassennamen "Edit":
HWND hChild = ::FindWindowEx(hParent, NULL, _T("Edit"), NULL);
Suche in einem Handle nach dem (ersten) Handle mit der Aufschrift "&Ja":
HWND hChild = ::FindWindowEx(<HANDLE>, NULL, NULL, "&Ja");
d) weitere Methoden
Außerdem können Handles mit Befehlen wie GetActiveWindow() oder WindowFromPoint(POINT*) z.B. unter dem Mauszeiger gefunden werden.
Diese Handles können Nachrichten (Meldungen) empfangen. Zum Senden einer Nachricht kann der Befehl PostMessage oder SendMessage verwendet werden.
Dazu wird diesem Befehl z.B. der Handle eines Textfeldes, der Nachrichtentyp sowie ein Buffer mit dem Inhalt übergeben.
PostMessage(<TEXT-HANDLE>,WM_CHAR,chararray[position],0);
Die Übergabe der Nachricht eines Klicks an ein Buttonhandle sieht so aus:
PostMessage(<BUTTONHANDLE>,BM_CLICK,0,0);
Allerdings kann nicht nur etwas "zu einem Handle" gesendet, sondern auch empfangen werden.
Beispielsweise kann der Inhalt (window name) eines Textfeld-Handles (von einem anderen Programm) ausgelesen werden:
HWND programm = FindWindow(NULL,_T("Fenstertitel")); HWND teilfenster = ::FindWindowEx(programm, NULL, _T("RichViewEdit"), NULL); char buffer[1024]; SendMessage(teilfenster, WM_GETTEXT, (WPARAM)256,(LPARAM)buffer); MessageBox (NULL, buffer, "Inhalt des Textfeldes:", NULL);
Dies sollte nur auf sehr einfachem Niveau verdeutlichen, wie ungefähr mit Handles umgegangen werden kann - natürlich stellt dies keine Referenz dar und ersetzt keine Dokumentation.
Weitere Informationen zu diesen Themen können z.B. in der MSDN-Dokumentation gefunden werden. Hilfreich zur Ermittlung von Handles und Meldungen ist auch das Programm "Microsoft Spy++", das in Visual Studio mitgeliefert ist.
Aufbauend auf diesen Grundlagen sollte es möglich sein, den Quellcode des Programmes zu verstehen.