I am working with a simple Text to Speech application using the System.Speech.Synthesis reference. I would like to add a slider control to the application and control the volume of the speech with it. In order to set the volume I'm using:
speech.Volume = 100;
Do I need to use some kind of event handler in order to update this value? By the way I'm creating this as a WPF application with C# (please not VB.NET code).
<Slider Ticks="1, 2, 3, 4, 5, 6, 7, 8, 9, 10"
Value="1"
Delay="100"
Interval="5"
TickPlacement="BottomRight"
Minimum="1"
Maximum="10"
Width="100"
AutoToolTipPlacement="BottomRight"
ValueChanged="slider_ValueChanged"
Grid.Row="1"
Grid.Column="0">
Slider>
create event of slider_ValueChanged and set Speech.volume = (int)sliderID.value;
Add two sliders, sliderVolume for Volume control and sliderRate for Rate control. Then in SpeakProgress event, assign new volume and rate to speech and by using characterPosition make a sub-string of original reading content. Then restart speak using this new sub-string. See the following code.
string selectedSpeakData = "Sample Text Sample Text Sample Text Sample Text Sample Text";
private SpeechSynthesizer speech;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
speech= new SpeechSynthesizer();
speech.SpeakProgress += new EventHandler<System.Speech.Synthesis.SpeakProgressEventArgs>(speech_SpeakProgress);
speech.SpeakAsync(selectedSpeakData);
}
void speech_SpeakProgress(object sender, System.Speech.Synthesis.SpeakProgressEventArgs e)
{
if (speech.Volume != Convert.ToInt32(sliderVolume.Value) || speech.Rate != Convert.ToInt32(sliderRate.Value))
{
speech.Volume = Convert.ToInt32(sliderVolume.Value);
speech.Rate = Convert.ToInt32(sliderRate.Value);
selectedSpeakData = selectedSpeakData.Remove(0, e.CharacterPosition);
speech.SpeakAsyncCancelAll();
speech.SpeakAsync(selectedSpeakData);
}
}
The Slider control raises an event ValueChanged whenever its value changes. If you handle this event you could update your speech volume from there by checking the Value property.
There does not appear to be a built-in way of doing this. Handling the SpeakProgress event will give you access to the CharacterPosition property. This gives you position in the prompt at the start of the last word read. If you do a substring on the next white-space character and pass this as a new prompt, the rest of the prompt will be spoken from this point. If you're up to it, you can calculate how long a prompt will take to be read and use the AudioPosition property to get a TimeSpan object for how long the prompt has been running.
Related
I'm building a Xaml based app with a C# backend.
I have data that needs to be entered by the user in a specific format (example: AAAA-BBBBBB-CCCC-DD etc). I currently have one text box that takes the whole thing, but for user experience I would prefer to break the example text into four boxes
one for AAAA
one for BBBBBB
one for CCCC
one for DD etc
So what I expect from the user would be abundantly clear. That part is easy enough with string concatenation
But I would like the four boxes to behave like a single box in a largely transparent manner.
Once the user enters 4 characters into textbox 1, the focus would shift to textbox 2 and they could continue typing. Additionally, if possible, I would like the focus shift to select all text already in the box, so they can easily overwrite without having to go to their mouse or doing a ctrl+a.
I've searched for how to change focus between texboxes, but could not get examples to work.
You can listen to TextChanged event of each TextBox, then check if text length is equal maximum length. If it is equal (or even greater) than maximum, move focus to next TextBox and select all text there. Refactor the logic to a method so you can simply call the same method in event handler function of each TextBox, hence can avoid writing similar codes repeatedly. Something like this will do :
private void textboxAAAA_TextChanged(object sender, TextChangedEventArgs e)
{
HandleTextChanged(textboxAAAA, textboxBBBBBB, 4);
}
private void textboxBBBBBB_TextChanged(object sender, TextChangedEventArgs e)
{
HandleTextChanged(textboxBBBBBB, textboxCCCC, 6);
}
private void textboxCCCC_TextChanged(object sender, TextChangedEventArgs e)
{
HandleTextChanged(textboxCCCC, textboxDD, 4);
}
private void HandleTextChanged(TextBox currentTextBox, TextBox nextTextBox, int maxLength)
{
var textLength = currentTextBox.Text.Length;
if (textLength >= maxLength)
{
nextTextBox.Focus(FocusState.Keyboard);
nextTextBox.SelectAll();
}
}
//in XAML
<StackPanel Orientation="Horizontal">
<TextBox x:Name="textboxAAAA" Width="60" TextChanged="textboxAAAA_TextChanged"/>
<TextBlock Text="-"/>
<TextBox x:Name="textboxBBBBBB" Width="60" TextChanged="textboxBBBBBB_TextChanged"/>
<TextBlock Text="-"/>
<TextBox x:Name="textboxCCCC" Width="60" TextChanged="textboxCCCC_TextChanged"/>
<TextBlock Text="-"/>
<TextBox x:Name="textboxDD" Width="60"/>
</StackPanel>
Note, that you don't consider case when user copy-paste serial number. What the program should do if user copy 7 letters text, and paste it to the first text box?
Other solution:
1.- You configure sequencial TabIndex properties in your four TextBoxes.
2.- You configure maxLength propoerties en your TextBoxes.
3.- You configure the next method in TextChanged event in your TextBoxex.
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var tb = (TextBox)sender;
if (tb.Text.Length == tb.MaxLength)
{
var nextTB = this.PrincipalGrid.Children.OfType<TextBox>().Where(t => t.TabIndex == (tb.TabIndex + 1)).FirstOrDefault();
if (nextTB != default(TextBox))
nextTB.Focus();
}
}
Why not to use one TextBox? Listen for text changes and include a dash(-) in text every time when it need. Do not allow user to type dashes (ignore them). Some small logic should be done for clipboard pasting and for the whole product key/text validation. Later you can split the Text via String.Split( new Char("-")) and you will get an array of codes (if you need it in this way).
I'm using Bindings to populate a Listbox, with TextBlocks, etc.
The question is :
How do I make sure that the text bound to the the Text property of a TextBlock is of specific length, or that it is displayed trimmed at some specific character length (e.g. "some very very long t..."), so that the text doesn't "overflow" the phone screen or its container?
Since Mango SDK, there is a property call TextTrimming.
So this xaml
<TextBlock Text="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" TextTrimming="WordEllipsis" Width="200" />
will produce somehting like "aaaaaaa....."
Tricky one! I forced myself to think that if the characters exceeds, say some 10 then i am going to append dots to it. So i added this textchanged event to the textbox and then made the code as follows:
private void TestTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
string temp = TestTextBox.Text;
if (temp.Length > 10)
{
char[] charArray=temp.ToCharArray();
temp = new string(charArray, 0, 10);
temp += "...";
}
TestTextBox.Text = temp;
}
I want to set a text on a textfield / textbox element with the Mircosoft UI Automation framework, that means on a AutomationElement from the ControlType.Edit or ControlType.Document.
At the moment i'm using the TextPattern to get the text from one of these AutomationElements:
TextPattern tp = (TextPattern)element.GetCurrentPattern(TextPattern.Pattern);
string text = tp.DocumentRange.GetText(-1).Trim();
But now I want to set a new text in the AutomationElement. I can't find a method for this in the TextPattern class. So I'm trying to use the ValuePattern but I'm not sure if that's the right way to do it:
ValuePattern value = element.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
value.SetValue(insertText);
Is there an other way to set the text value?
An other question is how can I get an event when the text was changed on a Edit / Document element? I tried to use the TextChangedEvent but i don't get any events fired when changing the text:
AutomationEventHandler ehTextChanged = new AutomationEventHandler(text_event);
Automation.AddAutomationEventHandler(TextPattern.TextChangedEvent, element, TreeScope.Element, ehTextChanged);
private void text_event(object sender, AutomationEventArgs e)
{
Console.WriteLine("Text changed");
}
You can use the ValuePatern, it's the way to do it. From my own code :
ValuePattern etb = EditableTextBox.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
etb.SetValue("test");
You can register to Event using:
var myEventHandler=
new AutomationEventHandler(handler);
Automation.AddAutomationEventHandler(
SelectionItemPattern.ElementSelectedEvent, // In your case you might want to use another pattern
targetApp,
TreeScope.Descendants,
myEventHandler);
And the handler method:
private void handler(object src, AutomationEventArgs e) {...}
There is also an AutomationPropertyChangedEventHandler (use Automation.AddAutomationPropertyChangedEventHandler(...) in this case) that can be useful.
Based on this sample from MSDN.
I suppose there's a limit for the lines alowed in a TextBox with the MultiLine option set to true.
I have a program that every several minutes, checks an email account, but for control purposes i put a TextBox that indicates what's been doing.
My curiosity is, does anyone know how much lines are allowed ? And does throw an exception when reached that line ?
EDIT Sorry forgot to mention is in WinForms
EDIT 2 Perhaps, someone knows of a way to eliminate older lines, will grated appreciated
There's no limit on the number of lines that a text box can display.
There is, however, a limit on the number of characters that the control can hold. See this question for further details on this topic.
If you set the TextBox.MaxLength property to zero, the amount of text is limited only by available memory.
Another solution:
<TextBox x:Name="txtAddress"
MaxLines="6"
TextWrapping="Wrap" AcceptsReturn="True"
VerticalScrollBarVisibility="Hidden"
HorizontalScrollBarVisibility="Hidden"
TextChanged="txtAddress_TextChanged"
PreviewTextInput="txtAddress_PreviewTextInput"
PreviewKeyDown="txtAddress_PreviewTextInput"/>
//...
private void txtAddress_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox txtBx = sender as TextBox;
if (txtBx.LineCount > txtBx.MaxLines)
txtAddress.Text = this._textBeforInput;
}
private string _textBeforInput = string.Empty;
private void txtAddress_PreviewTextInput(object sender, EventArgs e)
{
this._textBeforInput = txtAddress.Text;
}
There is no such limitation on Multiline TextBox both in WinForms and ASP.NET. (I have no idea of WPF :) )
I know this question is really old and has already been answered, but for those searching for an HTML/ASP.NET solution I have created a short jsFiddle http://jsfiddle.net/Z3rdZ/2/
HTML
<textarea id="limited-lines" maxlines="4"></textarea>
jQuery
$('#limited-lines').keydown(function(event){
if ( event.which == 13 ) {
var numberOfLines = $(this).val().split('\n').length;
if(numberOfLines >= $(this).attr('maxlines')){
event.preventDefault();
}
}
});
Here's my code:
private void DialogFont_Load(object sender, EventArgs e)
{
LoadInstalledFonts();
}
private void LoadInstalledFonts()
{
var fontCollection = new System.Drawing.Text.InstalledFontCollection();
foreach (var font in fontCollection.Families)
{
lstFonts.Items.Add(font.Name);
}
}
How can I display each font using its own design, sort of like a preview of the fonts? I'm using the ListBox control to list the fonts.
You can do it easily in WPF.
The XAML would look like:
<ComboBox Width="100" Height="30" x:Name="FontSelector">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" FontFamily="{Binding}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
And C# codebehind:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
FontSelector.ItemsSource = Fonts.SystemFontFamilies;
}
You could also check this article over on CodeProject which walks through (in a Winforms example) how to populate a list box with fonts like you want: http://www.codeproject.com/KB/selection/FontListBoxAndCombo.aspx
Maybe go with a ListView instead of a ListBox? The ListViewItem type has a Font property you could use. I'm not aware of any special per-item formatting capabilities of ListBox.
Update: In case you're still working on this, here's a snippet of some code that worked for me (this won't compile as-is as it's just a clip from a larger user control; I'm sure you can figure out what goes where though):
private void PopulateListView(IEnumerable<FontFamily> fontFamilies)
{
try
{
m_listView.BeginUpdate();
float fontSize = m_listView.Font.Size;
Color foreColor = m_listView.ForeColor;
Color backColor = m_listView.BackColor;
string sampleText = m_sampleText;
foreach (FontFamily fontFamily in fontFamilies)
{
var listViewItem = new ListViewItem(fontFamily.Name)
{
UseItemStyleForSubItems = false
};
var sampleSubItem = new ListViewItem.ListViewSubItem(listViewItem, sampleText, foreColor, backColor, new Font(fontFamily, fontSize));
listViewItem.SubItems.Add(sampleSubItem);
m_listView.Items.Add(listViewItem);
}
}
finally
{
m_listView.EndUpdate();
}
}
Here's what the result looks like:
First thing, I want to make sure that you are aware of the FontDialog control, and you are purposely wanting to create a custom Font Dialog. If you weren't aware of it, then maybe you can take a look at it and make sure that it doesn't fit your needs before trying to create your own. And the following Stack Overflow question shows you how to make sure it is populated with all the device fonts and not just TrueType fonts.
Now, if you still want to create your own, then the following is a simplified solution:
Add a Label to your Font Dialog and set its text to whatever you want the user to see as a sample of the font. Something like AabBcC, or it could even be a random sentence.
You can set the Font of the label in the SelectedIndexChanged event of your ListBox. This in effect changes the sample text to match the font you specify. The following is a simple example:
Note that you can also use a Textbox if you want your user to specify the text that they want to see in another font. Also, some fonts like Andy and Aharomi throw an ArgumentException stating that the Font doesn't support a regular style, so it would be wise to catch this exception type.
private void lstFonts_SelectedIndexChanged(object sender, EventArgs e)
{
lblSample.Font = new Font(lstFonts.SelectedItem.ToString(), 12);
}
Using a ListBox, I would think you'd need to do owner-draw. When drawing each list item, you'd need to select the font for that item.