用API得到自己程序中的某个窗口的hwnd,不使用循环测试每个窗口的hwnd的方法,
我想调用该窗口内的子程序。怎么办?

解决方案 »

  1.   

    FindWindowEx VB声明 
    Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long 
    说明 
    在窗口列表中寻找与指定条件相符的第一个子窗口 
    返回值 
    Long,找到的窗口的句柄。如未找到相符窗口,则返回零。会设置GetLastError 
    参数表 
    参数 类型及说明 
    hWnd1 Long,在其中查找子的父窗口。如设为零,表示使用桌面窗口(通常说的顶级窗口都被认为是桌面的子窗口,所以也会对它们进行查找) 
    hWnd2 Long,从这个窗口后开始查找。这样便可利用对FindWindowEx的多次调用找到符合条件的所有子窗口。如设为零,表示从第一个子窗口开始搜索 
    lpsz1 String,欲搜索的类名。零表示忽略 
    lpsz2 String,欲搜索的类名。零表示忽略 
      

  2.   

    我想调用该窗口内的子程序。怎么办?==========================================窗口内的子程序是基于VB的,与系统API无关
      

  3.   

    to yefanqiu(叶帆) 
    因为各个窗口是相关联的,就像radiobox,当用户选中某一个窗口后其它窗口要作出反应,调用那些窗口的子程序,用循环很用资源的,不合算。
      

  4.   


    事情是这样的,我做了一个用户控件,当窗口得到或失去焦点时,该控件就会做出相应的变化。
    我拦截了WM_ACTIVATE消息得到窗口焦点的变化得到hwnd,问题是我怎么通知该控件窗口的焦点
    已变化。我现在的做法是用循环的方法判断hwnd是属于哪个窗口的,从而知道哪个窗口焦点发
    生变化,再直接调用该窗口的子程序去通知那控件。每次都这样做很耗资源,谁有更好的方法呢?
      

  5.   

    发送一个消息给控件,触发控件的某事件
    用PostMessage
      

  6.   

    不可能 窗体是窗体 子程序是子程序 怎么调用呢?你最多是用SendMessage触发它的事件。
    如果是另一个进程 你不能调用 如果是同一个进程 你直接调用就行 何必用hWnd?
      

  7.   

    问一下:1、你这个控件是每个窗体都放一个,还是只放在一个主窗体上?
           2、当前窗体你是用窗体子类分别判断的?
           3、控件知道当前窗体要执行什么操作(和当前窗体相关)? 我的一点看法:
         Private Declare Function GetActiveWindow Lib "user32" Alias "GetActiveWindow" () As Long
         在控件里,你可以用以上api活动当前活动窗体呀!!
      

  8.   

    我本来也是想通过Message来沟通的,但在VB中,所有的Hook处理只能放在model里面,怎样才能区分是哪个窗口的控件呢?to Greaitm(夜草) 
    我要得到窗口焦点的变化,就只能得到它的hwnd,我如何直接调用呀?详细一点可以吗?to yefanqiu(叶帆):
    是部分窗口有这个控件。
    另外,无论窗口是得到或失去焦点控件都要作出反应,GetActiveWindow可以做到吗?而且控件是被动的,实际运行时我应该在哪个窗口的控件里使用GetActiveWindow
      

  9.   

    你可以这样做,对控件来说,它可以通过GetParent API(或Parent属性)获得父窗体的句柄,然后用GetActiveWindow获得当前窗体,比较它两个就可知是不是得到和失去焦点。每个控件都执行同样的程序,只是控件被实例化了,窗体所谓的当前只和具体的窗体相关
      

  10.   

    我已经得到那个焦点发生变化的窗口的hwnd,如果用你的方法这样的话,还是要引用所有的窗口。资源是很多的。
      

  11.   

    如果是计时可以我早就用了,我看到网上一些类似的控件源代码,它就是用计时,很浪费资源,所以我现在是用拦截消息来做,现在消息是拦了下来,最头疼的是拦截消息得到的窗口hwnd如何直接使用来通知控件焦点发生改变.
      

  12.   

    用sendmessage,自定义消息,向控件或窗体发消息,反正用子类做,消息很容易截到
      

  13.   

    to yefanqiu(叶帆)
    消息如何截呀?用Hook吗?那要放在标准模块中,在自定义控件中无法截消息.
      

  14.   

    对,在自定义控件的工程里添加一个模块,窗口句柄为UserControl.hWnd ,和做普通窗体的子类一样。
      

  15.   

    这是内部自定义控件,无法像你这样做.UserControl无法在标准模块里引用.
      

  16.   

    这是我刚做的,挺好使
    '----------------------------
    '控件 UserControl1
    Option Explicit
    '设置窗口附加内存长型数值
    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal HWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Const GWL_WNDPROC = (-4)Private Sub UserControl_Initialize()
       Set UseCon = MeEnd Sub
    Public Sub SetColor(intFlag As Integer)
      If intFlag = 0 Then
         UserControl.BackColor = RGB(255, 0, 0)
      Else
         UserControl.BackColor = RGB(0, 255, 0)
      End IfEnd Sub
    Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
       
       If Ambient.UserMode = True Then    '加载
          OldWindowProc = SetWindowLong(UserControl.HWnd, GWL_WNDPROC, AddressOf SubClass1_WndMessage)
          Exit Sub
       End If
       
       If Ambient.UserMode = False And OldWindowProc > 0 Then '卸载
          Call SetWindowLong(UserControl.HWnd, GWL_WNDPROC, OldWindowProc)
          OldWindowProc = 0
         Exit Sub
       End IfEnd Sub
    Public Property Get HWnd() As Long
      HWnd = UserControl.HWnd
    End Property'----------------------------------
    '控件工程中的模块
    Option Explicit
    Public OldWindowProc As Long
    Public UseCon As Object
    Public Const WM_USER = &H400
    Public Const WM_RED = WM_USER + 100
    Public Const WM_GREEN = WM_USER + 200
    '将消息传答窗口函数
    Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal HWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Public Function SubClass1_WndMessage(ByVal HWnd As OLE_HANDLE, ByVal Msg As OLE_HANDLE, ByVal wp As OLE_HANDLE, ByVal lp As Long) As Long
        Select Case Msg
          Case WM_RED
            Call UseCon.SetColor(0)
          Case WM_GREEN
            Call UseCon.SetColor(1)
        End Select
        SubClass1_WndMessage = CallWindowProc(OldWindowProc, HWnd, Msg, wp, lp)
    End Function'---------------------------------
    '加载用户控件的工程中的form1Option ExplicitPrivate Const WM_USER = &H400
    Private Const WM_RED = WM_USER + 100
    Private Const WM_GREEN = WM_USER + 200
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As LongPrivate Sub Command1_Click()
      SendMessage UserControl11.hwnd, WM_RED, 0, 0
    End Sub
    Private Sub Command2_Click()
      SendMessage UserControl11.hwnd, WM_GREEN, 0, 0
    End Sub
      

  17.   

    to yefanqiu(叶帆)刚试了你的程序,虽然能实现用消息与某一个指定的窗口通讯,但有很大一个问题.你在窗口上放两个这样的控件,无论你发送消息到UserControl11还是UserControl12都只能对UserControl11有效,无法实现对哪个控件发消息,就那个控件作出反应.
      

  18.   

    '这次就没问题了,
    ’这段代码改成如下
    Public Sub SetColor(intFlag As Integer, hWnds As Long)
      Dim hdc As Long
      Dim hRPen As Long
      Dim re As RECT
      hdc = GetDC(hWnds)
      GetWindowRect hWnds, re
      
      If intFlag = 0 Then
         hRPen = CreatePen(PS_SOLID, 100, vbRed)
         
         
      Else
         hRPen = CreatePen(PS_SOLID, 100, vbGreen)
       
       
      End If
       DeleteObject SelectObject(hdc, hRPen)
       Rectangle hdc, 0, 0, re.Right - re.Left, re.Bottom - re.Top
       DeleteObject hRPen
      
      
    End Sub'模块里的代码改成这样Public Function SubClass1_WndMessage(ByVal hwnd As OLE_HANDLE, ByVal Msg As OLE_HANDLE, ByVal wp As OLE_HANDLE, ByVal lp As Long) As Long
        Select Case Msg
          Case WM_RED
            Call UseCon.SetColor(0, hwnd) ’-----------
          Case WM_GREEN
            Call UseCon.SetColor(1, hwnd) ‘-----------
        End Select
        SubClass1_WndMessage = CallWindowProc(OldWindowProc, hwnd, Msg, wp, lp)
    End Function‘测试程序Private Sub Command1_Click()
      SendMessage UserControl11.hwnd, WM_RED, 0, 0
    End Sub
    Private Sub Command2_Click()
      SendMessage UserControl11.hwnd, WM_GREEN, 0, 0
    End SubPrivate Sub Command3_Click()
      SendMessage UserControl12.hwnd, WM_RED, 0, 0
    End Sub
    Private Sub Command4_Click()
      SendMessage UserControl12.hwnd, WM_GREEN, 0, 0
    End Sub
      

  19.   

    注意要声明相应API
    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Const GWL_WNDPROC = (-4)
    Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function CreatePen Lib "gdi32" (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long
    Private Const PS_SOLID = 0
    Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
    Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
    Private Declare Function Rectangle Lib "gdi32" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
    Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
    Private Type RECT
            Left As Long
            Top As Long
            Right As Long
            Bottom As Long
    End Type
      

  20.   

    to yefanqiu(叶帆):首先要谢谢你的关注.看了你的程序,在某个特殊情况下,这个效果是做到了,你巧妙地避开了直接对VB进行操作,得到的hwnd,最终还只是给API用的,只是在VB里兜了一圈,VB结果什么也不知道,什么也没做,也没法知道那个hwnd是属于哪个的窗口,拦截了消息后,我还要对相应的窗口的某些局部变量进行设置,也需要对某些子控件的属性进行设置,请问有办法直接得到相应窗口的引用吗?to all:我想,这一类问题每个人迟早都会遇到的,也很有用,希望有人能解决这个问题,谢谢!分数继续加.
      

  21.   

    Public Sub SetColor(intFlag As Integer, hWnds As Long)
     ' 你可以在这个函数里面判断:
       hwnds和UserControl.hwnd  是否相同,然后再决定该怎么做!
    endsub
    你可以把你的问题说的明白些,这样正面的办法找不到,可以采用其他的替代方法也可以
      

  22.   

    我希望做一个XP界面的控件(XP窗口),窗口焦点改变时控件的子控件(picture)换图片,及设定子控件所处的状态.这样说你明白吗?