I am calling GetIDsOfNames() on a dispatch interface but changed the string to a wstring.
It seems incompatible, should i stick with ansi string here?
HRESULT GetIDsOfNames(
REFIID riid,
OLECHAR FAR* FAR* rgszNames,
unsigned int cNames,
LCID lcid,
DISPID FAR* rgDispId
);
I am using it like:
hr = o.GetIDsOfNames( IID_NULL, sMemberName, 1, 0, rgDispID )
Thanks,
It should be AS WSTRING, but the built-in implementation of IDispatch still uses AS STRING.
You must use hr = o.GetIDsOfNames(IID_NULL, UCODE$(sMemberName), 1, 0, rgDispID)
Thanks, great!
The original is a wstring so i'll use movememory into an ansistring :)
There is a good chance this wrapper never worked, for the old compiler i assume it should have been unicode as well.
Guess i never used this once actually..
The build-in IDispatch interface declaration is undocumented and, therefore, subject to change.
' *** As built into the PowerBASIC compiler ***
' Note: GetIDsOfNames still uses AS STRING, instead of AS WSTRING, for the rgszNames parameter.
' Therefore, you must use a variable declared AS STRING and convert it to unicode with UCODE$.
'INTERFACE IDispatch $IID_IDispatch
' INHERIT IUnknown
' ' =====================================================================================
' METHOD GetTypeInfoCount ( _ ' VTable offset = 12
' BYREF pctinfo AS DWORD _ ' __out unsigned int *pctinfo
' ) AS LONG ' HRESULT
' ' =====================================================================================
' METHOD GetTypeInfo ( _ ' VTable offset = 16
' BYVAL iTInfo AS DWORD _ ' __in unsigned int iTInfo
' , BYVAL lcid AS DWORD _ ' __in LCID lcid
' , BYREF ppTInfo AS DWORD _ ' __out ITypeInfo **ppTInfo
' ) AS LONG ' HRESULT
' ' =====================================================================================
' METHOD GetIDsOfNames ( _ ' VTable offset = 20
' BYREF riid AS GUID _ ' __in REFIID riid
' , BYREF rgszNames AS STRING _ ' __in OLECHAR **rgszNames
' , BYVAL cNames AS DWORD _ ' __in unsigned int cNames
' , BYVAL lcid AS DWORD _ ' __in LCID lcid
' , BYREF rgDispId AS LONG _ ' __out DISPID *rgDispId
' ) AS LONG ' HRESULT
' ' =====================================================================================
' METHOD Invoke ( _ ' VTable offset = 24
' BYVAL dispIdMember AS LONG _ ' __in DISPID dispIdMember
' , BYREF riid AS GUID _ ' __in REFIID riid
' , BYVAL lcid AS DWORD _ ' __in LCID lcid
' , BYVAL wFlags AS DWORD _ ' __in WORD wFlags
' , BYREF pDispParams AS DISPPARAMS _ ' __in DISPPARAMS *pDispParams
' , BYREF pVarResult AS VARIANT _ ' __out VARIANT *pVarResult
' , BYVAL pExcepInfo AS DWORD _ ' __out EXCEPINFO *pExcepInfo
' , BYREF puArgErr AS DWORD _ ' __out unsigned int *puArgErr
' ) AS LONG ' HRESULT
' ' =====================================================================================
'END INTERFACE
In my headers, I use COM_IDispatch instead:
INTERFACE COM_IDispatch $IID_IDispatch
INHERIT IUnknown
' =====================================================================================
METHOD GetTypeInfoCount ( _ ' VTable offset = 12
BYREF pctinfo AS DWORD _ ' __out unsigned int *pctinfo
) AS LONG ' HRESULT
' =====================================================================================
METHOD GetTypeInfo ( _ ' VTable offset = 16
BYVAL iTInfo AS DWORD _ ' __in unsigned int iTInfo
, BYVAL lcid AS DWORD _ ' __in LCID lcid
, BYREF ppTInfo AS ITypeInfo _ ' __out ITypeInfo **ppTInfo
) AS LONG ' HRESULT
' =====================================================================================
METHOD GetIDsOfNames ( _ ' VTable offset = 20
BYREF riid AS GUID _ ' __in REFIID riid
, BYREF rgszNames AS WSTRING _ ' __in OLECHAR **rgszNames
, BYVAL cNames AS DWORD _ ' __in unsigned int cNames
, BYVAL lcid AS DWORD _ ' __in LCID lcid
, BYREF rgDispId AS LONG _ ' __out DISPID *rgDispId
) AS LONG ' HRESULT
' =====================================================================================
METHOD Invoke ( _ ' VTable offset = 24
BYVAL dispIdMember AS LONG _ ' __in DISPID dispIdMember
, BYREF riid AS GUID _ ' __in REFIID riid
, BYVAL lcid AS DWORD _ ' __in LCID lcid
, BYVAL wFlags AS WORD _ ' __in WORD wFlags
, BYREF pDispParams AS DISPPARAMS _ ' __in DISPPARAMS *pDispParams
, BYREF pVarResult AS VARIANT _ ' __out VARIANT *pVarResult
, BYREF pExcepInfo AS EXCEPINFO _ ' __out EXCEPINFO *pExcepInfo
, BYREF puArgErr AS DWORD _ ' __out unsigned int *puArgErr
) AS LONG ' HRESULT
' =====================================================================================
END INTERFACE
I may need to use the vtable offset [5] directly then, already thought about that today but it's a bit old fashion :)
I've found that some of the 'built in' interface members are somewhat less than optimal; at least for me. For example, I believe IConnectionPointContainer::FindConnectionPoint takes a Byref Dword as a first parameter instead of a Byref Guid (the IID of the event sink) which seems to make more sense. Especially as PB has a GUID data type.
Don't forget that the compiler is written in assembler, not with PowerBASIC, and the assembler has not the GUID type defined.
' *** As built into the PowerBASIC compiler ***
'INTERFACE IConnectionPointContainer $IID_IConnectionPointContainer
' INHERIT IUnknown
' ' =====================================================================================
' METHOD EnumConnectionPoints ( _ ' VTable offset = 12
' BYREF ppEnum AS DWORD _ ' __out IEnumConnectionPoints **ppEnum
' ) AS LONG ' HRESULT
' ' =====================================================================================
' METHOD FindConnectionPoint ( _ ' VTable offset = 14
' BYREF riid AS DWORD _ ' __in REFIID riid
' , BYREF ppCP AS DWORD _ ' __out IConnectionPoint **ppCP
' ) AS LONG ' HRESULT
' ' =====================================================================================
'END INTERFACE
That thought occurred to me too Jose, but hearing you say it too confirms my thoughts. I had studied your declare and the one you mentioned as being built in, and that was the only sense I could make out of it.
I was just working with this lately, and found this to be easier to work with...
Type IEnumConnectionPointsVtbl
QueryInterface As Dword Ptr
AddRef As Dword Ptr
Release As Dword Ptr
Next As Dword Ptr
Skip As Dword Ptr
Reset As Dword Ptr
Clone As Dword Ptr
End Type
Type IEnumConnectionPoints1
lpVtbl As IEnumConnectionPointsVtbl Ptr
End Type
Interface IMyConnPtContainer $IID_IConnectionPointContainer : Inherit IUnknown
Method EnumConnectionPoints(Byref ppEnum As IEnumConnectionPoints1) As Long
Method FindConnectionPoint(Byref riid As Guid, Byref ppCP As IConnectionPoint) As Long
End Interface
And then the call is more natural...
Call pConPtCon.FindConnectionPoint($IID_IGridEvents, pConPt) To hr
But in the end I decided to go with the built in interfaces to avoid having to provide alternate declares, and it can be made to work fairly easily too...
Global pSink As IGridEvents
Global pGrid As IGrid
Global pConnectionPointContainer As IConnectionPointContainer
Global pConnectionPoint As IConnectionPoint
Global dwCookie As Dword
Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long
Local pCreateStruct As CREATESTRUCT Ptr
Local strSetup,strCoordinate As BStr
Local EventGuid As Guid
Local hCtl As Dword
Register i As Long
Register j As Long
pCreateStruct=wea.lParam : wea.hInst=@pCreateStruct.hInstance 'Get Module Instance Handle
Let pGrid = NewCom "FJHGrid.Grid" 'Load Com Component Containing Grid
strSetup="120:Column 1:^,130:Column 2:^,140:Column 3:^,150:Column 4:^,160:Column 5:^" 'Comma delimited Column Setup String For Grid
pGrid.Create(Wea.hWnd, strSetup, 10, 10, 570, 222, 25, 5, 20, "", 18, %FW_DONTCARE) 'Create Grid Through Method Call
pConnectionPointContainer = pGrid 'Do QueryInterface(IConnectionPointContainer)
EventGuid=$IID_IGridEvents 'Convert Guid String To Guid
Call pConnectionPointContainer.FindConnectionPoint(Byval Varptr(EventGuid), Byval Varptr(pConnectionPoint)) 'Find Connection Point
Let pSink = Class "CEventClass" 'Instantiate Event Sink Class
Call pConnectionPoint.Advise(Byval Objptr(pSink), dwCookie) 'Notify Grid Component of Sink Address
For i=1 To 25 'Load Grid With Sample Strings
For j=1 To 5 'Refresh() Method Needs To Be
strCoordinate="(" & Trim$(Str$(i)) & "," & Trim$(Str$(j)) & ")" 'Called Afterwards To Make Them Visible
pGrid.SetData(i, j, strCoordinate) 'The Button Lower Left Retrieves The
Next j 'Text From Row 3, Col 2. The Button
Next i 'Lower Right Unloads The Grid.
pGrid.Refresh()
fnWndProc_OnCreate=0
End Function
I guess I hijacked your thread Edwin. Just lately I've been trying to see if I could use some of the built in interface declarations, so I thought it pertained somewhat. I've found that usually interface pointers are passed in as Byref dwords.