Solved

Intercepting WM_ACTIVATE message for any window (detecting activation with hooks/subclassing)

Posted on 2004-08-05
8
3,917 Views
Last Modified: 2012-06-27
hello,

i currently need to detect when a certain application's window is activated and deactivated.  this is a 3rd party window, not one that is part of my vb.net project.  i have read a bit about hooks and subclassing, but i have not seen a concrete example of this in vb.net.  i would basically like to do what Spy++ does for message logging.  i can get the window's basic attributes like hWnd just fine.  i am just having problem's hooking into the messages.  i have successfully written code which intercepts messages from my own forms, but when i try to use a 3rd party window, i am unsuccessful.  the APIs i have been using are SetWindowLong and CallWindowProc.  please advise.

thanks,
jim
0
Comment
Question by:vanveghj
  • 5
  • 3
8 Comments
 
LVL 3

Expert Comment

by:imu79
ID: 11755480
take a look at this:

http://www.codeproject.com/csharp/GlobalSystemHook.asp

It's in C# but you should be able to get an idea on how to setup system level hooks.

hope this helps..
Imran.
0
 

Author Comment

by:vanveghj
ID: 11759692
hi,

thanks for the link.  however, from the site, "Some hook types are not suited to this implementation of global hooks."  what i want is not supported.  he only shows keyboard and mouse hooks.  examples of those are all over.

if anyone has a better way to detect when windows with a certain title are created/activated, let me know.  and of course, i do not want to use polling.

thanks,
jim v.
0
 
LVL 3

Expert Comment

by:imu79
ID: 11773407
hmmm..it seems installing a system level hook is a bit more involved than mouse and keyboard hooks (thread level hooks). here is a link I found that explains (not in detail though) how to implement a system level hook:

http://www.macadamian.com/column/windowshooks.html

Also, check out this discussion:

http://tinyurl.com/6owes

(if you can't resolve the above, just search for 'ShellProc' in groups.google.com and look at the first message)

According to that discussion, you cannot implement system level hooks using VB .NET or .NET in general. It makes sense after reading that discussion. Also, although the article says that you need to have your filter function in an unmanaged C++ dll, I had read somewhere that you could also do away with implementing the filter function in vb 6 bas module and compiling it to a dll. Ofcourse, you would want to make the function as fast and concise as possible (and yes, absolutely error-free or it could bring down the whole system) considering that windows is going to inject the dll code into each of the running processes.

here's another general article about hooks written way back in 1993 in case you haven't stumbled upon it already:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_hooks32.asp?frame=true&hidetoc=true

you're right - there isn't much out there about system level hooks. I would really be interested in someone implement this in VB/VB .NET. Maybe I'll venture this if I get enough free time from my day job :(

hope this helps..
Imran.



0
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 

Author Comment

by:vanveghj
ID: 11790590
Imran,

thanks for your continued help.  i will read those sites within the next few days, too busy right now ;-).  i am now realizing i will need to write a dll in c++, but this is no problem.  hopefully i can piece it all together.  i will update you in a few days.  i will also try to post the code if i get it working.

thanks,
jim v.
0
 
LVL 3

Expert Comment

by:imu79
ID: 11792324
Jim,

a couple of other links that I think might be useful:

http://www.planet-source-code.com/vb/scripts/showcode.asp?txtCodeId=51403&lngWId=1
ttp://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=1&txtCodeId=9153

both of these have source code on how to implement system level shell hooks in VB 6. I'm not sure if they work under VB .NET.

Also look at the documentation of the two API functions:
RegisterShellHookWindow
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/registershellhookwindow.asp

DeregisterShellHookWindow
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/Windowing/Hooks/HookReference/HookFunctions/DeregisterShellHookWindow.asp

I think those are the functions you'll basically need to setup the shell hook (yes, without ever using SetWindowsHookEx and UnhookWindowsHookEx)

I'm going to be trying that myself probably this weekend. I'll let you know.

hope this helps..
Imran.
0
 
LVL 3

Accepted Solution

by:
imu79 earned 500 total points
ID: 11817448
Jim,

I think this works in .NET as well :)
It turned out to be much simpler than I thought. Here's the code:

' Shell Events Constants
Public Enum ShellEvents
        HSHELL_WINDOWCREATED = 1
        HSHELL_WINDOWDESTROYED = 2
        HSHELL_ACTIVATESHELLWINDOW = 3
        HSHELL_WINDOWACTIVATED = 4
        HSHELL_GETMINRECT = 5
        HSHELL_REDRAW = 6
        HSHELL_TASKMAN = 7
        HSHELL_LANGUAGE = 8
        HSHELL_ACCESSIBILITYSTATE = 11
End Enum

' API Declares
Public Declare Function RegisterWindowMessage Lib "user32.dll" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Integer
Public Declare Function DeregisterShellHookWindow Lib "user32" (ByVal hWnd As IntPtr) As Integer
Public Declare Function RegisterShellHookWindow Lib "user32" (ByVal hWnd As IntPtr) As Integer

Imports System.Runtime.InteropServices

Public Class Form1
    Inherits System.Windows.Forms.Form

    Private uMsgNotify As Integer

#Region " Windows Form Designer generated code "

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

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' This will register the ShellHook event messages between the shell and our application.
        ' The uMsgNotify is then used to communicate between the shell and our application whenever any
        ' of the shell events are fired such as an app starting up, shutting down, activating, minimizing, etc
        uMsgNotify = RegisterWindowMessage("SHELLHOOK")
        ' This basically registers our window to receive the shell events
        Call RegisterShellHookWindow(Me.Handle)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg = uMsgNotify Then
            Select Case m.WParam.ToInt32
                Case ShellEvents.HSHELL_WINDOWACTIVATED
                    Debug.WriteLine("window activated")
            End Select
        End If
        MyBase.WndProc(m)
    End Sub

let me know if this helps..
Imran.
0
 

Author Comment

by:vanveghj
ID: 11817868
Imran,

WOW, THANK YOU SO MUCH!  i took 5 minutes and got this working in vb.net.  you have no idea how much i appreciate you taking the time to do this.  you're right, it does seem easier then i expected.  i am guessing others will find this code valuable too.

thanks again,
jim v.
0
 
LVL 3

Expert Comment

by:imu79
ID: 11819820
Happy to help :)
In the process, I learnt something new too :)
enjoy!
0

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you're writing a .NET application to connect to an Access .mdb database and use pre-existing queries that require parameters, you've come to the right place! Let's say the pre-existing query(qryCust) in Access takes a Date as a parameter and l…
Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, just open a new email message. In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

813 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now