C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.90434 の関連記事表示

<< 0 | 1 >>
■90511  Re[6]: AddHandler Eventの別スレッドについて
□投稿者/ 魔界の仮面弁士 -(2019/03/15(Fri) 11:55:19)
    2019/03/15(Fri) 12:07:39 編集(投稿者)

    解決済みで閉じられているので、いちおうチェックは付けた状態に戻しておきます。


    No90477 (TanuTanu さん) に返信
    > その結果、yahooButton = DirectCast(doc.all.item("yahoo"), mshtml.IHTMLElement)の行にて下記エラーが発生致しました。

    その行のどの部分に問題があるのかを確認してみてください。

    NullReferenceException とは、インスタンスが空の時、すなわち
    オブジェクトが Nothing である場合に、
    そのメンバーを操作しようとして発生する例外ですよね。


    If doc Is Nothing Then
     MsgBox("doc が空だった")
    ElseIf doc.all Is Nothing Then
     MsgBox("doc.all が空だった")
    ElseIf doc.all.item("yahoo") Is Nothing Then
     MsgBox("doc.all.item(""yahoo"") が空だった")
    Else
     MsgBox("いずれも空ではなさそう")
     yahooButton = DirectCast(doc.all.item("yahoo"), mshtml.IHTMLElement)
    End If




    > FindWindowExWの値は0ですが、FindWindowではハンドル値取得できました。
    > PWnd1 = FindWindowExW(IntPtr.Zero, IntPtr.Zero, "TabThumbnailWindow", "JavaScript テスト - Internet Explorer")

    示されているのが結果だけで、要因となりうる情報が隠されたままなので、修正すべき箇所を指摘できないです。(^^;

    あえてもう一度質問させていただきます。
    『その API (FindWindowEx および FindWindowExW) の宣言部はどうなっていますか?』( No90475 の再掲 )


    少なくとも当方では、下記の API 宣言で取得できています。

    ' Imports System.Runtime.InteropServices

    ' === 案1 ===
    <DllImport("user32", CharSet:=CharSet.Unicode, SetLastError:=True)>
    Private Shared Function FindWindowExW(hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr
    End Function

    ' === 案2 ===
    <DllImport("user32", CharSet:=CharSet.Auto, SetLastError:=True)>
    Private Shared Function FindWindowEx(hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr
    End Function

    ' === 案3 ===
    Private Declare Unicode Function FindWindowExW Lib "user32" (hwndParent As IntPtr, hwndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPTStr)> lpszClass As String, <MarshalAs(UnmanagedType.LPTStr)> lpszWindow As String) As IntPtr

    ' === 案4 ===
    Private Declare Auto Function FindWindowEx Lib "user32" (hwndParent As IntPtr, hwndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPTStr)> lpszClass As String, <MarshalAs(UnmanagedType.LPTStr)> lpszWindow As String) As IntPtr




    宣言が間違っていて、IntPtr.Zero が返却されてしまうパターン。

    ' === 没1 ===
    <DllImport("user32", EntryPoint:="FindWindowExW", SetLastError:=True)>
    Private Shared Function FindWindowEx(hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr
    End Function

    ' === 没2 ===
    <DllImport("user32", SetLastError:=True)>
    Private Shared Function FindWindowExW(hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr
    End Function

    ' === 没3 ===
    Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExW" (hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr



    正しい宣言ではないが、一応呼び出せてしまうパターン。

    ' === 非推奨1 ===
    Private Declare Unicode Function FindWindowExW Lib "user32" (hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr

    ' === 非推奨2 ===
    Private Declare Unicode Function FindWindowEx Lib "user32" Alias "FindWindowExW" (hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr



    >  WEBページ・・・CreateObject("Shell.Application").Windowsで対応しております。
    これを用いている部分のコードも見せていただけないでしょうか。

    SHDocVw.ShellWindows を宣言しておきながら、FindWindowEx API や、GetIEDocument までも
    追加で呼び出している理由が、どうしても分からなかったのです。

    No90463 の発言より、「objIE.LocationName」を利用しているであろうことは推察できましたが、
    目的は LocationName プロパティでウィンドウのタイトルを得ることだけなのでしょうか。
    あるいは HWND プロパティからウィンドウハンドルも得ているとか?

    objIE.Document プロパティを通じて HTMLDocument を得ることができるはずなので、
    わざわざ GetIEDocument を呼び出す必要性は無いと思っています。( No90469 で指摘 )

    (例)
    http://jumbofoot.cocolog-nifty.com/yass_vbnet_tips/2007/02/shellhtmldocume_f1cd.html


    WM_HTML_GETOBJECT でないと取得できない相手の場合は、API 宣言が必要になりますが、
    その場合、今度は CreateObject("Shell.Application").Window を使う意味が分からない…。



    >  上記WEBページから派生したWEBページダイアログ ・・・ GetIEDocument で対応(現在、ここのボタンクリックのイベントを対応しております。)

    ここでいう『派生』とは何を示していますか? ページ遷移の事でしょうか?

    ページが遷移したのであれば、以前の HTMLDocument はもう使えないので、
    読み込みが完了したことを通知するための DocumentComplete イベントにて、
    イベント引数 pDisp の Document プロパティを受け取るようにします。
    (フレームを持つページの場合は、各フレームごとに発生することに注意)

    あるいは、ターゲットとなる InternetExplorer オブジェクト(IWebBrowser2)を保持しておいて、
    その Document プロパティを取得しなおすという方法も使えますが、いずれにせよ、
    読み込みが完了する前に GetIEDocument なり Document プロパティなりで
    HTMLDocument を得ていた場合、DOM が不完全な状態になっていることがあります。

    なので、取得した HTMLDocument が、目的のページの内容を指しているかを
    確認しておくことも重要です。(これも No90469 で指摘 )


    それに、FindWindowEx を使うにしても、その使い方が不自然に思えます。
    そもそも "TabThumbnailWindow" クラスを探している理由は何でしょうか?
    先の GetIEDocument を使うことが目的なら、探すべきウィンドウは
    "Internet Explorer_Server" クラスのウィンドウ(またはその親ウィンドウ)の
    ハンドルであるはずですよね。


    また、「WEBページダイアログ」とは何を指していますか?
    キャプションが "JavaScript テスト - Internet Explorer" となる、 No90454
    https://www.javadrive.jp/javascript/event/sample2_1.html だとすれば、
    そもそもダイアログは存在していません。
    別のページが対象なのかもしれませんが、その場合は、doc.all.item("yahoo") は存在しないかもしれませんし。

    No90476 では「javascriptによる擬似モーダルダイアログ『だと思う』」とお答えいただきましたが、
    それが具体的になんであるのか(たとえば jQuery の colorbox とか)や、
    イベント割り当てが onclick なのかそれ以外なのかもはっきりしないままです。
記事No.90434 のレス / END /過去ログ156より / 関連記事表示
削除チェック/

■90492  Re[5]: AddHandler Eventの別スレッドについて
□投稿者/ PANG2 -(2019/03/14(Thu) 18:59:01)
    2019/03/14(Thu) 18:59:46 編集(投稿者)

    No90476 (TanuTanu さん) に返信
    > ご質問の件ですがCのjavascriptによる擬似モーダルダイアログだと思います。

    jQueryの疑似ダイアログでしょうか?
    ボタンのonclickもjQueryで実装しているなら難しいと思う。


    WebBrowser上にダイアログが出現するのをtimerで監視するサンプル

    private void timer1_Tick(object sender, EventArgs e)
    {
    dynamic doc = webBrowser1.Document.DomDocument;
    dynamic titles = doc.getElementsByClassName("ui-dialog-title");
    foreach (dynamic title in titles) {
    if (title.innerText == "テストダイアログ1") {
    foreach (dynamic btn in title.parentnode.parentnode.getElementsByTagName("button")) {
    string s = btn.innerText;
    if (s.Contains("確認"))
    btn.click();
    }
    }
    }
    }
記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90508  Re[6]: AddHandler Eventの別スレッドについて
□投稿者/ TanuTanu -(2019/03/15(Fri) 10:28:12)
    魔界の仮面弁士 様
    Azulean 様
    PANG2 様

    この度は、ご教授頂きありがとうございました。
    小生の知識が乏しく、実現したい事が出来ませんでしたが
    FOCUSOUTでの対応は出来るのでそちらで対応したいと思います。

    今後、スキルを身につけた後、改めてトライしてみようと思います。

    今回、ビギナーの私にとても親切にして頂いた事、感謝申し上げます。
    ありがとうございました。
記事No.90434 のレス / END /過去ログ156より / 関連記事表示
削除チェック/

■90531  Re[7]: AddHandler Eventの別スレッドについて
□投稿者/ TanuTanu -(2019/03/18(Mon) 16:52:42)
    !!

    魔界の仮面弁士 様

    このような未熟者にここまで親切にして頂いて何てお礼を申せばよいやら・・・
    あれから何とかならないかと試行錯誤致しまして、TabThumbnailWindowではなくて
    IEFRAMEを取得出来ました。
    しかし、VBAではInternet Explorer_Serverまで辿り付いたのですが
    VB.NETで子ウィンドウを列挙することが出来ません。
    何卒、ご教授のほど宜しくお願いいたします。

    又、■90511で教わった件は順次取り組んでまいります。


    コードは下記の通りです。

    Public Function EnumWindowCallBack(hWnd As IntPtr, lparam As IntPtr) As Boolean

    Dim textLen As Integer = GetWindowTextLength(hWnd)
    Dim tsb As New StringBuilder(textLen + 1)
    Dim csb As New StringBuilder(256)

    If 0 < textLen Then
    GetWindowText(hWnd, tsb, tsb.Capacity)
    GetClassName(hWnd, csb, csb.Capacity)

    If tsb.ToString() = "JavaScript テスト - Internet Explorer" Then
    If csb.ToString() = "IEFrame" Then
    Debug.WriteLine(tsb.ToString())
    Debug.WriteLine(csb.ToString())
    Debug.WriteLine(hWnd)
    hWnd_IEFRAME = hWnd

              EnumChildWindows(hWnd_IEFRAME, AddressOf EnumChildWindowsProc, IntPtr.Zero) ’IEFrame下のInternet Explorer_Serverを取得したいがここでエラーになります。

    ■エラー内容
    BC31143 メソッド 'Public Function EnumChildWindowsProc(hWnd As IntPtr, lparam As IntPtr) As IntPtr' に、デリゲート 'Delegate Function API.EnumChildProc(hWnd As IntPtr, ByRef lParam As IntPtr) As Boolean' と互換性があるシグネチャがありません。


    End If
    End If

    End If

    Return True
    End Function

    Public Function EnumChildWindowsProc(hWnd As IntPtr, lparam As IntPtr) As Integer

    Dim textLen As Integer = GetWindowTextLength(hWnd)
    Dim tsb As New StringBuilder(textLen + 1)
    Dim csb As New StringBuilder(256)

    ' クラス名取得
    GetClassName(hWnd, csb, csb.Capacity)

    Debug.WriteLine(csb.ToString())

    ' リターン
    EnumChildWindowsProc = 1
    End Function

    <DllImport("user32")>
    Function EnumChildWindows(
    <[In]()> ByVal hWndParent As IntPtr,
    <[In]()> ByVal lpEnumFunc As EnumChildProc,
    <[In]()> ByRef lParam As IntPtr
    ) As Boolean
    End Function

記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90533  Re[8]: AddHandler Eventの別スレッドについて
□投稿者/ 魔界の仮面弁士 -(2019/03/18(Mon) 18:18:44)
    No90531 (TanuTanu さん) に返信
    > しかし、VBAではInternet Explorer_Serverまで辿り付いたのですが
    > VB.NETで子ウィンドウを列挙することが出来ません。

    VBA のコードを移植している、ということでしょうか。

    それでは、VBA の API 宣言と VB2017 の API 宣言の
    【両方】を見せてもらえますか?

    提示をお願いする理由は、特に「ByVal」と「ByRef」の違いが重要だからです。


    引数に ByVal も ByRef も書かなかった場合、
    VBA では ByRef として解釈され、
    .NET では ByVal として解釈される仕様であることにご注意ください。


    > <DllImport("user32")>
    > Function EnumChildWindows(
    >  <[In]()> ByVal hWndParent As IntPtr,
    >  <[In]()> ByVal lpEnumFunc As EnumChildProc,
    >  <[In]()> ByRef lParam As IntPtr
    >  ) As Boolean
    > End Function


    第4引数を ByRef IntPtr にしたのですね。
    では、EnumChildProc の Delegate 宣言も見せてください。

    AddressOf で指定した側が ByVal で、Delegate 定義が ByRef になっていて不整合を引き起こしていると思います。



    ' 参考資料1: https://dobon.net/vb/dotnet/process/enumwindows.html
     Public Delegate Function EnumWindowsDelegate(hWnd As IntPtr, lparam As IntPtr) As Boolean
     <DllImport("user32.dll")> _
     Public Function EnumWindows(lpEnumFunc As EnumWindowsDelegate, lparam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
     End Function


    ' 参考資料2: https://smdn.jp/programming/tips/enumwindows/
     Private Delegate Function WNDENUMPROC(ByVal hWnd As IntPtr, ByVal lParam As IntPtr) As Boolean
     <DllImport("user32")> _
     Private Function EnumWindows(ByVal lpEnumFunc As WNDENUMPROC, ByVal lParam As IntPtr) As Boolean
     End Function


    ' 参考資料3: http://mt-soft.sakura.ne.jp/web_dl/vb-parts/enum_window/
     Private Delegate Function EnumerateWindowsCallback(ByVal hWnd As IntPtr, ByVal lParam As Integer) As Integer
     <DllImport("user32", EntryPoint:="EnumWindows")> _
     Private Shared Function EnumWindows(ByVal lpEnumFunc As EnumerateWindowsCallback, ByVal lParam As Integer) As Integer
     End Function


    ' 参考資料4: http://nonsoft.la.coocan.jp/SoftSample/VB.NET/SampleEnumWindows.html
     Private Delegate Function D_EnumWindowsProc(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
     Private Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As D_EnumWindowsProc, ByVal lParam As Integer) As Integer
記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90543  Re[9]: AddHandler Eventの別スレッドについて
□投稿者/ TanuTanu -(2019/03/19(Tue) 20:43:43)
    魔界の仮面弁士 様

    大変お世話になっております。
    ご教授頂いたお蔭で■90455が当方でもようやく動作致しました。
    ありがとうございます。明日、これを用いてWEBページダイアログのボタンイベントに取り掛かろうと思います。

    ちなみに試行錯誤の結果、下記のようになりましたのでご報告致します。

    'Option Strict On 'これオンすると遅延バインディング使用できませんと出る為、削除しました。

    Public Class Form1

    Dim o As Object
    Dim aShell As SHDocVw.ShellWindows
    Dim doc As mshtml.HTMLDocument
    Dim yahooButton As mshtml.IHTMLElement
    Dim Event1 As mshtml.HTMLInputTextElementEvents2_Event


    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click


    EnumWindows(New EnumWindowsDelegate(AddressOf EnumWindowCallBack), IntPtr.Zero)

    o = GetIEDocument(hWnd_IES) ' No90411 を参照

    doc = DirectCast(o, mshtml.HTMLDocument)

    Debug.WriteLine(doc.body.document.body.innerHTML)

    yahooButton = DirectCast(doc.all.item("yahoo"), mshtml.IHTMLElement)

    Event1 = DirectCast(DirectCast(doc.all.item("yahoo"), mshtml.IHTMLElement), mshtml.HTMLInputTextElementEvents2_Event)
    AddHandler Event1.onclick, AddressOf WebDisp_click

    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    yahooButton.click()
    End Sub

    Private Function WebDisp_click(ByVal e As mshtml.IHTMLEventObj) As Boolean
    MsgBox("webDisp_onclick", MsgBoxStyle.SystemModal)
    Return True
    End Function


    End Class

    '***************************************************************************************

    Imports System.Runtime.InteropServices
    Imports System.Text

    Module API

    Public hWnd_IEFRAME As IntPtr
    Public hWnd_IES As IntPtr


    <DllImport("user32")>
    Function GetClassName(
    <[In]()> ByVal hWnd As IntPtr,
    <Out()> ByVal lpClassName As StringBuilder,
    <[In]()> ByVal nMaxCount As Integer
    ) As Integer
    End Function

    <DllImport("user32")>
    Function EnumChildWindows(
    <[In]()> ByVal hWndParent As IntPtr,
    <[In]()> ByVal lpEnumFunc As EnumChildProc,
    <[In]()> ByRef lParam As IntPtr
    ) As Boolean
    End Function

    <DllImport("user32")>
    Function RegisterWindowMessage(
    <[In]()> ByVal lpString As String
    ) As Integer
    End Function

    <DllImport("user32")>
    Function SendMessageTimeout(
    <[In]()> ByVal hWnd As IntPtr,
    <[In]()> ByVal msg As Integer,
    <[In]()> ByVal wParam As Integer,
    <[In]()> ByVal lParam As Integer,
    <[In]()> ByVal fuFlags As Integer,
    <[In]()> ByVal uTimeout As Integer,
    <Out()> ByRef lpdwResult As IntPtr
    ) As IntPtr
    End Function

    <DllImport("oleacc")>
    Function ObjectFromLresult(
    <[In]()> ByVal lResult As Int32,
    <[In]()> ByRef riid As System.Guid,
    <[In]()> ByVal wParam As Int32,
    <Out(), MarshalAs(UnmanagedType.Interface)> ByRef ppvObject As Object
    ) As IntPtr
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
    Public Function GetWindowText(hWnd As IntPtr,
    lpString As StringBuilder, nMaxCount As Integer) As Integer
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
    Public Function GetWindowTextLength(hWnd As IntPtr) As Integer
    End Function

    <DllImport("user32.dll")>
    Public Function EnumWindows(lpEnumFunc As EnumWindowsDelegate,
    ByVal lparam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    Delegate Function EnumWindowsDelegate(hWnd As IntPtr, ByVal lparam As IntPtr) As Boolean

    Delegate Function EnumChildProc(hWnd As IntPtr, ByVal lParam As IntPtr) As Boolean

    Public Function EnumWindowCallBack(hWnd As IntPtr, ByVal lparam As IntPtr) As Boolean

    Dim textLen As Integer = GetWindowTextLength(hWnd)
    Dim tsb As New StringBuilder(textLen + 1)
    Dim csb As New StringBuilder(256)

    If 0 <textLen Then
    GetWindowText(hWnd, tsb, tsb.Capacity)
    GetClassName(hWnd, csb, csb.Capacity)

    If tsb.ToString() = "JavaScript テスト - Internet Explorer" Then
    If csb.ToString() = "IEFrame" Then

    hWnd_IEFRAME = hWnd

    EnumChildWindows(hWnd_IEFRAME, AddressOf EnumChildWindowsProc, IntPtr.Zero)

    End If
    End If

    End If

    Return True
    End Function

    Public Function EnumChildWindowsProc(hWnd As IntPtr, lparam As IntPtr) As IntPtr

    Dim textLen As Integer = GetWindowTextLength(hWnd)
    Dim tsb As New StringBuilder(textLen + 1)
    Dim csb As New StringBuilder(256)

    GetClassName(hWnd, csb, csb.Capacity)

    If csb.ToString() = "Internet Explorer_Server" Then

    hWnd_IES = hWnd

    End If

    EnumChildWindowsProc = 1
    End Function

    '***********************************************************************

    'IEオブジェクト取得メソッド

    Function GetIEDocument(ByVal hWnd As IntPtr) As Object

    Dim nMsg As Integer
    Dim lRes As IntPtr
    Dim IID_IHTMLDocument As System.Guid = New System.Guid("626FC520-A41E-11CF-A731-00A0C9082637")
    Dim SMTO_ABORTIFHUNG As Integer = &H2
    Dim spDoc As Object = Nothing

    nMsg = RegisterWindowMessage("WM_HTML_GETOBJECT")

    If nMsg <> 0 Then
    SendMessageTimeout(hWnd, nMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes)
    If Not lRes = IntPtr.Zero Then
    ObjectFromLresult(lRes, IID_IHTMLDocument, 0, spDoc)
    End If
    End If

    Return spDoc
    End Function

    End Module


記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90547  Re[10]: AddHandler Eventの別スレッドについて
□投稿者/ TanuTanu -(2019/03/20(Wed) 14:04:06)
    魔界の仮面弁士 様

    大変お世話になっております。
    下記ご教授頂きたく存じます。
    宜しくお願いいたします。


    下記コードが「基になる RCW から分割された COM オブジェクトを使うことはできません。」のエラーになります。

    Return CBool(CallByName(btn_Button_onclick, "[DispId=0]", CallType.Method, e)) 

    Private Function WebDisp_click(ByVal e As mshtml.IHTMLEventObj) As Booleanの中では使えないのでしょうか?

    https://elleneast.com/?p=2654に書いてますが、別スレッドだと難しいのでしょうか?

    Private Sub DoSomething()の中にCallByName(btn_Button_onclick, "[DispId=0]", CallType.Method)を入れた時は
    上記はエラーは出ませんが、勝手にクリックして次の画面が開いてしまいます。

    ※1 $(function(){のような記述はありませんでしたのでjQueryではないようです。
    ※2 onclickのところは右記のような記述でした。 <INPUT onclick=onClick***() ・・・>

    VBコードは下記となります。(WIN APIは正常動作する為、省略)

    Imports System.Runtime.InteropServices
    Imports mshtml
    Imports SHDocVw

    Public Class Form1

    Dim aShell As SHDocVw.ShellWindows
    Dim objIE As Object

    Dim WithEvents IE_1 As InternetExplorer

    Dim IE_2 As HTMLDocument
    Dim IE_2_2 As HTMLDocument
    Dim IE_2_2_doc As mshtml.HTMLDocument
    Dim btn_Button As mshtml.IHTMLElement
    Dim btn_Button_onclick As Object

    Dim Event1 As mshtml.HTMLInputTextElementEvents2_Event
    Dim doc As mshtml.HTMLDocument
    Dim frms2 As mshtml.FramesCollection


    '最初の画面

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    aShell = CreateObject("Shell.Application").Windows

    ’For Each で回す
    IE_1 = objIE
        ’next

    End Sub

    ’最初の画面からWEBページダイアログ開くをキャッチ

    Private Sub IE_1_DownloadComplete() Handles IE_1.DownloadComplete

    Dim t As New System.Threading.Thread(New System.Threading.ThreadStart(AddressOf DoSomething))

    t.SetApartmentState(System.Threading.ApartmentState.STA)

    t.Start()

    End Sub


    Private Sub DoSomething()

    System.Threading.Thread.Sleep(2000) 'WEBページダイアログ開くのを待つ

    EnumWindows(New EnumWindowsDelegate(AddressOf EnumWindowCallBack), IntPtr.Zero)

    IE_2 = GetIEDocument(hWnd_IES)

    doc = DirectCast(IE_2, mshtml.HTMLDocument)

    frms2 = CType(doc.frames.item(2), mshtml.FramesCollection)
    IE_2_2 = CType(frms2.document, mshtml.HTMLDocument)

    IE_2_2_doc = DirectCast(IE_2_2, mshtml.HTMLDocument)
    btn_Button = DirectCast(IE_2_2_doc.all.item("btn"), mshtml.IHTMLElement)


    btn_Button_onclick = btn_Button.onclick '元の function オブジェクト

    btn_Button.onclick = DBNull.Value

    Event1 = DirectCast(DirectCast(IE_2_2_doc.all.item("btn"), mshtml.IHTMLElement), mshtml.HTMLInputTextElementEvents2_Event)

    AddHandler Event1.onclick, AddressOf WebDisp_click

    End Sub


    Private Function WebDisp_click(ByVal e As mshtml.IHTMLEventObj) As Boolean

    MsgBox("webDisp_onclick", MsgBoxStyle.SystemModal)

    Return CBool(CallByName(btn_Button_onclick, "[DispId=0]", CallType.Method, e)) '元の onclick 処理をここで呼び出す


    End Function

    End Class


記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90556  Re[11]: AddHandler Eventの別スレッドについて
□投稿者/ TanuTanu -(2019/03/20(Wed) 23:14:04)
    魔界の仮面弁士 様

    大変お世話になっております。

    invokeが気になったので調べてみたら2008年に魔界の仮面弁士 様が回答している件
    がまさに私が悩んでる案件かも知れません。

    http://hanatyan.sakura.ne.jp/patio/read.cgi?no=192

    結果が出ましたらまたご連絡致します。
記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90557  Re[12]: AddHandler Eventの別スレッドについて
□投稿者/ PANG2 -(2019/03/21(Thu) 07:17:12)
    2019/03/21(Thu) 07:37:35 編集(投稿者)

    Private Sub IE_1_DownloadComplete() Handles IE_1.DownloadComplete
    DoSomething()
    End Sub

    で、何が問題あるのでしょうか?

    また、NewWindowイベントなら第一引数で別窓をつかめるはずです。
記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90558  Re[12]: AddHandler Eventの別スレッドについて
□投稿者/ 魔界の仮面弁士 -(2019/03/21(Thu) 10:39:08)
    No90556 (TanuTanu さん) に返信
    > invokeが気になったので調べてみたら2008年に魔界の仮面弁士 様が回答している件
    > がまさに私が悩んでる案件かも知れません。

    そもそも何故、UI スレッドとワーカースレッドの間でのやり取りを必要としているのでしょうか。
    わざわざスレッドを立ち上げずとも、イベントドリブンな非同期実装にするだけで良いと思うのですが。

    もしもスレッドを分けるとしても、複数のスレッドでやりとりしようとせず、
    取得から操作までを同一のスレッドで行うべきかと。



    それと、IE 側から切断されたまま使おうとすると、COMException や InvalidComObjectException に
    陥る可能性がありますので、ShellWindows を列挙した後、そのウィンドウが閉じられた場合に備えて、
    OnQuit イベントを捕らえておくことをお奨めします。



    No90557 (PANG2 さん) に返信
    > NewWindowイベントなら第一引数で別窓をつかめるはずです。

    COM 版の NewWindow イベント だとしたら、第一引数は URL のはず。
     ' DWebBrowserEvents::NewWindow
     ' void NewWindow(BSTR URL, long Flags, BSTR TargetFrameName, VARIANT* PostData, BSTR Headers, [in, out] VARIANT_BOOL* Processed);
     Sub NewWindow(URL As String, Flags As Integer, TargetFrameName As String, ByRef PostData As Object, Headers As String, ByRef Processed As Boolean)


    使うとすれば、NewWindow2 イベントか
     ' DWebBrowserEvents2::NewWindow2
     ' void NewWindow2([in, out] IDispatch** ppDisp, [in, out] VARIANT_BOOL* Cancel);
     Sub NewWindow2(ByRef ppDisp As Object, ByRef Cancel As Boolean)


    もしくは NewWindow3 イベントが良さそうです。
     ' DWebBrowserEvents2::NewWindow3
     ' void NewWindow3([in, out] IDispatch **ppDisp, [in, out] VARIANT_BOOL *Cancel, /* NWMF */ DWORD dwFlags, BSTR bstrUrlContext, BSTR bstrUrl);
     Sub NewWindow3(ByRef ppDisp As Object, ByRef Cancel As Boolean, dwFlags As UInteger, bstrUrlContext As String, bstrUrl As String)
記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90583  Re[13]: AddHandler Eventの別スレッド
□投稿者/ TanuTanu -(2019/03/22(Fri) 12:36:15)
    2019/03/22(Fri) 12:40:09 編集(投稿者)

    魔界の仮面弁士 様
    PANG2 様

    お世話になっております。
    恐れ入りますが、ご教授頂きたく存じます。

    ■90547の件 INVOKEを使いたいのですが小生の知識では上手く動作させる事が出来ませんでした;;
    どのように記述すれば良いのでしょうか?

    Private Function WebDisp_click(ByVal e As mshtml.IHTMLEventObj) As Boolean
    MsgBox("webDisp_onclick", MsgBoxStyle.SystemModal)
    Return CBool(Invoke(CallByName(btnYoinTehai_Button_onclick, "[DispId=0]", CallType.Method, e))) 
    End Function

    エラー内容
    System.InvalidCastException
    Message=型 'System.__ComObject' の COM オブジェクトをクラス型 'System.Delegate' にキャストできません。
    COM コンポーネントを表す型のインターフェイスを COM コンポーネントを表さない型にキャストすることはできません。
    ただし、基になる COM コンポーネントがインターフェイスの IID の QueryInterface 呼び出しをサポートする場合は、
    インターフェイスにキャストすることができます。

    ■90558の件 スレッドを分ける理由について

    ビギナーですので出来ればイベントドリブンな非同期実装や同一スレッドで組みたいのですが方法が解りません。

    WEBページのボタンを手動クリック⇒DownloadCompleteを捕まえて重い処理させるとWEBページダイアログが重い処理終了しないと表示されない為、
    DownloadCompleteで別スレッドにしようと考えました。


    ■90557の件 下記を試しましたが、GetIEDocument(hWnd_IES)にてハンドル取得出来ませんでした。

    Private Sub IE_1_DownloadComplete() Handles IE_1.DownloadComplete
    DoSomething()
    End Sub

    宜しくお願いいたします。




記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90588  Re[14]: AddHandler Eventの別スレッド
□投稿者/ PANG2 -(2019/03/22(Fri) 13:20:41)
    No90583 (TanuTanu さん) に返信

    > ■90558の件 スレッドを分ける理由について
    >
    > ビギナーですので出来ればイベントドリブンな非同期実装や同一スレッドで組みたいのですが方法が解りません。
    >
    > WEBページのボタンを手動クリック⇒DownloadCompleteを捕まえて重い処理させるとWEBページダイアログが重い処理終了しないと表示されない為、
    > DownloadCompleteで別スレッドにしようと考えました。

    DocumentCompletedを使うとか。
    さらに問題があれば、Windows.Forms.Timer を使うとか。

記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90589  Re[14]: AddHandler Eventの別スレッド
□投稿者/ 魔界の仮面弁士 -(2019/03/22(Fri) 15:03:37)
    No90588 (PANG2 さん) に返信
    > DocumentCompletedを使うとか。

    DocumentComplete イベントですね。名前は似ていますが、
    DocumentCompleted はマネージ版 WebBrowser のイベントです。


    No90583 (TanuTanu さん) に返信
    > ■90547の件 INVOKEを使いたいのですが小生の知識では上手く動作させる事が出来ませんでした;;
    使う方法はありますが、そもそも今回の要件では、
    無理にスレッドを分けるべきではないように思います。


    > Message=型 'System.__ComObject' の COM オブジェクトをクラス型 'System.Delegate' にキャストできません。
    Invoke の引数にはデリゲートインスタンスを渡す必要があります。ラムダ式でも良いですが。
    手っ取り早いのは、そのメソッド自身を AddressOf で呼びなおすとか。
    https://www.atmarkit.co.jp/ait/articles/0506/17/news111.html


    > ■90558の件 スレッドを分ける理由について
    > ビギナーですので出来ればイベントドリブンな非同期実装や同一スレッドで組みたいのですが方法が解りません。
    ビギナーなら尚の事、イベント駆動型の開発スタイルで組むことをお奨めします。
    現状の理解度でスレッドセーフな設計を組むのは難易度が高すぎるかと。


    > WEBページのボタンを手動クリック⇒DownloadCompleteを捕まえて重い処理させるとWEBページダイアログが重い処理終了しないと表示されない為、
    > DownloadCompleteで別スレッドにしようと考えました。

    DownloadComplete は Document の取得とは無関係ですよね。
    DocumentComplete では駄目でしょうか?
    https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa752084%28v=vs.85%29#events

    DocumentComplete では期待する結果が得られない場合(Refresh 時など)は、
    PANG2 さんも指摘されていたように、Timer を併用することも検討してみてください。



    > ■90557の件 下記を試しましたが、GetIEDocument(hWnd_IES)にてハンドル取得出来ませんでした。
    取得できないというのは、具体的にはどういう状況でしょうか。

    その処理を呼び出す前の、hWnd_IES を取得する処理に問題が生じているのか、
    hWnd_IES は得ているが、それが指し示すウィンドウが失われている状態なのか、
    SendMessageTimeout がタイムアウトしてゼロを返してくるのか、
    SendMessageTimeout は成功しているけれど ObjectFromLresult が失敗しているのか、
    ObjectFromLresult まで成功したけれど、想定外していたオブジェクトではないのか…。

    あるいはそもそも、GetIEDocument を呼び出すところまで辿りつけていない状態なのか。


    なお GetIEDocument では、hWnd_IES 配下に複数の "Internet Explorer_Server" が
    存在していた場合を考慮した実装になっていないように見えます。最初に見つかったものが
    目的のウィンドウであるかどうかを確認するための機構も用意されていないようですし。

    ビギナーであるというのなら、無闇に API に頼ることはおすすめできません。

    以前にも指摘していますが、New SHDocVw.ShellWindows() あるいは
    CreateObject("Shell.Application").Windows を For Each して InternetExplorer を列挙し、
    そのイベントやプロパティを通じて操作することをお奨めします。
記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90590  Re[15]: AddHandler Eventの別スレッド
□投稿者/ TanuTanu -(2019/03/22(Fri) 16:21:22)
    魔界の仮面弁士 様
    PANG2 様

    大変お世話になっております。

    ■下記転記文

    >無理にスレッドを分けるべきではないように思います。

    >現状の理解度でスレッドセーフな設計を組むのは難易度が高すぎるかと。

    >以前にも指摘していますが、New SHDocVw.ShellWindows() あるいは
    >CreateObject("Shell.Application").Windows を For Each して InternetExplorer を列挙し、
    >そのイベントやプロパティを通じて操作することをお奨めします。

    >PANG2 さんも指摘されていたように、Timer を併用することも検討してみてください。

    *****************************

    上記、仰るとおりビギナーにはとても難易度高いです。この機能を実装するのはもう暫く先にしようと思います。

    ただ今回、ご教授頂いた事で何とか下記まで辿り付く事が出来ました。
    これを何とか動くようにする方法をお教え頂くことは出来ますでしょうか。
    宜しくお願いいたします。


    No90583 の件

    Private Function WebDisp_click(ByVal e As mshtml.IHTMLEventObj) As Boolean

    MsgBox("webDisp_onclick", MsgBoxStyle.SystemModal)

    Return CBool(Invoke(New TESTAAADelegate(AddressOf TESTAAA)))

    End Function

    Delegate Function TESTAAADelegate() As Boolean

    Sub TESTAAA(ByVal e As mshtml.IHTMLEventObj)
    CallByName(btn_Button_onclick, "[DispId=0]", CallType.Method, e)
    End Sub

    エラー BC31143
    メソッド 'Public Sub TESTAAA(e As IHTMLEventObj)' に、デリゲート 'Delegate Function Form1.TESTDelegate() As Boolean'
    と互換性があるシグネチャがありません。
記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90591  Re[16]: AddHandler Eventの別スレッド
□投稿者/ 魔界の仮面弁士 -(2019/03/22(Fri) 17:17:04)
    No90590 (TanuTanu さん) に返信
    > Delegate Function TESTAAADelegate() As Boolean
    このデリゲートのシグネチャは、
     引数:0個
     戻り値:Boolean
    となっています。


    > Sub TESTAAA(ByVal e As mshtml.IHTMLEventObj)
    一方、このメソッドのシグネチャは、
     引数:1個(IHTMLEventObj)
     戻り値:なし
    ですよね。


    そのため、
    > New TESTAAADelegate(AddressOf TESTAAA)
    と書かれた部分で、
    > メソッド 'Public Sub TESTAAA(e As IHTMLEventObj)' に、デリゲート 'Delegate Function Form1.TESTDelegate() As Boolean'
    > と互換性があるシグネチャがありません。
    というエラーが生じているというわけです。


    本来必要なのは WebDisp_click と同じシグネチャなので、
    ひとまずコンパイルを通すだけで良いなら、たとえばこんな感じ。


    ' Func(Of mshtml.IHTMLEventObj, Boolean) デリゲートでも可
    Private Delegate Function ExampleDelegate(ByVal e As mshtml.IHTMLEventObj) As Boolean

    Private Function Example(ByVal e As mshtml.IHTMLEventObj) As Boolean
     Return CBool(CallByName(〜〜))
    End Function

    Private Function WebDisp_click(ByVal e As mshtml.IHTMLEventObj) As Boolean
     Return CBool(Invoke(New ExampleDelegate(AddressOf Example), e))
    End Function


    > これを何とか動くようにする方法をお教え頂くことは出来ますでしょうか。
    このパターンでワーカースレッドを立てるのは、パフォーマンス面でも管理面でもデメリットになるかも。
記事No.90434 のレス /過去ログ156より / 関連記事表示
削除チェック/

■90592  Re[17]: AddHandler Eventの別スレッド
□投稿者/ TanuTanu -(2019/03/22(Fri) 20:17:57)
    魔界の仮面弁士 様
    PANG2 様

    何とかコンパイル出来ましたが、Invoke、Delegateしても基になる RCW から分割された COM オブジェクトを使うことはできません。が出てしまいました;;

    今回、大分引っ張ってしまいましたが素人が手を付ける案件では無い事を身をもって体験致しました。

    このような素人に親切にして頂いた事、誠に感謝申し上げます。

    この質問掲示板の益々の発展と皆様のご健勝を祈願致しましてお礼とさせて頂きます。
    ありがとうございました。


記事No.90434 のレス / END /過去ログ156より / 関連記事表示
削除チェック/

<前の20件

<< 0 | 1 >>

パスワード/

- Child Tree -