Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

COM Standard Library


  • Please log in to reply
669 replies to this topic
frescalus
  • Members
  • 163 posts
  • Last active: Dec 14 2012 09:34 PM
  • Joined: 19 Nov 2009
Well, the code I provided is almost the same, the only difference is I'm just using google in a modal window created with javascript:window.showModalDialog('http://www.google.com','','') prior to running the script.

The only code that I've copied is under COMInitializeTest which I got from the forums. The rest I had to read and figure out.


TestNewHotkey:
COM_init()
COM_CoInitialize()
;COM_Error(0)

GotIt = 0

DetectHiddenText, On   

GoSub, COMInitializeTest
WinGet, Modal_ID, ID, -- Web Page Dialog
WinGetTitle, ModalSite, ahk_id %Modal_ID%
ModalWeb = ahk_id %Modal_ID%
WinWait, %ModalWeb%
IfWinNotActive, %ModalWeb%, ,WinActivate, %ModalWeb%
WinWaitActive, %ModalWeb%
Sleep, 1000
COM_Invoke(iWebBrowser2, "Document.parentWindow.execScript", "window.dialogArguments.getElementsByTagName('input').item[2].focus()")  ;focus in search box
Sleep, 500
COM_Invoke(iWebBrowser2, "Document.parentWindow.execScript", "window.dialogArguments.getElementsByTagName('input').item[3].focus()")  ;focus on first search button
Sleep, 500
COM_Invoke(iWebBrowser2, "Document.parentWindow.execScript", "window.dialogArguments.getElementsByTagName('input').item[4].focus()")  ;focus on second search button

COM_CoUnInitialize()
COM_Term()
Return

COMInitializeTest:
COM_init()
COM_CoInitialize()
website := "-- Web Page Dialog"

psh   :=   COM_CreateObject("Shell.Application")
psw   :=   COM_Invoke(psh,   "Windows") ; note this captures windows explorer windows as well
Loop, %   COM_Invoke(psw,   "Count")
{
   LocationName := COM_Invoke(psw,"Item[" A_Index-1 "].LocationName")
   IfInString, LocationName,%website%
   {
      iWebBrowser2         :=   COM_Invoke(psw,"Item",A_Index-1)
      break   
   }
}
COM_Release(psw),   VarSetCapacity(psw,   0),   COM_Release(psh),   VarSetCapacity(psh,   0)

RETURN

Even with iweb functions, I still can't access any objects.

What I'm doing is I'm creating automation for billing orders in our intranet site. I need to enter information into the text boxes and select from drop downs etc. The problem is, I can't get the objects in the modal window, if I try to access the elements the script accesses the parent window instead. This is using COM functions

With the iweb functions, I can activate the modal window, but it runs way slow and it won't enter the information in the text boxes or press any buttons. Again, I'm using Google to test all this out with.

If I can get to do actions inside that modal window I can get the rest from there and proceed.

tank
  • Moderators
  • 4242 posts
  • Last active: Oct 01 2014 01:38 PM
  • Joined: 21 Dec 2007
Of course you cant because a ModalDialog doesnt show in the shell windows group and the browser object cant be queried from the document object

this has nothing whatsoever to do with the COM library ahk or the iweb library your just trying to do something that has not way to be done aside from keystrokes and clicks

iWeb_Init()


/*
>>>>>>>>>>( Window Title & Class )<<<<<<<<<<< 
Google -- Webpage Dialog 
ahk_class Internet Explorer_TridentDlgFrame 

>>>>>>>>>>>>( Mouse Position )<<<<<<<<<<<<< 
On Screen:   787, 269  (less often used) 
In Active Window:   319, 79 

>>>>>>>>>( Now Under Mouse Cursor )<<<<<<<< 
ClassNN:   Internet Explorer_Server1

*/
SetTitleMatchMode,2
ControlGet,hWnd,Hwnd,,Internet Explorer_Server1,-- Webpage Dialog ahk_class Internet Explorer_TridentDlgFrame
pDoc:=IE_GetDocument(hWnd)


iWeb_setDomObj(pDoc,"q,","dragons")
iWeb_clickValue(pDoc,"Google Search")

iWeb_Release(pDoc)
iWeb_Term()
ExitApp
IE_GetDocument(hWnd)
{
   Static
   If Not   pfn
      pfn := DllCall("GetProcAddress", "Uint", DllCall("LoadLibrary", "str", "oleacc.dll"), "str", "ObjectFromLresult")
   ,   msg := DllCall("RegisterWindowMessage", "str", "WM_HTML_GETOBJECT")
   ,   COM_GUID4String(iid, "{00020400-0000-0000-C000-000000000046}")
   If   DllCall("SendMessageTimeout", "Uint", hWnd, "Uint", msg, "Uint", 0, "Uint", 0, "Uint", 2, "Uint", 1000, "UintP", lr:=0) && DllCall(pfn, "Uint", lr, "Uint", &iid, "Uint", 0, "UintP", pdoc:=0)=0
   Return   pdoc
}
I have not nor do i intend to support ModalDialog boxes with iWeb library (at least in the near future there is no reason to expect to see them in the real world often and its likely they will get fazed out in the future al together

Lexikos
  • Administrators
  • 9449 posts
  • Last active:
  • Joined: 17 Oct 2006
Sean, removing the parameters from COM_CreateObject (in COM_L) unnecessarily broke some of my scripts, including CLR and VA. I realise that the functionality is still present, but naming the functions differently (COM_CreateObject in COM.ahk, COM_CreateInstance in COM_L.ahk) makes it difficult to "cleanly" support both from the one source. Why not keep the parameters but wrap when no interface is specified? For instance,
COM_CreateObject(CLSID, IID = "", CLSCTX = 21)
{
	ppv := COM_CreateInstance(CLSID, IID, CLSCTX)
	Return	IID = "" ? COM_Enwrap(ppv) : ppv
}


Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
Oh, sorry, I didn't realize that it could break other libraries. I was aware that it would break some posted codes like
COM_CreateObject("Messenger.UIAutomation", "", 4)
and have been waiting for reports on those to tell the internal change/difference then. I thought the breaking was worth to do, as with the removal of COM_Invoke_, however, didn't count other libraries. The parameters are now restored back.

fincs
  • Moderators
  • 1662 posts
  • Last active:
  • Joined: 05 May 2007
There's a typo in COM_U.ahk. Here's a fix:
COM_SysAllocString(pstr)
{
	Return	DllCall("oleaut32\SysAllocString", "Uint", [color=red]&[/color]pstr)
}

COM_SysFreeString(pstr)
{
		DllCall("oleaut32\SysFreeString", "Uint", [color=red]&[/color]pstr)
}


Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
There's no typo, pstr is already a pointer in COM_U.

fincs
  • Moderators
  • 1662 posts
  • Last active:
  • Joined: 05 May 2007
Then how come the non-Unicode versions accept an AutoHotkey string whilst the Unicode version accepts a pointer? It makes code compatibility harder.
COM_SysAllocString(astr)
{
	Return	DllCall("oleaut32\SysAllocString", "Uint", COM_Unicode4Ansi(astr,[color=red]astr[/color]))
}

COM_Unicode4Ansi(ByRef wString, sString)
{
	VarSetCapacity(wString,3+2*nLen:=1+[color=red]StrLen(sString)[/color])
	Return	NumPut(DllCall("kernel32\MultiByteToWideChar","Uint",0,"Uint",0,"Uint",[color=red]&sString[/color],"int",nLen,"Uint",&wString+4,"int",nLen,"Uint")*2-2,wString)
}

Oh, and I've added a COM_IsObjectOriented() function to detect COM_L and COM_U (in order to pass objects to COM_Invoke() with or without "+").

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

Then how come the non-Unicode versions accept an AutoHotkey string whilst the Unicode version accepts a pointer?

Needless to say using pointer is more flexible than variable. Having used variable instead of pointer in ANSI version was now of historical origin: allowing to take advantage of length property of variable in AHK when converting ANSI to Unicode. Why are you bothering about it anyway? COM_SysAllocString is meant to be used internally. Where do you need to call it yourself?

fincs
  • Moderators
  • 1662 posts
  • Last active:
  • Joined: 05 May 2007
Yesterday I was playing with Lexikos' NET interop as you might know now :p. It was failing to work with COM_U so I looked further at its code. I found out that it uses COM_SysAllocString() on a native AutoHotkey string and that was the cause of the incompatibility.

COM_SysAllocString() is a good candidate to be "public" because it converts strings to BSTR format which is used a lot in COM.

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
Interesting as even COM_L/COM_U barely use COM_SysAllocString, only once where it's absolutely necessary.

Lexikos
  • Administrators
  • 9449 posts
  • Last active:
  • Joined: 17 Oct 2006
IIRC, the COM interfaces exposed by .NET have BSTR in place of System.String, hence my use of SysAllocString.

Inconsistencies between COM-COM_L-COM_U really bother me - maybe it showed in my previous post. There is enough difference (between the builds) already without having to worry about minor interface changes. I'm much less concerned about whether COM_SysAllocString accepts a pointer or string. (Btw, thanks for restoring COM_CreateObject's parameters.)

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
From hindsight, there were many decisions I regretted on COM.ahk. I felt rather unfortunate that I was little acquainted with AHK when wrote it, more precisely CoHelper.ahk. I think I went too conservative about designing the functions, which resulted in inflexibility IMO. For example, at first, I used too many ByRef parameters in worry of performance impact, then changed it, however, still used strings instead of pointers, again for performance worry, to allow to use StrLen, which was actually never utilized in COM.ahk. What a mess. So, I finally broke it in COM_U, but, only where I thought the impact was negligible as in COM_SysAllocString.

As with COM_CreateObject, I regretted it should have been from the start with COM.ahk: CreateObject/GetObject/GetActiveObject should have been strictly for IDispatch objects, I mean, no explicit IID/CLSCTX should be allowed. A separate function for generic cases. Then I wanted to combine the three functions into a single one, however, I decided rather not as VBS/JS use/recommend separate functions for those.

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
OK, I restored back to the older format COM_SysAllocString in COM_U as CLR.ahk uses it in many places. It's rather fortunate that it doesn't use explicitly COM_Unicode4Ansi. To future members who's gonna use COM_Unicode4Ansi in COM/COM_L, I suggest to use it always inline or like
ptr := COM_Unicode4Ansi(...)
Notice that, however, there still is nothing to restore for COM_SysFreeString.

incith
  • Members
  • 130 posts
  • Last active: Apr 03 2010 03:08 AM
  • Joined: 01 Oct 2005

I have not nor do i intend to support ModalDialog boxes with iWeb library (at least in the near future there is no reason to expect to see them in the real world often and its likely they will get fazed out in the future al together


I'm having a problem in that my program is simply freezing up when a modal window is opened however. I'm sending a iWeb_clickDomObj command which clicks a button that opens a modal dialog window, and then the whole program just freezes. I cannot _Release() or _Term() or anything. Once the modal window closes, then the rest of the functions continue to execute. I'm not waiting on the window or anything, literally just opening the window, and then nothing will continue to process. The GUI window is completely frozen.

I've tested this on IE8 and IE6. So if you can suggest a way to avoid the freezing, I can still do what I need to do without iWeb, but the freezing I cannot figure out at all.

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
That's what a modal window is supposed to do. You're like complaining a player stop playing when you press the pause key.