Extracting an image from an external application
Hey folks,
I'm hoping someone can provide me with some help in regards to this, here's a quick overview of what I'm doing:
I'm using user32.dll API on a 2 second timer to detect which window is open, FindWindow(), once I've found the window I'm looking for, I use FindWindowEx() to get the child window of the previously found one.
So I've got my window which contains 2 items. An image, and an Input box.
2 questions (Minor, and Major)
Minor: Is there a better way to monitor when a particular window opens?
Major: How would I extract the image that is held on the form? And then insert text into the input box?
Note: The image is variable - it's polled from a website.
Thanks for any help you can provide :-)
Re: Extracting an image from an external application
Is the window you are looking for generated by a 3rd party app? If so, I can't think of a better way to monitor. If the window is generated by your app - there are much better ways.
Is the window you are looking for, a web browser window?
Is the image by any chance a Captcha?
Re: Extracting an image from an external application
Yes, this image is a captcha and before anyone jumps on it, I'm not trying to write a spam bot or anything along those lines.
No, the window is not an internet explorer instance. It's an internal application at my workplace, with only 2 controls on the visible (Child) window.
Re: Extracting an image from an external application
Yeah, the window is generated by a 3rd party app, and no it's not a web browser.
It's an internal application that show's only a picture and a text box for input. Oh, and a button to submit.
You could call it a captcha I suppose, but they're basically images of words without all the distortion, which is why I can use OCR on it with a near 100% success rate.
Thanks :-)
Re: Extracting an image from an external application
You can find the child window of the picture box control, and then do a screen grab of the area covered by the child window.
As for sending text to the text box control, that topic has been discussed on the forum many times before. If you go to the Advanced Search, and search within the vb.net forum you should be able to find those threads.
Re: Extracting an image from an external application
Excuse my ignorance, but how on earth would I detect the child window of the picture window?
If you could just point me in the direction of something that would accomplish this for me, or even the functions I'd need, I'd be appreciated
Thanks
Edit - Also, how would I do a screen grab of a particular area? I know I'll be able to find the offsets by the location of the window, but what would be the API/Function I'd use to get a copy of a specific area?
Re: Extracting an image from an external application
To get the child window, you use FindWindowEx, just as you have described in your first post. The picture box is a child window of the main application.
There are a lot of threads on screen capture on this forum. For example, this one has working code:
http://www.vbforums.com/showthread.php?t=574859
Or, you can look in the code bank:
http://www.vbforums.com/showthread.php?t=385497
Re: Extracting an image from an external application
So each element on the page is a child window of that window? Would there be a way to navigate via the name of it, or is there some way of getting a constant yet unique identifier for it?
Just trying to clarify.
Re: Extracting an image from an external application
Quote:
Originally Posted by
HeWhoWas
So each element on the page is a child window of that window? Would there be a way to navigate via the name of it, or is there some way of getting a constant yet unique identifier for it?
Just trying to clarify.
Searching for the child window belonging to the control can be tricky.
First, you must have a way of identifying the child window you want (handle, title etc). You need to find the application window you want (using FindWindow), then go through all the child windows in there (using FindWindowEx). If your control is nested within other controls (eg. it is within a container control), you need to get the child windows of that container control window etc. When you find the child window that matches the identification criteria - you have found your picturebox.
See the following threads:
http://www.vbforums.com/showthread.php?t=568052
http://www.vbforums.com/showthread.php?t=567473
Re: Extracting an image from an external application
Re-edited. Apparantly I wasn't stupid.
When I use the data type Long to store the hwnd, I get a massive numberm and I can locate the correct child window. However the Easy Screen Capture Class you pointed me towards is expecting an IntPtr to reference the handle. Here's some code with comments to help you visualise this, if you need it.
Code:
Private Sub tmrWindowFind_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrWindowFind.Tick
Dim hwnd As IntPtr
Dim wnd2 As IntPtr
Dim Img As Image
Dim SC As New ScreenShot.ScreenCapture
hwnd = General.FindWindow(vbNullString, "Challenge") 'This stores the hwnd of the window as a short number. About 6 - 8 digits long.
If hwnd <> 0 Then
tmrWindowFind.Stop()
wnd2 = FindWindowEx(hwnd, vbNull, vbNull, vbNull) 'This returns 0
wnd2 = FindWindowEx(hwnd, wnd2, vbNull, vbNull) 'This should be the correct one, but again, it returns 0
Img = SC.CaptureWindow(wnd2)
Img.Save("C:\tmp.jpeg", System.Drawing.Imaging.ImageFormat.Jpeg)
And I'm declaring the API functions as such:
Code:
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As IntPtr, ByVal hWnd2 As IntPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As IntPtr
Re: Extracting an image from an external application
Re: Extracting an image from an external application
Ok, I don't see how people have been using this function with Integers as the data type. Even taking code straight out of the code bank and modifying only the name of the window I'm looking for, I get an error because the number is way too large to be in an Integer or IntPtr.
What's going on? :-(
Edit - Is there any way to check the hwnd of the window? Outside of code I mean. Also, this is the average hwnd I'm receiving using data type long: 1305670057984
Re: Extracting an image from an external application
...do API calls to FindWindow and FindWindowEx require Administrator privileges?
Re: Extracting an image from an external application
Quote:
Originally Posted by
HeWhoWas
...do API calls to FindWindow and FindWindowEx require Administrator privileges?
Not that I know of.
The VB.net Integer class is equivalent to the Long type in VB6, so you should replace all references to Long with Integer (or to be more precise, you can use Int32 if you compile for 32-bit Windows).
Re: Extracting an image from an external application
Quote:
Originally Posted by
HeWhoWas
... modifying only the name of the window I'm looking for...
If you know the name of the window (I mean, all or part of the title bar text), you can use a "pure" .net method to get the window handle without calling FindWindow API.
I have been using this method ever since I found it on this forum:
Code:
Private Function FindWinHandle() As Integer
For Each p As System.Diagnostics.Process In System.Diagnostics.Process.GetProcesses
If Not p.MainWindowHandle.ToInt32 = 0 AndAlso Not p.ProcessName = "explorer" Then
If p.MainWindowTitle.ToLower.Contains("part of window title here") Then
FindWinHandle = p.MainWindowHandle.ToInt32
Return FindWinHandle
End If
End If
Next
End Function
You will still need to use FindWindowEx to get to the controls inside, though.
This thread gives examples of how to declare FindWindow and FindWindowEx and to get handles of controls within the main window, using NotePad as an example:
http://www.pinvoke.net/default.aspx/user32.FindWindow
Re: Extracting an image from an external application
If hwnd is an Integer datatype, then why does the Easy Screen Capture class ask for an IntPtr? or will it implicitly cast it?
Ok, it doesn't cast from Integer to IntPtr. And If the Long and Integer variable types are the same, why is it that when I declare hwnd as a long, I get a number > 10 long, while Integer gives me one around 5?
Re: Extracting an image from an external application
IntPtr is used to store handles and pointers in VB. Any API function that returns a handle or a pointer can be declared in VB to return either an Integer or an IntPtr. Either will work fine. If you then want to call a method that takes an IntPtr as an argument it would make sense for you to declare your API function to return an IntPtr.
That said, it's easy to convert between Integer and IntPtr. The IntPtr structure has a constructor that takes an Integer as an argument and it also has a ToInt32 method that returns an Integer, so you can go either way.
Re: Extracting an image from an external application
I just realised that I have been staring at a piece of code that shows me exactly what you described there. Let me test, then I'll be happy to mark this topic as resolved, finally :-)
It worked! But....I didn't realise that the window had to be visible to the user for this function to work. Is there any way to get a shot of a particular control, without having the window containing it visible?