Gehe zu deutscher Webseite

ViaThinkSoft CodeLib

This article is in:
CodeLibProgramming aidsDelphi

Viele Nutzer ärgern sich über nicht eingehaltene Design-Standards bei Windows Anwendungen. Es gibt bei Delphi viele Eigenentwicklungen in der VCL, die jedoch aufgründen der Kompatibilität und Unabhängig auch teilweise von Vorteil sind. Mich ärgert jedoch häufig der hässliche Hand-Mauszeiger crHandPoint von Borland (besonders wegen den Ärmeln). Dieser passt nicht in den Stil von Windows und lässt dem Benutzer keinen Freiraum für eigene Windows-Styles. Hat der Benutzer statt der weißen Hand einen völlig anderen Zeiger definiert, ist es sogar noch gravierender. Folgende Unit löst das Problem durch simples Einbinden.

Code der einzubindenen Unit

unit HandCursor;

{
* WINDOWS HAND CURSOR UNIT FOR DELPHI BY DANIEL MARSCHALL
* (C)Copyright 2008 - 2009 ViaThinkSoft [ www.viathinksoft.de ]
*
* Requirements: Windows 95/NT and Delphi 3
* Revision: 2009-09-06
}

{$WARNINGS OFF}

{$IFNDEF VER80} // Delphi 1.0
{$IFNDEF VER90} // Delphi 2.0
{$IFNDEF VER93} // C++ Builder 1.0
{$IFNDEF VER100} // Delphi 3.0
{$IFNDEF VER110} // C++ Builder 3.0
{$DEFINE DELPHI_4_UP}
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$ENDIF}

interface

implementation

uses
  Windows { HCURSOR, LoadCursor, IDC_HAND },
  Controls { crHandPoint },
  Forms { Screen };

// IDC_HAND is existing in Windows.pas since Delphi 4

{$IFNDEF DELPHI_4_UP}
const
  IDC_HAND = MakeIntResource(32649);
{$ENDIF}

var
  hCur: HCURSOR;

{$R Hand.res}

initialization
  hCur := LoadCursor(0, IDC_HAND);
  if hCur > 0 then
  begin
    Screen.Cursors[crHandPoint] := hCur;
  end
  else
  begin
    hCur := LoadCursor(HInstance, 'HAND');
    if hCur > 0 then
    begin
      Screen.Cursors[crHandPoint] := hCur;
    end;
  end;
end.

Ich hoffe, ich konnte für diese Angelegenheit eine nahezu perfekte Musterlösung erstellen.

Ich würde mich freuen, wenn mir noch jemand bestätigen könnte, ob es mit C++ Builder 2, 3, 4 oder Lazarus (welche Versionen?) auch funktioniert. Ich habe die Vermutung, dass es bei C++ Builder 2 keinen crHandPoint als Cursor gibt (so wie bei Delphi 2). Außerdem würde ich gerne bestätigt bekommen, dass IDC_HAND erst in C++ Builder 4 hinzugekommen ist (in C++ Builder 3 also nicht existiert).

Vielen Dank an omata für den Test in Delphi 4!

Kompatibilität

Windows: Getestet unter Windows 95 bis ME
Windows NT: Getestet unter Windows 2000 bis Vista (NT unbekannt)

Delphi: Getestet unter Delphi 3 .. 2009; Delphi 2 ist garantiert ausgeschlossen.
C++ Builder: Keine Tests vorliegen. Wahrscheinlich funktioniert es für C++ Builder 3 .. 2009.
Lazarus: Keine Tests vorliegen

Herleitung

Zunächst einmal würde folgender Code im OnCreate Ereignis alle crHandPoint mit dem Windows-Handzeiger ersetzen:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Screen.Cursors[crHandPoint] := LoadCursor(0, IDC_HAND);
end;

Dieser Code hat aber den großen Nachteil, dass er auf Windows 95 und NT nicht arbeitet, da es dort noch kein IDC_HAND gibt. Eine "Fallback"-Lösung, die automatisch auf einen anderen Cursor zurückgreift wäre hier angebracht.

Dieser Code überprüft zusätzlich, ob der Cursor IDC_HAND verfügbar ist. Bei Windows 95 und NT bleibt der Handzeiger von Borland erhalten (Fallback):

procedure TForm1.FormCreate(Sender: TObject);
var
  hCur: HCURSOR;
begin
  hCur := LoadCursor(0, IDC_HAND);
  if hCur > 0 then Screen.Cursors[crHandPoint] := hCur;
end;

Nun ein etwas erweiterter Code, der es auch erlaubt, unter Windows 95/NT beim Fehlschlag von IDC_HAND einen Windows-Handzeiger per Ressource einzubinden. Auch hier ist ein Fallback vorgesehen, wenn der Ressource etwas seltsames passiert sein sollte (z.B. Einbinden vergessen):

{$R Hand.res}

procedure TForm1.FormCreate(Sender: TObject);
var
  hCur: HCURSOR;
begin
  hCur := LoadCursor(0, IDC_HAND);
  if hCur > 0 then
  begin
    Screen.Cursors[crHandPoint] := hCur;
  end
  else
  begin
    hCur := LoadCursor(HInstance, 'HAND');
    if hCur > 0 then
    begin
      Screen.Cursors[crHandPoint] := hCur;
    end;
  end;
end;

Anmerkung: Die beigelegte Hand.res muss im Suchpfad des Compilers sein!

Jetzt muss das ganze nur noch in eine eigene Unit gepackt werden, die dann einfach nur noch eingebunden werden muss. Außerdem setze ich Compilerdirektiven, um die höchst mögliche Codecompatibilität zu erreichen.

Download der Unit und der Ressourcendatei:

https://www.viathinksoft.de/?page=projektanzeige&seite=download&id=157

Referenz: http://www.delphipraxis.net/topic141178.html
Daniel Marschall
ViaThinkSoft Co-Founder