🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.nativeapi
20 messages
20 total messages Started by Dan Wed, 28 Feb 2007 15:04
Getting text from an external Grid
#2399
Author: Dan
Date: Wed, 28 Feb 2007 15:04
11 lines
1347 bytes
In previous messages I learned how to get test from external edit boxes 
or labels with GetWindowText or sending the WM_GETTEXT message to the 
appropriate handle.

For external String Grids, those messages don't seem to work.  Do I have 
to get a handle of an object within the stringgrid?  Spy++ doesn't seem 
to find any other handle other than the grid.  Am I using the wrong 
windows message?

How can I retrieve text from an external process's stringgrid (actually 
it's a TxtListCtl per Spy++)?
Re: Getting text from an external Grid
#2402
Author: Remy Lebeau (TeamB)
Date: Wed, 28 Feb 2007 17:26
31 lines
2014 bytes
"Dan" <Dan@do.not.spam> wrote in message
news:45e59a3a$1@newsgroups.borland.com...

> For external String Grids, those messages don't seem to work.

No, they do not.  TStringGrid is a completely custom-written control.
It does not provide any kind of external access at all, sorry.  If you
are trying to access a grid in a program that you wrote yourself, or
have control of its source code, then you would have to implement your
own access, such as by creating your own message (I would suggest
basing it on WM_COPYDATA) that the parent form handles on the grid's
behalf.

> Do I have to get a handle of an object within the stringgrid?

No, because there is none.

> Spy++ doesn't seem to find any other handle other than the grid.

Exactly.  There is only one HWND available, and it is for the overall
grid window.  The text is not stored inside that HWND at all.  It is
stored in memory only, and then manually drawn onto the HWND's HDC
when needed.

> Am I using the wrong windows message?

No.  There simply aren't any available for grids in the first place.


Gambit
Re: Getting text from an external Grid
#2405
Author: Dan
Date: Wed, 28 Feb 2007 18:52
12 lines
1629 bytes
> No.  There simply aren't any available for grids in the first place.

Oh fun...

so, any suggestions?  I have this third party application that I don't 
have code for, and the developer won't add any features to; and 
basically I just want to automate collection of data from it.  I can 
automate data collection by sending windows messages to push specific 
buttons, but the total goal is to get data out of a grid (Spy++ has it 
as a TxtListCtl) and save it to a file and unfortunetly there aren't any 
features to facilitate getting the data to a file native to the app 
(thus why I was called)
Re: Getting text from an external Grid
#2406
Author: Remy Lebeau (TeamB)
Date: Wed, 28 Feb 2007 21:39
16 lines
1298 bytes
"Dan" <Dan@do.not.spam> wrote in message
news:45e5cfa5$1@newsgroups.borland.com...

> so, any suggestions?

I have already given you my suggestion.

> I have this third party application that I don't have code for,
> and the developer won't add any features to

Then you are out of luck, sorry.  There is no external access
available for grid controls.


Gambit
Re: Getting text from an external Grid
#2407
Author: Dan
Date: Wed, 28 Feb 2007 22:05
7 lines
1435 bytes
How about this idea:

I can get the color of each pixel in the object as it is displayed, and 
can basically repaint the object onto my own canvas.  I could then 
export that as a bitmap or jpeg.  Are there any components available 
that will take that data (in a bitmap or jpeg) and translate it into 
text?  Like optical character recognition on a scanner?
Re: Getting text from an external Grid
#2408
Author: Remy Lebeau (TeamB)
Date: Wed, 28 Feb 2007 23:25
20 lines
1726 bytes
"Dan" <Dan@do.not.spam> wrote in message
news:45e5fd07$1@newsgroups.borland.com...

> I can get the color of each pixel in the object as it is displayed,
> and can basically repaint the object onto my own canvas.
> I could then export that as a bitmap or jpeg.

There is an easier way.  You can copy the entire contents of a HWND
using GetWindowDC() and BitBlt().  You do not have to deal with the
individual pixels.

> Are there any components available that will take that data
> (in a bitmap or jpeg) and translate it into text?  Like optical
> character recognition on a scanner?

None from Borland.  You would need third-party ones for that.


Gambit
Re: Getting text from an external Grid
#2412
Author: Dan
Date: Thu, 01 Mar 2007 15:35
26 lines
2516 bytes
> There is an easier way.  You can copy the entire contents of a HWND
> using GetWindowDC() and BitBlt().  You do not have to deal with the
> individual pixels.

Humm.. I'll have to look at that; I had to use GetWindowDC to be able to 
access the pixels; didn't see BitBlt().  I did have three problems here 
though:
(1) I couldn't access the pixels unless the dialog I was copying was 
visibly on the screen; I was using the 
ShowWindow(MainWindow,SW_SHOWNORMAL); command to make the 'MainWindow' 
(a handle to the application I was copying) visible; however, it didn't 
bring it to the front and therefore the pixel grabbing didn't always 
work.  Is there a way to get the target application 'On Top' always, or 
a better way to grap the pixels that will work even if the target app is 
off screen, behind something else, or minimized?

(2) I couldn't find a clear way to get the height and width, in pixels, 
of the target I was copying.  Is there a way to grab the height in 
pixels of the target handle or DC?

(3) The OCR library I found didn't do that great of a job using just the 
screen image copied pixel by pixel, therefore to get the OCR to work 
better, I had to enlarge the image by a factor of two.  I guess this 
isn't a problem so much with the nativeapi; however, if anyone has ideas 
for 1 and 2 above, I hope that the solution keeps in mind that I will 
then have to scale the image up, potentially, so that OCR works.
Re: Getting text from an external Grid
#2413
Author: Bob Gonder
Date: Thu, 01 Mar 2007 17:14
22 lines
1863 bytes
Dan wrote:

>(1) I couldn't access the pixels unless the dialog I was copying was 
>visibly on the screen;

You might try BringWindowToTop( hWnd )

>(2) I couldn't find a clear way to get the height and width, in pixels, 
>of the target I was copying.  Is there a way to grab the height in 
>pixels of the target handle or DC?

W = GetDeviceCaps( hDC, HORZRES );
H = GetDeviceCaps( hDC, VERTRES );

See the topic "Capturing an Image" in the BCB/BDS helps

>(3), I had to enlarge the image by a factor of two.

See the very next topic: "Scaling an Image"

Basically, besides adjusting the size of the created bitmap, you use
StretchBlt instead of BitBlt to capture the image.
Re: Getting text from an external Grid
#2414
Author: Dan
Date: Thu, 01 Mar 2007 19:05
10 lines
1536 bytes
  > W = GetDeviceCaps( hDC, HORZRES );
> H = GetDeviceCaps( hDC, VERTRES );

Seems to get the Application size, not the actual component (eg. label) 
size.

> Basically, besides adjusting the size of the created bitmap, you use
> StretchBlt instead of BitBlt to capture the image.

True,.. but this only works if I know the size of the component :)
Re: Getting text from an external Grid
#2415
Author: Remy Lebeau (TeamB)
Date: Thu, 01 Mar 2007 20:11
14 lines
1520 bytes
"Dan" <Dan@do.not.spam> wrote in message
news:45e72444$1@newsgroups.borland.com...

> Seems to get the Application size, not the actual component (eg.
label)
> size.

Which HWND are you passing to GetWindowDC()?  The main window or the
grid's window?  Since you are only intereste in the grid, you should
be using its HWND for everything.


Gambit
Re: Getting text from an external Grid
#2417
Author: Dan
Date: Thu, 01 Mar 2007 20:42
33 lines
2716 bytes
> Which HWND are you passing to GetWindowDC()?  The main window or the
> grid's window?  Since you are only intereste in the grid, you should
> be using its HWND for everything.
> 

I'm using the HWND for the grid.
In my 'CopyObject' routine that graphically copies the HWND I want (or 
the grid), I am doing the following:

   HANDLE HandleToTheGrid = HANDLE(HexIdOfGrid);
   if (HandleToTheGrid==NULL) return;
   HDC DCToTheGrid= GetWindowDC(HandleToTheGrid);

   //this displays the app that has the Grid
   ShowWindow(TheHandleToTheApp,SW_SHOWNORMAL);

   int w = GetDeviceCaps(DCToTheGrid, HORZRES);
   int h = GetDeviceCaps(DCToTheGrid, VERTRES);

   //then, basically I can fill a TImage, pixel by pixel.. (whoohoo)
   Unfortunetly, w and h are always the same, and equal to the 
application.  However, interestingly, the image of the grid, does start 
at pixel 0,0 and correctly corresponds to the grid I want and doesn't 
include any other GUI items.  So rather than calling GetDeviceCaps, 
right now, I am simply hardcoding worst cases; which results in 
extraordinarily slow code obviously.

To get pixels, I am looping from 0 to height within a 0 to width loop 
where I get the color of the pixel with GetPixel(DCToTheGrid,x,y); and 
then paint it to a TImage using ImageClassPointer->Canvas->Pixels[x][y] 
= c;

Better ways are welcome.
Re: Getting text from an external Grid
#2418
Author: Remy Lebeau (TeamB)
Date: Thu, 01 Mar 2007 21:12
33 lines
2212 bytes
"Dan" <Dan@do.not.spam> wrote in message
news:45e73ae4@newsgroups.borland.com...

>    HANDLE HandleToTheGrid = HANDLE(HexIdOfGrid);

What is HexIdOfGrid?

>    Unfortunetly, w and h are always the same, and equal to the
> application.

Then you are not using the correct HDC.

Try using GetWindowRect() instead, using the grid's HWND.

> To get pixels, I am looping from 0 to height within a 0 to width
loop
> where I get the color of the pixel with GetPixel(DCToTheGrid,x,y);
> and then paint it to a TImage using
ImageClassPointer->Canvas->Pixels[x][y]
> = c;

Again, you do not need to access the individual pixels.  Once you have
a suitable HDC, you can BitBlt() or StretchBlt() the entire window to
a bitmap, and then use that as needed.  For example:

    ImageClassPointer->Picture->Bitmap->Width = width;
    ImageClassPointer->Picture->Bitmap->Height = height;
    ::BitBlt(ImageClassPointer->Canvas->Handle, 0, 0, width, height,
DCToTheGrid, 0, 0, SRCCOPY);


Gambit
Re: Getting text from an external Grid
#2419
Author: Dan
Date: Thu, 01 Mar 2007 22:16
23 lines
2168 bytes
> What is HexIdOfGrid?

The result of a FindWindowEx(...) function that identified the handle of 
the grid I was looking for.

> Try using GetWindowRect() instead, using the grid's HWND.
GetWindowRect yields the same results.

> Again, you do not need to access the individual pixels.  Once you have
> a suitable HDC, you can BitBlt() or StretchBlt() the entire window to
> a bitmap, and then use that as needed.  For example:

Forgive my frustration, but oh, I've tried, what's wrong with this code?:

BitBlt(GetWindowDC(TheTImagePointer->Canvas->Handle),0,0,w,h,DCToTheGrid,0,0,PATCOPY);

It doesn't copy anything.

 >>>Then you are not using the correct HDC.
I find it hard to belive that I am using the incorrect HDC, since the 
GetPixel(DCToTheGrid,x,y); call returns the correct color for each 
pixel, allowing me to copy the beast.
Re: Getting text from an external Grid
#2422
Author: Remy Lebeau (TeamB)
Date: Thu, 01 Mar 2007 22:34
30 lines
2161 bytes
"Dan" <Dan@do.not.spam> wrote in message
news:45e75113$1@newsgroups.borland.com...
>
> > What is HexIdOfGrid?
>
> The result of a FindWindowEx(...) function that identified the
handle of
> the grid I was looking for.

Why are you casting it to a HANDLE?  FindWindowEx() returns an HWND,
and GetWindowDC() expects an HWND.

> Forgive my frustration, but oh, I've tried, what's wrong with this
code?:
>
>
BitBlt(GetWindowDC(TheTImagePointer->Canvas->Handle),0,0,w,h,DCToTheGr
id,0,0,PATCOPY);
>
> It doesn't copy anything.

Look at that code, and compare it with the code I gave you in my last
reply.  See anything different?  Your first parameter is wrong, so the
function is failing.  The TCanvas::Handle property is not an HWND.  It
is an HDC, so use it as-is.  Also, why are you using PATCOPY?  You are
not copying a pattern.


Gambit
Re: Getting text from an external Grid
#2426
Author: Dan
Date: Fri, 02 Mar 2007 14:42
7 lines
1707 bytes
Well.. I have changed the code from HANDLE to HWND; same results.

I'll take a step back and look to see if I have made any other obvious 
errors.

On another note:  Will I have the same problem with a MenuItem type 
control?  Is there a way to automate that from an external app?
Re: Getting text from an external Grid
#2420
Author: Remy Lebeau (TeamB)
Date: Fri, 02 Mar 2007 17:48
18 lines
2010 bytes
"Dan" <Dan@do.not.spam> wrote in message
news:45e83813$1@newsgroups.borland.com...
> Well.. I have changed the code from HANDLE to HWND; same results.

Did you notice the other change I pointed out?

> Will I have the same problem with a MenuItem type control?
> Is there a way to automate that from an external app?

Menus are much easier to automate, as there are several menu-related
window messages available.  The easiest one is to simply send
WM_COMMAND to the menu's parent window, specifying the ID of the item
you wish to execute.  You don't need to actually drop the menu down
and select the item manually beforehand.


Gambit
Re: Getting text from an external Grid
#2428
Author: Dan
Date: Fri, 02 Mar 2007 19:19
17 lines
2220 bytes
 >>>>>  The easiest one is to simply send WM_COMMAND

Thanks!

When I send this message, I can get a FileSave Dialog to appear, but the 
dialog appears to be modal, in so much that after I send the above 
message, control doesn't resume to the next line in my code until the 
dialog is closed.

Can I get around that by placing the SendMessage in another thread?
Is there a way to get around this?

I tried creating another thread that would monitor to see if the 
FileSave Dialog appeared, and if so, then take some action... but that 
thread too doesn't seem to get any action until the dialog is closed.

Does that sound right?  Or am I yet again doing something wrong?
Re: Getting text from an external Grid
#2430
Author: Dan
Date: Fri, 02 Mar 2007 19:21
20 lines
2228 bytes
Dan wrote:
>  >>>>>  The easiest one is to simply send WM_COMMAND
> 
> Thanks!
> 
> When I send this message, I can get a FileSave Dialog to appear, but the 
> dialog appears to be modal, in so much that after I send the above 
> message, control doesn't resume to the next line in my code until the 
> dialog is closed.
> 
> Can I get around that by placing the SendMessage in another thread?
> Is there a way to get around this?
> 
> I tried creating another thread that would monitor to see if the 
> FileSave Dialog appeared, and if so, then take some action... but that 
> thread too doesn't seem to get any action until the dialog is closed.
> 
> Does that sound right?  Or am I yet again doing something wrong?

Oh,.. maybe PostMessage will work?
Re: Getting text from an external Grid
#2429
Author: Dan
Date: Fri, 02 Mar 2007 19:26
3 lines
1572 bytes
> Oh,.. maybe PostMessage will work?
Never mind,.. yes PostMessage works fine.
Re: Getting text from an external Grid
#2431
Author: Remy Lebeau (TeamB)
Date: Fri, 02 Mar 2007 20:00
27 lines
2272 bytes
"Dan" <Dan@do.not.spam> wrote in message
news:45e87917$1@newsgroups.borland.com...

> When I send this message, I can get a FileSave Dialog to appear, but
> the dialog appears to be modal, in so much that after I send the
above
> message, control doesn't resume to the next line in my code until
the
> dialog is closed.

That is because the dialog is displayed in the context of the message
handler.  SendMessage() can't return until the message handler exits.
Try using PostMessage() instead of SendMessage() if you need your code
to continue immediately.

> Can I get around that by placing the SendMessage in another thread?

Yes.

> Is there a way to get around this?

You could alternatively use SendMessageTimeout() instead of
SendMessage().


Gambit
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads