VB6中如何使用FindWindowW通过Unicode窗口标题查找对应窗口
问题根因定位
- 未正确声明
GetClassName的Unicode版本,VB6默认调用ANSI接口GetClassNameA,拿到的类名是ANSI编码,传给Unicode接口FindWindowW会出现编码不匹配,导致类名识别错误。 GetWindowTextW传参长度错误:GetWindowTextLengthW返回的是标题的字符数,不包含末尾的\0终止符,调用GetWindowTextW时第三个参数需要+1,否则标题字符串没有正确的终止符,FindWindowW读取时会带上后面的垃圾字符,无法匹配。- 类名和标题字符串未做空终止处理:
Space(500)和String$(256,0)生成的字符串后面带有大量多余的空字符/空格,未做截断的话,传给FindWindowW时会被当成字符串的一部分,导致匹配失败。 - 标题字符串长度固定为256,若目标窗口标题超过256字符会出现截断,也会导致匹配失败。
修正方案
首先增加字符串空截断辅助函数,再修正API声明和业务逻辑即可,完整代码如下:
' API声明 Private Declare Function FindWindowW Lib "user32" (ByVal lpClassName As Long, ByVal lpWindowName As Long) As Long Private Declare Function GetWindowTextW Lib "user32" (ByVal hWnd As Long, ByVal lpString As Long, ByVal cch As Long) As Long Private Declare Function GetWindowTextLengthW Lib "user32" (ByVal hWnd As Long) As Long Private Declare Function GetClassNameW Lib "user32" (ByVal hWnd As Long, ByVal lpClassName As Long, ByVal nMaxCount As Long) As Long ' 辅助函数:截断字符串末尾的空字符 Private Function TrimNull(ByVal str As String) As String Dim pos As Long pos = InStr(str, Chr$(0)) If pos > 0 Then TrimNull = Left$(str, pos - 1) Else TrimNull = str End If End Function Private Sub cmdOK_Click() Dim titleString As String Dim newHwnd As Long Dim className As String Dim titleLen As Long ' 获取Unicode类名并处理空字符 className = Space$(500) GetClassNameW currentHwnd, StrPtr(className), Len(className) className = TrimNull(className) ' 获取Unicode窗口标题并处理空字符 titleLen = GetWindowTextLengthW(currentHwnd) If titleLen > 0 Then titleString = String$(titleLen + 1, 0) ' 预留终止符位置 GetWindowTextW currentHwnd, StrPtr(titleString), titleLen + 1 titleString = TrimNull(titleString) End If ' 查找窗口,如果不需要按类名匹配,第一个参数可传0 newHwnd = FindWindowW(StrPtr(className), StrPtr(titleString)) End Sub
内容的提问来源于stack exchange,提问作者SuperBerry
相关产品推荐
相关产品推荐

