How can I bring the main WPF window to the front? - wpf

How do maximize and bring a WPF mainwindow to the front of my desktop? I have a filewatcher monitoring a directory. If a new file is created in the directory I want to bring my WPF apps main window to the front of the dekstop. As you can see I have tried several methods on the mainwidnow.
Modified Code: (I am getting the following error: "The calling thread cannot access this object because a different thread owns it")
DispatcherOperation o = Dispatcher.CurrentDispatcher.BeginInvoke(new
Action(delegate
{
var win = System.Windows.Application.Current.MainWindow;
win.Activate();
win.WindowState = System.Windows.WindowState.Normal;
win.Topmost = true;
win.Focus();
}), System.Windows.Threading.DispatcherPriority.ContextIdle, null);
Debug.WriteLine("Invoke");
o.Wait();
Modified 2 (Tried getting the dispatcher of the main window. I still get " "The calling thread cannot access this object because a different thread owns it".
System.Windows.Application.Current.MainWindow.Dispatcher.Invoke(() =>
{
var win = System.Windows.Application.Current.MainWindow;
win.Activate();
win.WindowState = System.Windows.WindowState.Normal;
win.Topmost = true;
win.Focus();
}, DispatcherPriority.Normal);
UPDATE (Working)
I guess I was not calling the dispatcher tied to the mainwindow with the above examples. I ended up creating a variable called _mainWindow of type MainWindow in the window class. In the MainWindow constructor I instantiated the variable:
_mainwidow = this;
Then I pass the _mainwindow variable in the constructor of the class where I use the FileWatcher. Here I can access the dispatcher of the _mainwindow variable:
_mainWindow.Dispatcher.Invoke(() =>
{
var win = System.Windows.Application.Current.MainWindow;
win.Activate();
win.WindowState = System.Windows.WindowState.Normal;
win.Topmost = true;
win.Focus();
}, DispatcherPriority.Normal);

Try this code
Dispatcher.Invoke(() =>
{
this.Activate();
this.WindowState = System.Windows.WindowState.Normal;
this.Topmost = true;
this.Focus();
});

Related

CefSharp Offscreen example as a dynamic library called by WinForm application

I wrote a shared library which consumes CefSharp.Offscreen to do the html retrieving work. It works fine when a Console Application calls it. But when a WinForm app connects it, after tcs.TrySetResult(true) is executed, it does not jump into await browser.GetSourceAsync() as what it did in Console App.
In WinForm App, it could be successful if any UI element is not created and not in the UI constructor, but if I create a UI element before calling the shared library, it fails always.
In another way, I force calling "var source = await browser.GetSourceAsync();" to get current html source, but it still does not response in WinForm connection.
[STAThread]
static void Main()
{
// I can put the init code here, but it does not help
//CefSimpleLib.CefTest.Initialize();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
TextBox tb = new TextBox(); // this blocks below call
CefSimpleLib.CefTest cf = new CefSimpleLib.CefTest();
Application.Run(new FormMain());
//CefSimpleLib.CefTest.UnInitialize();
}
namespace CefSimpleLib
{
public class CefTest
{
public CefTest()
{
// You need to replace this with your own call to Cef.Initialize();
// Default is to use an InMemory cache, set CachePath to persist cache
Cef.Initialize(new CefSettings { CachePath = "cache" });
MainAsync();
System.Threading.Thread.Sleep(1000 * 1000);
Cef.Shutdown();
}
private async void MainAsync()
{
var browserSettings = new BrowserSettings();
//Reduce rendering speed to one frame per second, tweak this to whatever suites you best
browserSettings.WindowlessFrameRate = 1;
using (var browser = new ChromiumWebBrowser("https://www.baidu.com", browserSettings))
{
await LoadPageAsync(browser);
var source = await browser.GetSourceAsync();
await Task.Delay(10);
}
}
public Task LoadPageAsync(IWebBrowser browser)
{
var tcs = new TaskCompletionSource<bool>();
EventHandler<LoadingStateChangedEventArgs> handler = null;
handler = (sender, args) =>
{
//Wait for while page to finish loading not just the first frame
if (!args.IsLoading)
{
browser.LoadingStateChanged -= handler;
tcs.TrySetResult(true);
}
};
browser.LoadingStateChanged += handler;
return tcs.Task;
}
}
}

WPF: Exception if new EllipseGeometry() called on non UI thread

I have a WPF application that retrieves object 'movement' messages from a EasyNetQ/RabbitMQ message queue. Getting the message works fine as I can see in my logger.
private void btnSubscribeToMessageQ_Click(object sender, RoutedEventArgs e)
{
_logger.Debug("Listening for messages.");
_messageBus.Subscribe<RZMD.Messages.Movement>("test", HandleMovement);
}
Handling the message happens with:
private void HandleMovement(RZMD.Messages.Movement movementMessage)
{
_logger.Debug("Movement: {0}", movementMessage);
AddCirkelToCanvasWithDispatcher(movementMessage);
_movements.Add(movementMessage);
}
The UI is updated as follows by drawing a cirkel on the canvas:
private void AddCirkelToCanvasWithDispatcher(RZMD.Messages.Movement movementMessage)
{
var center = new Point(movementMessage.X, movementMessage.Y);
//var cirkel = new EllipseGeometry() { Center = center, RadiusX = 5, RadiusY = 5 }; <<
// above line causes exception re threads
// System.InvalidOperationException: 'The calling thread cannot access
// this object because a different thread owns it.'
Application.Current.Dispatcher.Invoke( ()=>
{
//if I put new EllipseGeometry() here all is fine
var cirkel = new EllipseGeometry() { Center = center, RadiusX = 5, RadiusY = 5 };
var path = new Path() { Stroke = Brushes.Black, Data = cirkel };
cnvFloor.Children.Add(path);
});
}
What I don't understand is why the call to var cirkel = new EllipsGeometry()... throws an exception when it is placed before the Dispatcher.
There is no problem creating the center Point object of the cirkel before the dispatcher. How is the Ellipse object different?
Is this the right (modern) approach? Or are there better tools such as 'async/await', 'TPL' or 'Parallel Linq'
Also I'm adding the movements to a collection of movements.
Should I investigate using an Observable collection and Notify events to draw the cirkel on the canvas instead?
How is the EllipseGeometry object different?
It is a System.Windows.Threading.DispatcherObject, and hence has thread affinity, i.e. unless it is frozen, it can only be accessed in the thread where it was created.
Instead of creating the EllipseGeometry inside the Dispatcher action, you may freeze it to make it cross-thread accessible:
var cirkel = new EllipseGeometry() { Center = center, RadiusX = 5, RadiusY = 5 };
cirkel.Freeze();
Application.Current.Dispatcher.Invoke(() =>
{
var path = new Path() { Stroke = Brushes.Black, Data = cirkel };
cnvFloor.Children.Add(path);
});

How to make JAWS screen reader recognize and read content of cefsharp ChromiumWebBrowser control?

I have winforms application that contains cefsharp ChromiumWebBrowser component. I want JAWS to read it's content. Now JAWS only read title of main window. Is there any way to achieve this? I tried "force-renderer-accessibility" flag but it didn't help me.
Here is the code i tried:
var settings = new CefSettings()
{
CefCommandLineArgs = { new KeyValuePair<string, string>("force-renderer-accessibility", "true") }
};
Cef.Initialize(settings, performDependencyCheck: false, browserProcessHandler: null);
Following amaitland's prompting above we found the following solution.
Disable MultiThreadedMessageLoop - you then need to periodically invoke DoMessageLoopWork as per the crude sample below.
var settings = new CefSettings()
{
MultiThreadedMessageLoop = false
};
Cef.Initialize(settings);
browser = new ChromiumWebBrowser ("https://url.com/");
var t = new Timer {Interval = 5};
t.Start();
t.Tick += t_Tick;
this.panel1.Controls.Add(browser);
}
void t_Tick(object sender, EventArgs e)
{
this.BeginInvoke((Action) (() => Cef.DoMessageLoopWork()));
}

WPF InvalidOperationException Getting MainWindow Reference

I have MainWindow, which contains an instance of DemoUI (a UserControl).
From within a class instance called DemoModule, I have a reference to DemoUI which I call _demoUI.
When I try to get a reference to the MainWindow from within DemoModule using
var parentWindow = Window.GetWindow(_demoUI);
I get this InvalidOperationException:
The calling thread cannot access this object because a different thread owns it.
Ultimately, I want to be able to update the MainWindow's progress bar's value using it's Dispatcher as follows:
var progressBar = parentWindow.FindName("ProgressBar") as ProgressBar;
progressBar.Dispatcher.Invoke(DispatcherPriority.Normal,
new DispatcherOperationCallback(o => {
progressBar.Value = Progress = args.Current;
return null;
}), null);
Update 1
public void OnProgressChanged(object sender, ProgressChangedEventArgs args)
{
Progress = Convert.ToInt32(args.Current * 100);
var progressBar = Application.Current.MainWindow.FindName("ProgressBar") as ProgressBar;
if (progressBar != null)
progressBar.Value = Progress;
}
From the code you include here it doesn't seem like you need to get the progressBar reference in order to update the ProgressBar on your _demoUI? Is there another ProgressBar on the MainWindow? Regardless, you can use the _demoUI reference to get to the dispatcher.
_demoUI.Dispatcher.Invoke(DispatcherPriority.Normal,
new DispatcherOperationCallback(o => {
_demoUI.ProgressBar.Value = Progress = args.Current;
return null;
}), null);
Or
_demoUI.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(o => {
var window = Window.GetWindow(_demoUI);
//do what you need to with the window here.
}), null);

wpf threading, thread must be STA

I have a window(say main window) with a frame which has a page in it. A button on the page opens another window(say popup window). Now i am trying to invoke a method in the main window from a button on the popup window. The method has to be multi-threaded, i had a similar solution running in windows forms but i keep getting the calling thread must be STA because many UI components require this in WPF.
The method on the page which opens the popup window modally
Scripts showStocks = new Scripts();
showStocks.ShowInTaskbar = false;
showStocks.ShowDialog();
if (showStocks.DialogResult==true)
{
Window1 wd1 = new Window1();
wd1.doneDeal();
}
Here window1 is our main window. The doneDeal method is
public void doneDeal()
{
// **Some Code**
BackgroundWorker wworks1 = new BackgroundWorker();
wworks1.DoWork += Tickes;
wworks1.RunWorkerCompleted += Tickes2;
wworks1.RunWorkerAsync();
// Page1 pg1 = frame1.Content as Page1;
//NextPrimeDelegate dd=new NextPrimeDelegate(okreport);
// pg1.addScriptBtn.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
// new NextPrimeDelegate(okreport));
//startStopButton.Dispatcher.BeginInvoke(
// DispatcherPriority.Normal,
// new NextPrimeDelegate(CheckNextNumber));
//new Thread(() => Tick(stock, rowID, exchange)) { IsBackground = false }.Start();
}
Finally the method that i am trying to run in the background
public void Tickes(object sender, DoWorkEventArgs e)
{
}
Also i want to populate a gridview from the result of the tickes method, this will be looping and running over and over in the background but periodically returning data to be added to the grid. SHould i do that in the progress update event ? Have tried a lot to wrap my head around the dispatcher and background worker in wpf but am failing to understand the STA apartment state bit. If someone can help me to get my tickes method going or point me in the right direction, i would be very very thankful.
Well i finally was able to solve the STA thread problem am posting the answer just in case somebody comes across a similar problem in the future.
public void doneDeal()
{
if (StockData.flag == 1)
{
row1 = table.NewRow();
row1[col1] = "";
row1[col2] = "";
row1[col3] = "";
row1[col4] = "";
row1[col5] = "";
row1[col6] = "";
row1[col7] = "";
row1[col8] = "";
row1[col9] = "";
row1[col10] = "";
row1[col11] = "";
row1[col12] = "";
table.Rows.Add(row1);
string stock = StockData.stock;
int rowID = (table.Rows.Count - 1);
string exchange = StockData.exchange;
Thread bh = new Thread(delegate()
{
Tick7(stock, rowID, exchange);
});
bh.SetApartmentState(ApartmentState.STA);
bh.IsBackground = true;
bh.Start();
StockData.flag = -1;
}
}
The Tick7 method which is being called is declared like this
[STAThread]
public void Tick7(string stock, int rowID, string exchange)
{
int rowNum = rowID;
int counter = -1;
deletecounter = StockData.deletecounter;
Thread.CurrentThread.Name = StockData.stock;
.
.
.
}

Resources