In a desktop application needing some serious re-factoring, I have several chunks of code that look like this:
private void LoadSettings()
{
WindowState = Properties.Settings.Default.WindowState;
Location = Properties.Settings.Default.WindowLocation;
...
}
private void SaveSettings()
{
Properties.Settings.Default.WindowState = WindowState;
Properties.Settings.Default.WindowLocation = Location;
...
}
What's the best way to replace this? Project-imposed constraints:
Visual Studio 2005
C# / .NET 2.0
Windows Forms
Update
For posterity, I've also found two useful tutorials: "Windows Forms User Settings in C#" and "Exploring Secrets of Persistent Application Settings".
I've asked a follow-up question about using this technique to bind a form's Size here. I separated them out to help people who search for similar issues.
If you open your windows form in the designer, look in the properties box. The first item should be "(ApplicationSetting)". Under that is "(PropertyBinding)". That's where you'll find the option to do exactly what you want.
Related
The issue:
We have an application written in C# that uses UIAutomation to get the current text (either selected or the word behind the carret) in other applications (Word, OpenOffice, Notepad, etc.).
All is working great on Windows 10, even up to 21H2, last update check done today.
But we had several clients informing us that the application is closing abruptly on Windows 11.
After some debugging I've seen some System.AccessViolationException thrown when trying to use the TextPatternRange.GetText() method:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
What we've tried so far:
Setting uiaccess=true in manifest and signing the app : as mentionned here https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/350ceab8-436b-4ef1-8512-3fee4b470c0a/problem-with-manifest-and-uiaccess-set-to-true?forum=windowsgeneraldevelopmentissues => no changes (app is in C:\Program Files\
In addition to the above, I did try to set the level to "requireAdministrator" in the manifest, no changes either
As I've seen that it may come from a bug in Windows 11 (https://forum.emclient.com/t/emclient-9-0-1317-0-up-to-9-0-1361-0-password-correction-crashes-the-app/79904), I tried to install the 22H2 Preview release, still no changes.
Reproductible example
In order to be able to isolate the issue (and check it was not something else in our app that was causing the exception) I quickly made the following test (based on : How to get selected text of currently focused window? validated answer)
private void btnRefresh_Click(object sender, RoutedEventArgs e)
{
var p = Process.GetProcessesByName("notepad").FirstOrDefault();
var root = AutomationElement.FromHandle(p.MainWindowHandle);
var documentControl = new
PropertyCondition(AutomationElement.ControlTypeProperty,
ControlType.Document);
var textPatternAvailable = new PropertyCondition(AutomationElement.IsTextPatternAvailableProperty, true);
var findControl = new AndCondition(documentControl, textPatternAvailable);
var targetDocument = root.FindFirst(TreeScope.Descendants, findControl);
var textPattern = targetDocument.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
string text = "";
foreach (var selection in textPattern.GetSelection())
{
text += selection.GetText(255);
Console.WriteLine($"Selection: \"{selection.GetText(255)}\"");
}
lblFocusedProcess.Content = p.ProcessName;
lblSelectedText.Content = text;
}
When pressing a button, this method is called and the results displayed in labels.
The method uses UIAutomation to get the notepad process and extract the selected text.
This works well in Windows 10 with latest update, crashes immediately on Windows 11 with the AccessViolationException.
On Windows 10 it works even without the uiaccess=true setting in the manifest.
Questions/Next steps
Do anyone know/has a clue about what can cause this?
Is Windows 11 way more regarding towards UIAutomation?
On my side I'll probably open an issue by Microsoft.
And one track we might follow is getting an EV and sign the app itself and the installer as it'll also enhance the installation process, removing the big red warnings. But as this is an app distributed for free we had not done it as it was working without it.
I'll also continue testing with the reproductible code and update this question should anything new appear.
I posted the same question on MSDN forums and got this answer:
https://learn.microsoft.com/en-us/answers/questions/915789/uiautomation-throws-accessviolationexception-on-wi.html
Using IUIautomation instead of System.Windows.Automation works on Windows 11.
So I'm marking this as solved but if anyone has another idea or knows what happens you're welcome to comment!
I have an Ionic / Cordova application hosted in the Windows UWP application, and which I am looking into swapping to host within a WPF application (latest .net, eg 6.0), and using WebView2.
Note, the Ionic/Cordova part is not really relevant to this question, this is purely related to WPF.
When running on a Tablet (eg Microsoft surface), I need to resize the app when the soft keyboard is shown, and hidden.
When in UWP, I could hook into the following events in my TypeScript file...
let w = <any>window;
const inputPane = w.Windows.UI.ViewManagement.InputPane.getForCurrentView();
if (!inputPane) {
this.logger.error('WindowsKeyboardService.hookupKeyboardHandlers: could not get inputPane');
return;
}
inputPane.addEventListener('showing', _ => this.onWindowsKeyboardUp);
inputPane.addEventListener('hiding', _ => this.onWindowsKeyboardClose);
So I won't have the WinJS any longer in the WPF, so I will do all the native in the WPF and then call into the JS myself using the appropriate API on the webview.
If I was in UWP, I could do something like the following:
System.Windows.UI.ViewManagement.InputPane.GetForCurrentView().Showing += (s, args) =>
{
GeneralTransform gt = loginButton.TransformToVisual(this);
Point buttonPoint = gt.TransformPoint(new Point(0, loginButton.RenderSize.Height - 1));
var trans = new TranslateTransform { Y = -(buttonPoint.Y - args.OccludedRect.Top) };
loginButton.RenderTransform = trans;
args.EnsuredFocusedElementInView = true;
};
But in WPF, I do not seem to have the `System.Windows.UI namespace:
Is there an equivalent way of doing this within a WPF application?
Update 1
I found this sample code
The whole solution will build in .net framework (4.7), but not in .net 6, as still missing the namespace Windows.UI. Perhaps this is renamed to something?
Update 2
I create a new WinUI project. Calling
var pane = Windows.UI.ViewManagement.InputPane.GetForCurrentView();
gives the same Element Not found error. I call this in a button click event, to give the main app/Window plenty of time to be fully initialized.
Note I am trying this out running from Visual Studio (i.e. Desktop Windows 10), and not on an actual tablet at this stage.
I this similar post where there is a comment
#LeftTwixWand ApplicationView.GetForCurrentView and CoreApplication.GetCurrentView() are only for UWP apps. For WinUI 3 desktop apps, use the Window class for some of the functionality. I'm not completely sure but some of them also now a GetForWindowId method.
It mentions using the Window class, but there is nothing on how to do what I am after here (monitoring the soft keyboard show/hide events).
Update 3
Following #Victor below, I added the code and it asks me to install
#Victor is this correct?
For WPF you just need to use net6.0-windows10.0.17763.0 target framework or newer. APIs will be available for you via existing Interop classes. Do not use System.Runtime.InteropServices.WindowsRuntime, it is .net framework approach.
IntPtr handle = new WindowInteropHelper(window).Handle;
InputPane inputPane = InputPaneInterop.GetForWindow(handle);
I'm using the TestStack.White framework for a WinForms .Net 2.0 C# application's coded automated regression tests. I have no problem handling OK/Cancel message boxes (MessageBox.Show(...)) but I'm having trouble handling the Yes/No buttons when using MessageBoxButtons.YesNoCancel. Thing is, I do not know what the button names are.
These work in my test jigs:
public ButtonTestJig OkButton
{
get { return new ButtonTestJig(Window, "okButton"); }
}
public ButtonTestJig CancelButton
{
get { return new ButtonTestJig(Window, "cancelButton"); }
}
Does anybody know the equivalent "cancelButton" for the NO button and the equivalent "okButton" for the YES button? Or perhaps even better, how to find them. My googling failed me.
Thanks
You can use http://uiautomationverify.codeplex.com/releases/view/11366 or inspect.exe (which comes in the windows SDK to see what the automation Id's for those controls are.
I have made a website using(Asp.net, c#) and its content in English.
Now i have a requirement to make this website in such a way that is support multiple languages ie (German,French).
Lable/Textbox/ string all values will display respective selected languages
While searching i came to know there are some ways like
Using localization
Use resource file.
Database(every thing is saved in database for different language).
frankly speaking I am not agree with 3rd option.
I want to know which is the best way to go or is there any other better way?
Note:Current Website was built using .NET framework 4.0/ vs 2010.
Thanks
Resx:
http://msdn.microsoft.com/en-us/library/ms227427.aspx
http://dreamdotnet.blogspot.com/2007/01/tutorial-translating-aspnet-web.html
You can use resx files for multiple languages and use the ResXResourceWrite to update them (if you want users to be able to update the files: http://msdn.microsoft.com/en-us/library/system.resources.resxresourcewriter.aspx)
This solution is only good for static content. If you want to be able to translate content from the database (for example if you have products stored in your database, and you want that the description of the product to be multilingual too). In this case you'll need to change you DB Scheme in order to support multilingual content.
PS
you can use GetLocalResourceObject("key") in order to retrieve values without using web controls.
If you're using MVC, see the following question: How to localize ASP.NET MVC application?
Sample code i have done using resource file add global.asax
void Application_BeginRequest(Object sender, EventArgs e)
{
// Code that runs on application startup
HttpCookie cookie = HttpContext.Current.Request.Cookies["CultureInfo"];
if (cookie != null && cookie.Value != null)
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(cookie.Value);
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cookie.Value);
}
else
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en");
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en");
}
}
For dynamic content a thrid party plugin or a adding something such as Google translate would do it;
http://translate.google.com/translate_tools
FYI; Google Chrome has built in auto-translate and Chrome's popularity is growing fast... wow imagine a web where regardless of language you have access to ALL content this isn't that but I though I would share my thoughts
What am I doing:
My main intent is to enable user friendly text to speech for personal use on Win 7. Approach should work in Google Chrome, VS and Eclipse.
Code example:
Following code creates global keyboard hook for ctrl + alt + space, called hookEvent. If event fires, it starts/stops speaking clipboard contents ( that can be updated with ctrl + c ).
/// <summary>
/// KeyboardHook from: http://www.liensberger.it/web/blog/?p=207
/// </summary>
private readonly KeyboardHook hook = new KeyboardHook();
private readonly SpeechSynthesizer speaker = //
new SpeechSynthesizer { Rate = 3, Volume = 100 };
private void doSpeaking(string text)
{
// starts / stops speaking, while not blocking UI
if (speaker.State != SynthesizerState.Speaking)
speaker.SpeakAsync(text);
else
speaker.SpeakAsyncCancelAll();
}
private void hookEvent(object sender, KeyPressedEventArgs e)
{
this.doSpeaking(Convert.ToString(Clipboard.GetText()));
}
public Form1()
{
InitializeComponent();
hook.KeyPressed += new EventHandler<KeyPressedEventArgs>(hookEvent);
hook.RegisterHotKey(ModifierKeysx.Control|ModifierKeysx.Alt, Keys.Space);
}
Question:
I would prefer not using the clipboard. Or at least, restoring the value after, something like:
[MethodImpl(MethodImplOptions.Synchronized)]
private string getSelectedTextHACK()
{
object restorePoint = Clipboard.GetData(DataFormats.UnicodeText);
SendKeys.SendWait("^c");
string result = Convert.ToString(Clipboard.GetText());
Clipboard.SetData(DataFormats.UnicodeText, restorePoint);
return result;
}
What are my options?
Edit:
To my surprise, I found that my clipboard reader is the best way to go. I created a notification area app, that responds to left click (speaking clipboard) and right click (menu opens up). In menu the user can chance speed, speak or create a audio file.
MS provide accessibility tools that do cover what you're trying to do. If you take a look at documents about screen scraping. In short, every component is accessible in some manner, if you use some of the windows debugging tools you can get to see the component names/structures within. You can then use that, however, its complicated as most times you would need to be very specific for each application you intend to scrape from.
If you manage to scrape you dont need to use the clipboard, as you can access the text property of the apps direct. Its not something I've had to do, hence, Ive no code to offer off the top of my head, but the term "screen scraping" should point you in the right direction.
If to expand a little on what Bugfinder said, Microsoft provider a UI Automation Framework to solve problems like the one you mentioned:
In particular you can use the TextSelectionChangedEvent of TextPattern:
The problem with this solution is that it only works on supported operating systems and applications - and not all support this.
Your clipboard solution is acceptable for applications that do not provide a good automation interface.
But for many applications the UI Automation Framework will work well and will provide you with a far better solution.