|
ms
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
mshtml - GETBLOCKFMTSA while ago I wrote some code in VB.NET which gets the block formats from mshtml like shown below. I am now converting this into C# and I have the problem that the IOleCommandTarget.Exec function doesn't return the supported formats - in VB it works fine. (sorry code is long) Thanks for helping Peter VB code: Imports System.Runtime.InteropServices ' 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 <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 Get the formats... Dim oOut As New OLEVARIANT() Dim oIn As OLEVARIANT Dim cmdt As IOleCommandTarget Try Dim pguidCmdGroup As System.Guid = New Guid("DE4BA900-59CA-11CF-9592-444553540000") cmdt = DirectCast(HtmlEditor1.Document, IOleCommandTarget) cmdt.Exec(pguidCmdGroup, cmdID, onlyconnect.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, oIn, oOut) Catch ex As Exception Throw New Exception("Exec Command: " & ex.Message) End Try C# code: using System; using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] public struct OLECMD { public long cmdID; public long cmdf; } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] public class OLECMDTEXT { public OLECMDTEXTF cmdtextf; public long cwActual; private long cwBuf = 256; // make sure this is the same as SizeConst below [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public String text; } public enum OLECMDTEXTF { OLECMDTEXTF_NONE = 0, OLECMDTEXTF_NAME, OLECMDTEXTF_STATUS } [ComVisible(true), ComImport(), Guid("b722bccb-4e68-101b-a2bc-00aa00404770"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IOleCommandTarget { [PreserveSig()] int QueryStatus(ref Guid pguidCmdGroup, long cCmds, [In, Out]OLECMD prgCmds, [In, Out]OLECMDTEXT pCmdText); [PreserveSig()] int Exec(ref Guid pguidCmdGroup, long nCmdId, long nCmdExecOpt, OLEVARIANT pvaIn, OLEVARIANT pvaOut); } [StructLayout(LayoutKind.Explicit)] public class OLEVARIANT { [FieldOffset(0)]public int vt; [FieldOffset(2)]public int wReserved1; [FieldOffset(4)]public int wReserved2; [FieldOffset(6)]public int wReserved3; [FieldOffset(8)]public long lVal; [FieldOffset(8)]public int iVal; [FieldOffset(8)]public IntPtr bstrVal; [FieldOffset(8)]public IntPtr bUnkVal; [FieldOffset(8)]public IntPtr pArray; [FieldOffset(8)]public IntPtr pvRecord; [FieldOffset(12)]public IntPtr pRecInfo; public void Clear() { VariantClear(this); } public void LoadString(String Value) { bstrVal = Marshal.StringToBSTR(Value); } public object ToNativeObject() { IntPtr p = IntPtr.Zero; try { // allocate a buffer to hold the data in this OLEVARIANT p = Marshal.AllocCoTaskMem(Marshal.SizeOf(this.GetType())); Marshal.StructureToPtr(this, p, false); return Marshal.GetObjectForNativeVariant(p); } finally { // called no matter what Marshal.FreeCoTaskMem(p); } } [DllImport("Oleaut32.dll", PreserveSig=false)] private static extern void VariantClear(OLEVARIANT var); } Well I don't know C# - but I think there's no need to work with the raw
interfaces :) The MFC contain a wrapper class for MSHTML, the CHtmlEditCtrlBase class (afxhtml.h) which implements retrieval of blockformats as follows: (sorry code is also long, but at least readable :P ) Hope this helps you, I don't know whether the code can be ported to C# or whether there's an equivalent class in C#. HRESULT GetBlockFormatNames(CStringArray &sa) const { CComVariant vaRet; HRESULT hr = E_FAIL; long lStatus = QueryStatus(IDM_GETBLOCKFMTS); if (lStatus & OLECMDF_ENABLED || lStatus & OLECMDF_LATCHED) { if (S_OK == ExecCommand(IDM_GETBLOCKFMTS, OLECMDEXECOPT_DODEFAULT, NULL, &vaRet)) { if(vaRet.vt & VT_ARRAY) { USES_CONVERSION; SAFEARRAY *psa = vaRet.parray; long lBound = 0,uBound = 0; if(S_OK == SafeArrayGetLBound(psa,1,&lBound) && S_OK == SafeArrayGetUBound(psa,1,&uBound) ) { for(long i=lBound; i<uBound; i++) { CComBSTR bstrElem; if( (S_OK == SafeArrayGetElement(psa, &i, &bstrElem) )) { sa.Add(CString(bstrElem)); } } hr = S_OK; } } } } if (vaRet.vt == VT_ERROR) hr = V_ERROR(&vaRet); return hr; } regards, Leo Peter Zentner wrote: Show quote > I have a weird problem... > > A while ago I wrote some code in VB.NET which gets the block formats from > mshtml like shown below. I am now converting this into C# and I have the > problem that the IOleCommandTarget.Exec function doesn't return the > supported formats - in VB it works fine. (sorry code is long) > > Thanks for helping > Peter > > VB code: > > Imports System.Runtime.InteropServices > ' 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 > > <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 > > Get the formats... > > Dim oOut As New OLEVARIANT() > Dim oIn As OLEVARIANT > Dim cmdt As IOleCommandTarget > > Try > Dim pguidCmdGroup As System.Guid = New > Guid("DE4BA900-59CA-11CF-9592-444553540000") > cmdt = DirectCast(HtmlEditor1.Document, IOleCommandTarget) > cmdt.Exec(pguidCmdGroup, cmdID, > onlyconnect.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, oIn, oOut) > Catch ex As Exception > Throw New Exception("Exec Command: " & ex.Message) > End Try > > C# code: > > using System; > using System.Runtime.InteropServices; > > [StructLayout(LayoutKind.Sequential)] > public struct OLECMD > { > public long cmdID; > public long cmdf; > } > > [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] > public class OLECMDTEXT > { > public OLECMDTEXTF cmdtextf; > public long cwActual; > private long cwBuf = 256; // make sure this is the same as SizeConst > below > [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] > public String text; > } > > public enum OLECMDTEXTF > { > OLECMDTEXTF_NONE = 0, > OLECMDTEXTF_NAME, > OLECMDTEXTF_STATUS > } > > [ComVisible(true), ComImport(), > Guid("b722bccb-4e68-101b-a2bc-00aa00404770"), > InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] > public interface IOleCommandTarget > { > [PreserveSig()] > int QueryStatus(ref Guid pguidCmdGroup, long cCmds, [In, Out]OLECMD > prgCmds, [In, Out]OLECMDTEXT pCmdText); > > [PreserveSig()] > int Exec(ref Guid pguidCmdGroup, long nCmdId, long nCmdExecOpt, > OLEVARIANT pvaIn, OLEVARIANT pvaOut); > } > > [StructLayout(LayoutKind.Explicit)] > public class OLEVARIANT > { > [FieldOffset(0)]public int vt; > [FieldOffset(2)]public int wReserved1; > [FieldOffset(4)]public int wReserved2; > [FieldOffset(6)]public int wReserved3; > [FieldOffset(8)]public long lVal; > [FieldOffset(8)]public int iVal; > [FieldOffset(8)]public IntPtr bstrVal; > [FieldOffset(8)]public IntPtr bUnkVal; > [FieldOffset(8)]public IntPtr pArray; > [FieldOffset(8)]public IntPtr pvRecord; > [FieldOffset(12)]public IntPtr pRecInfo; > > public void Clear() > { > VariantClear(this); > } > > public void LoadString(String Value) > { > bstrVal = Marshal.StringToBSTR(Value); > } > > public object ToNativeObject() > { > IntPtr p = IntPtr.Zero; > try > { > // allocate a buffer to hold the data in this OLEVARIANT > p = Marshal.AllocCoTaskMem(Marshal.SizeOf(this.GetType())); > Marshal.StructureToPtr(this, p, false); > return Marshal.GetObjectForNativeVariant(p); > } > finally > { > // called no matter what > Marshal.FreeCoTaskMem(p); > } > } > > [DllImport("Oleaut32.dll", PreserveSig=false)] > private static extern void VariantClear(OLEVARIANT var); > } > > |
|||||||||||||||||||||||