C# 如何通过C从mshtml元素获取所有应用的CSS样式信息#

C# 如何通过C从mshtml元素获取所有应用的CSS样式信息#,c#,html,css,C#,Html,Css,我正在开发一个C#应用程序,它需要解析网页并转换成另一种格式。我的问题是获取任何给定元素的计算CSS,在本例中,大多数元素都是如此。我正在处理内联样式、CSS和格式化元素的组合,如、等 我目前正在将网页加载到mshtml中,并使用IHTMLElement2接口访问currentStyle对象。事实证明,这太慢了。我已经分析了它,通过调用currentStyle.XXX获取样式规则的值花费了大量时间。由于我需要查询多个属性,即背景颜色、字体系列、字体大小、文本对齐、文本装饰等。每个元素都会重复这些

我正在开发一个C#应用程序,它需要解析网页并转换成另一种格式。我的问题是获取任何给定元素的计算CSS,在本例中,大多数元素都是如此。我正在处理内联样式、CSS和格式化元素的组合,如

我目前正在将网页加载到mshtml中,并使用IHTMLElement2接口访问currentStyle对象。事实证明,这太慢了。我已经分析了它,通过调用currentStyle.XXX获取样式规则的值花费了大量时间。由于我需要查询多个属性,即背景颜色、字体系列、字体大小、文本对齐、文本装饰等。每个元素都会重复这些属性,因此我要进行数千次COM调用,而一个小文档需要几分钟的时间。所有现代浏览器都是在几分之一秒的时间内完成的。我想是COM互操作杀了我

有更好的办法吗? 我想一次获得应用于元素的所有计算样式规则。 有人知道如何使用IHTMLElementAppliedStyles吗?它是否符合我的要求?你从哪里得到它的实例?旁注:我正在引用HTML对象库来获取mshtml,但它似乎不是IE9/10版本???并非所有接口都可用,即IHTMLDocument7


谢谢,

我一直在做这个,有一些更新

a) 我在代码中遇到了一个错误,它返回到树上,将相对值(如80%或1.2em)解析为绝对值(如pt等)。该修复导致了速度的巨大提高。它对我来说还是有点太慢了,对于一个相当于3页word文档(包含表格和有序列表等)的文档来说,它只需要20~30秒

b) 我为IHTMLElement2添加了一个C#包装器类,该类缓存CSS值,因此我至少只需要通过COM互操作在每个Dom节点上读取一次。这有一点帮助,所以我现在对于相同的3页word文档等价于html,时间减少到8~10秒

C)我正在研究为iHTMLNEL元素创建一个C++包装器,它将把所有CSS值加载到一个数组中,并通过一个COM互操作调用传递整个数组,但是到目前为止,C++和COM包装看起来像是一个陡峭的学习曲线:MFC、ATL、COM、O.M.<

d)由于我没有C++经验,包装器的想法看起来非常有挑战性,所以我正在考虑建立一个C sCSS解析器和解析器,这样我就可以转储MSHtML,并使用HTMLGraciPyACK+MCSS解析器/解析器。这也是一项艰巨的工作

期待评论、指导、回答 谢谢。

(对于最初的询问者来说可能太晚了,但希望对后来的人有用。)

使用
IHTMLWindow7::getComputedStyle(IHTMLDOMNode节点)
返回一个实时
IHTMLCSSStyleDeclaration
对象,该对象在考虑所有规则和内联样式(包括浏览器默认样式,例如赋予
更大的字体权重)后,给出完全计算的样式

如果要绑定到特定属性,例如
backgroundColor
,可以直接在
IHTMLCSSStyleDeclaration
IHTMLCSSStyleDeclaration2
等上使用它们。或者,您可以使用
IHTMLCSSStyleDeclaration::getPropertyValue(字符串名称)
按名称访问特定属性。要获取元素上定义的所有名称的列表,请使用
length
item
属性

需要注意的是,
IHTMLWindow7
IHTMLCSSStyleDeclaration
*接口未在mshtml的主互操作程序集中声明,因此默认情况下,它们不能以强绑定方式使用。因此,您可以动态访问它们,也可以创建一个自定义互操作程序集来提供对它们的访问

为mshtml创建自定义互操作程序集(IA)并不困难,但默认情况下,.NET成员定义通常并不理想,而且程序集非常庞大。如果您不介意,请在PC上找到mshtml.tlb,并在VS开发者提示符下运行它:

tlbimp mshtml.tlb /out:"custommshtml.dll" /namespace:"custommshtml" /transform:dispret /asmversion:"1.0.0.0" /tlbreference:"C:\Windows\System32\stdole2.tlb" /nologo /silence:3001 /silence:3002
这将为您安装的IE版本生成IA。您将收到一些警告,只要您不打算使用这些成员,就可以忽略这些警告。根据需要进行调整,但不要使用
mshtml
,因为名称空间会让事情变得非常混乱


在项目中,引用IA而不是mshtml。您需要使用语句调整
,等等来使用不同的名称空间。根据原始DOM对象的来源,您可能会发现它们在
mshtml
命名空间中有一个类型。那很好;您仍然可以对自定义接口进行案例分析。此外,在调试过程中,即时窗口可能会声明某些方法/属性不存在,即使它们在IntelliSense中出现,这只是因为它们没有在项目中被引用,因此编译器没有嵌入所需的定义。

谢谢Emdot,是的,现在已经太晚了,但是如果我们有机会重构,这些信息对我来说仍然很有价值。