AutoHotkey Community

It is currently May 26th, 2012, 4:09 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 56 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject:
PostPosted: November 19th, 2007, 1:57 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
a wrote:
Code:
xvariable = %sInfo%

but it does not work (and I have no idea why).

You must declare xvariable as Global with DDEMessage.
I recommend using DDEML.ahk, and the following will apply to DDEML. The variables will be sURL and sTitle. Replace
Code:
MsgBox, % sData

with
Code:
Loop,   Parse,   sData, CSV
   If   A_Index = 1
      sURL   := A_LoopField
   Else If   A_Index = 2
      sTitle   := A_LoopField


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 19th, 2007, 11:34 am 
thank you!


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: April 13th, 2009, 4:07 pm 
Offline

Joined: September 28th, 2004, 7:10 am
Posts: 17
Here is the complete code that does the job. It extracts both the current URL and the current Window Title.
Code:
   DDE_Connect("firefox" , "WWW_GetWindowInfo")
   Data := DDE_Request("WWW_GetWindowInfo")
   DDE_KILL()

   if(RegexMatch(Data, "^\x22(?P<URL>.*?)\x22,\x22(?P<Title>.*?)\x22", R)) {
      URL   := RURL
      Title := RTitle
   }
   else {
      ; Error Handling Code here if any
   }


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 14th, 2009, 5:15 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
Wade Hatler wrote:
Here is the complete code that does the job.
What's the point of it? Parsing Loop exactly does the same. If you want to use regex, try to write one to parse
Code:
Data="http://www.autohotkey.com/forum/",""AutoHotkey\\Forum""

The result should be equivalent to
Code:
sData="http://www.autohotkey.com/forum/",""AutoHotkey\\Forum""
StringReplace, sData, sData, ", "", All
StringReplace, sData, sData, \\,  \, All
Loop,   Parse,   sData,   CSV
   If   A_Index = 1
      sURL   := A_LoopField
   Else If   A_Index = 2
      sTitle   := A_LoopField
MsgBox, %  sURL "`n" sTitle


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 14th, 2009, 2:07 pm 
Offline

Joined: September 28th, 2004, 7:10 am
Posts: 17
The point of the Regex is that for most parsing jobs a Regex is faster, simpler, shorter, more flexible and easier to understand than the equivalent parsing loop. It's not always better, but it usually is. This particular example is one where the Regex doesn't have as much of an advantage as they usually do, but if you make a habit of using Regexs then you'll find they are better than a parsing loop in the vast majority of cases. The Regex is also self-documenting if you know Regex syntax. The sample I gave actually works with Firefox.

For this particular example, the parsing job is made much simpler by CSV support in AHK, which is fairly rare as a built in feature for languages, so the advantage isn't as big in this particular example as it would be in most languages, unless you add a CSV library.

I also noticed from your example that I didn't properly account for having quotes in the title in my code, so the corrected version that does take it into account, and turns it into a function is as follows:

Code:
FF_Page(ByRef URL, ByRef Title) {
   DDE_Connect("firefox" , "WWW_GetWindowInfo")
   Data := DDE_Request("WWW_GetWindowInfo")
   DDE_KILL()

   Data := RegexReplace(Data, "\\([\x22])", "$1")
   if(RegexMatch(Data, "^\x22(?P<URL>.*?)\x22,\x22(?P<Title>.*?)\x22(,|$)", R)) {
      URL   := RURL
      Title := RTitle
      Return True
   }

   else {
      URL   := ""
      Title := ""     
      Return False
   }
}

The biggest differences are:

1. Like in your example, I need to unescape quotes. You show unescaping backslashes as well, although I don't see FF escaping them in the first place, so I wouldn't do that in this case.
2. I didn't have a terminator, so my example would fail if you had a double-quote in the title (notice (,|$) at the end of the Regex).

So to answer your original question, your 7 lines of Parse code become 2 lines of Regex code:
Code:
   sData = "http://www.autohotkey.com/forum/","\"AutoHotkey\\Forum\"",
;   StringReplace, sData, sData, \", "", All
;   StringReplace, sData, sData, \\,  \, All
;   Loop,   Parse,   sData,   CSV
;      If   A_Index = 1
;         sURL   := A_LoopField
;      Else If   A_Index = 2
;         sTitle   := A_LoopField

   sData := RegexReplace(sData, "\\([\x22\\])", "$1")
   RegexMatch(sData, "^\x22(?P<URL>.*?)\x22,\x22(?P<Title>.*)\x22(,|$)", s)

   MsgBox, %  sURL . "`n" sTitle

And if the parsing is anything more complicated than a simple CSV list, the Regex advantage just gets bigger.


Last edited by Wade Hatler on April 14th, 2009, 3:15 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 14th, 2009, 2:45 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
Wade Hatler wrote:
Code:
sData := RegexReplace(sData, "\\([\x22\\])", "$1")
RegexMatch(sData, "^\x22(?P<URL>.*?)\x22,\x22(?P<Title>.*)\x22(|$),", s)
Try to parse this.
Code:
sData="http://www.autohotkey.com/forum/",""AutoHotkey",Forum"

Wade Hatler newly wrote:
Code:
sData := RegexReplace(sData, "\\([\x22\\])", "$1")
RegexMatch(sData, "^\x22(?P<URL>.*?)\x22,\x22(?P<Title>.*)\x22(,|$)", s)
Then this.
Code:
sData="http://www.autohotkey.com/forum/",""AutoHotkey",Forum",""

Quote:
For this particular example, the parsing job is made much simpler by CSV support in AHK, which is fairly rare as a built in feature for languages, so the advantage isn't as big in this particular example as it would be in most languages, unless you add a CSV library.
So, what's your point again? Are you worried about that I may be unable to use regex? Well, you better be about yourself.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 14th, 2009, 3:37 pm 
Offline

Joined: September 28th, 2004, 7:10 am
Posts: 17
Yow, I pasted in the wrong code. Sorry about that.

The correct 2 lines should be
Code:
sData := RegexReplace(sData, "\\([\x22\\])", "$1")
RegexMatch(sData, "^\x22(?P<URL>.*?)\x22,\x22(?P<Title>.*)\x22(,|$)", s)


Quote:
So, what's your point again? Are you worried about that I may be unable to use regex? Well, you don't have to.


I don't quite understand the question, but I'll try to answer it anyway. I pull Regex out of the toolbox first in most cases because it works so well. The Regex support is one of my favorite parts of AHK. It's a lot cleaner and more flexible than most of the other half-dozen scripting languages I use. You have a good point that I posted a buggy Regex before I really tested it… my bad on that one. I also didn't really think of using the built in CSV support, just because I didn't think of it.

Your original question was why I used a Regex and I just tried to explain why I use them by preference. One should of course use non-buggy Regexs, but I do like them. In the case of almost any parsing task other than CSV, a Regex will beat any other solution hands-down.

Having said that, in this case your solution is at least as good and probably better. I just didn't think of using CSV support in the first place, but for this particular parsing task it's probably better.

For example, my Regex only works on this particular flavor of CSV entry. It would fail if you had a third field, or if one of the fields wasn't quoted, and it seems likely your loop, Parse..CSV solution would handle those tasks more gracefully. I'll keep it in mind next time I need to parse something CSV like.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 14th, 2009, 4:28 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
Wade Hatler wrote:
I don't quite understand the question
My point was that you must not remove the escape character \ from the escaped character " before matching. So, it would be, neglecting the case of unquoted fields,
Code:
sData="http://www.autohotkey.com/forum/",""AutoHotkey",Forum"
RegExMatch(sData, "^\x22(?<URL>(\\\\|\\\x22|[^\x22])*)\x22,\x22(?<Title>(\\\\|\\\x22|[^\x22])*)\x22", s)
sURL := RegexReplace(sURL, "\\([\\\x22])", "$1")
sTitle := RegexReplace(sTitle, "\\([\\\x22])", "$1")
MsgBox % sURL "`n" sTitle

So, it became more cumbersome than using the Parsing Loop.


Last edited by Sean on April 14th, 2009, 5:47 pm, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 14th, 2009, 4:37 pm 
Offline

Joined: September 28th, 2004, 7:10 am
Posts: 17
Correct. I wasn't worrying about unquoted fields because I happened to know that I didn't have them in this case. I wasn't trying to make a generic CSV parser.

Either way, your original solution using the parse loop is probably the simplest and best alternative, so I'd say to stick with that.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 7th, 2010, 12:14 pm 
Offline

Joined: March 18th, 2010, 9:12 am
Posts: 72
Hi Sean.

I'm using this script alot, but it only works with one explorer/firefox open.
It is always taken the last opened window, and not the last active.
How do I code it to take the active explorer window and tab that is active?

Thanks for the good script.
Benny


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 7th, 2010, 6:19 pm 
Offline

Joined: September 28th, 2004, 7:10 am
Posts: 17
I ran into the same problem myself, so I made a new program that uses some brute-force DDE code I hacked from somewhere else in this forum to make sure the DDE is directed to the most recently active instance of Firefox. I use it all the time, and it seems to work mostly OK.

This script can be called from another script with RunWait, and then the results are read from an INI file.

Code:
;=============================================================================================================
;This reprieves the URL and Title of the page currently displayed in the most recently active instance of
;Firefox.  It uses DDE to read the data, and then writes the results into an INI file.
;
;Results are written to %Temp%\BrowserInfo.ini in the following form:
;  [Global]
;  Address=http://www.autohotkey.com/forum/viewtopic.php?p=381624#381624
;  Title=Retrieve AddressBar of Firefox through DDE Message
;  Link=<a href="http://www.autohotkey.com/forum/viewtopic.php?p=381624#381624">Retrieve AddressBar of Firefox through DDE Message</a>
;
; For details, read the post at the address shown above.
;-------------------------------------------------------------------------------------------------------------
sApplication := "firefox"  ; iexplore, opera
sTopic       := "WWW_GetWindowInfo"
sItem        := "0xFFFFFFFF"
Noise        := "Free source code and programming help"

CF_TEXT          := 1
WM_DDE_INITIATE  := 0x3E0
WM_DDE_TERMINATE := 0x3E1
WM_DDE_ADVISE    := 0x3E2
WM_DDE_UNADVISE  := 0x3E3
WM_DDE_ACK       := 0x3E4
WM_DDE_DATA      := 0x3E5
WM_DDE_REQUEST   := 0x3E6
WM_DDE_POKE      := 0x3E7
WM_DDE_EXECUTE   := 0x3E8

DetectHiddenWindows, On

OnMessage(WM_DDE_ACK , "DDE_ACK")
OnMessage(WM_DDE_DATA, "DDE_DATA")

nAppli := DllCall("GlobalAddAtom", "str", sApplication, "Ushort")
nTopic := DllCall("GlobalAddAtom", "str", sTopic      , "Ushort")

Process, Exist
WinGet, hAHK, ID, ahk_pid %ErrorLevel%

SendMessage, WM_DDE_INITIATE, hAHK, nAppli | nTopic << 16,, ahk_id 0xFFFF

DllCall("GlobalDeleteAtom", "Ushort", nAppli)
DllCall("GlobalDeleteAtom", "Ushort", nTopic)
Return

DDE_ACK(wParam, lParam, MsgID, hWnd) {
   Global sItem, CF_TEXT, WM_DDE_REQUEST
   nItem := DllCall("GlobalAddAtom", "str", sItem, "Ushort")
   PostMessage, WM_DDE_REQUEST, hWnd, CF_TEXT | nItem << 16,, ahk_id %wParam%
   If ErrorLevel
   DllCall("GlobalDeleteAtom", "Ushort", nItem)
}

DDE_DATA(wParam, lParam, MsgID) {
   Global
   DllCall("UnpackDDElParam", "Uint", MsgID, "Uint", lParam, "UintP", hData, "UintP", nItem)
   DllCall(  "FreeDDElParam", "Uint", MsgID, "Uint", lParam)

   pData := DllCall("GlobalLock", "Uint", hData)
   VarSetCapacity(sInfo, DllCall("lstrlen", "Uint", pData+4))
   DllCall("lstrcpy", "str", sInfo, "Uint", pData+4)
   DllCall("GlobalUnlock", "Uint", hData)
   If (*(pData+1) & 0x20)
      DllCall("GlobalFree", "Uint", hData)
   If (*(pData+1) & 0x80)
      PostMessage, WM_DDE_ACK, hWnd, 0x80 << 8 | nItem << 16,, ahk_id %wParam%

   Loop, Parse, sInfo, CSV
   {
      if(A_Index == 1) {
         Address := A_LoopField
         IniWrite %A_LoopField%, C:\Temp\BrowserInfo.ini,Global,Address
      }
      else if(A_Index == 2) {
         Title := A_LoopField
         IniWrite %A_LoopField%, C:\Temp\BrowserInfo.ini,Global,Title
      }
   }

   GSub(Title, " - Opera$", "")
   GSub(Title, "\x22"     , "'")
   GSub(Title, Noise      , "")

   Link := "<a href=""" . Address . """>" . Title "</a>"
   EnvGet Temp, Temp
   IniWrite %Link%, %Temp%\BrowserInfo.ini,Global,Link

   ExitApp
}

DDE_POKE(sItem, sData) {
   Global  WM_DDE_POKE, hWndClient, hWndServer
   If SubStr(sData, -1) <> "`r`n"
      sData .= "`r`n"

   hItem := DllCall("GlobalAddAtom", "str", sItem, "Ushort")
   hData := DllCall("GlobalAlloc", "Uint", 0x0002, "Uint", 2+2+StrLen(sData)+1)   ; GMEM_MOVEABLE
   pData := DllCall("GlobalLock" , "Uint", hData)
   DllCall("ntdll\RtlFillMemoryUlong", "Uint", pData, "Uint", 4, "Uint", 1<<13|1<<14|1<<16) ; bRelease, CF_TEXT
   DllCall("lstrcpy", "Uint", pData+4, "Uint",&sData)
   DllCall("GlobalUnlock", "Uint", hData)

   lParam := DllCall("PackDDElParam", "Uint", WM_DDE_POKE, "Uint", hData, "Uint", hItem)
   PostMessage, WM_DDE_POKE, hWndClient, lParam,, ahk_id %hWndServer%
   If ErrorLevel
   {
      DllCall("GlobalFree", "Uint"  , hData)
      DllCall("GlobalDeleteAtom", "Ushort", hItem)
      DllCall("FreeDDElParam", "Uint", WM_DDE_POKE, "Uint", lParam)
   }
}

DDE_EXECUTE(sCmd) {
   Global  WM_DDE_EXECUTE, hWndClient, hWndServer

   hCmd := DllCall("GlobalAlloc", "Uint", 0x0002, "Uint", StrLen(sCmd)+1)
   pCmd := DllCall("GlobalLock" , "Uint", hCmd)
   DllCall("lstrcpy", "Uint", pCmd, "str",sCmd)
   DllCall("GlobalUnlock", "Uint", hCmd)

   PostMessage, WM_DDE_EXECUTE, hWndClient, hCmd,, ahk_id %hWndServer%
   If ErrorLevel
   DllCall("GlobalFree", "Uint", hCmd)
}

;-------------------------------------------------------------------------------------------------------------
GSub(byref Haystack, Needle, Replacement) {
    Haystack := RegexReplace(Haystack, Needle, Replacement)
    return Haystack
}



I use this all the time with another script that grabs this information, filters it down, there's a bunch of other processing, and then generates an e-mail with a hyperlink to the page. I have various hotkeys that filter the data differently, or send it to different people, etc.

Note that if all you want to do is send a link to the current page via e-mail, there are easier ways to do it. The easiest way is using a small Bookmarklet. That's what I do on my iPad where I don't have access to AHK (which practically cripples me). Make a bookmark with this text:

Code:
javascript:(function(){location.href='mailto:?SUBJECT=Link: ' + document.title + '&BODY=<html><body><a href=\x27' + escape(location.href) + '\x27>' + document.title + '</a></body></html>';})()


or look http://www.freewaregenius.com/2009/02/05/email-this-a-bookmarklet-that-can-email-any-page-from-any-browser/ or http://www.bing.com/search?q=email+bookmarklet


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 8th, 2010, 1:08 pm 
Offline

Joined: March 18th, 2010, 9:12 am
Posts: 72
Hi Wade.

No, I'm not using it for email, but for my autopassword script:
http://www.autohotkey.com/forum/viewtop ... highlight=

I use the http-adress to identify the site, so need the active one.

I have now tryed the script, and it is working for firefox, but not for iexplore, witch I'm using mostly. Could you take a look at that, please?


Report this post
Top
 Profile  
Reply with quote  
PostPosted: September 30th, 2010, 4:02 pm 
Hi,

When working with AHK_L DdeConnect() seems to return zero. The same code with the same parameters works great at standard AHK.
Basically it is a simple DLL call:
Code:
DllCall("DdeConnect", "Uint", idInst, "Uint", hServer, "Uint", hTopic, "Uint", pCC)

But I don't see how it should be changed to work under AHK_L.

Can someone help porting this DLL code to AHK_L?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: December 10th, 2010, 11:31 am 
Offline

Joined: March 18th, 2010, 9:12 am
Posts: 72
Hi again.
I have tryed Wade's script, but it does not take the URL from the active explorer/firefox window, but the last opened one.

It very annoying, when I'm pasting in username and password, and it is looking at a wrong URL.

Please, can someone help with this issue? Thanks.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 10th, 2010, 5:50 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
Which one did you use, DDE.ahk or DDEMessage.ahk? BTW, it always returned the active one in my case. As you can see, there is not much you can control with DDE. In this case, you may try other values, like "0x1", than "0xFFFFFFFF" for sItem in the script. If still not work, then use Accessibility:
http://www.autohotkey.com/forum/topic40980.html


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 56 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: G. Sperotto and 13 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group