 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Sean Guest
|
Posted: Wed Jan 31, 2007 5:27 pm Post subject: |
|
|
| Quote: | | It is a known problem, still mysterious for me, but the problem might be in Windows rather than in AHK (just an hypothesis). |
Thanks for the explanation. It made me embarrassed at first.
| Quote: | | I checked on a couple of WinXP Pro SP2 computers at work and both have it in System32. |
It was missing in my system, so I had to extract it from the non-SP XP CD. |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3615 Location: Belgrade
|
Posted: Thu Feb 01, 2007 11:16 am Post subject: |
|
|
Hm... this is very intersting topic for me. I didn't know com functions can be called this way....
Need some more information from you:
| Code: |
DllCall("msjava\call", "Uint", DecodeInteger(pv + 4*5), "Uint", ppv, "Uint", &wFile, "Uint", 0)
DllCall("msjava\call", "Uint", DecodeInteger(pv + 4*3), "Uint", ppv, "Uint", 7)
DllCall("msjava\call", "Uint", DecodeInteger(pv + 4*2), "Uint", ppv) |
I see that first func you call is IActiveDesktop::SetWallpaper. But how did you find 4*5 offset ?
The last one is ApplyChanges i guess... the middle is unknown
I watched definition of interface here but I didn't connected the third and second offset
Anyway, I understand now what you want, at it would be really convinient in this sceneraio. This can really lead to COM solution with AHK if you can explain me how did you find those offsets
BTW, don't expect that anyone will read your code if you don't present it the correct way. It happend that I interested much in topic you started so I was willing to investigate. I seriously dobut that anybody can read your topic and understand what you want, or what you use... _________________
 |
|
| Back to top |
|
 |
Sean Guest
|
Posted: Thu Feb 01, 2007 1:56 pm Post subject: |
|
|
| majkinetor wrote: | I see that first func you call is IActiveDesktop::SetWallpaper. But how did you find 4*5 offset ?
The last one is ApplyChanges i guess... the middle is unknown |
It's in ShlObj.h. You may search there by Active Desktop in this case.
BTW, you seemed to miss that they should be 0-based.
So, the middle one is ApplyChanges and the last one is Release.
I know this site. As a matter of fact, my friend googled and found this site after I told him about my idea on ComCall via DllCall. I found it handy, but I believe Platform SDK is the ultimate place to go.
| Quote: | Anyway, I understand now what you want, at it would be really convinient in this sceneraio. This can really lead to COM solution with AHK if you can explain me how did you find those offsets  |
Good news. Just keep in mind that it may require a lot of researches and experiments sometimes, especially regarding the ones intended for VB scripts, they are so opaque and obscure.
| Quote: | | BTW, don't expect that anyone will read your code if you don't present it the correct way. It happend that I interested much in topic you started so I was willing to investigate. I seriously dobut that anybody can read your topic and understand what you want, or what you use... |
To be honest, I thought just one person would be enough. Now I suppose I'm relieved. |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3615 Location: Belgrade
|
Posted: Thu Feb 01, 2007 3:43 pm Post subject: |
|
|
I didn't count IUnknown functions for some reason..
Ok, I think Chris should take this request into account and as it is very easy to implement to make it high priority. Then we can experiment with COM and create some nice wrappers without msjava.dll or equivalent _________________
 |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Sat Feb 03, 2007 5:54 am Post subject: |
|
|
I've applied the suggestion. (Edit: It's now in the current release.)
Here's an example based on yours:
| Code: | if not hmodule := DllCall("GetModuleHandle", str, "user32")
MsgBox !hmodule
else
{
if not CharUpperProc := DllCall("GetProcAddress", uint, hmodule, str, "CharUpperA")
MsgBox !CharUpperProc
else
{
MyVar = abc
result := DllCall(CharUpperProc, str, MyVar, str)
if !(MyVar == "ABC" && result == "ABC")
MsgBox Result: %result%|%MyVar%`nErr: "%ErrorLevel%"
}
} |
| Sean wrote: | | BTW, is this a bug? I have to use VarSetCapacity(sText, 10240, 1) | This is documented in the fine print: When a variable's address (e.g. &MyVar) is passed to a function and that function alters the length of the variable's contents, subsequent uses of the variable may behave incorrectly. To fix this, do one of the following: 1) Pass MyVar as a "str" argument rather than as a uint/address; 2) In v1.0.44.03+, call VarSetCapacity(MyVar, -1) to update the variable's internally-stored length after calling DllCall.
I've changed the documentation to bring more attention to this limitation. By the way, AutoHotkey remembers the string-length of each variable because it improves performance.
Thanks.
Last edited by Chris on Wed Feb 07, 2007 6:54 pm; edited 1 time in total |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 5723
|
Posted: Sat Feb 03, 2007 9:01 am Post subject: |
|
|
@ majkinetor / PhiLho
Looks very interesting. Can you throw more light on this ? Maybe test and post a couple of examples ?
Please..
 |
|
| Back to top |
|
 |
Sean Guest
|
Posted: Sat Feb 03, 2007 12:18 pm Post subject: |
|
|
It's a really fast implementation. Thanks for considering it.
| Quote: | | Sean wrote: | | BTW, is this a bug? I have to use VarSetCapacity(sText, 10240, 1) | This is documented in the fine print: |
It was my fault. I seemed to miss it, I was quickly reading the "Variables and Expressions" section and DllCall() section before writing the examples.
I'd like to post one more example whose ProgID is InternetExplorer.Application (:it's in ExDisp.h).
I chose this example because in this case the COM Server resides in exe file (:iexplore.exe) and a new string type is unavoidable: BSTRING which is probably unfamiliar to many users. In reality, BSTRING is nothing but a UTF-16 string prepended with 4-byte string length data, but an important property of it is that it's owned by the system so can cross the process boundaries without a problem.
An excellent tool for getting information about COM is MS's oleview.exe which is included in reskit. And tlb from the site mentioned once is also good for this approach.
| Code: |
sUrl := "http://www.autohotkey.com/forum/"
DCOM := False ; here no need for DCOM
VarSetCapacity(wUrl, StrLen(sUrl) * 2 + 2)
; Convert from ANSI to UTF-16
DllCall("MultiByteToWideChar"
, "Uint", 0
, "Uint", 0
, "Uint", &sUrl
, "int", -1
, "Uint", &wUrl
, "int", StrLen(sUrl) + 1)
; Allocate BSTRING from UTF-16
pstr := DllCall("oleaut32\SysAllocString", "Uint", &wUrl)
; Initialize COM
DllCall("ole32\CoInitialize", "Uint", 0)
VarSetCapacity(CLSID_InternetExplorer, 16)
; Encode 128bit CLSID_InternetExplorer
EncodeInteger(&CLSID_InternetExplorer , 0x0002DF01)
EncodeInteger(&CLSID_InternetExplorer + 4, 0)
EncodeInteger(&CLSID_InternetExplorer + 8, 0xC0)
EncodeInteger(&CLSID_InternetExplorer +12, 0x46 << 24)
VarSetCapacity(IID_IWebBrowser2, 16)
; Encode 128bit IID_IWebBrowser2
EncodeInteger(&IID_IWebBrowser2 , 0xD30C1661)
EncodeInteger(&IID_IWebBrowser2 + 4, 0xCDAF | 0x11D0 << 16)
EncodeInteger(&IID_IWebBrowser2 + 8, 0x8A | 0x3E << 8 | 0x00 << 16 | 0xC0 << 24)
EncodeInteger(&IID_IWebBrowser2 +12, 0x4F | 0xC9 << 8 | 0xE2 << 16 | 0x6E << 24)
; CreateObject( "InternetExplorer.Application" )
DllCall("ole32\CoCreateInstance"
, "Uint", &CLSID_InternetExplorer
, "Uint", 0
, "Uint", 1 | 2 | 4 | (DCOM ? 0x10 : 0) ; CLSCTX_ALL
, "Uint", &IID_IWebBrowser2
, "UintP", ppwb)
pwb := DecodeInteger(ppwb)
; VARIANT
VarSetCapacity(var, 8 * 2, 0)
DllCall(DecodeInteger(pwb + 4*11) ; Navigate
, "Uint", ppwb
, "Uint", pstr
, "Uint", &var
, "Uint", &var
, "Uint", &var
, "Uint", &var)
DllCall(DecodeInteger(pwb + 4*41) ; (Make) Visible
, "Uint", ppwb
, "int", true)
DllCall(DecodeInteger(pwb + 4* 2) ; Release
, "Uint", ppwb)
; Uninitialize COM
DllCall("ole32\CoUninitialize")
; Free the allocated BSTRING
DllCall("oleaut32\SysFreeString", "Uint", pstr)
DecodeInteger(ref)
{
DllCall("ntdll\RtlMoveMemory", "UintP", val, "Uint", ref, "Uint", 4)
Return val
}
EncodeInteger(ref, val)
{
DllCall("ntdll\RtlFillMemoryUlong", "Uint", ref, "Uint", 4, "Uint", val)
}
|
|
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3615 Location: Belgrade
|
Posted: Sat Feb 03, 2007 1:03 pm Post subject: |
|
|
It seems that it is time now, Sean, to encapsulate some of the interesting COM objects. I think that WebBrowser2 control should on top of the request. It would be nice to pit things you already done in AHK form.
If you are interesting we can do that on wiki (cuz of colaboration).
Thank you Crhis for fast update. I guess we will have some COM functionality within AHK soon.
Thank you Sean for this COM insight. _________________
 |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Sat Feb 03, 2007 2:00 pm Post subject: |
|
|
| Nice example. Thanks for trying it out so quickly; and thanks again for the idea. |
|
| Back to top |
|
 |
Sean Guest
|
Posted: Sat Feb 03, 2007 5:57 pm Post subject: |
|
|
| majkinetor wrote: | | I think that WebBrowser2 control should on top of the request. |
There was a reason I used CLSID_InternetExplorer than CLSID_WebBrowser. This WebBrowser object owns a window, i.e., should be tied to a (Internet Explorer) window to be useful. If I had used merely CLSID_WebBrowser, the object created would have been useless as it's bound to no window at all, contrary to CLSID_InternetExplorer which creates own window.
To obtain the corresponding WebBrowser object of an existing Internet Explorer window is non-trivial, but possible fortunately. Windows provides IShellWindows interface which keeps all running windows of explorer.exe and iexplore.exe and returns the corresponding WebBrowser object on request. But, unfortunately this time, it's provided only when the shell is explorer.exe. If using an alt shell, then can't have it.
BTW, I found out that the script I mentioned is really about embedding a WebBrowser control in GUI of AHK. And, I think what you're really interested in is also this.
If merely embedding a WebPage in GUI is the sole purpose, there is a really simple way. I saw this method in at least two sites. I borrowed the code from them:
DllCall("atl\AtlAxWinInit")
DllCall("CreateWindowEx", 0, "AtlAxWin", "", 0x50000000, ..., GUI's Handle, ...)
; I omitted parameter types and some parameters for simplicity
Then, if explorer.exe is the shell, we can obtain the control object indirectly using IShellWindows.
But, if to completely control the embedded WebBrowser from creation to closing regardless of the environment, like the library cwebpage.dll does, is the purpose, then I can't tell if it's possible atm. Need a reseach. |
|
| Back to top |
|
 |
Sean Guest
|
Posted: Sat Feb 03, 2007 5:58 pm Post subject: |
|
|
| Chris wrote: | | Nice example. |
Thanks for good words. |
|
| Back to top |
|
 |
Sean Guest
|
Posted: Mon Feb 05, 2007 5:45 am Post subject: |
|
|
This is an example how to embed and control WebBrowser control.
I suppose now no need for an external library.
| Code: |
Gui, Show, w800 h600 Center, WebControl
hWnd := WinExist( "WebControl" )
CLSID_WebBrowser := "{8856F961-340A-11D0-A96B-00C04FD705A2}"
VarSetCapacity(IID_IWebBrowser2, 16)
;Encode 128bit IID_IWebBrowser2
EncodeInteger(&IID_IWebBrowser2 , 0xD30C1661)
EncodeInteger(&IID_IWebBrowser2 + 4, 0xCDAF | 0x11D0 << 16)
EncodeInteger(&IID_IWebBrowser2 + 8, 0x8A | 0x3E << 8 | 0x00 << 16 | 0xC0 << 24)
EncodeInteger(&IID_IWebBrowser2 +12, 0x4F | 0xC9 << 8 | 0xE2 << 16 | 0x6E << 24)
hModule := DllCall("LoadLibrary", "str", "atl.dll")
DllCall("atl\AtlAxWinInit")
hCtrl := DllCall("CreateWindowEx"
, "Uint", 0x200 ; WS_EX_CLIENTEDGE
, "str", "AtlAxWin" ; ClassName
, "Uint", &CLSID_WebBrowser ; WindowName
, "Uint", 0x10000000 | 0x40000000 ; WS_VISIBLE | WS_CHILD
, "int", 0 ; Left
, "int", 0 ; Top
, "int", 800 ; Width
, "int", 600 ; Height
, "Uint", hWnd
, "Uint", 0
, "Uint", 0
, "Uint", 0)
; Obtain IUnknown Interface
DllCall("atl\AtlAxGetControl", "Uint", hCtrl, "UintP", ppunk)
; Obtain IWebBrowser2 Interface
DllCall(DecodeInteger(DecodeInteger(ppunk) + 4*0) ; QueryInterface
, "Uint", ppunk
, "Uint", &IID_IWebBrowser2
, "UintP", ppwb)
DllCall(DecodeInteger(DecodeInteger(ppunk) + 4*2) ; Release
, "Uint", ppunk)
pwb := DecodeInteger(ppwb)
sUrl := "http://www.autohotkey.com/"
VarSetCapacity(wUrl, StrLen(sUrl) * 2 + 2)
Unicode(sUrl, wUrl)
sUrl1 := "http://www.autohotkey.com/forum/"
VarSetCapacity(wUrl1, StrLen(sUrl1) * 2 + 2)
Unicode(sUrl1, wUrl1)
; VARIANT
VarSetCapacity(var, 8 * 2, 0)
DllCall(DecodeInteger(pwb + 4*11) ; Navigate
, "Uint", ppwb
, "Uint", &wUrl
, "Uint", &var
, "Uint", &var
, "Uint", &var
, "Uint", &var)
Sleep, 5000
DllCall(DecodeInteger(pwb + 4*11) ; Navigate
, "Uint", ppwb
, "Uint", &wUrl1
, "Uint", &var
, "Uint", &var
, "Uint", &var
, "Uint", &var)
Sleep, 5000
DllCall(DecodeInteger(pwb + 4*7) ; GoBack
, "Uint", ppwb)
Sleep, 3000
DllCall(DecodeInteger(pwb + 4*8) ; GoForward
, "Uint", ppwb)
Sleep, 2000
DllCall(DecodeInteger(pwb + 4*2) ; Release
, "Uint", ppwb)
DllCall("FreeLibary", "Uint", hModule)
MsgBox, DONE
Unicode(ByRef sString, ByRef wString)
{
DllCall("MultiByteToWideChar"
, "Uint", 0
, "Uint", 0
, "Uint", &sString
, "int", -1
, "Uint", &wString
, "int", StrLen(sString) + 1)
}
DecodeInteger(ref)
{
DllCall("ntdll\RtlMoveMemory", "UintP", val, "Uint", ref, "Uint", 4)
Return val
}
EncodeInteger(ref, val)
{
DllCall("ntdll\RtlFillMemoryUlong", "Uint", ref, "Uint", 4, "Uint", val)
}
|
|
|
| Back to top |
|
 |
BoBo Guest
|
Posted: Mon Feb 05, 2007 2:21 pm Post subject: |
|
|
| Quote: | sUrl := "http://www.autohotkey.com/"
VarSetCapacity(wUrl, StrLen(sUrl) * 2 + 2)
Unicode(sUrl, wUrl)
sUrl1 := "http://www.autohotkey.com/forum/"
VarSetCapacity(wUrl1, StrLen(sUrl1) * 2 + 2)
Unicode(sUrl1, wUrl1) | Looks promising (TBH, all that looks cryptic to me, so my expectations are 100% 'consumer orientated' ).
I've executed your script/sample and based on the above links, set within the code I've expected to get/see one of those pages loaded within the Gui/Control. But I might be wrong.
Unfortunatly the control is staying empty. Could the following setting cause that issue because it's OS/Browser related: | Code: | | CLSID_WebBrowser := "{8856F961-340A-11D0-A96B-00C04FD705A2}" | ??
Thx for your effort. Much appreciated.  |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3615 Location: Belgrade
|
Posted: Mon Feb 05, 2007 3:23 pm Post subject: |
|
|
[deleted] _________________

Last edited by majkinetor on Tue Feb 06, 2007 9:34 am; edited 2 times in total |
|
| Back to top |
|
 |
foom
Joined: 19 Apr 2006 Posts: 386
|
Posted: Mon Feb 05, 2007 5:33 pm Post subject: |
|
|
| Sean could you please elaborate where you get the information to build for example the IID_IWebBrowser2 (InterfaceID?)? |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|