I am building a Mac app in Xamarin and have a need to send keystrokes (with words and phrases) to other applications. Something like SendKeys in .Net on Windows.
Is there a SendKeys equivalent API for Mac in Xamarin?
CGEventCreateKeyboardEvent is what you are looking for, it is Quartz-based and thus a low-level C API.
Xamarin has a shim-wrapper over it via an CGEvent .ctor. After you create the event, include any-keyboard modifiers (shift/apple/alt/....), you can Post it to a process id of your choosing.
Really quick example that sends stackoverflow to active process/window.
using (var eventSource = new CGEventSource(CGEventSourceStateID.HidSystem))
{
var eventString = "StackOverflow";
foreach (var eventChar in eventString)
{
// 🍣 my most favorite Enum.Parse line ever written 🍣
var key = (ushort)(NSKey)Enum.Parse(typeof(NSKey), eventChar.ToString().ToUpper());
using (var keyEvent = new CGEvent(eventSource, key, true))
{
CGEvent.Post(keyEvent, CGEventTapLocation.HID);
}
}
}
Note: To see it in action, place a Task.Delay before it, run it and then switch to/activate an editor, maybe Visual Studio for Mac :-) and let it type into the active editor panel.
FYI: You might want to refer to the Xamarin wrapper/source code for CGEvent.cs, as their naming is not vary ObjC or Swift friendly in terms of be able from translate Apple docs to Xamarin.Mac code.
Re: xamarin-macios/src/CoreGraphics/CGEvent.cs
Related
I am trying to automate button presses for a desktop application on Windows 7 - 10. I have been able to do this using AutoHotKey and PowerShell. However, I have had the following issues:
The controls I am trying to click do not have text that I can use to
isolate the control
The ClassNN name for the components is not
static
I have looked through the MSDN documentation for the System.Windows.Automation namespace, but the documentation doesn't provide actual examples or describe how to use the namespace.
Question
If I always have a window handle (HWND) and an Automation ID for a control, how do I invoke a button press on the control using AutoHotKey, PowerShell(3.0+), or C#?
You can do it with C# and System.Windows.Automation.
First of all get your control as an AutomationElement (let's call it thiselement).
Then you can invoke InvokePattern to perform click action.
InvokePattern ip;
ip = thiselement.GetCurrentPattern(InvokePattern.Pattern) as
InvokePattern;
ip.Invoke();
Suppose your window handle is 'handle' and automation id of the button is 'automationId' then you can do something like
AutomationElement parentWin = AutomationElement.FromHandle(handle);
Condition c1 = new PropertyCondition(AutomationElement.AutomationIdProperty,
automationId);
AutomationElement thiselement = parentWin.FindFirst(TreeScope.Descendants, c1);
once you get the button object,just invoke the InvokePattern .Please forgive the foramatting of text
I'm trying to use System.AppDomain.CurentDomain.ApplicationExit += new System.EventHandler(SomeFunction); to call the function SomeFunction when the application closes. In this case Unity 3D. But it doesn't work. I have no idea why. It is an editor script and is not an instance (static). What do you think I'm doing wrong?
There is no OnApplicationQuit method for Windows. According to the official documentation:
On Windows Store Apps and Windows Phone 8.1 there is no application quit event. Consider using OnApplicationFocus event when focusStatus equals false.
Therefore, instead of checking whether or not the application closed, you'll want to check whether or not the application obtained or lost focus.
In C#:
void OnApplicationFocus(bool focus)
{
if (!focus)
{
//Do something
}
}
The documentation does not explicitly mention it, but it can be assumed OnApplicationQuit is intended for Android only as iOS also does not support it.
You could use
function OnApplicationQuit() {
//put script in here
}
So that before the application quits it calls that function and does what ever is in the { and }
I've Followed a tutorial on getting ironruby up and running and that works great. However when I try to delve a little deeper, like using button click events I get this error;
Could not load type 'System.Reflection.Emit.ModuleBuilder' from assembly 'mscorlib, Version=3.7.0.0, Culture=neutral, PublicKeyToken=969DB8053D3322AC'.
And my MainPage.rb
include System
include System::Windows
include System::Windows::Controls
# Set the titles
Phone.find_name("ApplicationTitle").text = "this is the application title"
Phone.find_name("PageTitle").text = "and page title here"
# Create a new button and add to page
button = Button.new
button.content = "Click Me"
Phone.find_name("ContentPanel").children.add(button)
button.click do |s,e| # breaks here
MessageBox.show("Button Click Works!")
end
Is it currently posisible to build professional apps with ironruby?
The issue with using dynamic languages on Windows Phone 7 is it's omission of the System.Reflection.Emit implementation. However, IronRuby is able to run most code through it's interpreter, rather than emitting IL, which makes it possible to run in Windows Phone 7. However, things like subclassing CLR types and implementing interfaces require emitting IL, so those .NET interop features will not be functional on Windows Phone 7.
For your specific example, instead of using a block, try using a method:
def on_button_click(s, e)
MessageBox.show("Button Click Works!")
end
button.click.add(method(:on_button_click))
However, if this is not working for you, please submit an issue.
Probably BUT I personally think the only way to do a professional job is using the native OS. That way you have the most power of what you have to do
I used the VS 2010 SDK to create and show a custom ToolWindowPane with a WPF control as content. I create a new instance and show it each time a Tool menu item is clicked (the ProvideToolWindow attribute has MultiInstances = true).
When the user attaches the debugger (e.g., hits F5 while in C# project) my ToolWindowPane suddenly hides. I'd like to make sure my tool window is always visible while open, no matter what context the user is in. Is there a way I can enforce that?
I've tried using the ProvideToolWindowVisibility attribute but that automatically shows a new instance of my tool window rather than keeping a remaining one open.
For VS 2010 SDK Microsoft added a new flag __VSCREATETOOLWIN2.CTW_fDocumentLikeTool
You can use this way:
public override void OnToolWindowCreated()
{
IVsWindowFrame windowFrame = Frame as IVsWindowFrame;
object varFlags;
windowFrame.GetProperty((int)__VSFPROPID.VSFPROPID_CreateToolWinFlags, out varFlags);
int flags = (int)varFlags | (int)__VSCREATETOOLWIN2.CTW_fDocumentLikeTool;
windowFrame.SetProperty((int)__VSFPROPID.VSFPROPID_CreateToolWinFlags, flags);
}
This way Tool Window persist open at "Document Well" when you go Debugging
However I have to say this give us some problems when debugging projects, avoiding us to open code files while debugging, like if Visual Studio document management was 'block', there are not so much information for this new flag...
So we preferred to hook to EnvDTE.DebuggerEvents and show the ToolWindow if hide when a debugging session start...
(our ToolWindow has MultiInstances = false)
Implement QueryShowTool
public:
int QueryShowTool(Guid % rguidPersistenceSlot, System::UInt32 dwId, [Runtime::InteropServices::Out] int % pfShowTool);
Enables the VSPackage to control whether to show or hide the tool
window. The shell calls this method when the user switches views or
contexts, for example Design, Debugging, Full Screen.
See https://learn.microsoft.com/en-us/visualstudio/extensibility/opening-a-dynamic-tool-window?view=vs-2017
In an Win/IE environment with the right settings you can fire up a .exe file.
The following code runs fine to fire up Microsoft Lync (the new name for Office Communicator).
...
start chat
</body>
</html>
<script type="text/javascript">
function fnShellExecute()
{
var objShell = new ActiveXObject("shell.Application");
objShell.ShellExecute("communicator.exe", "", "C:\Program Files (x86)\Microsoft Lync", "open", 10);
}
</script>
But I can't work out the parameters (or if it is possible) to create a shortcut that would open the Lync client with the chat box to another available user open. Basically I know who is available and I want to be able to create (in HTML) a simple link that would open a chat window to that person (outside of WPF or Silverlight or any of the built in controls).
Does anyone know how to adjust this line in the javascript to open a Lync chat window to a specified contact?
objShell.ShellExecute("communicator.exe", "", "C:\Program Files (x86)\Microsoft Lync", "open", 10);
Or if there is another way to open Lync in chat mode via some kind of shortcut?
Thank you in advance.
Depending on your requirements, the easiest will be to use the existing NameCtrl persona menu - this is the pop-up menu that gets displayed in SharePoint (and other web-based apps like Dynamics CRM) when hovering over a users presence icon. This menu allows you to call the user, start a new conversation etc. You'd need Office installed on the machine you are running on in order for it to work.
As an example, try this on any client machine running Office 2007/2010 and IE. Hover over the "Your Contact" text to see the persona menu:
<script>
var sipUri = "your.contact#your.domain.com";
var nameCtrl = new ActiveXObject('Name.NameCtrl.1');
if (nameCtrl.PresenceEnabled)
{
nameCtrl.OnStatusChange = onStatusChange;
nameCtrl.GetStatus(sipUri, "1");
}
function onStatusChange(name, status, id)
{
// This function is fired when the contacts presence status changes.
// In a real world solution, you would want to update an image to reflect the users presence
alert(name + ", " + status + ", " + id);
}
function ShowOOUI()
{
nameCtrl.ShowOOUI(sipUri, 0, 15, 15);
}
function HideOOUI()
{
nameCtrl.HideOOUI();
}
</script>
<span onmouseover="ShowOOUI()" onmouseout="HideOOUI()" style="border-style:solid">Your Contact</span>
If the NameCtrl answer doesn't meet your requirements, you could try the Lync SDK. It would be pretty straightforward to create a .NET DLL that uses the Automation API to open a conversation with a given user.
You would then need to expose this via COM to ensure it could be called from JavaScript. Again, pretty straightforward using .NET's COM Interop features.