Solved

RegisterShellHookWindow to find handle of newly opened dialog.

Posted on 2009-05-14
6
1,464 Views
Last Modified: 2012-05-07
I have an app that is essentially using the same code as in the refernce question

I've used both: HSHELL_WINDOWACTIVATED and HSHELL_WINDOWCREATED to attempt to detect when a new window is created.  It works but only seems to detect main applications threads and not any dialog windows that may be created.  How would I go about modifying this to display the dialog windows or child windows of the main thread?
This behaviour can be duplicated by opening outlook and then opening messages or new message windows.  They always display the same handle.  I also made my own vb.net app, that just spawns new forms and the WINDOWCREATED event doesn't even get detected.
Imports System.Runtime.InteropServices
 
Public Class Form1
    Inherits System.Windows.Forms.Form
 
    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
 
    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
    Public Declare Function GetForegroundWindow Lib "user32" () As IntPtr
    Public Declare Function SetForegroundWindow Lib "user32" Alias "SetForegroundWindow" (ByVal hWnd As IntPtr) As Integer
 
    Private uMsgNotify As Integer
    Private lastWindow As IntPtr
 
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        uMsgNotify = RegisterWindowMessage("SHELLHOOK")
        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_WINDOWCREATED
                    Dim curWindow As IntPtr = GetForegroundWindow()
                    Debug.WriteLine("Window Created: " & curWindow.ToString)
            End Select
        End If
        MyBase.WndProc(m)
    End Sub
 
    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        DeregisterShellHookWindow(Me.Handle)
    End Sub
 
End Class

Open in new window

0
Comment
Question by:Pber
  • 3
  • 3
6 Comments
 
LVL 39

Expert Comment

by:abel
ID: 24390418
Well, that seems correct. Reading up on this shows (ms documentation aboutRegisterShellHookWindow):

The event messages received are only those sent to the Shell window associated  with the specified window's desktop.
which means: only the main windows, because they become children of the shell window (desktop). What you need instead is the SetWindowsHookEx function, which you can set the moment the main window is created. Here's an example of using that function as a keyboard hook to illustrate the process, but the idea is the same, you need WH_CALLWNDPROC I think: http://www.pinvoke.net/default.aspx/user32/SetWindowsHookEx.html


0
 
LVL 39

Accepted Solution

by:
abel earned 500 total points
ID: 24390460
Yes, that appears to be right. And then you need to filter for WM_CREATE. So, the procedure becomes as follows:

- your current hook
- whenever a main window is created, you cal SetWindowsHookEx
- you monitor (first param) for WH_CALLWNDPROC (messages before they arrive in the window proc)
- you react on any WM_CREATE. The rest you leave
- always call CallNextHookEx

0
 
LVL 26

Author Comment

by:Pber
ID: 24395357
Thanks for the reply, I have a load of meetings today, so I'll poke at this when I have some free time.  I'm not that experienced with windows hooking, so I'll see how it going.
Ultimately what I'm trying to do is create a systray application that will monitor window creation (in this case, dialogs from other apps) and if specific dialog pops up (based on the WindowText) I reposition the window to a certain location on the screen.  I have everything else working, I just want a way of making it happen on window creation.
0
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.

 
LVL 26

Author Comment

by:Pber
ID: 24435599
Sorry 4 not getting back sooner.  Turns out "we" don't feel comfortable enough with the stability of our 3rd party application and the hook chain involved in this solution.  
Anyhow, thanks for the solution.  I will likely put it to use on other projects of mine.
(:
 
0
 
LVL 26

Author Closing Comment

by:Pber
ID: 31581709
Thanks again.
0
 
LVL 39

Expert Comment

by:abel
ID: 24436655
Ok, that's understandable, I may not have gone for it myself either if I had the choice. Tx for the points :)
0

Featured Post

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.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
VB 6 error 5 in windows 10 but not in XP 7 55
fso.FolderExists("\\server\HiddenFolder$") 4 64
C# Single Form 8 42
RLDC Reporting in Visual studio 11 13
Enums (shorthand for ‘enumerations’) are not often used by programmers but they can be quite valuable when they are.  What are they? An Enum is just a type of variable like a string or an Integer, but in this case one that you create that contains…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…

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

15 Experts available now in Live!

Get 1:1 Help Now