Firefox, mozilla based browser URL
Firefox, mozilla based browser URL
Try as I might I can not seem to figure out how to get the url from a mozilla based browser. Seems they do it somewhat different than ie and it requires traversing some damn (or was that Dom?) tree structure I haven't been able to navigate - or even understand how to get to.
Freak had some information in the post
http://www.purebasic.fr/english/viewtopic.php?t=16965
but it seems to be for ie and not Dom.
Anyone who's gotten a firefox URL or traversed the Dom or has any other suggestion or pointers?
cheers
Freak had some information in the post
http://www.purebasic.fr/english/viewtopic.php?t=16965
but it seems to be for ie and not Dom.
Anyone who's gotten a firefox URL or traversed the Dom or has any other suggestion or pointers?
cheers
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
I love nothing better than an ugly hack, especially when I get to blame it on another coder! In this case, it's Sparkie's fault.
One wrinkle is that the F6 key will alternately select and deselect the address bar, so it has to be sent once, tested, and resent if it didn't get a result. So it's even that much uglier.
Enough preamble, on to the junk coding! This is working here:
Garbage to the end of all the lines, but - it works.
One wrinkle is that the F6 key will alternately select and deselect the address bar, so it has to be sent once, tested, and resent if it didn't get a result. So it's even that much uglier.
Enough preamble, on to the junk coding! This is working here:
Code: Select all
Procedure.s GetFireFoxURL()
w = FindWindow_("MozillaUIWindowClass",0)
If w
safetext.s = GetClipboardText()
ClearClipboard()
If IsIconic_(w)
ShowWindow_(w,#SW_SHOWNORMAL)
EndIf
SetForegroundWindow_(w)
keybd_event_(#VK_F6,0,0,0)
keybd_event_(#VK_F6,0,#KEYEVENTF_KEYUP,0)
Delay(50)
keybd_event_(#VK_LCONTROL,0,0,0)
keybd_event_(#VK_C,0,0,0)
Delay(50)
keybd_event_(#VK_C,0,#KEYEVENTF_KEYUP,0)
keybd_event_(#VK_LCONTROL,0,#KEYEVENTF_KEYUP,0)
If LCase(Left(GetClipboardText(),7))<>"http://"
SetForegroundWindow_(w)
keybd_event_(#VK_F6,0,0,0)
keybd_event_(#VK_F6,0,#KEYEVENTF_KEYUP,0)
Delay(50)
keybd_event_(#VK_LCONTROL,0,0,0)
keybd_event_(#VK_C,0,0,0)
Delay(50)
keybd_event_(#VK_C,0,#KEYEVENTF_KEYUP,0)
keybd_event_(#VK_LCONTROL,0,#KEYEVENTF_KEYUP,0)
EndIf
result.s = GetClipboardText()
If safetext <> ""
SetClipboardText(safetext)
EndIf
ProcedureReturn result
Else
ProcedureReturn "Failed"
EndIf
EndProcedure
Debug GetFireFoxURL()
Last edited by netmaestro on Sat Dec 16, 2006 9:22 pm, edited 1 time in total.
BERESHEIT
> An ugly hack would be to send the Firefox window the F6 shortcut (selects
> text in address bar) and copy it to the clipboard
Hehe, I've been doing that for years, but with CTRL+L to select the Address
Bar, to avoid the F6 bug that netmaestro mentions. I never posted my tip
here because I was ashamed of having to do it that way.
But here it is.
@netmaestro: Again, I swear I did not copy your code. We just think alike!
And also, you should check for both "http://" and "https://", for secure sites.
Further, here's some Visual Basic code that I once found that supposedly
does it... maybe someone here can convert it to PureBasic?
> text in address bar) and copy it to the clipboard
Hehe, I've been doing that for years, but with CTRL+L to select the Address
Bar, to avoid the F6 bug that netmaestro mentions. I never posted my tip
here because I was ashamed of having to do it that way.

@netmaestro: Again, I swear I did not copy your code. We just think alike!
And also, you should check for both "http://" and "https://", for secure sites.
Code: Select all
Procedure.s GetFirefoxURL()
ff=FindWindow_("MozillaUIWindowClass",0)
If ff
SetForegroundWindow_(ff)
keybd_event_(#VK_CONTROL,0,0,0) ; Hold down Control key.
keybd_event_(#VK_L,0,0,0) : keybd_event_(#VK_L,0,#KEYEVENTF_KEYUP,0) ; Go to Address Bar.
keybd_event_(#VK_C,0,0,0) : keybd_event_(#VK_C,0,#KEYEVENTF_KEYUP,0) ; Copy the address.
keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release Control key.
Sleep_(125) : u$=GetClipboardText() ; Delay seems to be needed here.
EndIf
ProcedureReturn u$
EndProcedure
Debug GetFirefoxURL()
does it... maybe someone here can convert it to PureBasic?
Code: Select all
I got to playing around with the Active Accessibility
approach. I don't know whether this is really a usable
solution, but it's interesting. This is VB6 code. I guess
it's about the same for VB5.
This code would need some adjustments for your
purpose, but this shows it can be done, at least.
As for AA, it's in Windows at least as far back as
Win98, but I'm not certain that it's always installed
by default.
----------------------------------------------
Set the following code if a form named "F1":
Private Sub bHook_Click()
Hook
End Sub
Private Sub bUnhook_Click()
UnHook
End Sub
Place 2 buttons, as named above, with captions "hook" and
"unhook".
Place a textbox named "Text1"
-----------------------------------
In a module add this code (Reference to Accessibility needed in
Project -> References. Lib. is oleacc.dll. Set "Show hidden
Objects" in object browser if you want intellisense.)
Public Const EVENT_MIN = 1&
Private Const ROLE_COMBOBOX = &H2E&
Private Const OB_ACCELERATORCHANGE = &H8012&
Private Const SYS_ALERT = 2&
Public Const WINEVENT_SKIPOWNPROCESS = 2&
Public Const OB_REORDER = &H8004&
Private Declare Function SetWinEventHook Lib "user32.dll" (ByVal eventMin As
Long, ByVal eventMax As Long, ByVal hmodWinEventProc As Long, ByVal
pfnWinEventProc As Long, ByVal idProcess As Long, ByVal idThread As Long,
ByVal dwFlags As Long) As Long
Private Declare Function UnhookWinEvent Lib "user32.dll" (ByVal lHandle As
Long) As Long
Private Declare Function AccessibleObjectFromEvent Lib "oleacc" (ByVal HWnd
As Long, ByVal dwId As Long, ByVal dwChildId As Long, ppacc As IAccessible,
pvarChild As Variant) As Long
Private LHook As Long
Public Sub Hook()
Dim LRet As Long
LHook = SetWinEventHook(SYS_ALERT, OB_ACCELERATORCHANGE, 0&, AddressOf
WinEventFunc, 0, 0, WINEVENT_SKIPOWNPROCESS)
End Sub
Public Sub UnHook()
Dim LRet As Long
If LHook = 0 Then Exit Sub
LRet = UnhookWinEvent(LHook)
End Sub
Public Function WinEventFunc(ByVal HookHandle As Long, ByVal LEvent As Long,
ByVal HWnd As Long, ByVal idObject As Long, ByVal idChild As Long, ByVal
idEventThread As Long, ByVal dwmsEventTime As Long) As Long
Dim ObA As IAccessible
Dim LRet As Long
Dim V As Variant
Dim s As String, s1 As String, sName As String
On Error Resume Next
Select Case LEvent
Case OB_REORDER
LRet = AccessibleObjectFromEvent(HWnd, idObject, idChild, ObA, V)
If LRet = 0 Then
F1.Text1.Text = "--"
If CLng(ObA.accRole(V)) = 46 Then '-- combobox.
If ObA.accName(V) = "Location" Then
F1.Text1.Text = ObA.accValue(V)
End If
End If
End If
End Select
WinEventFunc = 0
End Function
-------------------------------
Open Firefox, run the project, click "Hook".
Edit the Firefox location bar.
You should see the text in Text1 keep up
with any changes you make in Firefox's
location bar.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.
This isn't perfect but figured I'd throw it out there for someone to improve on it. I'm short on time but I'll try to get back to this later this weekend. Thanks to PB for posting the original VB code. 

Code: Select all
; ************************************************
; Code: Track Firefox url changes (no IE / Opera support as of yet)
; Author: Sparkie
; Date: December 21, 2006
; OS: Windows only
;...Code converted from VB to PB
;...Thanks To PB for posting the original VB code
;...Code is not yet perfect so feel free to clean
;...it up and use as you wish.
; ************************************************
;############
; Constants
;############
#WINEVENT_OUTOFCONTEXT = 0
#WINEVENT_SKIPOWNPROCESS = $2
#CHILDID_SELF = 0
#ROLE_COMBOBOX = $2E
#EVENT_OBJECT_VALUECHANGE = $800E
;############
; Hook proc
;############
Procedure WinEventFunc(HookHandle.l, LEvent.l, hwnd.l, idObject.l, idChild.l, idEventThread.l, dwmsEventTime.l)
Protected oba.IAccessible
Select LEvent
Case #EVENT_OBJECT_VALUECHANGE
If CallFunction(0, "AccessibleObjectFromEvent", hwnd, idObject, idChild, @oba, @v.VARIANT) = #S_OK
v\vt = #VT_I4
v\lVal = 0
r = oba\get_accRole(v, @v)
If v\lVal = #ROLE_COMBOBOX
v\vt = #VT_I4
v\lVal = 0
Asc$ = Space(#MAX_PATH)
Uni$ = Space(#MAX_PATH*2+2)
MultiByteToWideChar_(#CP_ACP, 0, @Asc$, -1, @Uni$, Len(Asc$)*2+2)
bstr = SysAllocString_(@Uni$)
If oba\get_accValue(v, @bstr) = #S_OK
;...accName = "Location" in Firefox
;...accName = "Address" in IE
;r = *oba\get_accName(v, @*bstr)
len = WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, 0, 0, 0, 0)
url$ = Space(len)
WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, @url$, len, 0, 0)
AddGadgetItem(1, -1, url$)
EndIf
SysFreeString_(bstr)
EndIf
EndIf
EndSelect
EndProcedure
;############
; Main Window
;############
If OpenWindow(0, 0, 0, 500, 400, "Read FireFox URL", #PB_Window_SystemMenu) And CreateGadgetList(WindowID(0))
hdll = OpenLibrary(0, "Oleacc.dll")
EditorGadget(1, 10, 15, 480, 380)
;...Set event hook
eHook = SetWinEventHook_(#EVENT_OBJECT_VALUECHANGE, #EVENT_OBJECT_VALUECHANGE, #Null, @WinEventFunc(), 0, 0, #WINEVENT_OUTOFCONTEXT | #WINEVENT_SKIPOWNPROCESS)
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
;...Cleanup in isle 53
If eHook
UnhookWinEvent_(eHook)
EndIf
If hdll
CloseLibrary(0)
EndIf
EndIf
End
What goes around comes around.
PB 5.21 LTS (x86) - Windows 8.1
PB 5.21 LTS (x86) - Windows 8.1
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
OK, main problem is too much filtering. The best idea, as I see it, is to take everything you get without restriction and only pay attention to an accValue with a URL in it. Also, restricting the hook to #EVENT_OBJECT_VALUECHANGE doesn't work as the "golden" event seems to be $8005, which I can't find the constant name for. But by setting MIN to EVENT_MIN and MAX to MAXWORD in the hook, you're saying "Gimme all of it, I'll keep what I want", which is safest as you may not be able to trust it to always be the same. Anyway - this is working well here:
Also, this version works equally well for IE, and theoretically should work for Opera too. If someone could test opera that would be great.
Code: Select all
;************************************************
; Code: Track Firefox url changes (no IE / Opera support as of yet)
; Author: Sparkie
; Date: December 21, 2006
; OS: Windows only
;...Code converted from VB to PB
;...Thanks To PB for posting the original VB code
;...Code is not yet perfect so feel free to clean
;...it up and use as you wish.
; ************************************************
;
; *** IMPORTANT *** This approach requires an editorgadget on your window
;
;############
; Constants
;############
#WINEVENT_OUTOFCONTEXT = 0
#WINEVENT_SKIPOWNPROCESS = $2
#CHILDID_SELF = 0
;############
; Hook proc
;############
Procedure WinEventFunc(HookHandle.l, LEvent.l, hwnd.l, idObject.l, idChild.l, idEventThread.l, dwmsEventTime.l)
Static oldurl$
Protected oba.IAccessible
If CallFunction(0, "AccessibleObjectFromEvent", hwnd, idObject, idChild, @oba, @v.VARIANT) = #S_OK
v\vt = #VT_I4
v\lVal = #CHILDID_SELF
; ...Prepare a spot for the bstr
Asc$ = Space(#MAX_PATH)
Uni$ = Space(#MAX_PATH*2+2)
MultiByteToWideChar_(#CP_ACP, 0, @Asc$, -1, @Uni$, Len(Asc$)*2+2)
bstr = SysAllocString_(@Uni$)
; ...Put the returned value in it
If oba\get_accValue(v, @bstr) = #S_OK
; ...Convert the bstr into an ascii string
len = WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, 0, 0, 0, 0)
url$ = Space(len)
WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, @url$, len, 0, 0)
; ...See if it contains a URL
If Left(url$,4) = "http"
If url$<>oldurl$
oldurl$ = url$
AddGadgetItem(1, -1, url$)
EndIf
EndIf
EndIf
SysFreeString_(bstr)
EndIf
EndProcedure
;############
; Main Window
;############
If OpenWindow(0, 0, 0, 500, 240, "Read URL From Any Browser",$CF0001) And CreateGadgetList(WindowID(0))
StickyWindow(0,1)
hdll = OpenLibrary(0, "Oleacc.dll")
EditorGadget(1,0, 0, 500, 240)
;...Set event hook
eHook = SetWinEventHook_(1, #MAXWORD, #Null, @WinEventFunc(), 0, 0, #WINEVENT_OUTOFCONTEXT | #WINEVENT_SKIPOWNPROCESS)
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
;...Cleanup in isle 53
If eHook
UnhookWinEvent_(eHook)
EndIf
If hdll
CloseLibrary(0)
EndIf
EndIf
End
Last edited by netmaestro on Wed Dec 20, 2006 1:34 pm, edited 2 times in total.
BERESHEIT
Great teamwork, guys! This topic shows how good this community is. 
The only catch with netmaestro's code is that it doesn't get the URL if Firefox
doesn't have the focus when his code runs, but that's a very trivial thing to fix.
BTW, does anyone know why this doesn't work if the EditorGadget is removed?

The only catch with netmaestro's code is that it doesn't get the URL if Firefox
doesn't have the focus when his code runs, but that's a very trivial thing to fix.
BTW, does anyone know why this doesn't work if the EditorGadget is removed?
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
I've been researching that for the past day or so and can come up with nothing. In fact, day before yesterday I almost chucked the whole project because I was using a text gadget and getting nothing. My current research is focused on getting away from the event hook altogether and trading it in for AccessibleObjectFromWindow or possibly AccessibleObjectFromPoint and just getting the current url when you want it, instead of a constant update from a hook proc.BTW, does anyone know why this doesn't work if the EditorGadget is removed?
BERESHEIT