ampapa
asked on
Is button visible ona form, API
How can I tell if a button is visible on a form "given the text" via the Windows API?
ASKER
Does this function only work if I know what the handle of the button is, I've only got the "caption" of the button?
Is there a way to Enumerate all the objects on a form?
So, I'm assuming GWL_STYLE is the button type what are the other variables checkbox, radiobutton, etc?
Is there a way to Enumerate all the objects on a form?
So, I'm assuming GWL_STYLE is the button type what are the other variables checkbox, radiobutton, etc?
Use FindWindowEx to find the window button having the specified caption( use the windows class name as well to make sure you get the button, not other control type). After the window was found use GetWindowLong to get the visible/hidden state of the control.
' assumes within form; otherwise, you'll need a reference to the Form object in place of Me, below.
Dim oControl As Control
Dim strCaption As String
Dim blnFound As Boolean
blnFound = False ' default
strCaption = "Command1" ' or passed as parameter
For Each oControl In Me.Controls
If TypeOf oControl Is CommandButton Then
If oControl.Caption = strCaption Then
blnFound = True
Exit For
End If
End If
Next
Dim oControl As Control
Dim strCaption As String
Dim blnFound As Boolean
blnFound = False ' default
strCaption = "Command1" ' or passed as parameter
For Each oControl In Me.Controls
If TypeOf oControl Is CommandButton Then
If oControl.Caption = strCaption Then
blnFound = True
Exit For
End If
End If
Next
And BTW, this is in response to your question "Is there a way to Enumerate all the objects on a form?" Since you asked for an API solution initially, this doesn't meet that requirement. It also doesn't meet your initial criterion of determining if the button is visible (although you could check the .Visible property once you find the caption desired).
ASKER
aParser, thanks for the snippet of code but I do need an API solution to this problem as I am not in control of this application that I am trying manage.
This window is not visible at the time so I am unable to get the handle to get the button handle...
Here is what I've got going, maybe I'm approaching this wrong...
I have an application that I need to uninstall remotely so all questions asked by this program when uninstalling need to be answered automatically. The application initially asks for permission to uninstall with a simple YES/NO and I now have this problem solved.
The next few windows that are generated by the uninstall are done on the fly so the hwnd will also be changing but the window captions aren't, this is causing me problems. I've been trying to catch new windows appearing and old windows closing by using the following.
'******
Do Until bClicked = True Or lngreturn <> 0
'Get's handle of Main Hyperion window to confirm uninstall
lngreturn = FindWindow(vbEmpty, "Confirm File Deletion")
DoEvents
Loop
'****
Do Until lngreturn = 0
DoEvents
Loop
Obviously the uninstall takes some time so I need a way to wait for certain processes? Maybe I need a routine that will catch any new windows that are generated and destroyed, are they destroyed if the aren't visible? Anyone have any ideas or thoughts?
This window is not visible at the time so I am unable to get the handle to get the button handle...
Here is what I've got going, maybe I'm approaching this wrong...
I have an application that I need to uninstall remotely so all questions asked by this program when uninstalling need to be answered automatically. The application initially asks for permission to uninstall with a simple YES/NO and I now have this problem solved.
The next few windows that are generated by the uninstall are done on the fly so the hwnd will also be changing but the window captions aren't, this is causing me problems. I've been trying to catch new windows appearing and old windows closing by using the following.
'******
Do Until bClicked = True Or lngreturn <> 0
'Get's handle of Main Hyperion window to confirm uninstall
lngreturn = FindWindow(vbEmpty, "Confirm File Deletion")
DoEvents
Loop
'****
Do Until lngreturn = 0
DoEvents
Loop
Obviously the uninstall takes some time so I need a way to wait for certain processes? Maybe I need a routine that will catch any new windows that are generated and destroyed, are they destroyed if the aren't visible? Anyone have any ideas or thoughts?
What you need is a callback hook to discover when windows are opening and closing.
This infor isn't exactly what you need, but it should give you an idea:
http://vbnet.mvps.org/index.html?code/hooks/messageboxhook.htm
This infor isn't exactly what you need, but it should give you an idea:
http://vbnet.mvps.org/index.html?code/hooks/messageboxhook.htm
ASKER
I came accross that link... In my search.
Is this something you can help me with?
Is this something you can help me with?
Certainly. What would you like to know specifically?
ASKER
Most of the examples that I have been able to find are for Mouse and Keyboard hooks. Do you have any example coding refering to hooking a window?
I'm certain that unless I had some example to follow that I would probably would not be able to implementthis solution, which I also feel is the correct way.
Thanks for the help.
I'm certain that unless I had some example to follow that I would probably would not be able to implementthis solution, which I also feel is the correct way.
Thanks for the help.
The example I posted above is a hook to windows (forms)
Very basically, you want to create a windowsproc in a bas module to which will be passed the parameters of the message:
Public Function WindowsProc(ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'Within the proc, you loog for the message passed and, when it's the one you want, do your processing
If uMsg = HCBT_ACTIVATE Then '(or HCBT_CREATEWND, I'm not sure which will work best for you)
'At this point, look for the particular window you want to process on and do it.
End If
'Don't forget to pass the message on to the queue
SendMessage hwnd, uMsg, wParam, lParam
End Function
Now, in your application start procedure (main form load?), you set the hook:
hInstance = GetWindowLong(0, GWL_HINSTANCE) '0 is the desktop, the parent of everything
hThreadId = GetCurrentThreadId()
'set up the MSGBOX_HOOK_PARAMS values
'By specifying a Windows hook as one
'of the params, we can intercept messages
'sent by Windows and thereby manipulate
'the dialog
With MSGHOOK
.hwndOwner = 0
.hHook = SetWindowsHookEx(WH_CBT, AddressOf WindowsProc, hInstance, hThreadId)
End With
Finally, at you application close, drop the hook
UnhookWindowsHookEx MSGHOOK.hHook
NOTE!!! MAKE ABSOLUTELY SURE YOU DROP THE HOOK BEFORE YOUR APPLICATION ENDS!!!!!
Very basically, you want to create a windowsproc in a bas module to which will be passed the parameters of the message:
Public Function WindowsProc(ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'Within the proc, you loog for the message passed and, when it's the one you want, do your processing
If uMsg = HCBT_ACTIVATE Then '(or HCBT_CREATEWND, I'm not sure which will work best for you)
'At this point, look for the particular window you want to process on and do it.
End If
'Don't forget to pass the message on to the queue
SendMessage hwnd, uMsg, wParam, lParam
End Function
Now, in your application start procedure (main form load?), you set the hook:
hInstance = GetWindowLong(0, GWL_HINSTANCE) '0 is the desktop, the parent of everything
hThreadId = GetCurrentThreadId()
'set up the MSGBOX_HOOK_PARAMS values
'By specifying a Windows hook as one
'of the params, we can intercept messages
'sent by Windows and thereby manipulate
'the dialog
With MSGHOOK
.hwndOwner = 0
.hHook = SetWindowsHookEx(WH_CBT, AddressOf WindowsProc, hInstance, hThreadId)
End With
Finally, at you application close, drop the hook
UnhookWindowsHookEx MSGHOOK.hHook
NOTE!!! MAKE ABSOLUTELY SURE YOU DROP THE HOOK BEFORE YOUR APPLICATION ENDS!!!!!
ASKER
hInstance = GetWindowLong(0, GWL_HINSTANCE) '0 is the desktop, the parent of everything
By passing "0" to the above function is there no need for the GetDesktopWindow function?
So, let's say this new window that is created how would I know if it is visible or not?
By passing "0" to the above function is there no need for the GetDesktopWindow function?
So, let's say this new window that is created how would I know if it is visible or not?
ASKER
Hang with me Clif I think approaching where I need to be.
It appears that HCBT_SETFOCUS might be what I'm looking for? Correct me if I'm wrong but if I am able to establish the WindowHook this function will supply "the HWND to the window losing the keyboard focus" and "the HWND of the window recieiving keyboard focus".
It appears that HCBT_SETFOCUS might be what I'm looking for? Correct me if I'm wrong but if I am able to establish the WindowHook this function will supply "the HWND to the window losing the keyboard focus" and "the HWND of the window recieiving keyboard focus".
ampapa,
Actually realizing that ME, 2000, and XP have changed the rules, perhaps GetDesktopWindow() wouldn't be such a bad idea.
As far is discovering whether or not the new window is visible, I covered that in my first post in this thread.
Actually realizing that ME, 2000, and XP have changed the rules, perhaps GetDesktopWindow() wouldn't be such a bad idea.
As far is discovering whether or not the new window is visible, I covered that in my first post in this thread.
ASKER
'misc constants
Private Const WH_CBT = 5
Private Const GWL_HINSTANCE = (-6)
Private Const HCBT_ACTIVATE = 5
Can I just change "HCBT_ACTIVATE" to "HCBT_SETFOCUS" would then the constant "WH_CBT" remain 5?
Private Const WH_CBT = 5
Private Const GWL_HINSTANCE = (-6)
Private Const HCBT_ACTIVATE = 5
Can I just change "HCBT_ACTIVATE" to "HCBT_SETFOCUS" would then the constant "WH_CBT" remain 5?
No, I don't think that's quite what you want. The reason being is that the users (or another app) might open a window causing the windows you're looking for to lose focus and the new unrelated window to gain focus.
Here's what you want in basic steps:
1. Your application is running, the target application is not.
2. Hook the windows messenger looking for new windows. You will use the instance of the desktop in your hook.
3. Every time a new window starts, use GetWindowText() to see if it's the target app starting.
4. Once your target app has started, start looking for it's child windows to open. To do this, you'll need a new hook using the instance of the target app.
5. Every time a child window opens, use GetWindowText() to see if it's the dialog window you're looking for.
6. Once you have the dialog box you're looking for, do what ever processing you want to it.
7. Before your app closes, drop all hooks.
Here's what you want in basic steps:
1. Your application is running, the target application is not.
2. Hook the windows messenger looking for new windows. You will use the instance of the desktop in your hook.
3. Every time a new window starts, use GetWindowText() to see if it's the target app starting.
4. Once your target app has started, start looking for it's child windows to open. To do this, you'll need a new hook using the instance of the target app.
5. Every time a child window opens, use GetWindowText() to see if it's the dialog window you're looking for.
6. Once you have the dialog box you're looking for, do what ever processing you want to it.
7. Before your app closes, drop all hooks.
ASKER
That's sort of how I'm doing it now with FindWindow but the issue is that there is more than 1 window with similar text... So, current code identify's the window as being open and the code continues.
User intervention in this particular case will be non-existent so what do you think about "HCBT_SETFOCUS"
This is what I've got in a module and form:
MODULE
'misc constants
Private Const WH_CBT = 5
Private Const GWL_HINSTANCE = (-6)
'Private Const HCBT_ACTIVATE = 5
'UDT for passing data through the hook
Private Type MSGBOX_HOOK_PARAMS
hwndOwner As Long
hHook As Long
End Type
'need this declared at module level as
'it is used in the call and the hook proc
Private MSGHOOK As MSGBOX_HOOK_PARAMS
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
'Public Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Private Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" _
(ByVal idHook As Long, _
ByVal lpfn As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Public Sub GetWindowData()
If uMsg = HCBT_ACTIVATE Then '(or HCBT_CREATEWND, I'm not sure which will work best for you)
'At this point, look for the particular window you want to process on and do it.
msgbox hwnd
End If
'Don't forget to pass the message on to the queue
SendMessage hwnd, uMsg, wParam, lParam
End Sub
FORM
Private Sub Form_Load()
hInstance = GetWindowLong(0, GWL_HINSTANCE) '0 is the desktop, the parent of everything
hThreadId = GetCurrentThreadId()
'set up the MSGBOX_HOOK_PARAMS values
'By specifying a Windows hook as one
'of the params, we can intercept messages
'sent by Windows and thereby manipulate
'the dialog
With MSGHOOK
.hwndOwner = 0
.hHook = SetWindowsHookEx(WH_CBT, AddressOf WindowsProc, hInstance, hThreadId)
End With
End Sub
Private Sub Form_Unload(Cancel As Integer)
UnhookWindowsHookEx MSGHOOK.hHook
End Sub
User intervention in this particular case will be non-existent so what do you think about "HCBT_SETFOCUS"
This is what I've got in a module and form:
MODULE
'misc constants
Private Const WH_CBT = 5
Private Const GWL_HINSTANCE = (-6)
'Private Const HCBT_ACTIVATE = 5
'UDT for passing data through the hook
Private Type MSGBOX_HOOK_PARAMS
hwndOwner As Long
hHook As Long
End Type
'need this declared at module level as
'it is used in the call and the hook proc
Private MSGHOOK As MSGBOX_HOOK_PARAMS
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
'Public Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Private Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" _
(ByVal idHook As Long, _
ByVal lpfn As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Public Sub GetWindowData()
If uMsg = HCBT_ACTIVATE Then '(or HCBT_CREATEWND, I'm not sure which will work best for you)
'At this point, look for the particular window you want to process on and do it.
msgbox hwnd
End If
'Don't forget to pass the message on to the queue
SendMessage hwnd, uMsg, wParam, lParam
End Sub
FORM
Private Sub Form_Load()
hInstance = GetWindowLong(0, GWL_HINSTANCE) '0 is the desktop, the parent of everything
hThreadId = GetCurrentThreadId()
'set up the MSGBOX_HOOK_PARAMS values
'By specifying a Windows hook as one
'of the params, we can intercept messages
'sent by Windows and thereby manipulate
'the dialog
With MSGHOOK
.hwndOwner = 0
.hHook = SetWindowsHookEx(WH_CBT, AddressOf WindowsProc, hInstance, hThreadId)
End With
End Sub
Private Sub Form_Unload(Cancel As Integer)
UnhookWindowsHookEx MSGHOOK.hHook
End Sub
You are missing the function WindowsProc from your module, or you forgot to change the name of the function in your AddressOf() statment in your SetWindowsHookEx() call.
Actually it looks like the latter.
Your sub GetWindowData should be a function:
Public Function GetWindowData(ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg = HCBT_ACTIVATE Then '(or HCBT_CREATEWND, I'm not sure which will work best for you)
'At this point, look for the particular window you want to process on and do it.
msgbox hwnd 'In this case hWnd is the handle of the desktop
End If
'Don't forget to pass the message on to the queue
SendMessage hwnd, uMsg, wParam, lParam
End Sub
And your call to SetWindowsHookEx should be:
.hHook = SetWindowsHookEx(WH_CBT, AddressOf GetWindowData, hInstance, hThreadId)
-----
It's your app. But I'm still not comfortable relying on a lost focus/got focus to control the app, even if it's running unattended. There's the potential that some other unattended app will throw an error causing a messagebox to be displayed, which will then gain focus throwing off your application.
Actually it looks like the latter.
Your sub GetWindowData should be a function:
Public Function GetWindowData(ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg = HCBT_ACTIVATE Then '(or HCBT_CREATEWND, I'm not sure which will work best for you)
'At this point, look for the particular window you want to process on and do it.
msgbox hwnd 'In this case hWnd is the handle of the desktop
End If
'Don't forget to pass the message on to the queue
SendMessage hwnd, uMsg, wParam, lParam
End Sub
And your call to SetWindowsHookEx should be:
.hHook = SetWindowsHookEx(WH_CBT, AddressOf GetWindowData, hInstance, hThreadId)
-----
It's your app. But I'm still not comfortable relying on a lost focus/got focus to control the app, even if it's running unattended. There's the potential that some other unattended app will throw an error causing a messagebox to be displayed, which will then gain focus throwing off your application.
ASKER
1. Your application is running, the target application is not.
2. Hook the windows messenger looking for new windows. You will use the instance of the desktop in your hook.
Currently this is what we are doing correct?
3. Every time a new window starts, use GetWindowText() to see if it's the target app starting.
So, if I a m able to see all messages with this hook I'm currently creating won't I be able to get the HWND of the New Windows being created? If I can get to this point I think I'm home free...
Steps 4 and 5 can be eliminated
6. Once you have the dialog box you're looking for, do what ever processing you want to it.
7. Before your app closes, drop all hooks.
'************************* ********** ********** ********** ********** *****
"At this point, look for the particular window you want to process on and do it."
When I added the msgbox you said "'In this case hWnd is the handle of the desktop" is that only because no other windows have been opened??? As windows are opened though shouldn't change to the handle of the window that was opened?
2. Hook the windows messenger looking for new windows. You will use the instance of the desktop in your hook.
Currently this is what we are doing correct?
3. Every time a new window starts, use GetWindowText() to see if it's the target app starting.
So, if I a m able to see all messages with this hook I'm currently creating won't I be able to get the HWND of the New Windows being created? If I can get to this point I think I'm home free...
Steps 4 and 5 can be eliminated
6. Once you have the dialog box you're looking for, do what ever processing you want to it.
7. Before your app closes, drop all hooks.
'*************************
"At this point, look for the particular window you want to process on and do it."
When I added the msgbox you said "'In this case hWnd is the handle of the desktop" is that only because no other windows have been opened??? As windows are opened though shouldn't change to the handle of the window that was opened?
ASKER
Here is what I've got at the moment when firing this up it crashes Visual Basic:
MODULE
'******
Public Function WindowsProc(ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'Within the proc, you loog for the message passed and, when it's the one you want, do your processing
If uMsg = HCBT_ACTIVATE Then '(or HCBT_CREATEWND, I'm not sure which will work best for you)
'At this point, look for the particular window you want to process on and do it.
MsgBox hwnd 'This should be the handle of the new Window
End If
'Don't forget to pass the message on to the queue
SendMessage hwnd, uMsg, wParam, lParam
End Function
FORM
'****
'UDT for passing data through the hook
Private Type MSGBOX_HOOK_PARAMS
hwndOwner As Long
hHook As Long
End Type
'need this declared at module level as
'it is used in the call and the hook proc
Private MSGHOOK As MSGBOX_HOOK_PARAMS
'Public Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" _
(ByVal idHook As Long, _
ByVal lpfn As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Private Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
'misc constants
Private Const WH_CBT = 5
Private Const GWL_HINSTANCE = (-6)
Private Const HCBT_ACTIVATE = 5
Private Sub Form_Load()
hInstance = GetWindowLong(0, GWL_HINSTANCE) '0 is the desktop, the parent of everything
hThreadId = GetCurrentThreadId()
'set up the MSGBOX_HOOK_PARAMS values
'By specifying a Windows hook as one
'of the params, we can intercept messages
'sent by Windows and thereby manipulate
'the dialog
With MSGHOOK
.hwndOwner = 0
.hHook = SetWindowsHookEx(WH_CBT, AddressOf WindowsProc, hInstance, hThreadId)
End With
End Sub
Private Sub Form_Unload(Cancel As Integer)
UnhookWindowsHookEx MSGHOOK.hHook
End Sub
MODULE
'******
Public Function WindowsProc(ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'Within the proc, you loog for the message passed and, when it's the one you want, do your processing
If uMsg = HCBT_ACTIVATE Then '(or HCBT_CREATEWND, I'm not sure which will work best for you)
'At this point, look for the particular window you want to process on and do it.
MsgBox hwnd 'This should be the handle of the new Window
End If
'Don't forget to pass the message on to the queue
SendMessage hwnd, uMsg, wParam, lParam
End Function
FORM
'****
'UDT for passing data through the hook
Private Type MSGBOX_HOOK_PARAMS
hwndOwner As Long
hHook As Long
End Type
'need this declared at module level as
'it is used in the call and the hook proc
Private MSGHOOK As MSGBOX_HOOK_PARAMS
'Public Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" _
(ByVal idHook As Long, _
ByVal lpfn As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Private Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
'misc constants
Private Const WH_CBT = 5
Private Const GWL_HINSTANCE = (-6)
Private Const HCBT_ACTIVATE = 5
Private Sub Form_Load()
hInstance = GetWindowLong(0, GWL_HINSTANCE) '0 is the desktop, the parent of everything
hThreadId = GetCurrentThreadId()
'set up the MSGBOX_HOOK_PARAMS values
'By specifying a Windows hook as one
'of the params, we can intercept messages
'sent by Windows and thereby manipulate
'the dialog
With MSGHOOK
.hwndOwner = 0
.hHook = SetWindowsHookEx(WH_CBT, AddressOf WindowsProc, hInstance, hThreadId)
End With
End Sub
Private Sub Form_Unload(Cancel As Integer)
UnhookWindowsHookEx MSGHOOK.hHook
End Sub
I'm sorry, but I have to put helping you on hold for a while. I'm in the middle of a four hour long process. If I run any tests that crash my system, I'll have to start the who process over again. :)
Over the weekend, I'll see what I can come up with on this.
Sorry I have to do this to you.
Over the weekend, I'll see what I can come up with on this.
Sorry I have to do this to you.
ASKER
Thanks for the post.
I'll keep my eyes on the forum this weekend.
I'll keep my eyes on the forum this weekend.
ASKER
CLif, I found a bitof code on MS site and it's helped me a long a bit. I'm having problems still identifying a particular window. Let's sayI'm looking for the "calculater" how can I get a msgbox with the HWND when it's window is launched?
FORM
'************************* ********** *********
Private Sub Command1_Click()
Dim hInst As Long
Dim Thread As Long
'Set up the CBT hook
hInst = GetWindowLong(Me.hwnd, GWL_HINSTANCE)
Thread = GetCurrentThreadId()
hHook = SetWindowsHookEx(WH_CBT, AddressOf WinProc1, hInst, _
Thread)
'Display the message box
MsgBox "This message box has been positioned at (0,0)."
End Sub
MODULE
'************************* ********** ********** ****
Public Declare Function UnhookWindowsHookEx Lib "user32" ( _
ByVal hHook As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias _
"GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) _
As Long
Public Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare Function SetWindowsHookEx Lib "user32" Alias _
"SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, _
ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Public Declare Function SetWindowPos Lib "user32" ( _
ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal x As Long, ByVal y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd _
As Long, lpRect As RECT) As Long
Public Const GWL_HINSTANCE = (-6)
Public Const SWP_NOSIZE = &H1
Public Const SWP_NOZORDER = &H4
Public Const SWP_NOACTIVATE = &H10
Public Const HCBT_ACTIVATE = 5
Public Const WH_CBT = 5
Public hHook As Long
Function WinProc1(ByVal lMsg As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
If lMsg = HCBT_ACTIVATE Then
'Show the MsgBox at a fixed location (0,0)
SetWindowPos wParam, 0, 0, 0, 0, 0, _
SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOACTIVATE
'Release the CBT hook
UnhookWindowsHookEx hHook
End If
WinProc1 = False
End Function
FORM
'*************************
Private Sub Command1_Click()
Dim hInst As Long
Dim Thread As Long
'Set up the CBT hook
hInst = GetWindowLong(Me.hwnd, GWL_HINSTANCE)
Thread = GetCurrentThreadId()
hHook = SetWindowsHookEx(WH_CBT, AddressOf WinProc1, hInst, _
Thread)
'Display the message box
MsgBox "This message box has been positioned at (0,0)."
End Sub
MODULE
'*************************
Public Declare Function UnhookWindowsHookEx Lib "user32" ( _
ByVal hHook As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias _
"GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) _
As Long
Public Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare Function SetWindowsHookEx Lib "user32" Alias _
"SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, _
ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Public Declare Function SetWindowPos Lib "user32" ( _
ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal x As Long, ByVal y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd _
As Long, lpRect As RECT) As Long
Public Const GWL_HINSTANCE = (-6)
Public Const SWP_NOSIZE = &H1
Public Const SWP_NOZORDER = &H4
Public Const SWP_NOACTIVATE = &H10
Public Const HCBT_ACTIVATE = 5
Public Const WH_CBT = 5
Public hHook As Long
Function WinProc1(ByVal lMsg As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
If lMsg = HCBT_ACTIVATE Then
'Show the MsgBox at a fixed location (0,0)
SetWindowPos wParam, 0, 0, 0, 0, 0, _
SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOACTIVATE
'Release the CBT hook
UnhookWindowsHookEx hHook
End If
WinProc1 = False
End Function
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Clif, thanks for the update. I'll take a better look at the link later this afternoon.
I've found in my search that I am actually trying to do something that can't be done through VB, well sort of unless it's accompanied by a .DLL that monitors the entire system. A 'local' application that I create can use a 'local' hook similar to the code I posted above, which came from Microsoft's site.
Your original code supplied above uses a given HWND to identify a button do you have a routine that loops through all the objects on a form given it's HWND?
I've found in my search that I am actually trying to do something that can't be done through VB, well sort of unless it's accompanied by a .DLL that monitors the entire system. A 'local' application that I create can use a 'local' hook similar to the code I posted above, which came from Microsoft's site.
Your original code supplied above uses a given HWND to identify a button do you have a routine that loops through all the objects on a form given it's HWND?
ASKER
Clif, thanks for all your great help. I certainly understand "hooks" much better than I did when I started and that's really all that matters, sometimes things just can't be done or answered...
Thanks again.
Thanks again.
TFTP.
Sorry I couldn't be of more help.
Sorry I couldn't be of more help.
Private Declare Function GetWindowLong _
Lib "user32" Alias "GetWindowLongA" _
(ByVal hWnd As Long, _
ByVal nIndex As Long) _
As Long
Private Const GWL_STYLE = (-16)
Private Const WS_VISIBLE = &H10000000
lRes = GetWindowLong(btn_hwnd, GWL_STYLE)
bIsVisible = ((lRes And WS_VISIBLE) = WS_VISIBLE)