2016-09-22 132 views
2

我正在使用VBA編寫一個帶有Canvas的InternetExplorer實例。我已經設置好了,所以我可以使用VBA中的類,例如Circle和Line在畫布上繪製。這一切工作正常,我有一個力量指導動畫圖工作。HTMLCanvasElement類型不匹配

但是,現在我試圖捕獲用戶事件,如鼠標點擊作爲VBA中的事件,並遇到一個奇怪的問題。 我創建了一個類型爲HTMLCanvasElement的變量,但是當我嘗試爲它分配HTMLCanvasElement對象時,出現類型不匹配錯誤。

注意:您需要爲類對象InternetExplorer和MSHTML類對象的「Microsoft HTML對象庫」添加對「Microsoft Internet控件」的引用。

Option Compare Database 
Option Explicit 

Dim ie As InternetExplorer 
Dim document As HTMLDocument 
Dim WithEvents window As HTMLWindow2 
Dim ctx As ICanvasRenderingContext2D 
Dim WithEvents canvas As MSHTML.HTMLCanvasElement 

Private Sub Class_Initialize() 
    Set ie = New InternetExplorer 
    ie.StatusBar = False 
    ie.AddressBar = False 
    ie.MenuBar = False 
    ie.Toolbar = False 

    ie.Navigate "about:blank" 
    While Not ie.ReadyState = READYSTATE_COMPLETE 
     DoEvents 
    Wend 
    ie.Visible = True 
    Set document = ie.document 
    document.body.innerHTML = "<div><canvas id='myCanvas' width='10' height='10' style=""border:1px solid #000000;"">" & _ 
      "Your browser does not support the HTML5 canvas tag" & _ 
      "</canvas></div>" 

    'Set canvas = document.getElementById("myCanvas") 'This line triggers a Type Mismatch!!! 

    Set ctx = document.getElementById("myCanvas").getContext("2d") 

    Set window = document.parentWindow 

    resizeCanvas 
End Sub 

Private Sub window_onload() 
    window_onresize 
End Sub 

Private Sub window_onresize() 
    resizeCanvas 
End Sub 

Public Sub resizeCanvas() 
    ctx.canvas.Width = window.innerWidth - 23 
    ctx.canvas.Height = window.innerHeight - 23 
    redraw 
End Sub 

Public Function isClosed() As Boolean 
    isClosed = window.closed 
End Function 

Private Sub redraw() 
    'redraw shapes using ctx 
End Sub 

Public Sub Clear() 
    ctx.clearRect 0, 0, ctx.canvas.Width, ctx.canvas.Height 
End Sub 

我註釋掉與類型不匹配的線,所以你可以看到一切,除此之外運行。

我測試了一些不同的東西:

  • 監視窗口中列出的document.getElementById("myCanvas")爲HTMLCanvasElement的類型,在立即窗口預期
  • ?TypeName(document.getElementById("myCanvas"))立即窗口返回「HTMLCanvasElement」
  • ?typeof document.getElementById("myCanvas") is HTMLCanvasElement返回錯誤。這是非常奇怪的,讓我懷疑,也許HTMLCanvasElement在mshtml.tlb類型庫中定義不正確。
+0

我正在考慮嘗試圍繞畫布與Div,然後使用HTMLDivElement作爲捕捉事件的方式 - 有誰知道如何確保畫布事件冒泡到周圍的Div? – Blackhawk

+0

查看'document.all'中的畫布,它的類型是'Variant \ Object \ HTMLCanvasElement'。 – ThunderFrame

+0

@ThunderFrame這正是我期望它工作的原因,但可惜:( – Blackhawk

回答

2

我把破解打開TLB來看看爲自己的自由。這是如何定義的:

[id(0x00000440)] 
    HRESULT getElementById(
        [in] BSTR v, 
        [out, retval] IHTMLElement** pel); 

請注意,它返回的是一個接口指針,而不是強類型對象。這可能會拋出一個扳手到您的作品,因爲HTMLCanvasElement是不可創建的:

[ 
    uuid(305106E5-98B5-11CF-BB82-00AA00BDCE0B), 
    noncreatable 
] 
coclass HTMLCanvasElement { 

而且沒有在TLB返回組件類的一個實例。由於IHTMLCanvasElement不會提供這些事件 - 這些來自HTMLElementEvents,所以這會產生一個問題來宣告它WithEvents

注意,目前也沒有辦法一個IHTMLElement和VBA一個HTMLCanvasElement之間投無論是。它看起來像tlb的佈局可能會限制你或者制定一個Function Declare來試圖欺騙編組,讓你回到一個強類型的對象引用或通過某種包裝將工作。