Looking for help on how to cast / convert a pointer to a record - similar to what dotNet's Marshal.PtrToStructure does - but using Delphi.
Details: using an ActiveX / COM (original code in C++). Implementing an interface allowing to catch events raised by the ActveX control.
One of the implemented interface's methods signature looks like:
procedure TIUIX_ObjImplEvent.OnEvent(const pSender: IUIX_Obj; const pEvent: IUIX_Event);
IUIX_Event is an interface (derives from IDispatch). Has a property Param1 of type Param_T.
Param1 holds a pointer to a record type.
Now, I have C# code I would like to convert to Delphi:
public void OnEvent(IUIX_Obj pSender, IUIX_Event pEvent)
{
//some more code before, and then this part:
IntPtr outPtr = new IntPtr(pEvent.Param1);
UIX_NotifyInfo ni = (UIX_NotifyInfo)System.Runtime.InteropServices.Marshal.PtrToStructure(outPtr, typeof(UIX_NotifyInfo));
}
UIX_NotifyInfo is a record (/struct).
Qustion: how to go from pEvent.Param1 to ni? Using Delphi:
procedure TIUIX_ObjImplEvent.OnEvent(const pSender: IUIX_Obj; const pEvent: IUIX_Event);
var
ni : UIX_NotifyInfo;
begin
pEvent.Handled := false;
if (pEvent.Code = e_Notify) then
begin
//how to go from pEvent.Param1 to ni like in C#'s PtrToStructure?
if (ni.nCode = UIX_Notify_BeforeShowPopup) then
begin
pEvent.Handled := true;
end;
end;
end;
My guess is using the Move procedure, but whatever I try it either does not compile or crashes :)
Move(??, ni, SizeOf(UIX_NotifyInfo));
I'm adding this after David answered...
Here's an extension to the above question (looking for how to go about Marshal.GetObjectForIUnknown).
I have this C# code:
public void OnEventMonitor(IUIX_Obj pTarget, IUIX_Event pEvent)
{
IntPtr outPtr;
pTarget.QueryImpl(typeof(IUIX_Dialog).GUID, null, out outPtr);
IUIX_Dialog dlg = (IUIX_Dialog)System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(outPtr);
}
Having:
IUIX_Event = interface(IDispatch)
IUIX_Obj = interface(IDispatch)
IUIX_Dialog = interface(IUIX_ObjImpl) (IDispatch)
My Delphi code (dlg : IUIX_Dialog, pImpl : Pointer):
pTarget.QueryImpl(GetTypeData(TypeInfo(IUIX_Dialog)).Guid, nil, @pImpl);
Move(pImpl, dlg, SizeOf(IUIX_Dialog));
The above does work.
Any better approach or that's correct way?
It's simple in unmanaged code, it's just an assignment.
var
Rec: TMyRec;
Ptr: Pointer;
....
Rec := TMyRec(Ptr^);