Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# - How to PostMessage to a flash window embedded in a WebBrowser?

I would like to know if there was any way to lock onto a Flash window and post a message to it? Another person here had the answer to it, his name is Spencer K. His question was: Sending simulated click via WebBrowser in C# to flash object embedded in HTML

Unfortunately, Mr. K wasn't very specific, and all he left behind for people reading his question was that he "got the handle and then iterated through the handles." I'm not extremely sure what he meant by that. I iterated through all visible handles using EnumWindows to no avail, as that did not return a window that was a flash window.

I hope somebody here could tell me, as it's been driving me mad for the past few days.

EDIT: I've just settled on inserting an SWF Object into my form and posting messages to the handle of that.

like image 922
Jc Gurango Avatar asked Jan 16 '23 22:01

Jc Gurango


2 Answers

Actually flash window has its own handle too. To get it you have to get the class names of the controls it is embedded in from Spy++, then you can reach it like this:

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
    public IntPtr Flash()
    {
        IntPtr pControl;
        pControl = FindWindowEx(webBrowser1.Handle, IntPtr.Zero, "Shell Embedding", IntPtr.Zero);
        pControl = FindWindowEx(pControl, IntPtr.Zero, "Shell DocObject View", IntPtr.Zero);
        pControl = FindWindowEx(pControl, IntPtr.Zero, "Internet Explorer_Server", IntPtr.Zero);
        pControl = FindWindowEx(pControl, IntPtr.Zero, "MacromediaFlashPlayerActiveX", IntPtr.Zero);
        return pControl;
    }

When you get the handle, you can post the clicks:

    [DllImport("user32.dll", SetLastError = true)]
    static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
    public enum WMessages : int
    {
        WM_LBUTTONDOWN = 0x201,
        WM_LBUTTONUP = 0x202
    }
    private int MAKELPARAM(int p, int p_2)
    {
        return ((p_2 << 16) | (p & 0xFFFF));
    }
    public void DoMouseLeftClick(IntPtr handle, Point x)
    {
        PostMessage(handle, (uint)WMessages.WM_LBUTTONDOWN, 0, MAKELPARAM(x.X, x.Y));
        PostMessage(handle, (uint)WMessages.WM_LBUTTONUP, 0, MAKELPARAM(x.X, x.Y));            
    }

The points will be relative to the client, so when you save them, you should save it like this:

    List<Point> plist = new List<Point>();
    private void webBrowser1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        switch (e.KeyCode)
        {
            case Keys.C:                   
                plist.Add(webBrowser1.PointToClient(Cursor.Position));                    
                break;
            default:
                break;
        }
    }

Hope this was helpful

like image 115
Kristof Kovacs Avatar answered Jan 30 '23 06:01

Kristof Kovacs


You can do it via javascript.

Import this:

import flash.external.ExternalInterface;

Ad this to your AS code:

if (ExternalInterface.available) {
   // add external interface
   ExternalInterface.addCallback("jsFunction", asFunction);
}

public static function asFunction(message:String):void {
}

On your JS object of the flash object you can call this function:

jsObject.jsFunction("message");

This is the function to get the js object of the flash object:

var InternetExplorer = navigator.appName.indexOf("Microsoft") != -1;
jsObject = InternetExplorer ? window.jsObjectName: window.document.jsObjectName;

I did not test this code, I just copied it out of a project.

edit: added js function to get js object

like image 43
Philipp Avatar answered Jan 30 '23 07:01

Philipp