 |
|
 |
Firstly Good, Informative article 
In your article you had pasted the cursor image over desktop image as image. I was just wondering if the same can be achieved using Bitblt? i.e directly copying the bitmap of cursor to bitmap of desktop without creating any intermediate image and pasting one bitmap over other using Bitblt?
|
|
|
|
 |
|
 |
Hi, I want to develop a utility in C# .Net that can be used for Remote Desktop Monitoring. I want to know whether any class or APIs are supporeted by .Net which will help me in this regard. In Java we have a Robot class which will provide us many APIs for the same.Is there any equivalent class in .Net?Please share your knowledge regarding this.Thanking you in advance.
pp
|
|
|
|
 |
|
 |
Hello, I need to capture the mouse cursor image in VC++ 6.0 . Can you guide me coz its pretty urgent!
Regards, Sobaan
|
|
|
|
 |
|
 |
Hi,
I tried to capture the cursor when it is over a text and the code did not capture it.
I think the issue is on the method ToBitmap(). Does anybody you know can I print the text cursor on the screen?
Thanks,
Marcelo Fornazin
|
|
|
|
 |
|
 |
One more information. I'm talking about the I-beam cursor. I can't draw the I-beam cursor using ToBitmap() method.
|
|
|
|
 |
|
 |
Hello, It is not rendering me desktop image with mouse. I have checked the image of bitmap, that is coming fine, but when i open the desktop image with mouse image, it is not working and showing me nothing. Kindly help me how i can also use it to capture the complete movement of the mouse over the captured screen image. Thanks
|
|
|
|
 |
|
 |
Hello, I want to know that is there any possibility to control the remote desktop using my own mouse and keyboard the same like WINdows XP RDP utility? Kindly send me the links where i can found the code sample or can you provide the code sample on the Code project.com to share your knowledge with others. I really need it urgently so that i may complete my final project.
Waiting for your reply. Regards,
|
|
|
|
 |
|
 |
When the cursor is an IBeam (like when over a text editor), the captured image is white, rather than black. This is because the cursor image is actually white, but the cursor mask is entirely white as well. When the cursor is applied to the screen, the mask is AND'ed with the screen contents, then the cursor bitmap is XOR'ed with this result. This is fine for applying it to the screen, but if one wants a picture of what the icon usually looks like on a white background, you would have to do something like this:
Step 1: destimage = image xor mask Step 2: destmask = (not mask) or image Step 3. dest = destmask and destimage
This would be the correct(?) result of a function returning an alpha-blended image of the cursor.
But if you just want to use it in a screen capture program, you should check for the presence of the mask/image information and use it the same way Windows does when rendering the screen. This would provide an exact match.
|
|
|
|
 |
|
 |
Theres a simpler way to solve this. Instead of exracting the bitmap and using graphics.DrawImage, one can call graphics.DrawIcon passing the icon obtained through Icon.FromHandle. This handles the mask.
|
|
|
|
 |
|
 |
Found the leaks. Wrapped it up in a self-contained class for just the single purpose of capturing an image of the cursor. Sorry about the VB.Net. I come from a VB6 background and haven't switched to C# yet.
There were two problems:
1) Not releasing the bitmap(s) created by the call to GetIconInfo (normally just one). 2) Not destroying the icon created using CopyIcon.
Since Windows 2000/XP only gives you approx. 10.000 GDI handles per process, this is the reason why the original version failed after around 5.000 iterations (two leaks per call).
Hope this sample helps anyone searching for this kind of information. Seems to work ok now. Using GetGuiResources really helped pinpoint the problem.
---snip---
Option Explicit On Option Strict On
'Research '-------- ' '"Capturing the Desktop Screen with the Mouse Cursor Image" 'The original screen capture sample from which CaptureCursor was adapted. 'http://www.codeproject.com/csharp/DesktopCaptureWithMouse.asp ' '"Example of overlaying a cursor on a bitmap multiple times" (Delphi code) 'Details some peculiarities of GetIconInfo. 'http://homepages.borland.com/efg2lab/Library/Graphics/CursorOverlay.htm
Imports System.Runtime.InteropServices
Public Class RTGlobalCursor Private Const CURSOR_SHOWING As Integer = 1
<StructLayout(LayoutKind.Sequential)> _ Private Structure CURSORINFO ' Fields Public cbSize As Integer Public flags As Integer Public hCursor As IntPtr Public ptScreenPos As Point End Structure
<StructLayout(LayoutKind.Sequential)> _ Private Structure ICONINFO ' Fields Public fIcon As Boolean Public xHotspot As Integer Public yHotspot As Integer Public hbmMask As IntPtr 'Handle of the icon’s bitmask bitmap. Public hbmColor As IntPtr 'Handle of the icon’s color bitmap. Optional for monochrome icons. End Structure
<StructLayout(LayoutKind.Sequential)> _ Private Structure POINT ' Fields Public x As Integer Public y As Integer End Structure
<DllImport("user32.dll")> _ Private Shared Function CopyIcon(ByVal hIcon As IntPtr) As IntPtr End Function
<DllImport("gdi32.dll")> _ Private Shared Function DeleteObject(ByVal hDc As IntPtr) As IntPtr End Function
<DllImport("user32.dll")> _ Private Shared Function DestroyIcon(ByVal hIcon As IntPtr) As Boolean End Function
<DllImport("user32.dll")> _ Private Shared Function GetCursorInfo(<Out()> ByRef pci As CURSORINFO) As Boolean End Function
<DllImport("user32.dll")> _ Private Shared Function GetIconInfo(ByVal hIcon As IntPtr, <Out()> ByRef piconinfo As ICONINFO) As Boolean End Function
<DllImport("user32.dll")> _ Private Shared Function GetGuiResources(ByVal hProcess As IntPtr, ByVal uiFlags As Integer) As Integer End Function
Private Shared Function GetGDIHandleCount() As Integer Return GetGuiResources(Process.GetCurrentProcess.Handle, 0) End Function
Private Shared Function GetUserHandleCount() As Integer Return GetGuiResources(Process.GetCurrentProcess.Handle, 1) End Function
Private Shared Sub HandleMessage(ByVal message As String) Debug.WriteLine("HC: " & message & ": GDI: " & GetGDIHandleCount().ToString & ": User: " & GetUserHandleCount().ToString) End Sub
Public Shared Function CaptureCursor(ByRef x As Integer, ByRef y As Integer) As Bitmap 'Return value initially nothing Dim bmp As Bitmap = Nothing
Dim curInfo As New CURSORINFO curInfo.cbSize = Marshal.SizeOf(curInfo)
'HandleMessage("Start")
If GetCursorInfo(curInfo) Then If curInfo.flags = CURSOR_SHOWING Then Dim hicon As IntPtr = CopyIcon(curInfo.hCursor)
If hicon <> IntPtr.Zero Then Dim icoInfo As ICONINFO If GetIconInfo(hicon, icoInfo) Then 'Delete the mask, if present. If icoInfo.hbmMask <> IntPtr.Zero Then DeleteObject(icoInfo.hbmMask) End If
'Delete the color bitmap, if present. If icoInfo.hbmColor <> IntPtr.Zero Then DeleteObject(icoInfo.hbmColor) End If
x = curInfo.ptScreenPos.x - icoInfo.xHotspot y = curInfo.ptScreenPos.y - icoInfo.yHotspot
End If
Dim ic As Icon = Icon.FromHandle(hicon) bmp = ic.ToBitmap
'Must destroy the icon object we got from CopyIcon DestroyIcon(hicon)
End If End If End If
'HandleMessage("End")
Return bmp
End Function
End Class
-- modified at 10:52 Tuesday 14th March, 2006
|
|
|
|
 |
|
 |
you such a genius...
really thanks
enjoy code.
|
|
|
|
 |
|
|
 |
|
 |
I was looking for some code to grab the current, global cursor and came across your sample code. Great! Exactly what I was looking for.
Except: To ensure that there was no memory or handle leaks in the code, I ran a call to CaptureCursor 1000s of times in a loop. I did not do anything with the bitmap returned. After nearly 5,000 calls an exception is generated by the .ToBitmap call. The stacktrace looks like this:
---snip--- at System.Drawing.Graphics.GetHdc() at System.Drawing.Internal.WindowsGraphics.FromGraphics(Graphics g, ApplyGraphicsProperties properties) at System.Drawing.Icon.Draw(Graphics graphics, Rectangle targetRect) at System.Drawing.Icon.ToBitmap() at ... CaptureCursor(Int32& x, Int32& y) ---snip---
This happens consistently after 4,975-4,981 calls (tested on two WinXP machines). I did not change anything in your code, except making the capture stuff public, so I could access it using a reference in a vb.net project.
Here is my test loop: ---snip--- Private Sub CaptureCursorLoop() Dim totalmemory As String = "" For i As Integer = 1 To 10000 Dim x As Integer Dim y As Integer Dim bm As Bitmap = ScreenshotCaptureWithMouse.ScreenCapture.CaptureScreen.CaptureCursor(x, y)
If i Mod 200 = 0 Then totalmemory = GC.GetTotalMemory(False).ToString End If
Me.Text = i.ToString & ": Memory: " & totalmemory
Next End Sub ---snip---
I know this is irrelevant to your sample application, but for other application types (e.g. a screen magnifier displaying a copy of the current global cursor, updated several times a second using a timer), well ... then it is another matter.
Any ideas?
-- modified at 13:10 Sunday 12th March, 2006
|
|
|
|
 |
|
 |
Try to use short delay between each capture.
Thanx
"Imagination is much more important than implementation"
|
|
|
|
 |
|
 |
Makes no difference. Only delays the inevitable.
I inserted some DoEvents/garbage collection into the loop. See below. Crashes after the same number of iterations. Added a few dozen DoEvents made no difference either. Calling a smaller loop multiple times (using a button, clicked manually, giving the system a chance to clean up) gave the same result as well: Crashes after around 4,975 total iterations.
I had a similar problem a few days ago (creating a cursor dynamically from a bitmap). Crashed consistently after around 1,200 iterations, so I had to find and fix the leak. Now I can call it millions of times without any problems. I hope to be able to do the same thing with your code. It goes a long way to solving my problem, but either a piece is missing or there is an InterOp problem that needs to be worked around.
---snip--- Private Sub CaptureCursorLoop() Dim totalmemory As String = "" For i As Integer = 1 To 10000 Dim x As Integer Dim y As Integer Dim bm As Bitmap = ScreenshotCaptureWithMouse.ScreenCapture.CaptureScreen.CaptureCursor(x, y)
bm.Dispose() bm = Nothing GC.Collect() Application.DoEvents()
If i Mod 200 = 0 Then totalmemory = GC.GetTotalMemory(False).ToString End If
Me.Text = i.ToString & ": Memory: " & totalmemory
Next End Sub ---snip---
|
|
|
|
 |
|
 |
I found a sollution to this.
you need to release the icon resources after retrieving it using:
[DllImport("user32.dll", EntryPoint = "DestroyIcon")] public static extern bool DestroyIcon(IntPtr hIcon);
Now i can read cursor million times.
modified on Monday, July 13, 2009 10:33 AM
|
|
|
|
 |
|
 |
This is a great example. I would like to do something very similar, but I don't want to use OS specific calls. Is there a way thins could be done without all the DllImports? Just raw C#?
Thanks,
-Scott
|
|
|
|
 |
|
 |
Yes you can use DirectX to do the same thing.
Thanx
"Imagination is much more important than implementation"
|
|
|
|
 |
|
 |
Thanks for the quick reply. I was under the impression DirectX would only work on the windowns platform? I am trying to come up with a way that my viewer could work on any platform the .NET framework had been ported to.
Thanks,
-Scott
|
|
|
|
 |
|
 |
I used the following code to capture desktop image with cursor. I am using .NET Framework 2.0.
Note: HotSpot property is new in the .NET Framework version 2.0.
using System.Drawing;
Bitmap desktopBMP = new Bitmap( System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height);
Graphics g = Graphics.FromImage(desktopBMP);
g.CopyFromScreen(0, 0, 0, 0, new Size( System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height)); Rectangle rect = new Rectangle( Cursor.Position.X - Cursor.Current.HotSpot.X, Cursor.Position.Y - Cursor.Current.HotSpot.Y, Cursor.Current.Size.Width, Cursor.Current.Size.Height); Cursor.Current.Draw(g,rect); return desktopBMP;
Razi
|
|
|
|
 |
|
 |
Thanks for this, it's quite helpful. I have mostly done web programming but I'm trying to get in to windows programming. One thing I've always wanted to know is how to make a screen capture utility where you select a portion using a mouse and dragging to create an "ants marching" box around an area and only capturing that area. I can't find a .Net way to do it. Is there one?
Michael J. Collins Web Application Programmer
|
|
|
|
 |
|
 |
Hi, I really liked this article.I had been looking at this issue for quite some time and the only work around I could make out was to get the cursor posotion and then put it at a spot on the captured bitmap but it was difficult to get to correct spot.
I have a question,supposing a user left clicks and a menu is displayed and at that time we capture the screen.Is their a way to see this menu with the cursor postion and all.I have not been able to solve this issue
Kindly advise Thanks Ketan
|
|
|
|
 |
|
 |
Do u want to capture the whole desktop? if so then i think it will work out. U just needs keyboard hooks so that u can capture against any combination of keys whether ur application is visible or not. And the captured desktop will surely have menu and then place mouse cursor at appropriate position.
Thanx.
"Imagination is much more important than implementation"
|
|
|
|
 |
|
 |
hey I was just using your APIs here and it seems if the cursor changes to anything other than the arrow[standard cursor shape] or the hourglass,it does not show them.I guess it has something to do with the CURSOR_SHOWING flag. Can you suggest what can be done?
Thanks.If I can find the solution I will update this thread coz I believe it would fulfill the purpose of ur article.
Regards, Ketan
|
|
|
|
 |
|
 |
How do programs like gotomypc capture the transparent dragging of icons whereas most screen savers cannot? I have also seen a program called Hypersnap6 do this. Standard BitBlt does not seem to capture those overlays.
Daniel Repich
|
|
|
|
 |