* Embed .hta in IUP GUI using OLE

For users to report plugin bugs and request plugin enhancements; and for authors to test new/new versions of plugins, and to discuss plugin development (in the Programming Technicalities sub-forum). If you want advice on choosing or using a plugin, please ask in General Usage or an appropriate sub-forum.
Post Reply
User avatar
tatewise
Megastar
Posts: 27076
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Embed .hta in IUP GUI using OLE

Post by tatewise » 16 Dec 2011 17:25

My Map Life Facts plugin uses the Google Maps Geocoder in an HTML Application (.hta) script.
This runs the Geocoder JavaScript and communicates with the plugin via the C: drive file system (which is not allowed by HTML).

I want to embed the Geocoder (.hta) window within the plugin IUP GUI window.
I hope to do this using http://www.tecgraf.puc-rio.br/iup/ > Controls > Additional > IupOleControl and LuaCOM.

The example code for embedding a web page .html script in a GUI works fine:

Code: Select all

require 'iuplua'
require 'iupluaole'
require 'luacom'

local control=iup.olecontrol{'Shell.Explorer.1'}   -- create WebBrowser using ProgID
control:CreateLuaCOM()             -- connect it to LuaCOM
control.designmode='NO'            -- Set production mode

local dlg=iup.dialog{ title='HTML in GUI', size='HALFxHALF', iup.vbox{control} }

dlg:show()

control.com:Navigate('C:\Users\Mike\Documents\example.html')

if (iup.MainLoopLevel()==0) then iup.MainLoop() end
However, this needs modifying to work for a .hta script.
Just changing the example.html file type to example.hta does not work (file content is unimportant as long as it is valid HTML).
I suspect the 'Shell.Explorer.1' ProgID also needs changing, but to what?
I have tried a few likely ProgID extracted from the Registry, but no luck.
The only thing I know is the program file is C:WindowsSystem32mshta.exe

This is not an area I am familiar with.
Have any experts out there got any ideas?

P.S.
I have used the above code to display the Help & Advice window in Map Life Facts and this revealed another limitation.
The dlg:show() command can be replaced by dlg:showxy() but not dlg:popup()!!!
Any idea why?

ID:5660
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Embed .hta in IUP GUI using OLE

Post by Jane » 19 Dec 2011 18:11

I think .hta files are treated as executables by windows, the 'a' on the end being application, so although they use IE components they are something of a rule to themselves and I suspect you will not be able to embed hta's, although I am happy to be proved wrong.
Jane
My Family History : My Photography "Knowledge is knowing that a tomato is a fruit. Wisdom is not putting it in a fruit salad."

User avatar
tatewise
Megastar
Posts: 27076
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Embed .hta in IUP GUI using OLE

Post by tatewise » 19 Dec 2011 22:40

I agree that .hta HTML Application files are rather unusual.
However, they don't appear to be executables, not in Windows Task Manager anyway.
e.g.
If I 'run' example.hta, then on the Applications tab Example is listed.
Just like if I 'run' a word document, then the document filename is listed.
Right-click on either Application and choose Go To Process.
The former is listed on Processes tab as C:WindowsSysWOW64mshta.exe   Microsoft HTML Application host
The latter is listed on Processes tab as C:Program Files (x86)Microsoft OfficeOffice 12WINWORD.EXE   Microsoft Office Word
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Embed .hta in IUP GUI using OLE

Post by Jane » 20 Dec 2011 14:00

I presume you need the 'promotion' using an hta gives you?

What limit to you hit if you use an embedded simple html page?
Jane
My Family History : My Photography "Knowledge is knowing that a tomato is a fruit. Wisdom is not putting it in a fruit salad."

User avatar
tatewise
Megastar
Posts: 27076
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Embed .hta in IUP GUI using OLE

Post by tatewise » 20 Dec 2011 18:00

No it is not that.

The reason I have to use HTA is that HTML correctly prevents any form of communication with the local PC such as C: drive file read/write access. Otherwise this would be a high security risk that could be exploited by malicious software.

Whereas, HTA is run as a local application that allows C: drive file read/write access. This is the method of communication between the Google Maps Geocoder running within HTA script and the Plugin script itself.
The Plugin script writes a file (.act) containing actions such as Geocoder location requests.
The HTA script reads this file when it exists, and writes the answers to a file (.ans) that is read by the Plugin script.
Deleting the files signals they have been read, and then another dialogue can begin.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Embed .hta in IUP GUI using OLE

Post by Jane » 21 Dec 2011 07:58

I suspect you might be able to use LuaCom to pass the data backwards and forwards, which might avoid the issue, but the documentation is poor, might be worth asking on Stack Overflow to see if some one could point you in the right direction.
Jane
My Family History : My Photography "Knowledge is knowing that a tomato is a fruit. Wisdom is not putting it in a fruit salad."

User avatar
tatewise
Megastar
Posts: 27076
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Embed .hta in IUP GUI using OLE

Post by tatewise » 21 Dec 2011 13:14

OK, I will ask, but not hopeful, as HTML script is really restricted to only communicating with the Internet server-side.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Embed .hta in IUP GUI using OLE

Post by Jane » 21 Dec 2011 13:54

I think you can as using
doc = control.com:Document()

you can get an object back which I suspect contains what you need I just can't work out how to interpret it as I can't find any examples in Lua, only in C#

Mike - I think I am nearly there

control.com:Navigate('D:\temp\testmap.html')
fhSleep(2000,100)
doc = control.com:Document()
print(doc)
ohtml = control.com.Document.DocumentElement.OuterHtml
print(ohtml)
if (not iup.MainLoopLevel or iup.MainLoopLevel()==0) then
iup.MainLoop()
end

ohtml contains all the current html code. If you either grab that or drill down more you should be able to get the data back.

Another option might be to just use the com object and trigger the api directly?
Jane
My Family History : My Photography "Knowledge is knowing that a tomato is a fruit. Wisdom is not putting it in a fruit salad."

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Embed .hta in IUP GUI using OLE

Post by Jane » 22 Dec 2011 12:23

I think I cracked it:

To read a value from the OLE object use:

Code: Select all

doc = control.com:Document()
print(doc)
ohtml = control.com.Document.DocumentElement.InnerHtml
o2 = control.com.Document:getElementById('Event List')
print(o2.InnerHtml)
So as long as the page has an item with an ID and a value you can read it directly from the window to the Lua script.

The trick is you must obtain a variable from the getElementById and then extract the value as a second pass.
Jane
My Family History : My Photography "Knowledge is knowing that a tomato is a fruit. Wisdom is not putting it in a fruit salad."

User avatar
tatewise
Megastar
Posts: 27076
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Embed .hta in IUP GUI using OLE

Post by tatewise » 22 Dec 2011 14:52

Thank you Jane sooooooo much, I think I have the workings of a solution.
Interestingly, I can get the Google Map Geocoder HTML file to display in a frame of the Map Life Facts GUI, and it can read an action file of Geocode, or Zoom, or similar commands OK.
Your COM technique allows the display of Latitude & Longitude to be retrieved from the HTML document.
So I think I can put all that together, although may have to wait until after Xmas to finish it off and test it.

Maybe, eventually, could use the COM to directly communicate with the Geocoder API as you suggested.

Have a great Christmas.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Embed .hta in IUP GUI using OLE

Post by Jane » 22 Dec 2011 15:03

I think I have found an even better way to get the data.

Using the Yahoo map api which does not require you to have a map active.

Code: Select all

--[[
@Title: Geocode Lookup
@Author: 
@LastUpdated: 
@Description: 
]]
function getXMLvalue(source,key)
local startkey = '<'..key..'>'
local endkey = '</'..key..'>'
local pattern = startkey..'.*'..endkey
local result = source:match(pattern)
result = result:gsub(startkey,'')
result = result:gsub(endkey,'')
return result
end
require('luacom')
http = luacom.CreateObject('winhttp.winhttprequest.5.1')

http:Open('GET','http://where.yahooapis.com/geocode?q=1600+Pennsylvania+Avenue,+Washington,+DC&appid={api}',false)
http:Send()
XML = http.Responsetext 
print(XML)
print(getXMLvalue(XML,'latitude'))
print(getXMLvalue(XML,'longitude'))
You need to get a Yahoo API id, but it's free and put it where {api} is.
Jane
My Family History : My Photography "Knowledge is knowing that a tomato is a fruit. Wisdom is not putting it in a fruit salad."

User avatar
tatewise
Megastar
Posts: 27076
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Embed .hta in IUP GUI using OLE

Post by tatewise » 22 Dec 2011 16:46

That looks interesting.
Perhaps what I will do is use Yahoo to Geocode locations into Lat/Long, and present them on the Google Map.

Then users can Zoom the map, nudge the marker, and check substitute locations until they are satisfactory.
I feel the Google Map is an important part of the user dialogue, but is easier to program if no response data is needed.

Thanks again.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Embed .hta in IUP GUI using OLE

Post by Jane » 22 Dec 2011 17:30

The google api is better when people are checking as they go, for the 'automatic one' the Yahoo one might be more stable, up to you, I was just pleased to be getting the hang of the COM interface.

I got it writing direct to an excel spreadsheet and word today as well.
Jane
My Family History : My Photography "Knowledge is knowing that a tomato is a fruit. Wisdom is not putting it in a fruit salad."

User avatar
tatewise
Megastar
Posts: 27076
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Embed .hta in IUP GUI using OLE

Post by tatewise » 22 Dec 2011 17:51

A few observations spring to mind.

I presume you have been unable to get the Google API working in a similar fashion.

Do you imagine that one Yahoo API Id would be made available via the Plugin to all FH users?
At first reading, the Terms & Conditions appear to make this approach unattractive and possibly illegal.
Alternatively, each FH user would obtain their own Yahoo API Id and enter it into the Plugin.

On the plus side, the Yahoo geocoding limit of 50,000 per day with no short-term rate limit, seems more generous than Google.

I have just seen this posting:
http://stackoverflow.com/questions/4346 ... -vs-others
that says 'If you won't display the results on a map, then neither Google nor Yahoo will do. You'll violate their terms of service.'
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Embed .hta in IUP GUI using OLE

Post by Jane » 22 Dec 2011 18:13

I would think there would be one api code per Plugin Author. Potentially you could retrieve the code from a web server so if there was a problem you could change the ID. The problem with scripts of course is anyone could potentially read the ID from the script, but this is true of many web pages as well.

My reading of the yahoo API is you can use it to geocode even if you are not using the yahoo map, this is not the case with Google Maps, but I will leave you to read the Ts & Cs
Jane
My Family History : My Photography "Knowledge is knowing that a tomato is a fruit. Wisdom is not putting it in a fruit salad."

User avatar
tatewise
Megastar
Posts: 27076
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Embed .hta in IUP GUI using OLE

Post by tatewise » 22 Dec 2011 18:30

I have both Yahoo API and Google API working with better getXMLvalue function, and did not even need a Yahoo API Id

Code: Select all

--[[
@Title: Geocode Lookup
@Author:
@LastUpdated:
@Description:
]]

require 'iuplua'
require 'iupluaole'
require 'luacom'

function getXMLvalue(source,key)
      local startkey = '<'..key..'>'
      local endkey = '</'..key..'>'
      local pattern = startkey..'(.-)'..endkey
      local result = source:match(pattern)
      return result
end

http = luacom.CreateObject('winhttp.winhttprequest.5.1')

http:Open('GET','http://where.yahooapis.com/geocode?q=1600+Pennsylvania+Avenue,+Washington,+DC&appid={api}',false)
http:Send()
XML = http.Responsetext
--print(XML)
print(getXMLvalue(XML,'latitude'))
print(getXMLvalue(XML,'longitude')) 

http:Open('GET','http://maps.googleapis.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false',false)
http:Send()
XML = http.Responsetext
--print(XML)
print(getXMLvalue(XML,'lat'))
print(getXMLvalue(XML,'lng'))
Output:
38.898717
-77.035974
37.4211444
-122.0853032
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
tatewise
Megastar
Posts: 27076
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Embed .hta in IUP GUI using OLE

Post by tatewise » 24 Dec 2011 01:38

I have incorporated the above techniques into the Plugin.

The Google Maps Geocoder HTML is embedded in an OLE frame in the IUP GUI, and is only used to display Markers at known Lat/Long locations.
This allows users to nudge locations N S E W and Zoom into them.
They also have the usual Google Maps options including Street View.

The address Geocoding uses the COM API technique, and with the Google API Geocoder runs about ten times faster than with Google Maps.
i.e. about 10 Geocodings per second.

I may try some experiments with the Yahoo API Place Finder but the need for an APPID is discouraging.
Thanks again for all your help.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

Post Reply