none
Intercepting Events in Open/Save Dialogs RRS feed

  • Question

  • Hello everybody.
    I'm developing a record/replay tool to automate tests of GUIs written in C# (WinForms) and I'm having some trouble intercepting events in the Open/Save dialogs. An important note to say that I don't have access to the application I'm testing, so I can't customize these dialogs.
    The problem is not intercepting the events themselves, but to interpret those events in order to get the path of the file to open/save. I couldn't find any information on the net about this.
    I'm able to install a Hook Procedure that is called when events on the dialog are executed, but I can't find a way to retrieve the path to the file that was selected. I've read about the OPENFILENAME struct but only from the point of view of someone that needs to customize the dialog. I can't find a way to get a reference to this structure from the events I'm intercepting.
    The hook procedure is installed with the following code:
    Win32Interop.SetWindowsHookEx(Win32Interop.WH_CALLWNDPROC, proc, IntPtr.Zero, Win32Interop.GetCurrentThreadId());
    Can anyone help on this?

    Thanks,
    José Tavares


    ---
    Automated Software Tests with TeStudio
    Monday, July 6, 2009 8:57 AM

Answers

  • When a file is selected, the dialog should send a WM_NOTIFY/CDN_FILEOK message to the owner window. lParam should contain a OFNOTIFY struct pointer from where you can get the selected file name(s).

    Mattias, C# MVP
    • Marked as answer by jpsstavares Tuesday, July 7, 2009 12:49 PM
    Monday, July 6, 2009 10:55 AM
    Moderator

All replies

  • When a file is selected, the dialog should send a WM_NOTIFY/CDN_FILEOK message to the owner window. lParam should contain a OFNOTIFY struct pointer from where you can get the selected file name(s).

    Mattias, C# MVP
    • Marked as answer by jpsstavares Tuesday, July 7, 2009 12:49 PM
    Monday, July 6, 2009 10:55 AM
    Moderator
  • Notifications are only sent when the app specified the hook procedure in the OPENFILENAME structure, not commonly done.  You cannot hook these notifications yourself, Windows makes a direct call to the user supplied function.  There is no way to find out anything about the OPENFILENAME content unless you get the app to cooperate.  You could find out something about the selected file by paying attention to the messages sent to the controls in the dialog.  This strikes me as pretty hard to do.

    Hans Passant.
    Monday, July 6, 2009 12:08 PM
    Moderator
  • Thanks for the quick reply. However I can't get this working. I've been trying since you reply me and I can't figure it out.

    This is how install the HookProcedure:
    proc2 = new Win32Interop.HookProc(DialogHookCallback);
    hookID2 = Win32Interop.SetWindowsHookEx(Win32Interop.WH_MSGFILTER, proc2, IntPtr.Zero, Win32Interop.GetCurrentThreadId());
    And this is the Hook Procedure Function:

            private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
    if (nCode < 0)
    return Win32Interop.CallNextHookEx(hookID, nCode, wParam, lParam);
    Win32Interop.CWPSTRUCT msg = (Win32Interop.CWPSTRUCT)Marshal.PtrToStructure(lParam, typeof(Win32Interop.CWPSTRUCT));
    if (msg.message == Convert.ToInt32(Win32Interop.WindowsMessages.WM_NOTIFY))
    {
    log("WM_NOTIFY");
    Win32Interop.OFNOTIFY ofNotify = (Win32Interop.OFNOTIFY)Marshal.PtrToStructure(msg.lparam, typeof(Win32Interop.OFNOTIFY));
    log(ofNotify.hdr.code.ToString());
    if (ofNotify.hdr.code == (uint)Win32Interop.DialogChangeStatus.CDN_FILEOK)
    {
    log("CDN_FILEOK");
    }
    }
    }
    I used the structure definition made in the code of this article . I'll post them here so you don't have to leave this page.
            [StructLayout(LayoutKind.Sequential)]
            public struct CWPSTRUCT
            {
                public IntPtr lparam;
                public IntPtr wparam;
                public int message;
                public IntPtr hwnd;
            }
    
            public enum DialogChangeStatus : long
            {
                CDN_FIRST = 0xFFFFFDA7,
                CDN_INITDONE = (CDN_FIRST - 0x0000),
                CDN_SELCHANGE = (CDN_FIRST - 0x0001),
                CDN_FOLDERCHANGE = (CDN_FIRST - 0x0002),
                CDN_SHAREVIOLATION = (CDN_FIRST - 0x0003),
                CDN_HELP = (CDN_FIRST - 0x0004),
                CDN_FILEOK = (CDN_FIRST - 0x0005),
                CDN_TYPECHANGE = (CDN_FIRST - 0x0006),
            }
    
            public struct NMHDR
            {
                public IntPtr hwndFrom;
                public uint idFrom;
                public uint code;
            } 
    
            [StructLayout(LayoutKind.Sequential)]
            public struct OFNOTIFY
            {
                public NMHDR hdr;
                public IntPtr OPENFILENAME;
                public IntPtr fileNameShareViolation;
            }

    The problem is that although some WM_NOTIFY messages are intercepted, none of them is a CDN_FILEOK. What am I doing wrong here?

    Thanks,
    José Tavares

    ---
    Automated Software Tests with TeStudio
    Monday, July 6, 2009 1:04 PM
  •  You could find out something about the selected file by paying attention to the messages sent to the controls in the dialog.  This strikes me as pretty hard to do.

    Hans Passant.

    Thanks for the clarification Hans. I've been trying to do this by printing all the messages and compare them, but it was working completely on the dark, that's why I wrote this post. But I guess I have to get back on the dark. I was able to get  the file path of the dialog using:

    Win32Interop.SendMessage(Win32Interop.GetParent(msg.hwnd), (int)Win32Interop.DialogChangeProperties.CDM_GETFILEPATH, (int)256, filePath);

    I guess I'm just missing the file name and know what message to use.

    José Tavares


    ---
    Automated Software Tests with TeStudio

    Monday, July 6, 2009 2:56 PM
  • hey ppl .. i have come across the same problem .. i wanted to know if anyone of you was able to crack the solution to this above mentioned problem .. i need to intercept WM_NOTIFY/CDN_FILEOK .. i have been able to hook it from the same application but i want to intercept it from another application (let say this is a monitoring application for monitoring all the files that have been opened using GetOpenFileName) .. need help .. i am not used to window api programming :( .. kindly reply urgently .. 
    Monday, May 9, 2011 4:47 PM