My application uses the UiElement.TouchDown event in various places, one of them is to let the user stop a spinning wheel. In this situation, one can easily notice a short delay of about 1/3s between the actual touching of the screen and the TouchDown event.
I have set Stylus.IsPressAndHoldEnabled to false.
In order to troubleshoot this problem, I've written a test tool that reports WPF events and native window messages, and I noticed that as soon as I touched the screen, messages with id 0x02CC, 0x011B and 0x011A are generated, about 100 to 300 ms before the TouchDown event. This leads me to believe that the drivers report the touch quickly, and the delay is introduced somewhere later in the WPF translations.
Is there a way to make the touch interaction more responsive? Please ask for any information you need!
Unless Flicks are needed set both in XAML or by manually setting in code behind: (I assume you meant to say IsPressAndHoldEnabled not IsTouchAndHoldEnabled)
Stylus.IsPressAndHoldEnabled="False" Stylus.IsFlicksEnabled="False"
Furthermore consider handling the TouchDown Event and also capturing it to the relevant UIElement (don't forget to release it in TouchUp).
uielement.CaptureTouch(e.TouchDevice);
e.Handled = true;
Related
I've been playing around with events in WPF and have so far I've got good mileage out of 'Source' and 'OriginalSource' properties of the event args as well as using the sending control and FocusManager. Here's the thing, when a chain of events starts firing, is there any way to know what control will be ending up with focus at the end barring any intervening logic throughout the chain of events?
I'm afraid that the only reliable way of doing this is actually letting focus change and then handling it in some PreviewGotKeyboardFocus handler at top view level.
You can then know which control was going to get the focus, and cancel the change with e.Handled = true.
PD. There's a function in all UIElements called PredictFocus, but it only works with positional traverse changes, not with tab-based changes (or custom focusing).
When reading some RichTextControl properties inside Application.Idle some IME won't work.
Given this simple code:
_richTextControl = new RichTextControl();
Application.Idle += delegate(object sender, EventArgs e) {
btnCopy.Enabled = _richTextControl.SelectionLength > 0;
btnPaste.Enabled = _richTextControl.CanPaste();
};
It'll work fine with most IME I tried but, at least, for Chinese (Traditional, Taiwan) with Microsoft Chinese Traditional Array (6.0) and Chinese Traditional DaYi (6.0) it'll prevent IME to work properly (I tried only with Windows 7, in English and Taiwanese). You can start typing but when Idle code is executed (reading SelectionLength property and invoking CanPaste() method, here I wrote them both but each one is enough to reproduce this) it'll stop working (you type but pop-up window is closed immediately and nothing is sent to RichTextControl).
I checked MSDN about EM_GETSELTEXT and EM_CANPASTE but it says nothing about this issue. I also tried to replace SelectionLength property manually sending EM_GETSELTEXT with SendMessage() but it doesn't change this odd behavior (however I checked WordPad - which uses rich editor - and it works properly even if (AFAIK) MFC commands use idle time to update UI status).
Of course I can move some code into SelectionChanged event and update UI both from Idle and from SelectionChanged (and it'll work) or I may update some flags in SelectionChanged and change UI in Idle but this will break existing code and it'll force a big change in UI library (all commands have not knowledge of Idle or SelectionChanged, they simply return true in a CanExecute() method when their target control allows their execution). If nothing else is viable then I may derive a class from RichTextControl to make these methods/properties callable in Idle (using flags updated elsewhere) but (to avoid a big refactoring) I would know if it's a knows issue, a bug related to IME itself or if there is something else I missed.
I have a full screen WPF application built for a touch monitor, and I have some Listboxs on the main screen.
When I flick the 'Listbox' it scrolls fine, but when it gets to the end of the list, the entire application gets pulled down from the top of the screen, can I stop this behavior somehow?
Has anyone else seen this?
Yes, that default behaviour of the ListBox (or rather, the ScrollViewer inside the default ListBox template) is weird - when I first came across it, I thought it must be a practical joke. In fact, it's really hard to find any documentation about it - but it is briefly mentioned here:
The ManipulationBoundaryFeedback event enables applications or components to provide visual feedback when an object hits a boundary. For example, the Window class handles the ManipulationBoundaryFeedback event to cause the window to slightly move when its edge is encountered.
So, a way around it is to handle ManipulationBoundaryFeedback on the ListBox, and set Handled to true:
<ListBox ManipulationBoundaryFeedback="OnManipulationBoundaryFeedback">
// ...
</ListBox>
Code-behind:
private void OnManipulationBoundaryFeedback(object sender, ManipulationBoundaryFeedbackEventArgs e)
{
e.Handled = true;
}
The AxAcroPDF swallows all key-related events as soon as it gets focus, including shortcuts, key presses, etc. I added a message filter, and it doesn't get any key-related messages either. It's a COM component, could that be relevant?
Is there any way to catch these before the control starts swallowing them?
Hans is correct, the Acrobat Reader spawns two child AcroRd32 processes which you have no direct access to from within your managed code.
I have experimented with this and you have three viable options:
You can create a global system hook, and then look for and filter out / respond to WM_SETFOCUS messages sent to your child AcroRd32 windows. You can accomplish some of this from within C# by using a wrapper library, such as the one here: http://www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx
You also need to identify the correct processes as there may be more than one instance of your application, or other instances of AcroRd32. This is the most deterministic solution, but because your application will now be filtering messages sent to every single window in existence, I generally don't recommend this approach because then your program could negatively affect system stability.
Find an alternate PDF viewing control. See this answer for a few commercial components: .net PDF Viewer control , or roll your own: http://www.codeproject.com/KB/applications/PDFViewerControl.aspx
Find an acceptable hack. Depending on how robust your application needs to be, code such as the following may be suitable (it was suitable for my case):
DateTime _lastRenav = DateTime.MinValue;
public Form1()
{
InitializeComponent();
listBox1.LostFocus += new EventHandler(listBox1_LostFocus);
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
axAcroPDF1.src = "sample.pdf"; //this will cause adobe to take away the focus
_lastRenav = DateTime.Now;
}
void listBox1_LostFocus(object sender, EventArgs e)
{
//restores focus if it were the result of a listbox navigation
if ((DateTime.Now - _lastRenav).TotalSeconds < 1)
listBox1.Focus();
}
I might finally have a ridiculously simple answer. So far in testing this is working.
Having suffered from this problem for quite some time and having built a complex system of each custom control recording which of them last had focus and using a timer to flip focus back (when acropdf grabbed it) I revisited this problem and read a great number of answers (looking for recent solutions). The information gleaned helped me with the idea.
The idea is to disable the (acropdf) control whilst it is loading as in the following example (code reduced for clarity)
AxAcroPDF_this.Enabled = False
AxAcroPDF_this.src = m_src
Then on a timer, after say 1 second.
AxAcroPDF_this.Enabled = True
Basically the idea is to tell Windows not to let users use the acropdf control until allowed, so asking Windows to prevent it from getting focus (because users are not allowed in there).
So far this is holding up, I will edit this if anything changes. If it doesn't work completely for you then maybe the idea points into a useful direction.
It is an out-of-process COM component, that's the problem. Completely in violation of Windows SDK requirements as laid out in SetParent(). Once its window gets the focus, the message loop in the acroread.exe process gets all the messages, your message filter cannot see any messages anymore.
Technically it is fixable by using SetWindowsHookEx() to inject a DLL into the process and monitor messages with WH_GETMESSAGE. But you can't write such a DLL in the C# language.
Major suck, I know. There never seems to be any lack of it with that program.
For some reason Tim's answer, disabling the AxAcroPDF control directly, didn't work in my case. The Leave event on the previously-selected Textbox would never fire, either.
What is working is nesting the AxAcroPDF control inside of a disabled GroupBox. Since the users of my application need to only see the PDF, not interact with it, the GroupBox's Enabled property is set to False in the designer.
I'm new here and have a really mysterious problem to start off. I'm a software developer in the UK and have over 15 years of experience but have only been developing in .Net for 18 months. My NotifyIcon mouse events are not firing!
I am using C# to write an application that starts as a NotifyIcon ('main app icon') and displays a ContextMenu on mouse right-click. This works fine: ContextMenu, forms launching and mouse click events firing.
A tiny bit of background: the application is supposed to sense the insertion of a usb 'device' (it does), interrogate it and create another NotifyIcon ('device icon') to allow the user to interact with that device. The 'main app icon', mentioned in my previous paragraph, allows the user to interact with the database and to configure the software.
To encapsulate these device interaction functions, I have constructed a 'device class' that
contains the device NotifyIcon, ContextMenu, forms, mouse click events etc which allow interaction with the device.
The Problem
The problem starts when I instantiate my 'device class' from the ManagementEventWatcher EventArrived event. If I instantiate the 'device class' in my program Main then the events fire correctly when I click the notifyicon.
So, please, can someone help me?
Cheers, in advance
Matthew
IIRC, the event usage (rather than WaitForNextEvent) works async. I would be interested to know what thread the event is being raised on. I wonder if there is no message pump servicing messages for your icon.
Do you have a form anywhere? Or something else with a message loop? I would be tempted to call into the form (using Control.Invoke), and ask the form to show the icon - since then it should have an active message pump.
Sorry for the delay; reading your comments, it sounds like you've broadly got a workaround. The only gotcha is cross-threaded issues; ideally, you would ask the UI to make such a change on the UI thread; for example, if you have a Form kicking around (owning the icon) - add to your form class:
// not a property, as there is no need to add a complex x-thread "get"
public void SetIconVisible(bool isVisible) {
if(this.InvokeRequired) {
this.Invoke((MethodInvoker) delegate {
myIcon.Visible = isVisible;
});
} else {
myIcon.Visible = isVisible;
}
}
This does a thread-switch (if needed) to the UI thread. Any use?
So the answer is:
The events will only work if when you make the NotifyIcon visible, you do it in the main thread. So the code given by Marc Gravell is the solution.
Mark, just to let you know -
I worked out that I could create the class instances that have the NotifyIcon as members in the main thread and then make the NotifyIcon(s) visible when the USB device(s) are connected.
It needed a bit of adjustment though because the NotifyIcon is created when it's first made visible, so I had to make sure that (in the main thread) I set Visible to true then to false for each - giving rise to the need for limiting the number of instances.
The ManagementEventWatcher thread could then set the Visible property to true when the device gets connected.
A workaround.
(see replies to your comments)