GTK# File Chooser Non Native Look on OSX - c#

I have C# App using the Mono Framework and GTK UI running on Mac.I have problems regarding the look and feel of the Filechooser dialog.As per gtk https://developer.gnome.org/gtk3/stable/GtkFileChooserDialog.html I should get these icons
But what i get is this one without proper icons in the left hand panel or icons of the drives.For drives there a folder named Volumes and the user needs to open it manually.I think that is not a native Mac user expects.I have posted 2 screenshots obtained from the web.
I have this GTK Version(2.2) Bundled with Mono for Mac.What should i do to get a more native look and feel? Please advice

You can use either the older open-source MonoMac or the newer Xamarin.Mac to open a NSOpenPanel and use the native OS-X file selector instead of the xplat based GTK 2 version.
Mixing MonoMac dialogs on top of GTK# is possible as long as you remember to initialize the application via the MonoMac static method NSApplication.Init(). Do this earlier in the application startup, but after GTK# initializes.
As for opening the native NSOpenPanel, here is an example used within a GTK# Button click handler:
button.Clicked += (object sender, EventArgs e) => {
Application.Invoke (delegate {
var nsOpenPanel = new NSOpenPanel ();
nsOpenPanel.ReleasedWhenClosed = true;
nsOpenPanel.Prompt = "Select file";
var result = nsOpenPanel.RunModal ();
if (result == 1) {
button.Label = nsOpenPanel.Url.ToString ();
}
});
};
Note: It is always wise to wrap the calls within an Application.Invokedelegate so everything is executed on the main GTK UI thread.

Related

UIAutomation throws AccessViolationException on Windows 11

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!

How to hook into Soft keyboard 'showing' and 'hiding' events in a WPF application running on Windows 10 (tablet)

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);

Mono WebBrowser control on Linux

I'm writing an application that I would like to have run under either Windows or Linux. Since it is a text application, the obvious choice for rendering and user interaction is to use html in a WebBrowser control. This all works great using Mono in Windows, but I'm absolutely stumped on how to get it to work using Mono in Linux. I'm running Linux Mint 17, have MonoDevelop and Firefox installed. The following code snippet compiles and runs, but when the application launches, wbMain does not show up. The application dies when trying to render an html string using wbMain.
private System.Windows.Forms.Panel pnlMain;
private Mono.WebBrowser.IWebBrowser wbMain;
private System.Windows.Forms.Button btnGo;
this.pnlMain = new System.Windows.Forms.Panel();
this.wbMain = Mono.WebBrowser.Manager.GetNewInstance();
this.wbMain.Activate();
this.btnGo = new System.Windows.Forms.Button();
this.pnlMain.SuspendLayout();
this.SuspendLayout();
//
// pnlMain
//
this.pnlMain.Controls.Add((System.Windows.Forms.Control)this.wbMain.Window);
this.pnlMain.Controls.Add(this.btnGo);
this.pnlMain.Location = new System.Drawing.Point(12, 1);
this.pnlMain.Name = "pnlMain";
this.pnlMain.Size = new System.Drawing.Size(260, 248);
this.pnlMain.TabIndex = 0;
//
// wbMain
//
this.wbMain.Resize(260, 216);
this.wbMain = Mono.WebBrowser.Manager.GetNewInstance();
The problem lies with your GetNewInstance() from what I understand here. GetNewInstance assumes platform of Windows by default, you need to pass in your own Mono.WebBrowser.Platform for it to render in the framework you want (like Gtk).
Source Code
You can see in the source code I linked, the default GetNewInstance() returns Platform.Winforms;
public static IWebBrowser GetNewInstance ()
{
return Manager.GetNewInstance (Platform.Winforms);
}
Also Mono.WebBrowser has been retired in favor of WebkitSharp. You really should be using WebkitSharp to do this now. WebkitSharp has had...some issues, so there's a currently open version of it called open-webkit-sharp that may work for you as well. The code on there is at least up to date as of 2012. Whereas Mono WebBrowser and webkit-sharp haven't had any major code changes...in years, at least 5 to 7 years.
I've also had good luck with the open version of Awesomium, and it's a staple of the gaming industry. Again, the open version of Awesomium hasn't had any major updates since 2012 though. However, you can get the paid version of Awesomium if money/cost isn't an issue and that has had recent updates.

How can I send input to Visual Studio using Windows API

I am trying to develop a util (using system-hook) for that works like an expander (user selects some text and presses a hotkey and it is expands). It should work with Visual Studio.
I want to implement this using Windows API because I want to develop an app that works globally with any application (whether you're using VS, or wordpad, you should get the same functionality).
I've been able to do this successfully with notepad, wordpad, etc. using EM_ GETSEL and EM_REPLACESEL messages. But these APIs are not working with Visual Studio, or ms word.
What APIs should I use to be able to
1. Detect what text is selected.
2. Send input to the editor.
I am programming in C#. If you must know what I am trying to do... I am trying to make a universal port of ZenCoding that works on any editor. So all help will be appreciated.
For part 2 you could try using Windows Input Simulator which is an open source project I've just released to Codeplex to wrap the Win32 SendInput. Instead of SendKeys which just simulates text input, you can actually simulate real key strokes and complex chords to the active window.
In your case, if the user can perform the task with the Keyboard, this project will help you, otherwise you'd need to find another solution.
Hope this helps.
Why don't you use a System.Windows.Forms.SendKeys class for simulating keyboard input from user?
You can use:
SendKeys.SendWait("^C"); //CTRL+C
var selectedText = Clipboard.GetText();
var newText = Replace(selectedText);
SendKEys.SendWait("^V"); //CTRL+V
You can use WPF's Automation functionality, encapsulated in these two namespaces:
System.Windows.Automation
System.Windows.Automation.Provider
As an example, this is a method for finding an automation target element (e.g. a typical win control):
public static AutomationElement FindElement(AutomationElement context, PropertyCondition[] conditions)
{
// if no conditions, there's no search to do: just return the context, will be used as target
if (conditions == null)
{
return (context);
}
// create the condition to find
System.Windows.Automation.Condition condition = null;
if (conditions.Length <= 0)
{
throw (new ArgumentException("No conditions specified"));
}
else if (conditions.Length == 1)
{
condition = conditions[0];
}
else
{
AndCondition ac = new AndCondition(conditions);
condition = ac;
}
// find the element
CacheRequest creq = new CacheRequest();
creq.TreeFilter = Automation.ControlViewCondition;
using (creq.Activate())
{
AutomationElement e = AutomationContext(context);
AutomationElement target = e.FindFirst(TreeScope.Subtree, condition);
return (target);
}
}
Whatever you try, be absolutely sure to try it, ASAP, with Visual Studio 2010 beta 2. The editor has largely been rewritten, and hacks that work with an earlier version should be tested again.

Is it possible to open a PDF inside a c# application with Acrobat.dll?

I know that I can display a PDF file in my c# executable (not web app) with:
private AxAcroPDFLib.AxAcroPDF axAcroPDF1;
axAcroPDF1.LoadFile(#"somefile.pdf");
axAcroPDF1.Show();
But that is the regular pdf viewer like in the browser. I don't want that. I want full Adobe Standard or Professional functionality in my C# application using the Adobe controls. For example, if I use the code above, it loads in the C# app and I can see the adobe toolbar (print, save, etc.) But it is useless to me because I need things like save which cannot be done with the activex viewer above. Specifically, you cannot save, just as you cannot within the broswer.
So, I referenced the acrobat.dll and am trying to use:
Acrobat.AcroAVDocClass _acroDoc = new Acrobat.AcroAVDocClass();
Acrobat.AcroApp _myAdobe = new Acrobat.AcroApp();
Acrobat.AcroPDDoc _pdDoc = null;
_acroDoc.Open(myPath, "test");
pdDoc = (Acrobat.AcroPDDoc)(_acroDoc.GetPDDoc());
_acroDoc.SetViewMode(2);
_myAdobe.Show();
It opens adobe acrobat but it opens it outside of my c# application. I need it to open in my c# application like the activex library does. Can it be done with these libraries?
If I cannot open it in my c# application I would like to be able to "hold" my c# app tied to it so the c# app knows when I close the adobe app. At least that way I'd have some measure of control. This means I would hit open, the adobe app opens. I close the adobe app, my C# app is aware of this and loads the newly changed doc with the activex library (because I don't need change ability anymore, just displaying.)
I have the full versions of adobe acrobat installed on my computer. It is not the reader.
Thank you for any help.
edit:
There is an example in vb in the adobe acrobat sdk. I believe it is called activeview.
you can check out ABCpdf. I dont know if it has this capability but we have used it for several of our apps
Using a webbrowser control would be an option to display the content.
IText# may help you out.
You can create PDF's and I believe you can use it to read and modify them.
As for displaying in the app..... I am not sure how to display them with iText or if it is possible (have not tried this yet), sorry. iText does let you convert to RTF which may be one approach.
Best option is to write a listener which tells your calling code when Adobe.exe is no longer running. Something like the following (with tweaks for your uses) should work:
public void Open(string myPath)
{
Acrobat.AcroAVDocClass _acroDoc = new Acrobat.AcroAVDocClass();
Acrobat.AcroApp _myAdobe = new Acrobat.AcroApp();
Acrobat.AcroPDDoc _pdDoc = null;
_acroDoc.Open(myPath, "test");
_pdDoc = (Acrobat.AcroPDDoc) (_acroDoc.GetPDDoc());
_acroDoc.SetViewMode(2);
_myAdobe.Show();
NotifyAdobeClosed += new EventHandler(Monitor_NotifyAdobeClosed);
MonitorAdobe();
}
private void Monitor_NotifyAdobeClosed(object sender, EventArgs e)
{
NotifyAdobeClosed -= Monitor_NotifyAdobeClosed;
//Do whatever it is you want to do when adobe is closed.
}
private void MonitorAdobe()
{
while(true)
{
var adcount = (from p in Process.GetProcesses()
where p.ProcessName.ToLower() == "acrobat"
select p).Count();
if (adcount == 0)
{
OnNotifyAdobeClosed();
break;
}
}
}
public event EventHandler NotifyAdobeClosed;
public void OnNotifyAdobeClosed()
{
if (NotifyAdobeClosed != null)
NotifyAdobeClosed(this, null);
}

Categories