open and manipulate a web form in firefox - winforms

I need to open a link from a winform application in a firefox browser. Then I would like to autocomplete the form's inputs (like username and password) and generate a button click (a login button to submit the form for instance).
I'm currently doing the same think with IE using Interop.SHDocVw.dll, but I need a firefox implementation.
Is there such a dll for the mozilla's broswer? Do I need to develop a plugin? or maybe I might have to use a UI testing framework?
thanks for the answers!
Bruno

So I start Firefox using Process start:
Process.Start("firefox.exe", "http://www.mywebsite.com");
I then use USER32.DLL to find and focus on the Firefox window:
// Get a handle to an application window.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
// Activate an application window.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
private void btnEnterText_Click(object sender, EventArgs e)
{
var handle = FindWindow("MozillaUIWindowClass", "Environnement de recette 1.4.0.3 - Mozilla Firefox");
SetForegroundWindow(handle);
SendKeys.SendWait(txtEntry.Text);
}
I found the window's class and title thanks to spy++.
So my problem no is to move to the next input on the page... when I use this:
SendKeys.SendWait("{TAB}");
it moves the focus as is I pressed TAB 2 times.... Does anyone knows what's happening ?

Related

Wpf webbrowser disable external links

elI am working on a Wpf application. it contains a webbrowser where the user authenticates via Facebook. The problem is that the user is capable of clicking on links (for example: Forgot your password?) the standaard browser then open... what i want to do is to disable/block all the external links. so users can only authenticate and not navigate through the webbrowser control. I hoop you guys can help me out.
Update 1
Like suggested i can check the source of the webbrowser. So i can allow the wanted pages. but the problem are the links. they open on IE. i dont want to open them, but to block them at all
Description image
private void webBrowserFacebook_Navigating_1(object sender, NavigatingCancelEventArgs e)
{
string huidigeLink = Convert.ToString(webBrowserFacebook.Source);
MessageBox.Show(huidigeLink);
// check for allowed pages
}
Update 2
I was able to find a solution: http://social.technet.microsoft.com/wiki/contents/articles/22943.preventing-external-links-from-opening-in-new-window-in-wpf-web-browser.aspx
Very slef explanatory.. thank you guys for the help!
void Window1_Loaded(object sender, RoutedEventArgs e)
{
browser = new WebBrowser();
browser.Navigate(new Uri("http://www.google.com"));
browser.Navigating += new NavigatingCancelEventHandler(browser_Navigating);
browser.Navigated += new NavigatedEventHandler(browser_Navigated);
}
void browser_Navigating(object sender, NavigatingCancelEventArgs e)
{
//Your checks should happen here..
Console.WriteLine("Loading Webpage !!");
}
void browser_Navigated(object sender, NavigationEventArgs e)
{
Console.WriteLine("Webpage Loaded !!");
}
You can register for WebBrowser.Navigating Event.
Navigating event handlers are passed an instance of the NavigatingCancelEventArgs class. You can cancel the navigation by setting the Cancel property of the NavigatingCancelEventArgs object to true.
Or you can invoke script or browser instance to stop loading if URL navigating doesn't matches.
yourWebBrowser.InvokeScript("eval", "document.execCommand('Stop');");

Wpf and Hwnd unique name

we have a wpf application that should be 'piloted' by a legacy win32 winform application. (We don't own the code ;) )
The legacy application should pilot our application (minimize, bring to front, shut, etc) via windowsclass name we should provide as a configuration parameter written into an ini file.
The problem is we cannot make it work with wpf since if we insert the classname Spy++ gives us, nothing happens. The point is Spi++ returns something like this
HwndWrapper[MyWpfProgram.exe;;16978ce2-3b8d-4c46-81ee-e1c6d6de4e6d]
where the guid is randomly generated at every run.
Is there any way to solve this issue?
Thank you.
There is no way to do what I asked. But we found a walkaround. "Simply" embedding the xaml windows within a windows form.
These are the steps we followed:
1 - Add a Windows Form to the project.
2 - Remove the app.xaml and make the new form the entry point of the application.
3 - Since we need the hwnd of the main.xaml we added this prop to its code behind
public IntPtr Hwnd
{
get { return new WindowInteropHelper(this).Handle; }
}
4 - then from the constructor of the form we create an instance of the wpf window class
private Main app;
public ContainerForm()
{
InitializeComponent();
app = new Main();
ElementHost.EnableModelessKeyboardInterop(app);
}
we needed
ElementHost.EnableModelessKeyboardInterop(app);
since we want all the keyboard input to pass from the the windows form to the xaml window
5 - now we want to bond the xpf window to the winform. In order to do that we need to use Windows Api and we do it at the OnShow event of the form (the reason why will be explicated later).
[DllImport("user32.dll", SetLastError = true)]
private static extern long SetFocus(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
[DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)]
private static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);
private const int GWL_STYLE = (-16);
private const int WS_VISIBLE = 0x10000000;
private void ContainerForm_Shown(object sender, EventArgs e)
{
app.Show();
SetParent(app.Hwnd, this.Handle);
SetWindowLong(app.Hwnd, GWL_STYLE, WS_VISIBLE);
MoveWindow(app.Hwnd, 0, 0, this.Width, this.Height, true);
SetFocus(app.Hwnd);
}
with
SetParent(app.Hwnd, this.Handle);
wo do the magic, then with
SetWindowLong(app.Hwnd, GWL_STYLE, WS_VISIBLE);
we remove al the chrome from the wpf window (there is a border even if the window is defined borderless, don't ask me why)
then we make the wpf window fill all the client area of the winform
MoveWindow(app.Hwnd, 0, 0, this.Width, this.Height, true);
and then we focus the wpf window
SetFocus(app.Hwnd);
that's the reason why we do everything in the show event. Since if we do it at form's constructor, then the wpf window will loose its focus since the in winform the main window got the focus from the operating system.
We didn't understand why we needed to add the other api calls at this point, but if we left them at constructor's the trick didn't work.
Anyway,
problem solved ;)
Use HwndSource.
You can use native Windows API calls to create a window with the expected classname, then use HwndSource to add WPF content to it:
var source = HwndSource.FromHwnd(nativeWindowHandle);
source.RootVisual = mainGrid;
If you need to use a WPF window, I think you could still solve this with a "proxy" window, but it wouldn't be pretty:
Have your WPF application spawn a native message-only window.
Use HwndSource.AddHook to handle messages like WM_CLOSE, WM_SIZE on the native window and pass them along to the "real" WPF window.
For the window handles, titles, and class names, Spy++ uses fairly simple Windows APIs.
FindWindowEx http://msdn.microsoft.com/en-us/library/windows/desktop/ms633500%28v=vs.85%29.aspx
EnumWindows http://msdn.microsoft.com/en-us/library/windows/desktop/ms633497%28v=vs.85%29.aspx
GetClassName http://msdn.microsoft.com/en-us/library/windows/desktop/ms633582%28v=vs.85%29.aspx
You can create a "loader" program that will...
Start the wpf app
Use the above APIs to get the proper class names and windows handles
Edit the legacy INI
Start the legacy app

Navigate back button with ssrs in Silverlight app

I have a Silverlight application which has a RadHtmlPlaceholder which points to ssrs to display reports like so:
<telerik:RadHtmlPlaceholder SourceUrl="http://serverName/ReportServer/Pages/ReportViewer.aspx?/Northwind/Employees&rs:Command=render" />
This works fine but when I have a report that allows you to drill down to display a child report, there is no way of getting back to the parent report without having to load the whole lot again. There doesn't seem to be an option to turn on the navigate back button toolbar option and I've seen other ways of implementing a back button by using javascript to set the window location back one in the history, but obviously this won't work in a Silverlight application. Is there anyway to implement a navigate back button?
Take a look at this thread over in the Telerik forums: http://www.telerik.com/community/forums/silverlight/htmlplaceholder/html-place-holder-back-forward-refresh.aspx
Basically you need to get a handle on the IFrame from the presenter and inject some JavaScript. The history object also has a length property you can use to evaluate if your buttons should be enabled.
public MainPage()
{
InitializeComponent();
// Get the IFrame from the HtmlPresenter
HtmlElement iframe = (HtmlElement)htmlPlaceholder.HtmlPresenter.Children[0];
// Set an ID to the IFrame so that can be used later when calling the javascript
iframe.SetAttribute("id", "myIFrame");
}
private void Refresh_Click(object sender, RoutedEventArgs e)
{
// Code to be executed
string code = "document.getElementById('myIFrame').contentWindow.location.reload(true);";
HtmlPage.Window.Eval(code);
}
private void Back_Click(object sender, RoutedEventArgs e)
{
// Code to be executed
string code = "document.getElementById('myIFrame').contentWindow.history.back();";
HtmlPage.Window.Eval(code);
}
private void Forward_Click(object sender, RoutedEventArgs e)
{
// Code to be executed
string code = "document.getElementById('myIFrame').contentWindow.history.forward();";
HtmlPage.Window.Eval(code);
}
}

How can I set the focused control after a Dialog Box?

I'm working on an XBAP app where Users primarily use the Keyboard for Navigation. When I display a MessageBox, I can hit Enter to close it but then the main application doesn't seem to regain focus. I have to manually click the mouse on the screen to put focus back on the application.
Is there a way around this?
Edit
I can verify that the app still has Logical Focus, but it just doesn't have Keyboard Focus
I found a hack that works, although I don't like it because I feel it ties my Views to my ViewModel
I'm using an IsFocused AttachedProperty to bind a control to a boolean property behind the View. The same View is also subscribing to a DisplayError event that displays a MessageBox error and reset the IsFocused property afterwards so it updates the UI. Last change made was to update my ViewModels to publish errors to the EventAggregator instead of handling themselves with a MessageBox, which is probably better anyways.
I suppose it works, even if I don't like it
Not sure if this will help your situation but in my circumstance it was ok for me to set focus back to main window, which was able to be accomplished with
App.Current.MainWindow.Focus();
Just be sure main window is properly initialized, which may not be the case if a splash screen or some login window or something initially grabbed the main window role (ie by StartupUri) and then nothing else was updated thereafter.
This worked for me since I was handling all keyboard events at the main window level to drive updates to my view model.
using System.Runtime.InteropServices;
using System.Windows.Interop;
public class Interop
{
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
public static IntPtr GetWindowHandle(Window window)
{
return new WindowInteropHelper(window).Handle;
}
}
// In main window, when the MessageBox is closed
IntPtr window = Interop.GetWindowHandle(this);
IntPtr focused = Interop.GetForegroundWindow();
if (window != focused)
{
Interop.SetForegroundWindow(window);
}
http://tech.avivo.si/2009/11/how-to-focus-window-in-wpf-when-it-gets-out-of-focus/

RTF with Links in a RichTextBox WPF

I am able to load an rtf document in a RichTextBox, but the links that the document contains to some websites are not working.
Anyone have any idea why? Some solution to make the links work?
Best regards,
Paulo Azevedo
WPF by default doesn't understand where you want the links to be displayed, so what's happening is that the Hyperlink class is firing an event, RequestNavigate, and expecting you, the application designer, to cause the actual navigation to occur.
I assume you just want to launch the system configured web browser, so here's all you need to do:
Hook the Hyperlink::RequestNavigate routed event
Call Process.Start with the URL you receive to have the OS launch the browser.
That might look a little something like this:
public class MyWindow : Window
{
public MyWindow()
{
this.InitializeComponent();
this.myRichTextBox.AddHandler(Hyperlink.RequestNavigate, MyWidow.HandleRequestNavigate);
}
private static void HandleRequestNavigate(object sender, RequestNavigateEventArgs args)
{
Process.Start(args.Uri.ToString());
}
}

Resources