 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Joy2DWorld
Joined: 04 Dec 2006 Posts: 561 Location: Galil, Israel
|
Posted: Fri Jun 01, 2007 6:15 am Post subject: |
|
|
| Quote: | I'm curious why you became interested in variant.
IMHO, it's useless, and no real need of the dedicated functions although VariantClear can be handy sometimes. |
if am understanding things correctly...
1. The code earlier in this thread that was 'problematic' is sending info in a TYPICAL COM way... via the variant...
the perlscript simply constructed the varient... and that's why it works!
BUT**.... here is where my brain is smooshed... how do we CREATE the variant ?????
2. Data is passed TO Com objects very must via the variants... *MANY* com controls (excel, word. etc. etc. etc, even browser), are via variant...
3. Your very cool CGID_MSHTML function... is ... well.... incompleted without the final two elements... the sending & receive back Variants...
you're ability to grasp and understand the philosphy & workings of the MS design... is ... well... amazing...
am not seeing the complete Variant pic...
| Code: | pItm := SysAllocString(sItm)
VarSetCapacity(var2, 8 * 2, 0)
EncodeInteger(&var2 + 0, 8)
EncodeInteger(&var2 + 8, pItm) |
as a substitute for variant use ??
| Code: | AllocBString(ByRef Key, ByRef Var, sString) {
Ansi2Unicode(sString, wString)
Key := DllCall("oleaut32\SysAllocString", Str,wString)
VarSetCapacity(Var, 16, 0)
DllCall("ntdll\RtlFillMemoryUlong", UInt,&Var, UInt,4, UInt,8)
DllCall("ntdll\RtlFillMemoryUlong", UInt,&Var+8,UInt,4, UInt,Key)
} |
as the same thing ??
| Code: | SysAllocString(sValue)
VariantInitiate(ByRef var, pValue)
|
seems correct as a start... but not used anywhere! ?
also... once variant is initiated... is it readily useable ??
and does the function end up something like this ??:
| Code: | CGID_MSHTML_S(pwb, nCmd, nOpt = 0, sVal = "0") ; added sVal
{
GUID4String(CGID_MSHTML , "{DE4BA900-59CA-11CF-9592-444553540000}")
GUID4String(IID_IOleCommandTarget, "{B722BCCB-4E68-101B-A2BC-00AA00404770}")
pct := QueryInterface(pwb, IID_IOleCommandTarget)
if SVal {
psVal := SysAllocString(sVal)
DllCall("VariantInit", "UINT", pSVal,"UINT",8)
;VarSetCapacity(bstr1, 8 * 2, 0)
;EncodeInteger(&SVal, 0x08,2)
}
DllCall(VTable(pct, 4), "Uint", pct, "str", CGID_MSHTML, "Uint", nCmd, "Uint", nOpt, "UINT", pSVal, "UINT", 0) ; end was UINT, 0
Release(pct)
if SVal
SysFreeString(psVal)
return ; RetVal
} |
or is it missing a converstion from unicode (?)... _________________ Joyce Jamce |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Fri Jun 01, 2007 7:11 am Post subject: |
|
|
| Joy2DWorld wrote: | | the perlscript simply constructed the varient... and that's why it works! |
No, I don't think so.
First, when I used variant instead (:after CoTaskMemAlloc, i.e., sort of Global Alloc), it output access violation. It means that the function regarded the first part of the variant as memory address. How do I know? Variant type parameter has a value of range 0 ~ 0xffff, which is equal to the so called "Null-Pointer Assignment Partition" by "Jeffrey Richter" in his famous book "Programming Applications for Microsoft Windows, 4th edition", i.e., off-limit. So, an accessible memory address should be given here.
Second, at first I assumed so, but there was no evidence that Perl does any sort of Global Alloc with the variant, which is absolutely necessary here if trying to use a variant, at least as far as I can tell.
| Quote: | | Code: | pItm := SysAllocString(sItm)
VarSetCapacity(var2, 8 * 2, 0)
EncodeInteger(&var2 + 0, 8)
EncodeInteger(&var2 + 8, pItm) |
as a substitute for variant use ?? |
It's a variant, not a mere substitute. It's only created without ever using the dedicated functions for a variant.
| Quote: | | Code: | AllocBString(ByRef Key, ByRef Var, sString) {
Ansi2Unicode(sString, wString)
Key := DllCall("oleaut32\SysAllocString", Str,wString)
VarSetCapacity(Var, 16, 0)
DllCall("ntdll\RtlFillMemoryUlong", UInt,&Var, UInt,4, UInt,8)
DllCall("ntdll\RtlFillMemoryUlong", UInt,&Var+8,UInt,4, UInt,Key)
} |
as the same thing ?? |
Sure.
| Quote: | | Code: | SysAllocString(sValue)
VariantInitiate(ByRef var, pValue)
|
seems correct as a start... but not used anywhere! ?
also... once variant is initiated... is it readily useable ?? |
If you used VariantInitiate, you have to specify the type-parameter again with the correct one.
| Quote: | | and does the function end up something like this ??: |
The last two (variant) parameters are optional.
There is already one example in IEControl.ahk where the parameters really needed:
| Code: | IE_DoFontSize(pwb, s)
{
VarSetCapacity(var, 8 * 2, 0)
EncodeInteger(&var + 0, 3)
EncodeInteger(&var + 8, s)
DllCall(VTable(pwb, 54), "Uint", pwb, "Uint", 19, "Uint", 2, "Uint", &var, "Uint", &var)
}
|
This function is essentially the same with CGID_MSHTML.
The first one is IN, the second one is OUT (variant) parameters, i.e., different ones, but I just used the same one for both, i.e., recycled it.
Last edited by Sean on Fri Jun 01, 2007 7:26 am; edited 1 time in total |
|
| Back to top |
|
 |
Joy2DWorld
Joined: 04 Dec 2006 Posts: 561 Location: Galil, Israel
|
Posted: Fri Jun 01, 2007 7:24 am Post subject: |
|
|
@Sean
thanks for the enlightenment...
ok, some 'stupid questions'...
how come in once case we need a " Ansi2Unicode(sString, wString) " which seems right,
but in other case, not needed "pItm := SysAllocString(sItm)
VarSetCapacity(var2, 8 * 2, 0) " that seems different ? where did I miss the thing I missed ?....
just curios.. if only a structure is needed... how come MS warns over and over... about making sure first to call variant Init... ?
and all a basic "Variant" is... is a Three byte pointer (?) with the first byte a 'type' ? _________________ Joyce Jamce |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Fri Jun 01, 2007 7:34 am Post subject: |
|
|
| Joy2DWorld wrote: | how come in once case we need a " Ansi2Unicode(sString, wString) " which seems right,
but in other case, not needed "pItm := SysAllocString(sItm)
VarSetCapacity(var2, 8 * 2, 0) " that seems different ? where did I miss the thing I missed ?.... |
The wrapper SysAllocString() really consists of two parts:
Ansi2Unicode() -> SysAllocString API
| Quote: | | just curios.. if only a structure is needed... how come MS warns over and over... about making sure first to call variant Init... ? |
I take it as a warning to the VB programmers.
| Quote: | | and all a basic "Variant" is... is a Three byte pointer (?) with the first byte a 'type' ? |
It's a 16byte struct, aligned on 8byte. |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Fri Jun 01, 2007 9:54 am Post subject: |
|
|
I forgot to tell about my opinion on why BookCat works on Perl, but not with this ComCall via DllCall, if you are interested in it.
It's mere guess, but I suspect the COM implementation of BookCat was tested only with IDispatch type invoke, i.e., VBS like method.
It involves some indirections, so sufficiently slow down the whole process.
As this can be mimicked with this VTable method too, may test it if curious enough. |
|
| Back to top |
|
 |
polyethene
Joined: 11 Aug 2004 Posts: 5248 Location: UK
|
Posted: Sat Jun 02, 2007 10:51 am Post subject: |
|
|
How can I get the id of a named reference, there is no __uuidof operator? _________________ GitHub • Scripts • IronAHK • Contact by email not private message. |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
|
| Back to top |
|
 |
polyethene
Joined: 11 Aug 2004 Posts: 5248 Location: UK
|
Posted: Sat Jun 02, 2007 12:15 pm Post subject: |
|
|
I tried the following but I get function not found error:
| Code: | VarSetCapacity(dispid, 8, 0)
hres := DllCall("GetIDsOfNames", "UInt", 0, "UInt", &member, "UInt", 1, "UInt", 2048, "UInt", &dispid)
MsgBox, %hres%`n%ErrorLevel% |
_________________ GitHub • Scripts • IronAHK • Contact by email not private message. |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Sat Jun 02, 2007 12:30 pm Post subject: |
|
|
Try this, e.g., in WebControl:
| Code: | MsgBox, % GetIDsOfNames(pwb, "Visible")
GetIDsOfNames(pdisp, sName, LCID = 0)
{
Ansi2Unicode(sName, wName)
GUID4String(IID_NULL, "{00000000-0000-0000-0000-000000000000}")
DllCall(VTable(pdisp,5), "Uint", pdisp, "str", IID_NULL, "UintP", &wName, "Uint", 1, "Uint", LCID, "UintP", dispID)
Return dispID
}
|
|
|
| Back to top |
|
 |
Joy2DWorld
Joined: 04 Dec 2006 Posts: 561 Location: Galil, Israel
|
Posted: Sun Jun 03, 2007 1:58 am Post subject: |
|
|
@Sean,
thanks for the very lucid insight.
mod to code (w/ example):
| Code: |
IE_BColor(color = "Red") {
return CGID_MSHTML(pwb, 51,0, color )
}
CGID_MSHTML(pwb, nCmd, nOpt = 0, sVal = ":~Null~:", sValT = 8) { ; added sVal
GUID4String(CGID_MSHTML , "{DE4BA900-59CA-11CF-9592-444553540000}")
GUID4String(IID_IOleCommandTarget, "{B722BCCB-4E68-101B-A2BC-00AA00404770}")
pct := QueryInterface(pwb, IID_IOleCommandTarget)
if (sVal = ":~Null~:")
Var := DllCall(VTable(pct, 4), "Uint", pct, "str", CGID_MSHTML, "Uint", nCmd, "Uint", nOpt, "UINT", 0 , "UINT", 0)
else {
VarSetCapacity(var, 8 * 2) ; VariantInit(sVal, sValT)
psVal := SysAllocString(sVal) ; converts to unicode & allocates
EncodeInteger(&var + 0, sValT) ; Variant Type
EncodeInteger(&var + 8, psVal) ;
DllCall(VTable(pct, 4), "Uint", pct, "str", CGID_MSHTML, "Uint", nCmd, "Uint", nOpt, "UINT", &Var, "UINT", &Var)
SysFreeString(psVal)
}
Release(pct)
return Var
}
|
btw, the IE_LoadURL() seems to accept only 512 bytes max...
likely a MS limitation (?)
tried to understand this:
| Code: | Loading HTML content from a Stream
The IPersistStreamInit interface, and its associated methods, can be used to load HTML content from a stream using the WebBrowser control and Microsoft Visual C++.
This article discusses the steps required to load HTML content from a stream and is divided into the following sections.
Navigating to about:blank
The IWebBrowser2::Navigate2 method of the IWebBrowser2 interface enables you to navigate the browser to a URL. In the following sample code, the IWebBrowser2::Navigate2 method is used to navigate to the about:blank page. Navigating to this empty page ensures that MSHTML is loaded and that the HTML elements are available through the Dynamic HTML (DHTML) Object Model.
This example demonstrates how to navigate the WebBrowser control to an empty page. The variable m_pBrowser contains the IWebBrowser2 interface pointer obtained from the WebBrowser control.
m_pBrowser->Navigate2( _T("about:blank"), NULL, NULL, NULL, NULL );
Availability of the DHTML Object Model
The DHTML Object Model is used to access and manipulate the contents of an HTML page and is not available until the page is loaded. Your application determines that a page is loaded by handling the DWebBrowserEvents2::DocumentComplete event of the WebBrowser control. This event may be fired once for each frame in the page, and once when the top frame of the document is loaded. You can determine if the DWebBrowserEvents2::DocumentComplete event is for the top frame by comparing the IDispatch interface pointer passed by this event with that of the WebBrowser control.
This sample handler code for the WebBrowser DWebBrowserEvents2::DocumentComplete event demonstrates how to determine if this event is for the top frame, which indicates that the HTML page has loaded. This sample also demonstrates how to create a stream from a block of memory—in this case a string that contains the HTML content to be displayed.
void myObject::DocumentComplete(LPDISPATCH pDisp, VARIANT* URL)
{
HRESULT hr;
IUnknown* pUnkBrowser = NULL;
IUnknown* pUnkDisp = NULL;
IStream* pStream = NULL;
HGLOBAL hHTMLText;
static TCHAR szHTMLText[] = "<html><h1>Stream Test</h1><p>This HTML content is/
being loaded from a stream.</html>";
// Is this the DocumentComplete event for the top frame window?
// Check COM identity: compare IUnknown interface pointers.
hr = m_pBrowser->QueryInterface( IID_IUnknown, (void**)&pUnkBrowser );
if ( SUCCEEDED(hr) )
{
hr = pDisp->QueryInterface( IID_IUnknown, (void**)&pUnkDisp );
if ( SUCCEEDED(hr) )
{
if ( pUnkBrowser == pUnkDisp )
{ // This is the DocumentComplete event for the top
// frame - page is loaded!
// Create a stream containing the HTML.
// Alternatively, this stream may have been passed to us.
size_t = cchLength;
// TODO: Safely determine the length of szHTMLText in TCHAR.
hHTMLText = GlobalAlloc( GPTR, cchLength+1 );
if ( hHTMLText )
{
size_t cchMax = 256;
StringCchCopy((TCHAR*)hHTMLText, cchMax + 1, szHTMLText);
// TODO: Add error handling code here.
hr = CreateStreamOnHGlobal( hHTMLText, TRUE, &pStream );
if ( SUCCEEDED(hr) )
{
// Call the helper function to load the browser from the stream.
LoadWebBrowserFromStream( m_pBrowser, pStream );
pStream->Release();
}
GlobalFree( hHTMLText );
}
}
pUnkDisp->Release();
}
pUnkBrowser->Release();
}
}
Using QueryInterface to Obtain the IPersistStreamInit Interface
The IWebBrowser2::get_Document property on the WebBrowser control retrieves the document object that represents the DHTML Object Model for the top frame. MSHTML implements the IPersistStreamInit interface to provide the ability to load and save HTML using a stream, through the document object. The IDispatch interface for the document object can be queried for the IPersistStreamInit interface pointer using QueryInterface with an identifier of IID_IPersistStreamInit, as shown in the following code example.
HRESULT LoadWebBrowserFromStream(IWebBrowser* pWebBrowser, IStream* pStream)
{
HRESULT hr;
IDispatch* pHtmlDoc = NULL;
IPersistStreamInit* pPersistStreamInit = NULL;
// Retrieve the document object.
hr = pWebBrowser->get_Document( &pHtmlDoc );
if ( SUCCEEDED(hr) )
{
// Query for IPersistStreamInit.
hr = pHtmlDoc->QueryInterface( IID_IPersistStreamInit, (void**)&pPersistStreamInit );
if ( SUCCEEDED(hr) )
{
// Initialize the document.
hr = pPersistStreamInit->InitNew();
if ( SUCCEEDED(hr) )
{
// Load the contents of the stream.
hr = pPersistStreamInit->Load( pStream );
}
pPersistStreamInit->Release();
}
}
}
Using the IPersistStreamInit Interface to Load HTML Content
The IPersistStreamInit interface has InitNew and Load methods that are used to initialize and load an HTML document from a stream. The InitNew method initializes the stream to a known state and the Load method loads the HTML content from the stream.
In the previous sample code, the HTML document is initialized and the HTML content is loaded from the stream.
Note In Microsoft Internet Explorer 5, more than one call to the Load method of the IPersist interfaces is supported. In earlier versions, only one call to Load per instance of MSHTML is supported. |
from: http://msdn2.microsoft.com/en-us/library/aa752047.aspx
but... am unclear about where/how this can be called... _________________ Joyce Jamce |
|
| Back to top |
|
 |
Elevator_Hazard
Joined: 28 Oct 2006 Posts: 297 Location: US
|
Posted: Sun Jun 03, 2007 3:24 am Post subject: |
|
|
Still bored on the linux and I decided to try this system so uh...
 _________________ Changed siggy at request of ahklerner  |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Sun Jun 03, 2007 8:57 am Post subject: |
|
|
| Joy2DWorld wrote: | | tried to understand this: |
You seem to try to access/manipulate DOM, so, you're in a whole new world.
Navigate2 is nearly identical to IE_LoadURL() whose original name is indeed Navigate.
And, you can obtain the DOM interface using IE_Document(). |
|
| Back to top |
|
 |
Joy2DWorld
Joined: 04 Dec 2006 Posts: 561 Location: Galil, Israel
|
Posted: Sun Jun 03, 2007 10:33 pm Post subject: |
|
|
@Sean,
your insight is incredibly helpful.
seems being able to load html DIRECTLY FROM MEMORY, could be a neat and powerful trick in your browser function... so...
hopefully these q's are not too too low in level....
1. pPersistStreamInit->Load( pStream ) seems to be the key to loading the stream. How specifically do we determine the call for this ?
2. am not clear about exactly what pHtmlDoc->QueryInterface( IID_IPersistStreamInit, (void**)&pPersistStreamInit ) is actually giving us... the index to the call ??
3. pWebBrowser->get_Document( &pHtmlDoc ) is giving an instance #??
4. CreateStreamOnHGlobal( hHTMLText, TRUE, &pStream ) is the stream creation call... are there any 'tricks'/prereqs that are especially necessary to call this ?
5. an not really understanding the bigger picture behind how we find & call this function... m_pBrowser->Navigate2( _T("about:blank"), NULL, NULL, NULL, NULL ).
assumes if have understood the MS directives that
| Code: | m_pBrowser->Navigate2( _T("about:blank"), NULL, NULL, NULL, NULL )
CreateStreamOnHGlobal( hHTMLText, TRUE, &pStream )
pWebBrowser->get_Document( &pHtmlDoc )
pHtmlDoc->QueryInterface( IID_IPersistStreamInit, (void**)&pPersistStreamInit )
pPersistStreamInit->Load( pStream ) |
is the basic structure for loading html from memory ? _________________ Joyce Jamce |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Mon Jun 04, 2007 1:07 am Post subject: |
|
|
| Joy2DWorld wrote: | | seems being able to load html DIRECTLY FROM MEMORY |
There is already one: IE_LoadHTML().
There could be a length limit to it, but I don't know of the value.
| Quote: | assumes if have understood the MS directives that
| Code: | m_pBrowser->Navigate2( _T("about:blank"), NULL, NULL, NULL, NULL )
CreateStreamOnHGlobal( hHTMLText, TRUE, &pStream )
pWebBrowser->get_Document( &pHtmlDoc )
pHtmlDoc->QueryInterface( IID_IPersistStreamInit, (void**)&pPersistStreamInit )
pPersistStreamInit->Load( pStream ) |
|
Although I haven't tried it, it appears to be straightforward to do it.
So, you may implement it as an alternative to IE_LoadHTML(). |
|
| Back to top |
|
 |
Joy2DWorld
Joined: 04 Dec 2006 Posts: 561 Location: Galil, Israel
|
Posted: Wed Jun 06, 2007 1:29 am Post subject: |
|
|
1. Confirmed design limitation of Iexplore. depending on version, Limit is 512 bytes to in ver. 7, 2048 bytes. (there is a thread on that somewhere here...)
so...
ABOUT: cannot be used as method for passing more than basic (very short) html.
2. | Quote: | it appears to be straightforward to do it.
So, you may implement it as an alternative to IE_LoadHTML(). |
Somehow my mind does not want to take in the MS structure details. attempts with this seemingly straightfoward code.. have *not* been successful. Unlike coding errors of logic, which can debug.. 'Conformity' to the MS structure/procedural order, etc. mind just is not seeming to want to absorb....
any help/guidance appreciated, streaming feed to the html from var seems like a valueable function... anyhow... _________________ Joyce Jamce |
|
| 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
|