I'm struggling with the WebBrowser control (both in Winforms and WPF). Basically I want to achieve the same behavior I got with a RTF editor: Handling some kind of OnTextInput event in order to get the last typed character for every keystroke.
I mean the textual characters, not Control, Alt, F5, Enter, ... that can be captured with the Keydown/Keyup events.
Any help? Thanks in advance.
You can hanlde KeyPress event of this.webBrowser1.Document.Body:
private void Form1_Load(object sender, EventArgs e)
{
this.webBrowser1.Navigate("http://www.google.com");
//Attach a handler to DocumentCompleted
this.webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
}
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//Attach a handler to Body.KeyPress when the document completed
this.webBrowser1.Document.Body.KeyPress += Body_KeyPress;
}
void Body_KeyPress(object sender, HtmlElementEventArgs e)
{
//handle the event, for example show a message box
MessageBox.Show(((char)e.KeyPressedCode).ToString());
}
Note:
It doesn't handle non-input keys as you need.
You can also suppress the input by setting e.ReturnValue = false; based on some criteria if you need.
You can also handle other key events like KeyUp and KeyDown the same way
Related
As described i input a datepicker in my xaml file
when i run the page ,datepicker just show like this:
then I have to tap the datepicker to enter the select page like this :
Now
I need to directly open the fullscreen datepicker select page when I click a button
the address give a way that I can just Navigate to the select page,
but I don't know how ?
I'm the poster.
i find a solution myself
Override DatePicker class with our custom DatePickerCustom class. Create new class "DatePickerCustom.cs"
public class DatePickerCustom : DatePicker
{
public void ClickTemplateButton()
{
Button btn = (GetTemplateChild("DateTimeButton") as Button);
ButtonAutomationPeer peer = new ButtonAutomationPeer(btn);
IInvokeProvider provider = (peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider);
provider.Invoke();
}
}
then in the mainpage.xaml.cs
private DatePickerCustom datePicker;
// Constructor
public MainPage()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainPage_Loaded);
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
// create datePicker programmatically
if (this.datePicker == null)
{
this.datePicker = new DatePickerCustom();
this.datePicker.IsTabStop = false;
this.datePicker.MaxHeight = 0;
this.datePicker.ValueChanged += new EventHandler<DateTimeValueChangedEventArgs>(datePicker_ValueChanged);
LayoutRoot.Children.Add(this.datePicker);
}
}
void datePicker_ValueChanged(object sender, DateTimeValueChangedEventArgs e)
{
// now we may use got value from datePicker
TextBlock1.Text = this.datePicker.ValueString;
}
so that when do an action like tap or click, the fullscreen datepicker page will be shown
private void button1_Click(object sender, RoutedEventArgs e)
{
this.datePicker.ClickTemplateButton();
}
ps: timepicker can also do the same thing
ps2:here is the details
#Mario Galván
hope it help u
I am learning Swing and created a sample GUI. I am trying to achieve the following in exact order...
The user enters text into some text fields.
The user clicks a "launch" button.
The "launch" button becomes disabled.
A background thread spawns and processes the text from text fields.
the background thread finishes.
the "launch" button becomes enabled again.
I am trying to use invokeandwait as can be seen below but I get "Cannot call invokeAndWait from the event dispatcher thread". My main method is in the same .class file and I'm not too sure what exactly the "event dispatcher thread" is. Whats the best approach for something like this, do I need to setup some kind of alert in my worker thread to route back to the "event dispatcher thread"?
LaunchButton code
private void launchButtonActionPerformed(java.awt.event.ActionEvent evt) {
launchButton.setEnabled(false);
try {
java.awt.EventQueue.invokeAndWait(new MyTestThread());
} catch (Exception e) {
}
launchButton.setEnabled(true);
}
Worker Thread
public class MyTestThread extends Thread {
private int i = 0;
public void run() {
while (i < 5) {
try {
System.out.println(i++);
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Solution
Worker Thread
public class WorkerThread extends SwingWorker<Integer[], Void> {
#Override
public Integer[] doInBackground() {
System.out.println("Doing in background");
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
System.out.println("Doing in background" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
#Override
public void done() {
System.out.println("Swingworker is Done");
}
}
Starting the worker thread from my Event Dispatch Thread (EDT)
new WorkerThread().execute();
The event dispatch thread (EDT) is the only thread allowed to access Swing classes and (almost all) methods. All the initizalization and events of the GUI are executed by the EDT. To execute something in the EDT you have to use SwingUtilities.invokeLater or invokeAndWait (this is equivalent to EventQueue.invokeXXX). This is why all Swing programs start with SwingUtilities.invokeLater() in the main: to execute the GUI initialization in the EDT.
While the EDT is busy the UI freezes that's why background threads are useful. When you need to do a big amount of work independent from the UI (calculations, I/O, transmission, ...) you have to use "worker threads".
For more about threading in Swing see this tutorial: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/
Now, what you are trying to accomplish is right but the tools you are using aren't.
You need to know two things: how to handle events (like button presses) and how to create background threads.
For the first one see this tutorial:
http://docs.oracle.com/javase/tutorial/uiswing/components/button.html
You just need to add anActionListener to a button and whenever the button throws an event the listener's actionPerformed method will be executed, in the EDT.
Minimal example:
JButton button = new JButton("Test button");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
System.out.println("The button was pressed.");
}
}
The event variable contains useful information, for example event.getSource() return the object that threw the event, in this case the button.
Now what you want to do when the button is pressed is create a worker thread. Worker threads are created using the SwingWorker class, as you've seen in the concurrency tutorial. There you can define a piece of code that will be executed in the background thread (in the doInBackground() method) and a piece of code that will be executed in the EDT after the work in the background is done (in the done() method).
So you'd want to do something like this:
private static JButton _button;
//...
_button = new JButton("Test button");
_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
System.out.println("The button was pressed.");
_button.setEnabled(false);
SwingWorker worker = new SwingWorker()
{
#Override
protected Object doInBackground() throws Exception
{
//do something useful in the background thread
return null;
}
#Override
protected void done()
{
_button.setEnabled(true);
}
}
worker.execute();
}
}
There's a lot of information out there about this. Read the Java reference for the classes, read the official tutorials and search in SO. Another good tutorial about SwingWorkers is: http://www.javacreed.com/swing-worker-example/
I am working on a Windows Phone 8 App which should be protected with a passcode. What is the best way to show the passcode screen everytime the app is lauchend or activated?
I think the central point of action shoule be the App.xaml.cs with its Launch and Activation event handlers. But how exactly can I show the passcode screen?
The problem is, that one never know which pages will be displayed when the app launches or is reactivated. It is either the main page or any other page which was last displayed when the app was deactivated.
I tried to intercept the navigation to the first page, cancel it and show the passcode page instead:
// App.xaml.cs
private void InitializePhoneApplication() {
...
RootFrame.Navigating += HandleFirstNavigation;
...
}
private void HandleFirstNavigation(object sender, NavigatingCancelEventArgs e) {
RootFrame.Navigating -= HandleFirstNavigation;
e.Cancel = true;
RootFrame.Dispatcher.BeginInvoke(new Action(this.OpenPasscodePage));
}
private void OpenPasscodePage() {
RootFrame.Navigate(PasscodePageUri);
}
This works, but only when the app lauchend. When the app reactivated (dormant or tombstoned) the e.Cancel is irgnored. Although the navigation to the passcode page is called the original page is shown.
Moving the navigation the the passcode page from Navigating to Navigated does not worth either:
private void InitializePhoneApplication() {
...
RootFrame.Navigated += PasscodePageAfterFirstNavigation;
...
}
private void PasscodePageAfterFirstNavigation(object sender, EventArgs e) {
RootFrame.Navigated-= PasscodePageAfterFirstNavigation;
RootFrame.Navigate(PasscodePageUri);
}
This seems to be some kind of race condition: Sometimes the passcode page is shown, sometimes the original page. Even if the passcode pages comes up this looks bad because one first see the original page for the fraction of a second before the app navigates further to the passcode page.
Both solution do not work. Any idea what is the right way to implement this?
EDIT: Meanwhile I tried a third solution which does not work either. This solution uses the Uri Mapper:
App.xaml.cs
public bool PasscodeWasConfirmed; private void Application_Launching(object sender, LaunchingEventArgs e) {
...
PasscodeWasConfirmed = false;
...
}
private void Application_Activated(object sender, ActivatedEventArgs e) {
...
PasscodeWasConfirmed = false;
...
}
public Uri InitialPageUri;
public bool ShouldRedirectToPasscodePage(Uri uri) {
if (PasswordWasConfirmend == false) {
InitialPageUri = uri;
return true;
}
return false;
}
UriMapper
public class AppUriMapper : UriMapperBase {
public override Uri MapUri(Uri uri) {
App app = (Application.Current as App);
if (app != null) {
if (app.ShouldRedirectToPasscodePage(uri))
return PasscodeQueryPage.PageUri;
}
// default
return uri;
}
}
PasscodePage
public partial class PasscodePage : PhoneApplicationPage {
...
private void PasscodeConfirmed() {
App app = (Application.Current as App);
app.PasscodeWasConfirmed = true;
NavigationService.Navigate(app.InitialPageUri);
}
}
The Logic is working without any problem, but the app does not navigate to InitialPageUri after the passcode was confirmed. The Uri Mapper is called and correctly and returns the InitialPageUri (no redirect any more). But no navigation happens...
There are no errors, exceptions or debug output. simply nothing happes...
Biggest problem when using Uri Mapper:
When the app is reactivated from Dormant state there is no navigation which could be mapped or redirected...
(I've edited previous answer instead of adding a new one)
I've spend a little time trying to find a solution, and I don't see why your code doesn't run.
In my case it's enough if I do such a change in App.xaml:
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
// Set the root visual to allow the application to render
if (RootVisual != RootFrame)
RootVisual = RootFrame;
// Remove this handler since it is no longer needed
RootFrame.Navigated -= CompleteInitializePhoneApplication;
App.RootFrame.Navigate(new Uri("/passPage.xaml", UriKind.RelativeOrAbsolute));
}
This works on my example which is under the link http://sdrv.ms/1ajH40E
But - I cannot prevent user from seeing last screen when he holds back buton and is chosing to which app return, and then for a blink he can see the last page before leaving the app. I don't know if it is possible to change this behaviour after clicking MS Button:
windows phone change deactivated app image
Second edit
Ok - maybe I've found solution why it sometiems work and sometimes not in your code. After pressing the Start or Search buton the App can go to two cases: Tombstone and non-tombsone. After return different events happen. Code above works with Tombstone case but not with non-tombstone. To work it with the second you need to add (because page is not initialized again) - (of course it can be different solution):
bool afterActivation = false;
private void Application_Activated(object sender, ActivatedEventArgs e)
{
afterActivation = true;
}
private void CheckForResetNavigation(object sender, NavigationEventArgs e)
{
// If the app has received a 'reset' navigation, then we need to check
// on the next navigation to see if the page stack should be reset
if (e.NavigationMode == NavigationMode.Reset)
RootFrame.Navigated += ClearBackStackAfterReset;
if (afterActivation)
{
afterActivation = false;
App.RootFrame.Navigate(new Uri("/passPage.xaml", UriKind.RelativeOrAbsolute));
}
}
Please also ensure of your debug properties in VS: Project->Properties->Debug->Tombstone upon deactiovation checkbox.
You can also find some information here (if you haven't seen it before):
http://blogs.msdn.com/b/ptorr/archive/2010/12/11/how-to-correctly-handle-application-deactivation-and-reactivation.aspx
Why we can not handle the tapped event of richtextblock, I want to get the tapped point of the richtextblock or richtextblockoverflow, how to workaround?
if you set IsTextSelectionEnabled to false its work but you cant use ScrollViewer to scroll i solved this with this issue
this.RichTextBlock.AddHandler(TappedEvent, new TappedEventHandler(RichTextBlock_Tapped), true);
private void medical_history_Tapped(object sender, TappedRoutedEventArgs e)
{
}
hope this helped you!
So I have a button on a WinRT UserControl that I want to increase or decrease a integer value (CurrentValue) while you hold down the button.
I ended up with this implementation below, which works but does not look to good or is it okay?
I searched for an event to use but I got stuck using click and setting the button.clickmode to press.
I use the bool _increasePushed to track if already pushed in so I don't get multiple event triggers.
private bool _increasePushed;
private const int PushDelay = 200;
private async void ButtonIncreaseClick(object sender, RoutedEventArgs e)
{
var button = sender as Button;
if (button == null) return;
if (_increasePushed)
{
return;
}
_increasePushed = true;
while (button.IsPressed)
{
CurrentValue++;
await Task.Delay(PushDelay);
}
_increasePushed = false;
}
XAML on UserControl
<Button x:Name="buttonIncrease" Content="Bla bla"
Click="ButtonIncreaseClick" ClickMode="Press" />
The better way would be to use a RepeatButton which does exactly what you are trying to replicate. It has a Delay property to wait for the first repeated click as well as an Interval property that controls how often the Click event is raised.