www.xordern.net

Scherzfunktionen-Programmieren

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).

ControlMouse I

Mauszeiger springen lassen...

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);
}

Control-IO

(Delphi) Beispiel herunterladen [200 kB]

BlockInput (Maus-/Tastatureingaben blockieren)

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;

Monitor ausschalten (Energiesparmodus)

=> Beispiel herunterladen

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)



ControlCDdoor

(Visual Basic) Beispiel herunterladen [10,1 kB]

CD-Laufwerk kontrollieren

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

Demo-WindowsForms-Net

(c#) Download des Beispiels "Demo-WindowsForms-Net" [17,2 kB]

Abblenden [Opacity]

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;

Durchsichtige Fenster [TransparencyKey]

=> Beispiel herunterladen


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".


ControlHandles

(c++) Download des Beispiels "ControlHandles" [65,2 kB]

Kontrolle von Programmen

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

Objekte / Fenster / Handles:

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.

Suchen von Handles.

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.

Nachrichten senden.

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);

Auslesen.

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);

Hinweis.

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.

  © 2009-2014 Dominik Bok