System.Windows.Clipboard and MS Office applications - wpf

I am currently using System.Windows.Clipboard to: set some text, call SendInput with control+V, finally restoring the previous clipboard.
This works in most applications, though in Microsoft's Office applications the send input is causing the previous clipboard to be restored. I am assuming it is something to do with a delay in the SendInput method, so I added a wait before restoring and resolved the issue for most users, but Outlook for a user is still restoring the previous clipboard.
is there a better way of doing it than below?
try
{
//method that uses GetDataObject and stores it to be restored
_clipboard.Acquire();
try
{
_clipboard.SetText(ClipboardText);
//a wrapper for SendInput()
SendInputWrapper.SendKeyCombination(new KeyCode(VirtualKeyShort.Control),
new KeyCode(VirtualKeyShort.KeyV));
}
finally
{
//without this pause word and outlook would paste the original clipboard
await Task.Delay(TimeSpan.FromMilliseconds(200));
//wrapper method for Clipboard.SetDataObject() using the above stored
clipboard
_clipboard.Restore();
}
}
catch (Exception ex)
{
_log.Error("Error caught pasting text", ex);
}

Though it does not answer my direct question to Offices Clipboard buffer, the solution I have which now works is using Word.Interop:
var currentSelection = _word.Selection;
// Store the user's current Overtype selection
var userOvertype = _word.Options.Overtype;
// Make sure Overtype is turned off.
if (_word.Options.Overtype) _word.Options.Overtype = false;
// Test to see if selection is an insertion point.
if (currentSelection.Type == WdSelectionType.wdSelectionIP)
currentSelection.TypeText(text);
else if (currentSelection.Type == WdSelectionType.wdSelectionNormal)
{
// Move to start of selection.
if (_word.Options.ReplaceSelection)
{
object direction = WdCollapseDirection.wdCollapseStart;
currentSelection.Collapse(ref direction);
}
currentSelection.TypeText(text);
}
// Restore the user's Overtype selection
_word.Options.Overtype = userOvertype;

Related

How to avoid that a Button with longPressListener also triggers the normal Command on longPress?

I have a Button which I want to have one behavior when pressed normally (launch a Command) and another when longPressed (using a longPressListener). However, when longPressing the Button, it also runs the 'normalPress' Command. How can I ensure that only the longPressListener is called on the longPress?
There's no builtin support for this. This is something your business logic will have to deal with manually. The core reason for this is that we have no way of knowing at that stage that the long press processed the action.
private boolean longPressHandled;
void callbackFromLongPress() {
longPressHandled = true;
// rest of your logic...
}
void actionEventCallback() {
if(longPressHandled) {
longPressHandled = false;
return;
}
// rest of your logic...
}

C# communicating with Arduino COM access denied

I'm working with a fingerprint sensor on Arduino, but sometimes, on runtime, my WPF app throws an exception on sp.Open() saying "COM3" Access denied"
Here's the code on c#:
public string ConfigPort()
{
SerialPort sp = new SerialPort();
sp.BaudRate = 9600;
sp.PortName = AutodetectArduinoPort();
sp.Open();
string s = "";
while (true)
{
s = sp.ReadLine();
Console.WriteLine(s);
return s;
}
}
Here's the AutodetectArduinoPort method:
public string AutodetectArduinoPort()
{
ManagementScope connectionScope = new ManagementScope();
SelectQuery serialQuery = new SelectQuery("SELECT * FROM Win32_SerialPort");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(connectionScope, serialQuery);
try
{
foreach (ManagementObject item in searcher.Get())
{
string desc = item["Description"].ToString();
string deviceId = item["DeviceID"].ToString();
if (desc.Contains("Arduino"))
{
return deviceId;
}
}
}
catch (ManagementException e)
{
/* Do Nothing */
}
return null;
}
Any solution??
This happens quite a lot with Arduino, personally I think there's a problem with the FTDI driver....certainly wouldn't be the first issue with them. What I do when this happens is physically unplug the device from the USB port, wait for the notification sound from Windows and then plug it back in again. This seems to "reset" the port and force whatever is holding it open to release it, and you're good to go again. You may need to do this quite a bit over time, so the only other tip I have is to use a cheap USB hub so that you wind up wearing out the port pins on that rather than your expensive laptop/desktop.
The error you're getting means that the port is already open. Make sure that you only call ConfigPort() once, and after you're done processing data from the Arduino, close the port with sp.Close(). I would suggest converting sp into a global variable, and subscribing to the OnClosing event of your WPF window, so you can close the port when the user closes the application.

How to resume playing audio with MediaPlayer?

I have a WPF Caliburn.Micro application, and I use MediaPlayer class to play audio. I implemented Play, Stop, and Pause functionality, but I don't see a method for Resume (after Pause) in MediaPlayer. Could you please help me with this?
Here is some of my code:
public void Play()
{
try
{
var audio = Tpv.GetAudio(SelectedTpv.TpvId);
var file = Path.GetTempFileName().Replace(".tmp", ".wma");
File.WriteAllBytes(file, audio);
Player.Open(new Uri(file, UriKind.Absolute));
Player.Play();
IsPlaying = true;
}
catch (Exception ex)
{
MessageBox.Show(String.Format("Failed to play audio:\n{0}", ex.Message), "Failure",
MessageBoxButton.OK, MessageBoxImage.Error);
Console.WriteLine(ex.Message);
}
}
Thanks.
I'm pretty sure that Play is also supposed to handle resume functionality. According to the MSDN for System.Windows.Media.MediaPlayer the Play method is supposed to "Play media from the current Position". This means that when you are playing media from the beginning, the position is 0. If you pause, then the media will be paused at a certain position. Pressing play again should resume playback from the same position that you paused the media on.
Edit:
Based on the code update you provided, it looks like your issue is that you are loading the file each time you click play. This would cause any previous pause information to be erased, and would treat the file as being brand new each time. You should put some sort of check in there to say that if the file is not already loaded, then load it. Otherwise, your Play method should just call Player.Play() to resume.
I would also note that you would need to also call Player.Close when you switch the selected item. This would let the Play method know that it needs to load a different file.
public void Play()
{
try
{
// Check if the player already has a file loaded, otherwise load it.
if(Player.Source == null) {
var audio = Tpv.GetAudio(SelectedTpv.TpvId);
var file = Path.GetTempFileName().Replace(".tmp", ".wma");
File.WriteAllBytes(file, audio);
Player.Open(new Uri(file, UriKind.Absolute));
}
Player.Play();
IsPlaying = true;
}
catch (Exception ex)
{
MessageBox.Show(String.Format("Failed to play audio:\n{0}", ex.Message), "Failure",
MessageBoxButton.OK, MessageBoxImage.Error);
Console.WriteLine(ex.Message);
}
}

Launch default web browser, but not if URL already open

I have a link on my app UI that launches a URL using System.Diagnostics.Process.Start(). If the user clicks the link several times, it opens several tabs.
Is there a way, maybe a command-line option, to still use the default web browser, but have it just reopen the same tab if the URL is already open? It would be OK if it doesn't work with every possible browser out there, but nice if it at least works with IE, Firefox and Chrome.
I doubt it, but since I didn't see any other questions/answers on this topic, I figured I'd ask.
This is somewhat of a workaround but it might get you started. I have used the System.Diagnostics.Process.ProcessId.
As an example I have used IE, I will explain later why I did this. The code is just "quick and dirty" but I just made it as proof of concept.
I have created a basic WinForm app with one button that will open google in IE, if it has already been opened by the application it will not be opened again.
I added the System.Diagnostics reference.
public int ProcessID;
public Form1()
{
InitializeComponent();
}
private void MyButton_Click(object sender, EventArgs e)
{
if (ProcessID == null)
{
StartIE();
}
else
{
if (!ProcessIsRunning())
{
StartIE();
}
}
}
private bool ProcessIsRunning()
{
bool ProcessRunning = false;
foreach (Process p in Process.GetProcesses())
{
try
{
if (p.Id == ProcessID)
{
ProcessRunning = true;
}
}
catch { }
}
return ProcessRunning;
}
private void StartIE()
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = "iexplore.exe";
proc.StartInfo.Arguments = "http://www.google.be";
proc.Start();
ProcessID = proc.Id;
}
This does not completely do what you requested but it might be a good start. There are a few reasons why I did it this way and what possible options are..
If you would use the url as the Filename, it would indeed open up the webpage in the default browser, it would however not return a processID. This is why the snippet shows usage of IE. (If you would use this option, you could use the System.IO.File.Exists to make sure the desired browser is installed)
If you would like to use this option, you can query the registry to pick up what te default browser is, if you have that you could launch that from the value obtained from the registry. If you then change the process.startinfo.filename to this value, then you will launch the default browser but you will still obtain a processId so this might be the way forward. You can check how to do this over here: http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/b200903e-ce69-4bd4-a436-3e20a7632dc4
Showing the internet window if it would already be opened, can be done by using the SetForegroundWindow property. As this is already documented in this article, I did not add it in this snippet.
I hope this helps to get you on your way.

WP7 check if internet is available

My app WP7 was not accepted because it fails to load if the internet is not available. I looked for a way to check it and found this command
NetworkInterface.GetIsNetworkAvailable()
But it isn't working on the emulator and I do not have any device to test it.
Could someone tell me if it returns false if the device is in Airplane mode? If not, how can I check for it?
Thanks,
Oscar
Edit: I also tried with this code:
try
{
wsClient.CurrenciesCompleted += new EventHandler<CurrencyConversion.CurrenciesCompletedEventArgs>(wsClient_CurrenciesCompleted);
wsClient.CurrenciesAsync(null);
}
catch
{
NetworkNotAvailable();
}
But I am not able to catch the exception, I also tried in the wsClient_CurrenciesCompleted method, but also no good.
Where could I test it?
Don't test for "the internet in general" - test for the service you'll actually be connecting to. Test for it by trying to connect to it - make some simple, non-destructive request on start-up. Yes, that will take a tiny bit of the user's data allowance, but:
You will be warming up the networking stack and making a connection which should end up being kept alive automatically, so future latency will be reduced.
You could warn the user that they may have limited functionality if the connection fails.
An Alternative to Jon's suggestion is to check which network interface is available. This is very handy in cases were you need to adjust which service you call based on network speed. For example the switch statement below could be modified to return an Enum to represent the quality of the network.
public class NetworkMonitorClass
{
private Timer timer;
private NetworkInterfaceType _currNetType = null;
private volatile bool _valueRetrieved = false;
public NetworkMonitorClass()
{
//using a timer to poll the network type.
timer = new Timer(new TimerCallBack((o)=>
{
//Copied comment from Microsoft Example:
// Checking the network type is not instantaneous
// so it is advised to always do it on a background thread.
_currNetType = Microsoft.Phone.Net.NetworkInformation.NetworkInterface.NetworkInterfaceType;
_valueRetrieved = true;
}), null, 200, 3000); // update the network type every 3 seconds.
}
public NetworkInterfaceType CurrentNetworkType
{
get
{
if(false == _valueRetrieved ) return NetworkInterfaceType.Unknown;
return _currNetType;
}
private set { ;}
}
public bool isNetworkReady()
{
if(false == _valueRetrieved ) return false;
switch (_currentNetworkType)
{
//Low speed networks
case NetworkInterfaceType.MobileBroadbandCdma:
case NetworkInterfaceType.MobileBroadbandGsm:
return true;
//High speed networks
case NetworkInterfaceType.Wireless80211:
case NetworkInterfaceType.Ethernet:
return true;
//No Network
case NetworkInterfaceType.None:
default:
return false;
}
}
}
See http://msdn.microsoft.com/en-us/library/microsoft.phone.net.networkinformation.networkinterface.networkinterfacetype(VS.92).aspx
GetIsNetworkAvailable() will always return true in the emulator. For testing in the emulator you'll need to work round this in code.
This can be a useful quick check but you also (as Jon pointed out) need to handle the scenario of not being able to connect to your specific server.
Handling this can be done by catching the WebException when you try and get the response in the callback.
private static void DownloadInfoCallback(IAsyncResult asynchronousResult)
{
try
{
var webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
// This will cause an error if the request failed
var webResponse = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);
.....
}
catch (WebException exc)
{
// Handle error here
}
}
GetIsNetworkAvailable() works properly on device.
You can mock your handling of this for testing in the emulator using Microsoft.Devices.Environment.DeviceType.
I would be inclined to test both for avaiability of the internet and availability of your site through exception handling and provide feedback to the user of the app that indicates what the true reason is for features being unavailable.

Resources