Discussion:
Im Mauszeiger Text anzeigen?
(zu alt für eine Antwort)
Christoph Ke?ler
2004-12-31 18:16:47 UTC
Permalink
Hallo,
hat jemdand eine gute Idee, wie ich Text (z.B. "Apfel", "Birne",..) in
einem Mauszeiger anzeigen kann (ich möchte dem Nutzer ermöglichen,
vorher eine Auswahl zu treffen, und dann durch den Cursor an die
Auswahl erinnert zu werden)?

Muss ich den Text erst in irendeiner Weise in eine Grafik Konvertieren
(wie ginge denn das am einfachsten?) oder gibt es einen einfacheren
Weg?

Ich habe bisher mit der API-Funktion CreateCaret und ShowCaret
gearbeitet. Habe aber keine weitere Dokumentation.

Ansonsten wünsche ich allen Delphi-Freunden noch einen guten Rutsch!

Christoph Keßler
Andreas
2005-01-01 02:00:57 UTC
Permalink
Hallo,
Post by Christoph Ke?ler
hat jemdand eine gute Idee, wie ich Text (z.B. "Apfel", "Birne",..) in
einem Mauszeiger anzeigen kann (ich möchte dem Nutzer ermöglichen,
vorher eine Auswahl zu treffen, und dann durch den Cursor an die
Auswahl erinnert zu werden)?
Hmmm, ist der Nutzer denn so vergesslich? ;-)
Post by Christoph Ke?ler
Muss ich den Text erst in irendeiner Weise in eine Grafik Konvertieren
(wie ginge denn das am einfachsten?) oder gibt es einen einfacheren
Weg?
(canvas.Font. ... := ...)
canvas.TextOut(x,y,'Apfel');
(wobei canvas z.B. das canvas einer Bitmap ist)
.. ist also nicht wirklich schwer.
Post by Christoph Ke?ler
Ich habe bisher mit der API-Funktion CreateCaret und ShowCaret
gearbeitet. Habe aber keine weitere Dokumentation.
In der Delphi Hilfe zur Windows API steht doch einiges...
Hmmmm,... was hat denn das mit nem Mauszeiger zu tun?
Damit kann man doch nur ein "Blinkendes Etwas", also z.B. den Balken in
einem Editfeld erzeugen. (oder hab ich mich da verlesen?)


V1)
Du könntest z.B. ein Panel nehmen (muß also ein TWincontrol sein, sonst
kannst du es nicht in den Vordergrund setzen) , dessen Caption deinen String
zuweisen, und das Ding dann immer bei einer Mausbewegung an die aktuelle
Position setzen.
...Transparent würde man das Panel auch noch bekommen... (oder gleich eine
fertige Komponente suchen, die sich transparent darstellen läßt)

V2)
Du zeichnest bei einer Mausbewegung immer dirkt auf den Bildschirm,..
sicherst also erst den Bereich, den du übermalen wirst, schreibst dann den
Text, und stellst anschließend den Originalzustand wieder her,..
(myCanvas.handle := GetWindowDC(GetDesktopWindow); .. und dann kannst du mit
myCanvas die notwendigen Aktionen ausführen)

V3)
Du änderst den Mauszeiger, schreibst also den Text dazu.
Eventuell ein Problem ist, daß so ein Mauszeiger nur 32x32 Pixel groß ist,
lange Strings passen da also nicht drauf.
Es hatte zwar auch funktioniert größere Mauszeiger zu erzeugen (bei mir
unter XP), dabei gab es aber, u.a. abhängig von der Größe einige
Problemchen,.. von falscher Darstellung bis zum BlueScreen,..

Und hier nun der Code:
=> Der Cursor ist hier 32x32 groß (ich nehme als Vorlage immer den gerade
sichtbaren), somit gibt es da keinen Ärger.
Funktioniert aber "nicht" bei animierten Cursorn, .. die Animation würde
nicht weiterlaufen, ansonsten geht's aber auch.

Im Nachfolgenden Code, wird jedesmal ein neuer Cursor erzeugt, man könnte
auch am Anfang alle generieren, und dann nur zwischen den einzelnen
wechseln.

Kurz die Funktionsweise:
- ID des gerade sichtbaren Cursor sichern (um ihn später wieder herstellen
zu können)
- Gerade sichtbaren Cursor nehmen und Bitmap und Maske extrahieren
- In die Beiden Bilder den Text dazuschreiben
- Daraus einen neuen Cursor ezeugen.
- Diesen in die Cursorliste des Programms eintragen
- Neuen Cursor setzen

// (global)
const MyCursorID = 2; // unter dieser ID wird der Cursor dann gespeichert,..
man kann alle Zahlen >0 nehemen
var oldCursorID:integer;

//(lokal)
var cursorICONINFO:ICONINFO;
tmpBitmap,tmpMaskBitmap:TBitmap;
cursortext:string;

begin
cursortext:='Apfel'; // <= CursorText

tmpMaskBitmap:=TBitmap.create;
tmpBitmap:=TBitmap.create;

// if screen.cursor = MyCursorID then exit; // oder was ähnliches, um
zu vermeiden, daß man oldCursorID mit MyCursorID überschreibt,..

oldCursorID:=screen.cursor; // alte CursorID sichern,..
GetIconInfo(Screen.Cursors[screen.cursor],cursorICONINFO); // Daten des
gerade sichtbaren Cursor holen
// Anstelle mit Bitmaps könnte man es natürlich auch direkt mit den API
Funktionen machen,..
tmpMaskBitmap.handle:=cursorICONINFO.hbmMask;
tmpBitmap.handle:=cursorICONINFO.hbmColor;

with tmpBitmap.canvas do
begin
Font.Color:=clred; // <= Farbe des Textes
Font.Size:=10; // <= Textgröße
brush.style:=bsClear; // <= Text hat keine Hintergrundfarbe
TextOut(0,textheight(cursortext),cursortext); // <= Text ausgeben,
(x,y,text)
end;

with tmpMaskBitmap.canvas do
begin
Font.Color:=clblack; // clblack -> Farbe aus tmpBitmap //
clwhite -> transparent / XOR
Font.Size:=10; // <= Textgröße
brush.style:=bsClear; // <= Text hat keine Hintergrundfarbe
TextOut(0,textheight(cursortext),cursortext);
end;

// kann sein, daß sich xxxBitmap.Handle geändert hat, also lieber noch
mal neu zuweisen
with cursorICONINFO do
begin
hbmMask:= tmpMaskBitmap.Handle;
hbmColor:=tmpBitmap.Handle;
end;
ExtCursor:=CreateIconIndirect(cursorICONINFO); // aus den Bitmaps nen
Cursor machen

// Testausgabe, um sich die beiden Bilder mal anzusehen, canvas war hier das
des Formulars
canvas.Draw(10,10,tmpBitmap); // Testausgabe
canvas.Draw(10,100,tmpMaskBitmap); // Testausgabe

// // denke, daß Screen den alten Cursor selbst wieder freigibt // //
Screen.Cursors[MyCursorID] := ExtCursor; // Cursor in Cursorliste
eintragen
Screen.Cursor:=MyCursorID; // CursorID zum neue erzeugten Cursor
setzen (Applikationsweit)
//Cursor:=MyCursorID; // Nur für Formular, also nicht für andere
Komponenten auf dem Formular

// Und die Bitmaps brauchen wir nicht mehr
tmpMaskBitmap.free;
tmpBitmap.free;
end;


//...
//und irgendwo dann wieder den alten Cursor herstellen:
Screen.Cursor:=oldCursorID;


Andreas.
Andreas
2005-01-01 15:14:15 UTC
Permalink
Post by Andreas
Post by Christoph Ke?ler
Ich habe bisher mit der API-Funktion CreateCaret und ShowCaret
gearbeitet. Habe aber keine weitere Dokumentation.
In der Delphi Hilfe zur Windows API steht doch einiges...
Hmmmm,... was hat denn das mit nem Mauszeiger zu tun?
Damit kann man doch nur ein "Blinkendes Etwas", also z.B. den Balken in
einem Editfeld erzeugen. (oder hab ich mich da verlesen?)
Naja, egal,.. hier auch noch was dazu:


procedure TForm1.setCaret;
var tmpBitmap:TBitmap;
cursortext:String;
begin

cursortext:='Apfel';
tmpBitmap:= TBitmap.Create;

with tmpBitmap do
begin
PixelFormat:=pf8bit;
with canvas do
begin
Font.Color:=clyellow; // Die dargestellt Farbe ergibt sich ja
als Farbe XOR Hintergrund (oder so)
Font.Size:=10;
brush.color:=clblack; //clblack -> Transparent
Width:=textWidth(cursortext);
Height:=textHeight(cursortext);
TextOut(0,0,cursortext);
end;
end;
canvas.Draw(100,10,tmpBitmap); // Testausgabe
if not CreateCaret(handle,tmpBitmap.handle,0,0) then
caption:='CreateCaret fehlgeschlagen';
SetCaretPos(100,10);
ShowCaret(handle);
end;

=> Damit wird auf dem Formular der blinkende Text Apfel angezeigt (handle
ist hier das handle des Formulars)
Um das ganze sinnvoll zu verwenden, also den blinkenden Balken in einem Memo
durch den blinkenden Text Apfel zu ersetzen, muß natürlich anstelle handle,
das MemoX.Handle verwendet werden, das SetCaretPos kommt weg, und man muß
setCaret zum richtigen Zeitpunkt aufrufen, also wenn das Memo den Fokus
bekommt, aber auch erst nachdem der entsprechende Standardcode des Memos
abgearbeitet wurde (in onEnter geht es also nicht,.. da würde dann das Memo
einfach wieder den Balken setzen)
-> Vermutlich würde es funktionieren, wenn man doEnter überschreibt,.. oder
man fängt WM_SETFOCUS ab,...

Ein Beispiel zu MausZeiger und Caret hab ich dir mal als Mail geschickt.
Ach ja: Das ganze hab ich gerade nur mal so ausprobiert,.. (fand es doch
interessant und hatte gerade Zeit). Folglich ist der Code mehr als
Orientierungshilfe zu sehen,.. es läßt sich noch einiges schöner machen, und
ob man hier und da noch was freigeben müßte oder nicht, oder...

Andreas.

Lesen Sie weiter auf narkive:
Loading...