views:

130

answers:

3

I'm using this TCanvas to draw cursors for my mice

Canv := TCanvas.Create;
Canv.Handle := GetWindowDC(0);

.... For every mice event do the following

Bitmap:=TBitmap.Create;
CursorInfo.cbSize := sizeof(CursorInfo);
GetCursorInfo(CursorInfo);

Bitmap.Width := 32;
Bitmap.Height := 32;
Bitmap.Transparent:=true;

DrawIconEx(Bitmap.Canvas.Handle, 0,0, CursorInfo.hCursor, 32,32, 0,0, DI_NORMAL) ;

Bitmap.Canvas.Brush.Color := RGB(250,250,250);
Bitmap.Canvas.FloodFill(31,0, clWhite, fsSurface);
Bitmap.Canvas.FloodFill(0,0, clWhite, fsSurface);

currentX:=getcurrentxpos;
currentY:=getcurrentypos;

Canv.Draw(currentX,currentY,Bitmap);
Bitmap.Free;

The problem is instead of just showing the individual cursors, it makes mouse trails. Can I clear the whole Canvas evertime a mouse moves? (doesn't sound like a good idea though). Maybe I could clear my previous Canv.Draw by doing the reverse of that code (if it is possible)? Any suggestions as to how I can show the cursors?

EDIT: tried inserting another Canv.Draw(currentX,currentY,Bitmap); just after setting the bitmap width and height...and now the problem is I have a white trail (rather than a mouse trail), much cleaner but still no good.

+1  A: 

I will show you one way, which is different from what I previously suggest you.
You store your canvas using Canvas.CopyRect in some temporary canvas. when your mouse is first hover on your canvas.
Then, when your mouse is moved, first copy the temporary canvas to your destination canvas then draw your cursor.

Himadri
How do I use these? I can't seem to find useful sample code.
Dian
@Dian I have updated my answer.
Himadri
I tried this solution but it was too difficult to keep track of all the mouse cursors and their previous positions. But thanks for answering, I appreciate it.
Dian
+1  A: 

Have a reference image (which is what your canvas should looks like without the mouse cursor painted on it), copy it to a temporary bitmap and then draw your cursor on that temp bitmap. Finally, draw your image on the canvas.

It also will allow you to have more complex temporary overlays very easily: you just have to draw them on top of the reference bitmap according to their Z-order. Since they aren't touching the background, you don't have to worry about clearing the ghosts.

Stephane
Would this still work if the background changes (A lot)? The background is the application itself, so the users do some typing and other stuff...and it changes frequently, almost as often as the mice move.
Dian
This is the same solution what I gave.
Himadri
+3  A: 

You're drawing on the DESKTOP, and that's something you should never do, because it's unreliable. As I understand it, you're hoping to find a way to paint your mouse cursor on the desktop, and when the mice moves again, "undo" your last paint and repaint the mice at the new coordinates. Imagine this: You move the mice somewhere over a Memo box, move your hands to the keyboard, type something and then move the mouse again. The image under the mice changed!

What you can do: Create a mouse-cursor-shaped form, there are known techniques to do that. Make your pseudo-cursor stay on top (you'll get into a bit of problem with that too, because Windows no longer likes stay-on-top things). This is not going to be easy, but it's manageable and it's PLAYING BY THE RULES.


A little code review on what you've got so far, because I spotted what I think it's a mistake, and you should know about. Fixing this is not enough to fix your problem, you need to stop drawing onto the desktop:

Don't free the Bitmap that holds the transparent cursor image, keep if for the life of the application: You'll save both RAM and CPU. This is critical in something that needs to react to the movement of a mice.

Cosmin Prund
Oh, yeah, thanks, I've decided to place the 'cursor shaping' code in the FormCreate and Bitmap.Free in the FormDestroy. If I use forms is the X,Y coordinates of the Canvas equivalent to the top,left attributes of the form?
Dian
I don't understand your question :( I'm suggesting using a TForm for the mouse. Start with a normal, square TForm, and when that works, "shape" it into an mouse cursor. Simply caching the Bitmap is not going to help much, because you can't control who writes what to the desktop.
Cosmin Prund
Dian
You move the form around using Left and Top. You'll need to take into account the cursor's "hot spot" (for the normal, arrow cursor, the hot spot appears to be in top-left corner, right in the tip of the arrow; For the "I" cursor used for editing, I think the hot spot is in the middle of the "I"; Don't know about the others and don't know how to read it programatically). For the kind of form you'll be using (no borders), drawing starts at Top and Left. And finally, the cursor-shaped form doesn't need to grab focus.
Cosmin Prund
I'm having a little trouble shaping it into a cursor..but otherwise it's working great. Thanks! :D
Dian
@Dian, look here: http://stackoverflow.com/questions/2979125/how-to-make-the-form-into-fully-transparent-32bit-alpha/2988037#2988037
Cosmin Prund
Thanks, but I found some source code the shapes the form into an image of your choice. Pretty darn cool. If hadn't told me I never thought it would be possible. So thanks again. :D
Dian
hmmm.. The Cursor-shaped Forms always shows behind the TMenuItem (for everything else, it shows fine). I already used SetWindowPos and fsStayOnTop. You wouldn't happen to know how to solve this would you?
Dian
No, I don't; My guess: The Menu window is also marked "stay on top". Try sending your window an SetWindowPos, see if you can get it higher.
Cosmin Prund