I am using IStylusSyncPlugin added to RealTimeStylus plugins to get X,Y,Pressure and timer tick from stylus. This works fine until the window on which I collect this data loses focus. After that, even if focus get back to window, the StylusSyncPlugin does not receiving data. Do anyone have any idea what can i do, to fix this problem? I've found, that stylus events from main window (for ex. PreviewStylusMove) are still firing, but points from these events does not contains timestamp.
A simple code example which could be helpful to reproduce this issue:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
RealTimeStylus rts = new RealTimeStylus(new WindowInteropHelper(this).Handle);
rts.AsyncPluginCollection.Add(new SyncStylusPlugin());
rts.Enabled = true;
}
class SyncStylusPlugin : IStylusSyncPlugin
{
public DataInterestMask DataInterest => DataInterestMask.Packets;
public void Packets(RealTimeStylus sender, PacketsData data)
{
Console.WriteLine("Packets arrived");
}
public void StylusDown(RealTimeStylus sender, StylusDownData data) { }
public void StylusUp(RealTimeStylus sender, StylusUpData data) { }
public void CustomStylusDataAdded(RealTimeStylus sender, CustomStylusData data) { }
public void Error(RealTimeStylus sender, ErrorData data) { }
public void InAirPackets(RealTimeStylus sender, InAirPacketsData data) { }
public void RealTimeStylusDisabled(RealTimeStylus sender, RealTimeStylusDisabledData data) { }
public void RealTimeStylusEnabled(RealTimeStylus sender, RealTimeStylusEnabledData data) { }
public void StylusButtonDown(RealTimeStylus sender, StylusButtonDownData data) { }
public void StylusButtonUp(RealTimeStylus sender, StylusButtonUpData data) { }
public void StylusInRange(RealTimeStylus sender, StylusInRangeData data) { }
public void StylusOutOfRange(RealTimeStylus sender, StylusOutOfRangeData data) { }
public void SystemGesture(RealTimeStylus sender, SystemGestureData data) { }
public void TabletAdded(RealTimeStylus sender, TabletAddedData data) { }
public void TabletRemoved(RealTimeStylus sender, TabletRemovedData data) { }
}
}
I've found, that click on application icon at taskbar making RealTimeStylus work again. Is there any way to fire the same events like mouse do when clicking on this icon? Which events should be fired?
EDIT:
During reading microsoft docs about RealTimeStylus I've found, that "When you create a RealTimeStylus object, you have the option of attaching it to a window handle or to a control. Attaching the RealTimeStylus object to a window handle requires additional permissions. For more information about these permissions, see Partial Trust Considerations for the StylusInput APIs." "The RealTimeStylus that takes the handle parameter requires the UIPermissionWindow.AllWindows and SecurityPermissionFlag.UnmanagedCode permissions, in addition to the permissions required by the constructor that takes the attachedControl parameter." Do anyone know how to check, if Window has these permissions, and how to track them to check if Window loses them sometimes on focus lost?
EDIT2:
I tried to set UIPermission by adding [UIPermission(SecurityAction.Demand, Window =UIPermissionWindow.AllWindows)] to main window class and also by setting new UIPermission(UIPermissionWindow.AllWindows).Demand(); in main window constructor, but it changes nothing.
EDIT3:
Next thing that I have noticed is that, the StylusInRange and StylusOutOfRange events are working everytime, even if window has no focus.
Related
I am working with windowsFrom in c#. I am trying to call mainfrom method in one of the from in user control.
I have mainfrom like this
namespace Project
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
public void TempCommand()
{
StartTemp();
}
}
}
I have the button click in the user control. When i click that button then it will open another form. I have the code like this in the user control.
private TempCalib _tempCalib = new TempCalib();
private void calibBtn_Click(object sender, EventArgs e)
{
_tempCalib.Show();
}
it will open another from and i have one button in that from. I need to call mainfrom method when i click "Ok" button in this from.
namespace Project
{
public partial class TempCalib : Form
{
public TempCalib()
{
InitializeComponent();
}
private void OkButton_Click(object sender, EventArgs e)
{
// I need to call the mainfrom "TempCommand" method here.
this.Hide();
}
}
}
Can anyone help me how to do this.
Thanks.
Quick answer
Just add a reference to the primary form in your secondary form:
public partial class TempCalib : Form
{
private MainForm _main
public TempCalib(MainForm main) : this()
{
_main = main;
}
/// Other stuffs
}
Then assign value when you construct your secondary form:
private TempCalib _tempCalib;
private void calibBtn_Click(object sender, EventArgs e)
{
if (_tempCalib == null)
_tempCalib = new TempCalib(this);
_tempCalib.Show();
}
If calibBtn_Click isn't inside MainForm (but it's inside a UserControl on it) then you can replace _tempCalib initialization with:
_tempCalib = new TempCalib((MainWindow)FindForm());
You'll be then able to call the primary form:
private void OkButton_Click(object sender, EventArgs e)
{
_main.TempCommand();
this.Hide();
}
Notes: this is just one option, you may create a property to hold MainForm reference (so secondary form can be reused and it'll be more designer friendly) moreover TempCalib is not an UserControl but a Form (pretty raw but for an UserControl you may just check its parent Form and cast it to proper type).
Improvements
Such kind of references are often an alert. Usually UI components shouldn't not be so coupled and a public Form's method to perform something very often is the signal that you have too much logic in your Form. How to improve this?
1. DECOUPLE CONTROLS. Well a first step may be to decouple them a little bit, just add an event in TempCalib and make MainForm its receiver:
public partial class TempCalib : Form
{
public event EventHandler SomethingMustBeDone;
private void OkButton_Click(object sender, EventArgs e)
{
OnSomethingMustBeDone(EventArgs.Empty); / TO DO
this.Hide();
}
}
Then in MainForm:
private TempCalib _tempCalib;
private void calibBtn_Click(object sender, EventArgs e)
{
if (_tempCalib == null)
{
_tempCalib = new TempCalib();
_tempCalib.SomethingMustBeDone += _tempCalib_SomethingMustBeDone;
// In _tempCalib_SomethingMustBeDone you'll invoke proper member
// and possibly hide _tempCalib (remove it from OkButton_Click)
}
_tempCalib.Show();
}
2. DECOUPLE LOGIC FROM CONTROLS. UI changes pretty often, logic not (and when it changes probably isn't in parallel with UI). This is just the first step (now TempCalib isn't aware of who will use it). Next step (to be performed when too much things happen inside your form) is to remove this kind of logic from the form itself. Little example (very raw), keep TempCalib as before (with the event) and change MainForm to be passive:
public partial class MainForm : Form
{
public event EventHandler Calibrate;
protected virtual void OnCalibrate(EventArgs e)
{
// TODO
}
}
Now let's create a class to control the flow and logic:
public class MyTaskController
{
private MainForm _main;
private TempCalib _tempCalib;
public void Start()
{
_main = new MainForm();
_main.Calibrate += OnCalibrationRequested;
_main.Show(); // Or whatever else
}
private void OnCalibrationRequested(object sender, EventArgs e)
{
if (_tempCalib == null)
{
_tempCalib = new TempCalib();
_tempCalib.SomethingMustBeDone += OnSomethingMustBeDone();
}
_tempCalib.Show();
}
private OnSomethingMustBeDone(object sender, EventArgs e)
{
// Perform the task here then hide calibration window
_tempCalib.Hide();
}
}
Yes, you'll need to write much more code but this will decouple logic (what to do as response to an action, for example) from UI itself. When program grows up this will help you to change UI as needed keeping logic unaware of that (and in one well defined place). I don't even mention that this will allow you to use different resources (people) to write logic and UI (or to reuse logic for different UI, WinForms and WPF, for example). Anyway IMO the most obvious and well repaid benefit is...readability: you'll always know where logic is and where UI management is, no search, no confusion, no mistakes.
3. DECOUPLE LOGIC FROM IMPLEMENTATION. Again you have more steps to perform (when needed). Your controller is still aware of concrete types (MainForm and TempCalib). In case you need to select a different form at run-time (for example to have a complex interface and a simplified one or to use dependency injection) then you have to decouple controller using interfaces. Just an example:
public interface IUiWindow
{
void Show();
void Hide();
}
public interface IMainWindow : IUiWindow
{
event EventHandler Calibrate;
}
public interface ICalibrationWindow : IUiWindow
{
event EventHandler SomethingMustBeDone;
}
You could use a custom event that is declared in your UserControl. Then your form needs to handle this event and call the method you want to call. If you let the UserControl access your form, you are hard-linking both with each other which decreases reusability of your UserControl.
For example, in TempCalib:
public delegate void OkClickedHandler(object sender, EventArgs e);
public event OkClickedHandler OkClicked;
private void OkButton_Click(object sender, EventArgs e)
{
// Make sure someone is listening to event
if (OkClicked == null) return;
OkClicked(sender, e);
this.Hide();
}
in your mainform:
private void Mainform_Load(object sender, EventArgs e)
{
_tempCalib.OkClicked += CalibOkClicked;
}
private void CalibOkClicked(Object sender, EventArgs e)
{
StartTemp();
}
You create an event in your usercontrol and subscribe to this in the mainform.
That is the usual way.
Form1 Code:
UserControl1 myusercontrol = new UserControl1();
public void TabClose(Object sender,EventArgs e)
{
int i = 0;
i = tabControl1.SelectedIndex;
tabControl1.TabPages.RemoveAt(i);
}
private void Form1_Load(object sender, EventArgs e)
{
myusercontrol.Dock = DockStyle.Fill;
TabPage myTabPage = new TabPage();
myTabPage.Text = "Student";
myTabPage.Controls.Add(myusercontrol);
tabControl1.TabPages.Add(myTabPage);
myusercontrol.OkClick += TabClose;
}
UserControl1 Code:
public delegate void OkClickedHandler(Object sender, EventArgs e);
public partial class UserControl1 : UserControl
{
public event OkClickedHandler OkClick;
public UserControl1()
{
InitializeComponent();
}
private void button3_Click(object sender, EventArgs e)
{
if (OkClick == null) return;
OkClick(sender, e);
}
}
Try this:
From user control try this:
MainForm form = this.TopLevelControl as MainForm;
form.TempCommand();
I'm using KeyDown and KeyUp handlers on Window.Current.CoreWindow to catch keystrokes in a VNC application for UWP. This works great with one exception: alt (VirtualKey.Menu/LeftMenu/RightMenu) never is sent to my application. In addition, alt+letter results in neither being sent to the handlers.
I assume that this is because some accelerator handler is eating these events before they reach CoreWindow. Is there any way around this?
Try to use Dispatcher.AcceleratorKeyActivated instead, it handles Alt key.
Also, it seems there is an issue with CoreWindow. More details on MSDN
Here an example of how I managed to solve this issue in Xamarin Forms.
// A model to store the values of the key event.
public class KeyEventArgs : EventArgs
{
public bool IsAltKeyPressed { get; set; }
public string Key { get; set; }
}
// UWP Custom render
public class MyPageViewRenderer : PageRenderer
{
/// <summary>
/// Monitor windows core ui keypress when MyPageView is showing
/// </summary>
public MyPageViewRenderer() : base()
{
// When ExplorePage appears then attach to the ui core keydown event
Loaded += (object sender, RoutedEventArgs e) =>
{
CoreWindow.GetForCurrentThread().Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated;
};
// When ExplorePage disappears then detach from the ui core keydown event
Unloaded += (object sender, RoutedEventArgs e) =>
{
CoreWindow.GetForCurrentThread().Dispatcher.AcceleratorKeyActivated -= Dispatcher_AcceleratorKeyActivated;
};
}
private void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args)
{
if ((args.EventType == CoreAcceleratorKeyEventType.KeyDown || args.EventType == CoreAcceleratorKeyEventType.SystemKeyDown)
&& !args.KeyStatus.WasKeyDown)
{
bool isAltKeyPressed = args.KeyStatus.IsMenuKeyDown;
(Element as MyPageView).MyPageView_KeyPressed(Element, new KeyEventArgs { IsAltKeyPressed = isAltKeyPressed, Key = args.VirtualKey.ToString() });
}
}
}
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MyPageView : ContentPage
{
public MyPageView()
{
InitializeComponent();
this.Focus();
}
public void MyPageView_KeyPressed(object sender, KeyEventArgs e)
{
(this.BindingContext as MyPageViewModel).CommandOnKeyPress?.Execute(e);
}
}
i have a really simple counter application, I made in C#.
Now what i want to know is it possible to clone the form design and code, so there are 2 counter's instead of one. with a button.
they both have to be working.
i'm an beginner.. so that's why i ask if this is possible.
So from this (this is what i currently have, without clone button):
http://i.stack.imgur.com/ASMY4.jpg
to this:
http://i.stack.imgur.com/acluZ.jpg
this is my code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void counteradd()
{
int current1 = Convert.ToInt32(totaltb.Text);
current1++;
totaltb.Text = Convert.ToString(current1);
}
public void counterreduce()
{
int current2 = Convert.ToInt32(totaltb.Text);
current2--;
totaltb.Text = Convert.ToString(current2);
}
public void counterreset()
{
totaltb.Text = ("0");
}
private void reducebttn_Click(object sender, EventArgs e)
{
counterreduce();
}
private void resetbttn_Click(object sender, EventArgs e)
{
counterreset();
}
private void addbttn_Click(object sender, EventArgs e)
{
counteradd();
}
}
Simply duplicating the controls and laying them out on the form will result in messy code. The "clone' that you are referring to would be to build the functional piece as a user-control, and then add that as a control to your form.
I have a User Control with with some search functionality, then I also have a control that contains a grid. In the control that has the grid I have all the functionality to retrieve some items I need to populate a report from the search control.
My question is, and I have read about this but not completely sure how to make it work, I read i need to register a event handler in control A that calls the function in control B. How does that work?
Say in control B there is a function that I need to call GetAllItemsByRegistrantID(int id). How can I make a call to this function from control A?
I would really appreciate any help or guidance on this.
Regards
Here is an example if you had to do it using events.
On your first user control (the search control) define a custom event.
public partial class UserControl1 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public event EventHandler<MyCustomeEventArgs> MyCustomClickEvent;
protected virtual void OnMyCustomClickEvent(MyCustomeEventArgs e)
{
if (MyCustomClickEvent != null)
MyCustomClickEvent(this, e);
}
public void button1_Click(object sender, EventArgs e)
{
OnMyCustomClickEvent(new MyCustomeEventArgs(5));
}
}
public class MyCustomeEventArgs : EventArgs
{
public MyCustomeEventArgs(int searchID)
{
SearchID = searchID;
}
public int SearchID { get; set; }
}
On your user control with the grid, define a handler.
public void HandleCustomEvent(object sender, MyCustomeEventArgs e)
{
GetAllItemsByRegistrantID(e.SearchID);
}
public void GetAllItemsByRegistrantID(int id)
{
Label1.Text = id.ToString();
}
On the page where they both live, wire them together.
protected void Page_Load(object sender, EventArgs e)
{
UserControl1Instance.MyCustomClickEvent += UserControl2Instance.HandleCustomEvent;
}
I would definitely try and avoid this sort of situation. You should be putting this sort of code in a class and sharing this between the two controls.
In a WPF application, I've got my events centralized in one class like this:
public class EventFactory
{
public static void Button_Edit_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("you clicked edit");
}
public static void Button_Add_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("you clicked add");
}
}
so that I can reuse them in many Windows like this:
public Window1()
{
InitializeComponent();
ButtonEdit.Click += EventFactory.Button_Edit_Click;
ButtonAdd.Click += EventFactory.Button_Add_Click;
}
This works fine, but now I want the events to act on the Windows which call them which I was able to do when the event handlers were simply in the code-behind for each window.
How can I e.g. inject a window object into the event handler so that that event handler can directly manipulate it, something like this:
ButtonEdit.Click += EventFactory.Button_Edit_Click(this);
One way:
ButtonEdit.Click += EventFactory.ForConsumer<Window1>().Button_Edit_Click;
In other words, turn your factory class into an actual factory that creates objects based on some context. In this case, the context is the object consuming the events.
Another way:
public static void Button_Edit_Click(object sender, RoutedEventArgs e)
{
Window window = Window.GetWindow(sender as DependencyObject);
MessageBox.Show("you clicked edit");
}
I'm not particularly fond of either of these approaches, but there you go.
You can try something like this:
public class CommonEventHandler
{
private CommonEventHandler() { }
private object Context { get; set; }
public static EventHandler CreateShowHandlerFor(object context)
{
CommonEventHandler handler = new CommonEventHandler();
handler.Context = context;
return new EventHandler(handler.HandleGenericShow);
}
private void HandleGenericShow(object sender, EventArgs e)
{
Console.WriteLine(this.Context);
}
}
class Program
{
static void Main(string[] args)
{
EventHandler show5 = CommonEventHandler.CreateShowHandlerFor(5);
EventHandler show7 = CommonEventHandler.CreateShowHandlerFor(7);
show5(null, EventArgs.Empty);
Console.WriteLine("===");
show7(null, EventArgs.Empty);
}
}
You need to adapt the types to suit your needs but it shows the general idea.