MSHTML: How to IDM_GETBLOCKFMTS in C#

  • Thread starter Thread starter Peter Zentner
  • Start date Start date
P

Peter Zentner

Hi,

how can I get the available block formats from the mshtml with
IDM_GETBLOCKFMTS? I'm pretty confused how to call the IOleCommandTarget.Exec
correctly. Can someone please provide me a small code snippet?

TIA

Peter
 
Hi Peter

Below is code (in VB.NET) that does the job. Hopefully, it will be straight
forward to convert. The function to call is GetBlockFormats(), which returns
a string array.

<code>
<StructLayout(LayoutKind.Explicit)> _
Public Class OLEVARIANT
<FieldOffset(0)> Public vt As System.Int16
<FieldOffset(2)> Public wReserved1 As System.Int16
<FieldOffset(4)> Public wReserved2 As System.Int16
<FieldOffset(6)> Public wReserved3 As System.Int16
<FieldOffset(8)> Public lVal As Integer
<FieldOffset(8)> Public iVal As Short
<FieldOffset(8)> Public bstrVal As IntPtr
<FieldOffset(8)> Public pUnkVal As IntPtr
<FieldOffset(8)> Public pArray As IntPtr
<FieldOffset(8)> Public pvRecord As IntPtr
<FieldOffset(12)> Public pRecInfo As IntPtr

Public Sub Clear()
VariantClear(Me)
End Sub 'Clear

Public Sub LoadString(ByVal Value As String)

bstrVal = Marshal.StringToBSTR(Value)

End Sub
Public Function ToNativeObject() As Object
Dim p As IntPtr
Try
'Allocate a buffer to hold the data in this OLEVARIANT
p = Marshal.AllocCoTaskMem(Marshal.SizeOf(Me.GetType()))
Marshal.StructureToPtr(Me, p, False)
Return Marshal.GetObjectForNativeVariant(p)
Finally
'Called no matter what
Marshal.FreeCoTaskMem(p)
End Try
End Function

<DllImport("Oleaut32.dll", PreserveSig:=False)> _
Private Shared Sub VariantClear(ByVal var As OLEVARIANT)
' Leave this blank. Call will be redirected to external DLL.
End Sub

End Class 'OLEVARIANT

Public Function GetBlockFormats() As String()

Dim oleVar As OLEVARIANT
Dim obj As Object
Dim fmts As String()

oleVar = GetCommand(MSHTMLCommandEnum.IDM_GETBLOCKFMTS)

'IE doesn't return a "well-formed" VARIANT here so
'Or in the VT_BSTR flag:
oleVar.vt = CType(oleVar.vt Or VarEnum.VT_BSTR, Short)

'This is a little wrapper to call
Marshal.GetObjectForNativeVariant()
obj = oleVar.ToNativeObject()

'Cleanup the Native Variant to avoid a memory leak
oleVar.Clear()

fmts = CType(obj, String())

' Return the block formats
Return fmts

End Sub

Private Function GetCommand(ByVal cmdID As MSHTMLCommandEnum) As
OLEVARIANT

Dim oOut As New OLEVARIANT
Dim oIn As OLEVARIANT

Dim cmdt As IOleCommandTarget

Try
cmdt = DirectCast(Document, IOleCommandTarget)

cmdt.Exec(CGID_MSHTML, cmdID, OLECMDEXECOPT_DONTPROMPTUSER, oIn,
oOut)

Catch ex As Exception
Throw New Exception("ExecCommand: " & ex.Message)

End Try

Return oOut

End Function
</code>

HTH

Charles
 
Hi Charles,

Thank you for posting. But for some reason I don't get anything back from
the "GetCommand". The oleVar is empty, but no errors or exceptions are
fired. Any suggestions?

Peter
 
Hi Peter

One possibility might be the definition of IOleCommandTarget. I have
modified mine because of inaccuracies in the predefined version. Have a look
at the one below:

<code>
' OLECMD
<StructLayout(LayoutKind.Sequential)> _
Public Structure OLECMD
Public cmdID As Int32
Public cmdf As Int32
End Structure

' OLECMDTEXT
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Class OLECMDTEXT
Public cmdtextf As OLECMDTEXTF
Public cwActual As Int32
Private cwBuf As Int32 = 256 'Make sure this is the same as SizeConst
below
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
Public text As String
End Class

Public Enum OLECMDTEXTF
OLECMDTEXTF_NONE = 0
OLECMDTEXTF_NAME = 1
OLECMDTEXTF_STATUS = 2
End Enum

' IOleCommandTarget interface
<ComVisible(True), ComImport(),
Guid("b722bccb-4e68-101b-a2bc-00aa00404770"), _
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IOleCommandTarget

<PreserveSig()> Function QueryStatus(ByRef pguidCmdGroup As Guid, ByVal
cCmds As Int32, _
<InAttribute(), Out(), MarshalAs(UnmanagedType.LPArray,
SizeParamIndex:=1)> ByVal prgCmds() As OLECMD, <InAttribute(), Out()> ByVal
pCmdText As OLECMDTEXT) As Integer

<PreserveSig()> Function Exec(ByRef pguidCmdGroup As Guid, ByVal nCmdId
As Int32, _
ByVal nCmdExecOpt As Int32, ByVal pvaIn As OLEVARIANT, ByVal pvaOut
As OLEVARIANT) As Integer

End Interface
</code>


HTH

Charles
 
Hi Charles,

It's working now. Your thoughts were right. Thank you very much, you helped
me a lot.

Peter
 
Back
Top