PDA

View Full Version : Accessing a control in another (non-Office) application



JimmyTheHand
10-10-2007, 03:23 PM
Hi

I have got an application written in Delphi, that has a Form1, with some textboxes and buttons. I need to fill the textboxes with values from an Excel worksheet, and then click the OK button on Form1 to initiate a certain calculation, and some other things the application does.

I would like to automate this process, that is, to fill the textboxes on Form1 via macro, and even have the macro simulate a clicking on the OK button, if possible. Then wait until the application is ready, then start again with the next set of values.

I don't know how to do it. Can anyone give me a start? Spiced with some explanation, perhaps?

Thank you for your time, in advance.

JimmyTheHand
10-11-2007, 10:07 AM
Nobody?
I don't ask for a full code, I only ask for some directions.

Please help.

Norie
10-11-2007, 10:38 AM
Why do you need to do this from Excel?

Surely if the application has been created you should be doing it from there.

I've only briefly used Delphi, free copy from a magazine a few years back, but I'm pretty sure it should have the capability to pull data from Excel.:)

JimmyTheHand
10-11-2007, 12:04 PM
Why do you need to do this from Excel?

Surely if the application has been created you should be doing it from there.


Because I only use the application, but I didn't create it. I guess it could've been equipped with an interface towards Excel, but it wasn't so I have to use it as it is.


I've only briefly used Delphi, free copy from a magazine a few years back, but I'm pretty sure it should have the capability to pull data from Excel.:)
Yes, as far as I know, Delphi has such capability, but the source code of the application is unavailable, too. Not to mention that, even if I had it, I'm not sure I could implement this "Pull Data From Excel" part :dunno

Norie
10-11-2007, 12:23 PM
What does this application actually do?

Must you use it?

JimmyTheHand
10-11-2007, 10:31 PM
Yes, I must use it. It is part of my job. It calculates Motoric Octane Number, Density and a few other physical properties of gasoline, based on chromatographic data, using an unknown algorithm.
The application pulls the data from the chromatograph, online. It also has a primitive GUI for modelling gasolines. That's what I called Form1. When I've got a real gasoline analysis ready, I can type in imaginary modifications, to see what would happen if o-xylene content were twice as large, normal octane was 3.05% etc. That is when I should be able pull data from an Excel worksheet.

johnske
10-11-2007, 10:56 PM
if you knew the shortcut keys, you could probably use the SendKeys method to do what you wanted

JimmyTheHand
10-11-2007, 11:50 PM
I'm counting on Sendkeys to send the data over, but first I have to set the focus to a particular TextBox. I can not simply send over some TAB's to move the focus to the desired TextBox because, to do this, I need to obtain the initial position of the focus so that I can know how many TAB's I need.

The need to learn the initial position of the focus puts me back to the start: how to identify a textbox in another application?

Charlize
10-12-2007, 01:12 AM
If your Delphi application is open and visible on the screen (no other window is active) you can let excel get a handle to the name of your delphi window. I'll see what I have in my collection (I use it to interact with our bookkeeping program).

JimmyTheHand
10-15-2007, 12:39 AM
If your Delphi application is open and visible on the screen (no other window is active) you can let excel get a handle to the name of your delphi window. I'll see what I have in my collection (I use it to interact with our bookkeeping program).


Great, thanks :thumb
I'm awaiting this precious part of your collection :yes

Charlize
10-15-2007, 06:55 AM
Found it. I've fetched it from somewhere at the web. I hope it gives you some idea's.Option Explicit
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, _
ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Private Declare Function VkKeyScan Lib "user32" Alias "VkKeyScanA" _
(ByVal cChar As Byte) As Integer
Private Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" _
(ByVal wCode As Long, ByVal wMapType As Long) As Long
Private Const KEYEVENTF_KEYUP = &H2
Private Const vbKeyShift = &H10
Private Const vbKeyCtrl = &H11
Private Const vbKeyAlt = &H12
Const VK_RETURN As Integer = &HD
Const SW_HIDE = 0
Private Sub PrintNotepad()
Dim hWnd As Long, Forewin As Long
Forewin = GetForegroundWindow()
' Change this to match your caption
hWnd = FindHwnd("Untitled - Notepad")
If hWnd = 0 Then Exit Sub
SetForegroundWindow hWnd
Call Send_Keys("this is some text", hWnd)
keybd_event vbKeyCtrl, 0, 0, 0
Call Send_Keys("p", hWnd)
keybd_event vbKeyCtrl, 0, KEYEVENTF_KEYUP, 0
' Send Return
keybd_event VK_RETURN, 0, 0, 0
keybd_event VK_RETURN, 0, KEYEVENTF_KEYUP, 0
SetForegroundWindow Forewin
End Sub
Public Sub Send_Keys(KeysToSend As String, WindowToSendTo As Long)
Dim ShiftDown As Boolean, AltDown As Boolean, ControlDown As Boolean
Dim intCount As Integer
Dim mScan As Long
Dim a As Integer
Dim mVK As Long

If KeysToSend = "" Then Exit Sub
If WindowToSendTo = 0 Then Exit Sub

For a = 1 To Len(KeysToSend)

mVK = VkKeyScan(Asc(Mid(KeysToSend, a, 1)))
mScan = MapVirtualKey(mVK, 0)

ShiftDown = (mVK And &H100)
ControlDown = (mVK And &H200)
AltDown = (mVK And &H400)

mVK = mVK And &HFF


' Do While GetForegroundWindow() <> WindowToSendTo And intCount < 20
' DoEvents
' intCount = intCount + 1
' SetForegroundWindow WindowToSendTo
' Loop
'
' If GetForegroundWindow() <> WindowToSendTo Then Exit Sub

If ShiftDown Then keybd_event &H10, 0, 0, 0
If ControlDown And &H200 Then keybd_event &H11, 0, 0, 0
If AltDown And &H400 Then keybd_event &H12, 0, 0, 0

keybd_event mVK, mScan, 0, 0

If ShiftDown Then keybd_event vbKeyShift, 0, KEYEVENTF_KEYUP, 0
If ControlDown Then keybd_event vbKeyCtrl, 0, KEYEVENTF_KEYUP, 0
If AltDown Then keybd_event vbKeyAlt, 0, KEYEVENTF_KEYUP, 0

Next a

' SetForegroundWindow Application.hWnd

End Sub
Private Function FindHwnd(strCaption As String) As Long
'Returns the handle of the specified window
FindHwnd = FindWindow(vbNullString, strCaption)
End Function

JimmyTheHand
10-17-2007, 01:10 PM
Thanks, Charlize.

Yes it gives me some ideas. Your code is a great, and living, example of calling external functions, which is a quite new area for me.:thumb

However, your code adresses only an application, and not one of the application's controls, and the latter is what I need right now.

Following the path you showed me, I started my research for the proper API function, but have found nothing relevant yet. I'll leave this thread on for a while, maybe someone, who can point out the right method, drops by.: pray2:

Thanks again,

Jimmy

Bob Phillips
10-17-2007, 01:28 PM
If the control has its own handle, you may be able to access that in a similar manner. Get hold of a window message spy tool, such as Winspector or Spy++ and see if you can get the window class.

Charlize
10-18-2007, 12:41 AM
This is one of the resources I use if I want to see how long I can try things out before my (test)computer crashes : http://allapi.mentalis.org/tips/tips1.shtml