none
VB2008 WinMessage 應用 RRS feed

  • 問題

  • 請教各位大大

    目前小弟遇到一個問題 客戶端 自行開發一個程式 希望 利用 WinMessage 的方式由我這邊取得一些資訊

    目前找到範例 是可以成功將直寫到記事本

    但若改由寫到範例程式Test

     Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
        Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
        Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWnd1 As IntPtr, ByVal hWnd2 As IntPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As IntPtr
    
        Private Const WM_SETTEXT As Integer = &HC
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
            Dim iHwnd As IntPtr = FindWindow("notepad", vbNullString)
           '  建立一個 Test 程式, 一個TextListBox 接收字串用 , 1個Button 發送 "Hello! "
           ' Dim iHwnd As IntPtr = FindWindow(vbNullString, "Test")
            Dim iHwndChild As IntPtr = FindWindowEx(iHwnd, IntPtr.Zero, "Edit", vbNullString)
            SendMessage(iHwndChild, WM_SETTEXT, 0, "Hello!")
          

    目前對於如何將 原本發送至筆記本的字串 送達到 Test程式的 TextListBox 中 , 及如何接收Test 傳送過來的字串 目前仍在思考中

    是否有大大提供建議方向 Or 簡易的範例可供參考?


    新手上路

    2016年10月14日 下午 03:52

解答

所有回覆

  • 先判斷視窗是不是 Unicode Window ,你的方法適用於 ANSI Window

    Unicode Window 用 WM_IME_CHAR ,可搜尋本論壇既有討論:

    https://social.msdn.microsoft.com/Forums/zh-TW/home?sort=relevancedesc&brandIgnore=True&searchTerm=WM_IME_CHAR


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2016年10月15日 上午 04:25
  • 看看這篇文件的範例有沒有幫助:

    Send strings to another application by using Windows messages

    2016年10月15日 上午 07:30
  • 目前依據 this 大大提供的資訊先做測試了解資料傳遞的現況

    範例中

    VB Code:

    Option Explicit

    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As Any, Source As Any, ByVal bytes As Long)
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal msg As Long, wParam As Long, lParam As Any) As Long

    Private Const APPVIEWER_OPEN = &H400

    Private Sub Command1_Click()
      Dim hwndAppViewer As Long
      Dim bytBuffer(1 To 255) As Byte
      Dim sParams As String
      Dim lStringAddress As Long

      hwndAppViewer = FindWindow(vbNullString, "Form1")

      If hwndAppViewer > 0 Then
        sParams = "STRINGDATA"
        CopyMemory bytBuffer(1), sParams, Len(sParams)
        lStringAddress = VarPtr(bytBuffer(1))
        SendMessage hwndAppViewer, APPVIEWER_OPEN, Me.hwnd, lStringAddress
      End If
    End Sub

    VB.net

    Imports System.Text

    Public Class BuildString

        Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
        Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

        Public Event StringOK(ByVal Result As String)
        Private hwnd As Integer = 0
        Private wMsg As Integer = 0
        Private wParam As Integer = 0
        Private lParam As String = ""
        Private tempA(-1) As Byte
        Private enc As Encoding = Encoding.UTF8

        Public Property Encode() As Encoding
            Get
                Return enc
            End Get
            Set(ByVal value As Encoding)
                enc = value
            End Set
        End Property

        Public Sub BuildString(ByVal b As IntPtr)
            If b <> 0 Then
                'build temp array
                Dim tempB(tempA.Length) As Byte
                tempA.CopyTo(tempB, 0)
                tempB(tempA.Length) = b ---> 數學運算導致溢位
                ReDim tempA(tempB.Length - 1)
                tempB.CopyTo(tempA, 0)
            Else
                'decode byte array to string
                Dim s As String
                If enc Is Encoding.UTF8 Then
                    s = Encoding.UTF8.GetString(tempA)
                ElseIf enc Is Encoding.Unicode Then
                    s = Encoding.Unicode.GetString(tempA)
                ElseIf enc Is Encoding.ASCII Then
                    s = Encoding.ASCII.GetString(tempA)
                Else
                    s = Encoding.Default.GetString(tempA)
                End If
                'send out result string via event
                RaiseEvent StringOK(s)
                ReDim tempA(-1)
            End If
        End Sub

        Public Sub PostString(ByVal hwnd As Integer, ByVal wMsg _
    As Integer, ByVal wParam As Integer, ByVal lParam As String)
            Me.hwnd = hwnd
            Me.wMsg = wMsg
            Me.wParam = wParam
            Me.lParam = lParam
            'create a new thread to post window message
            Dim t As Threading.Thread
            t = New Threading.Thread(AddressOf SendString)
            t.Start()
        End Sub

        Private Sub SendString()
            'create byte array
            Dim ba() As Byte
            'encode string to byte array
            If enc Is Encoding.UTF8 Then
                ba = Encoding.UTF8.GetBytes(lParam)
            ElseIf enc Is Encoding.Unicode Then
                ba = Encoding.Unicode.GetBytes(lParam)
            ElseIf enc Is Encoding.ASCII Then
                ba = Encoding.ASCII.GetBytes(lParam)
            Else
                ba = Encoding.Default.GetBytes(lParam)
            End If
            Dim i As Integer
            For i = 0 To ba.Length - 1
                'start post message
                ' PostMessage(hwnd, wMsg, wParam, ba(i))
                SendMessage(hwnd, wMsg, wParam, ba(i))
            Next
            'post a terminator message to destination window
            '  PostMessage(hwnd, wMsg, wParam, 0)
            SendMessage(hwnd, wMsg, wParam, 0)
        End Sub
    End Class

    上述程式 是例子中的程式碼 但是會出現運算溢位

    原先以為是 tempA 這各陣列數量錯誤,將其放大異常訊息仍舊出現在同一行Code

    這邊是否我在宣告中有誤會些什麼??

    現在先研究 心冷大 提供的資訊!了解SendMessage 的 發送及接收架構


    新手上路

    2016年10月17日 上午 05:07
  • Unicode程式可以直接呼叫SendMessageW和SendMessageW, 不需要利用Encoding類別進行轉換
    2016年10月17日 上午 07:18
  • 請教大大

    廠商給的SAMPLE 中收值的Code如下

    Function WndProc(ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
         Select Case msg
                   Case "MYMESSAGE"
                          Client.GotMessage wParam
                   Case Else
           WndProc   = CallWindowProc(ProcPrev, hwnd, msg, wParam, lParam)
        End Select
    End Function  

    因此 我如此下

     Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
        Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
        Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long
    
           Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            If Not IsNumeric(Me.TextBox1.Text) Then
                MsgBox("Try entering a valid number...")
            Else
                Dim Send_Long As Long = RegisterWindowMessage("MYMESSAGE")
    
                Dim hwndTarget As Long
                hwndTarget = FindWindow(vbNullString, "Clint")
                If hwndTarget <> 0 Then
                    SendMessage(hwndTarget, Send_Long, TextBox1.Text, 0)
                Else
                    MsgBox("The target windows could not be found. Make sure you have the client window running and try again.", vbOKOnly + vbInformation, "Send message failure...")
                End If
            End If
        End Sub

    但看來問題發生在 Send_Long 轉值上面 會出現 數學運算式導至溢位..

    這樣的話,是我參數下錯嗎? 這邊我該如何下呢?


    新手上路


    • 已編輯 eblue 2016年10月23日 下午 04:51
    2016年10月23日 下午 04:50
  • registerwindowmessage (user32)

    傳回型態應該是UInteger,而不是long...

    2016年10月24日 上午 12:48
  • registerwindowmessage (user32)

    傳回型態應該是UInteger,而不是long...

    補充:

    你的範例為 VB6 ,VBNET 跟 VB6 的型別位元組數已改變,基本上是兩倍的關係。

    比如說

    VB6 的 Interger 為 2 bytes ,VBNET 為 4 bytes 。

    VB6 的 Long 為 4 bytes ,VBNET 為 8 bytes 。

    所以前面 Joe 才會說你的型別錯誤。


    T.L. Cheng

    2016年10月29日 上午 04:50
    版主