I would like to add an in form numberpad to my form to make the program more touch friendly. I have multiple text boxes on this form that change focus when the enter key is pressed.
I tried SendKeys.Send("#"), but when I click the button it just changes focus to the button and does nothing inside the text box I was trying to type in.
Is there a guide or something for this? I have looked and all I can find are on screen keyboards that work outside of the form, but not inside.
Expanding a little bit on the idea from Hans Passant you could use this as a starting point.
Form
In your form add the textboxes you need and a PictureBox. The picturebox will have an image with the characters your users need to be able to type.
Set the property Image to an image file (browse for it) (or create your own)
Set the property SizeMode to AutoSize so the complete picture is shown.
Next goto the events and add an eventhandler for MouseClick.
Code
Add the following code to the handler:
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
// how many rows and columns do we have
// in the picture used
const int maxrows = 4;
const int maxcols = 3;
// based on each position (numbered from left to right, top to bottom)
// what character do we want to add the textbox
var chars = new [] {'1','2','3','4','5','6','7','8','9', '+', '0', '-'};
// on which row and col is clicked, based on the mouse event
// which hold the X and Y value of the coordinates relative to
// the control.
var row = (e.Y * maxrows) / this.pictureBox1.Height;
var col = (e.X * maxcols) / this.pictureBox1.Width;
// calculate the position in the char array
var scancode = row * maxcols + col;
// if the active control is a TextBox ...
if (this.ActiveControl is TextBox)
{
// ... add the char to the Text.
// add error and bounds checking as well as
// handling of special chars like delete/backspace/left/right
// if added and needed
this.ActiveControl.Text += chars[scancode];
}
}
The code is I think self explanatory. Keep in mind that no error checking whatsoever is being done here.
Result
This is what the end result will look like:
Related
I have created a Windows Forms application and I am using label_1.Visible = false; to make my label invisible.
I want to only make the first letter of the label visible.
How can I do it?
Visibility is all-or-nothing concept: if a label, or any other component for that matter, is marked invisible, none of it is going to appear on the form.
If you want to show only the first few letters of a string in a label, use Substring method to assign label's text. In order for this to work, the actual text must be stored somewhere outside the label - say, in labelText field:
private string labelText = "Quick brown fox";
...
label_1.Text = labelText.Substring(0, 1); // Only the first character is shown
Based on your answer to a comment, it sounded like you were interested in a Marquee-style display. Here's one way to do that, by storing the whole string in one variable, and then only displaying parts of it in a label.
In the example below, we have a string of text to display stored in a variable. We add a label to display the text, and a timer is used to repeatedly change the text to make it appear that it's scrolling.
To see it in action, start a new Windows Forms Application project and replace the partial form class with the following code:
public partial class Form1 : Form
{
// Some text to display in a scrolling label
private const string MarqueeText =
"Hello, this is a long string of text that I will show only a few characters at a time. ";
private const int NumCharsToDisplay = 10; // The number of characters to display
private int marqueeStart; // The start position of our text
private Label lblMarquee; // The label that will show the text
private void Form1_Load(object sender, EventArgs e)
{
// Add a label for displaying the marquee
lblMarquee = new Label
{
Width = 12 * NumCharsToDisplay,
Font = new Font(FontFamily.GenericMonospace, 12),
Location = new Point {X = 0, Y = 0},
Visible = true
};
Controls.Add(lblMarquee);
// Add a timer to control our marquee and start it
var timer = new System.Windows.Forms.Timer {Interval = 100};
timer.Tick += Timer_Tick;
timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
// Figure out the length of text to display.
// If we're near the end of the string, then we display the last few characters
// And the balance of characters are taken from the beginning of the string.
var startLength = Math.Min(NumCharsToDisplay, MarqueeText.Length - marqueeStart);
var endLength = NumCharsToDisplay - startLength;
lblMarquee.Text = MarqueeText.Substring(marqueeStart, startLength);
if (endLength > 0) lblMarquee.Text += MarqueeText.Substring(0, endLength);
// Increment our start position
marqueeStart++;
// If we're at the end of the string, start back at the beginning
if (marqueeStart > MarqueeText.Length) marqueeStart = 0;
}
public Form1()
{
InitializeComponent();
}
}
Strings are technically byte arrays, meaning each letter can be accessed with an index.
For example:
string x = "cat";
char y = x[0];
// y now has a value of 'c'!
Perform this on the string being used for your label and use the result for your label instead. I want to also add that you need to set label_1.Visible = true; otherwise nothing will appear at all.
Applying the above to your code, you should arrive at something like this:
label_1.Visible = true;
label_1.text = label_1.text[0].ToString();
Hope that works for you!
I'm implementing some drag drop features in one my controls inheriting from a datagridview. Basically I'm dragging a row from somewhere in the DGV and dropping it somewhere else, reordering the rows. I've run into a problem though. If the DGV is too large such that there's a scrollbar, how can I have the DGV scroll up or down while the user is in the middle of a dragdrop?
I know how to get the current mouse position and also get the position of the dgv rectangle and such. So, I can easily find out if i'm in the top or bottom half of the rectangle... I just need a way to programmatically scroll the dgv. I'd prefer if I don't have to keep changing the selected cell to do this.
Any suggestions?
Thanks
Isaac
Well, since this is a datagridview... Sorry for the 'winforms' in the question... but I could just do this.. scrolling up or down one row.
Scroll up:
this.FirstDisplayedScrollingRowIndex = this.FirstDisplayedScrollingRowIndex - 1
Scroll Down:
this.FirstDisplayedScrollingRowIndex = this.FirstDisplayedScrollingRowIndex + 1;
You've gotta make sure to check that the numbers don't go out of bounds though.
you can do this by setting HorizontalScrollingOffset / VerticalScrollingOffset of the DataGridView
to set HorizontalScrollingOffset
dataGridView1.HorizontalScrollingOffset = dataGridView1.HorizontalScrollingOffset + 10;
check
DataGridView.HorizontalScrollingOffset Property
and
for VerticalScrollingOffset you can use Reflection
include namespace System.Reflection
PropertyInfo verticalOffset = dataGridView1.GetType().GetProperty("VerticalOffset", BindingFlags.NonPublic | BindingFlags.Instance);
verticalOffset.SetValue(this.dataGridView1, 10, null);
dgv.FirstDisplayedScrollingRowIndex = dgv.RowCount - 1;
You may do that using WinAPI by sending message to the control telling it to scroll up or down.
Here is the code, I hope it helps:
private const int WM_SCROLL = 276; // Horizontal scroll
private const int WM_VSCROLL = 277; // Vertical scroll
private const int SB_LINEUP = 0; // Scrolls one line up
private const int SB_LINELEFT = 0;// Scrolls one cell left
private const int SB_LINEDOWN = 1; // Scrolls one line down
private const int SB_LINERIGHT = 1;// Scrolls one cell right
private const int SB_PAGEUP = 2; // Scrolls one page up
private const int SB_PAGELEFT = 2;// Scrolls one page left
private const int SB_PAGEDOWN = 3; // Scrolls one page down
private const int SB_PAGERIGTH = 3; // Scrolls one page right
private const int SB_PAGETOP = 6; // Scrolls to the upper left
private const int SB_LEFT = 6; // Scrolls to the left
private const int SB_PAGEBOTTOM = 7; // Scrolls to the upper right
private const int SB_RIGHT = 7; // Scrolls to the right
private const int SB_ENDSCROLL = 8; // Ends scroll
[DllImport("user32.dll",CharSet=CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg,IntPtr wParam, IntPtr lParam);
Now assuming you have a textbox control on your form. You can move it with:
SendMessage(textBox1.Handle,WM_VSCROLL,(IntPtr)SB_PAGEUP,IntPtr.Zero); //ScrollUp
SendMessage(textBox1.Handle,WM_VSCROLL,(IntPtr)SB_PAGEDOWN,IntPtr.Zero); //ScrollDown
If that classic general solution doesn't work for you. You may want to look at FirstDisplayedScrollingRowIndex Property and change it regarding your mouse position during dragging.
You need to implement the DragOver event. Check if the mouse is located close to the top or the bottom of the control (use PointToClient). When it is, enable a timer with an interval of ~200 msec. In the Tick event handler scroll the DGV by a row. Disable the timer when the mouse isn't close and after DoDragDrop returns. The user can now easily and intuitively scroll the grid just be hovering near the ends.
Answer using MaxEcho's answer as a base. You can override the OnScroll event of the DataGridView. The eventArgs in this method contain the first visible line number. You can pass this line number to the other DataGridView, and set the FirstDisplayedScrollRowIndex to cause it to scroll to that position.
The only issue is somewhat cosmetic, if you scroll quite fast, the second datagridview pauses updating/animating and blinks to the active line once your scrolling slows.
class DGVSubclass : DataGridView
{
public Action<ScrollEventArgs> delOnScroll;
....
protected override void OnScroll(ScrollEventArgs e)
{
base.OnScroll(e);
if (e.ScrollOrientation == ScrollOrientation.VerticalScroll &&
delOnScroll != null)
delOnScroll.Invoke(e);
}
public void setSrcoll(ScrollEventArgs e)
{
//ScrollEventArgs.NewValue is a line number
this.FirstDisplayedScrollingRowIndex = e.NewValue;
}
public void bindScroll(DGV3_Broker dgv)
{
delOnScroll = dgv.setSrcoll;
}
}
dgvTwo.bindScroll(dgvOne); //DGVTwo Scrollbar controls both,
I have 2 comboboxes for the font and the fontsize. When I click them it changes the font size or the font in my richtextbox. Now I want it to work like in word. If the line you just moved to is in a different font or size. It should detect that and change the comboxes to match the font and size of the current line. Somoeone else asked this same question and got a result which didn't work for me. It was as follows
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
MessageBox.Show("we got here"); // this is my added part to let me know if the code is even getting executed. It is not.
richTextBox1.SelectionStart = 1;
richTextBox1.SelectionLength = 1;
comboBox1.Text = richTextBox1.SelectionFont.ToString();
comboBox2.Text = null;
comboBox2.Text = richTextBox1.SelectionFont.Size.ToString();
}
I held out hope that it was my answer but I could not see how SelectionFont would make any difference when nothing was selected. Also the richTextBox1_SelectionChanged event seems to not be being called when I move through the document with the up/down arrows. The problem is not with the comboboxes, the problem is that as I arrow through my document I need to be able to know what font and size it is at the caret position so it can fire an event to change the combo boxes to match.
The code that you are using will always make the selection from character at index 1 and are of the length 1. instead for that you need to use which will give you the the following code without specifying the selection(so it will take the selection from the ritchTextBox).
string fontName = richTextBox1.SelectionFont.Name;
float fontsize = richTextBox1.SelectionFont.Size;
You should save the values for the new comboBox position temporarily in variables, otherwise if you do it directly
comboBox1.SelectedIndex = comboBox1.FindStringExact(richTextBox1.SelectionFont.Name);
the comboBox1_SelectedIndexChanged event will be immediately called and could affect the results.
So just try:
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
int comboBox1Index = comboBox1.FindStringExact(richTextBox1.SelectionFont.Name);
int comboBox2Index = comboBox2.FindStringExact(richTextBox1.SelectionFont.Size.ToString());
comboBox1.SelectedIndex = comboBox1Index;
comboBox2.SelectedIndex = comboBox2Index;
}
I adapted Sujith's solution and half of Markus's solution and came up with the following which works just fine for me:
Private Sub Description_SelectionChanged(sender As Object, e As EventArgs) Handles Description.SelectionChanged
Dim fontName As String = Description.SelectionFont.Name
Dim fontSize As Single = Description.SelectionFont.Size
tbSelectFont.Text = fontName
tbSelectSize.Text = fontSize
End Sub
My requirement is i am trying to develop a text editor for my mother tongue language.
That is i am trying to develop tamil text editor using unicode characters.
When i am pressing key on the keyboard(English character like) k that time i want to replace two characters like "&H0b95" "&H0bcd".
How to i implement this concept? whether it is possible or not.
sample code when keypress event
e.keychar=chrw("&H0b95") & chrw("&H0bcd") 'This code is not Execute Becuase it get Only One Character'
TextBox1.Text=chrw("&H0b95") & chrw("&H0bcd")
I am already finish this concept but the only problem is cursor position is scroll that is when i am assigning the character to textbox that time selection start is zero so the cursor go to first position. after second line i am set the cursor position to the length of the text that is cursor come to end of the text.
so the problem is the cursor move up and down when i am pressing a key at all the times. how to solve this problem. can any body given an idea to me.
Click here! To See the Tamil Unicode Characters Table.
You need to stop the textbox from rendering, while you update the cursor position. I had done something similar before with a console application. But can't find the code to reference it here.
You need to update the SelectionStart Property and increase its length with the size of the new text inserted.
Something like:
int curPos = txtEditor.SelectionStart;
if (e.KeyChar == 'k')
{
txtEditor.Text=txtEditor.Text.Insert(txtEditor.SelectionStart, "jj");
txtEditor.SelectionLength = 0;
}
txtEditor.SelectionStart = curPos + 2; //or whatever the length of text u inserted
this TextBox, adds "jj" when the user presses k key. The cursor position is corrcted.
public class MyTextBox : TextBox
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.K)
{
int pos = this.SelectionStart;
this.Text = this.Text.Substring(0, this.SelectionStart) + "jj"
+ this.Text.Substring(this.SelectionStart);
this.SelectionStart = pos + 2;
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
I need to allow a long label to be scrolled through on it's own. I do not want a text-box of any sort. I would like to be able to format the text inside. It definitely needs to scroll own its own, not with the window. I have added a scrollbar successfully, but I have no idea how to begin to use it's event/s.
thanks
i tried using a panel? I will again, perhaps I made an error.
:: yeah I tried that again, it simply cuts off my label.
Place the label inside a Panel and set AutoScroll to true.
Add a label (here label1) and a scrollbar (here hScrollBar1) and deal with the event in this fashion (assuming hScrollBar1.Maximum = 100 and hScrollBar1.Minimum = 0):
private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
{
const int labellength = 10;
String thetext = "Ozzie ozzie ozzie! OI OI OI! And then some...";
int offset = (int)((double)e.NewValue / 100 * (thetext.Length - labellength));
label1.Text = thetext.Substring(offset, labellength);
}
Naturally you would have to specify the 'amount' of text to appear in the label by changing labellength. If you find that you can not scroll to the very end, lower hScrollBar1.LargeChange to 1.