I'm trying to extend the standard TextBox control in the System.Windows.Forms namespace. One of the things I'm trying to accomplish is to modify padding on the top and bottom of the TextBox (the spacing between the text and the border).
Doing it on the left/right sides is pretty simple, but I'm having a hard time getting anything to work on the top/bottom.
Here are a couple of my requirements (if possible):
Avoid extending anything besides System.Windows.Forms.TextBox (no UserControls)
I want to keep MultiLine = false
This code allows me to resize vertically, and it adds a left padding:
public class TextBoxTest : TextBox
{
public TextBoxTest()
{
base.AutoSize = false;
NativeMethods.SendMessage(Handle, NativeMethods.EM_SETMARGINS, NativeMethods.EC_LEFTMARGIN, 20);
base.Height = 55;
base.Width = 150;
base.Text = "This is a test";
}
}
This will look like:
I also tried EM_SETRECT but it requires a MultiLine TextBox.
Is a top/bottom margin (or center vertically) possible - without using a UserControl and keeping MultiLine=false?
If so, can someone point me in the right direction?
UPDATE, to clarify, the reason I want to inherit from TextBox, and not a UserControl or Panel is so it passes the duck test (if it looks like a duck, quacks like a duck, etc). I want if (myControl is TextBox) ... to evaluate to true. There may be a way to do that, I haven't done much with Type Converters and maybe that's the path I should be taking.
I want this to be a true extension of a TextBox. In other words, it can do just about everything a textbox can do plus some, but no limitations due to the fact that it's not of type "TextBox". It seems like there's gotta be a way to adjust it somehow, it supports left and right margins but seemingly not upper/lower margins. Thanks again
You cannot change the padding property of Windows forms textbox from your code.
Instead you can place a textbox in a container, like a panel
remove the border of the textbox, make sure that the BackColor property for both is same
change the Dock property of the textbox to Fill
and then apply padding to the panel.
Related
I'm trying to make a calculator where the result of the calculation should display on the right side instead of the left.
Unfortunately, you can't use tbx_main.TextAlign = HorizontalAlignment.Right; since it makes the whole text align on the right. It would really be useful if there was a way like \t where that row only gets dragged to the right. I'm unsure if there even is a solution to this...
you can use TextBox.TextAlign Property if you are are using Windows Forms
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.textbox.textalign?view=netframework-4.8
for WPF
TextBox.TextAlignment Property for WPF
https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.textbox.textalignment?view=netframework-4.8
I've created Windows forms and I'm using the textbox control for input, but I like to use it without border and other layout for textbox etc. I just want to use a underscore line and blinking cursor.
I played with the borderStyle (Fixed3D, None), backcolor=InactiveBorder etc. But I still do net get the underline... like this-> _____________ result like this: This is underline______________
I think Backcolor=InactiveBorder and BorderStyle=None is ok to use, but how to get the underline and blinking cursor?
Requirement:
blinking cursor and underline. (The doesn't blink by default, I just see a vertical line))
To fake this, you could add a label below the text box with the content being _____________________. My preferred solution would be to create a simple custom control that just draws a line.
Doesn't the caret on your system blink by default? It does on my system if the focus is on the text box.
If the caret doesn't blink by default, go to the Windows Control Panel and check your Keyboard Settings there - this is the place where you can adjust the caret blink rate.
For creating a underline for your textbox you can do like this,
First add a panel which is in the height of text box's height + underline's height.
Now add your textbox inside of that panel and set its dock to TOP.
Then set the textbox's border to none.
Now set the backcolor of the panel, according to the color need of underline.
Update:
This is VB code, i hope that you can easily convert it into c#
[ Concept: You just need to set the border for all of your textboxes as none.then In forms paint event track those text boxes and draw a line under it. ]
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles Me.Paint
Using xPen As Pen = New Pen(Color.Blue)
' Here we are using LINQ to filter the controls.
' If you don't want it, you just check all the controls by using typeof
' inside the For Each loop.
For Each xTxtBox In Me.Controls.OfType(Of TextBox)()
e.Graphics.DrawLine(xPen,
xTxtBox.Location.X,
xTxtBox.Location.Y + xTxtBox.Height,
xTxtBox.Location.X + xTxtBox.Width,
xTxtBox.Location.Y + xTxtBox.Height)
Next
End Using
End Sub
Use Masked TextBox and set Focus , e.g. maskedtextbox1.Focus(); <== this is for the blinking cursor and the masked textbox to the underline !
try :
To set logical focus to an input control
FocusManager.SetFocusedElement(this, textboxJack);
To set keyboard focus to an input control
Keyboard.Focus(textboxJill);
and for the masked textbox you can set a mask that will not be changed when you delete the text from it not like the simple textbox :)
Good luck
To do this, I would recommend creating a custom control (which is accomplished in the WinForms world by inheriting from one of the provided control classes). That custom control would then:
Provide its own drawing logic (by overriding OnPaint) in order to draw the underline and skip drawing anything else you don't want to see (e.g., the borders of the control).
Create its own caret when it receives the focus, and destroy that caret when it loses the focus. You'll find all the details on how to do this in my answer here.
You can also configure the blink rate of the caret by calling the SetCaretBlinkTime function. But note that this is not recommended, as it changes the global system setting and therefore affects other applications. It is best to do as Thorsten suggests and modify the setting on your machine if you wish to see something different. You should always respect a user's settings. There's a reason that they (or someone else) set up their system to not blink the caret.
Naturally, you will need to use P/Invoke to call these Win32 API functions related to caret management from a C# application. That shouldn't be too difficult if you know what you're doing. If you need a complete solution, consider setting a bounty on this question to persuade me to write one up for you.
I faced the same issue and built something that works fine:
public class TextBox : System.Windows.Forms.TextBox
{
public TextBox()
{
BorderStyle = BorderStyle.None;
Text = "__________"; //Sometime this doesn't work while creating the control in design mode ; don't know why
}
//protected override void OnFontChanged(EventArgs e)
//{
// base.OnFontChanged(e);
// RefreshHeight();
//}
bool loaded = false;
protected override void OnCreateControl()
{
if(!loaded)
RefreshHeight();
base.OnCreateControl();
}
private void RefreshHeight()
{
loaded = true;
Multiline = true;
Size s = TextRenderer.MeasureText(Text, Font, Size.Empty, TextFormatFlags.TextBoxControl);
MinimumSize = new Size(0, s.Height + 1);
Multiline = false;
}
}
I used bool loaded = false to avoid the app to crash in a loop because of OnCreateControl. TextBox control doesn't have OnLoad event (I'm open to another approach).
OnFontChanged can be uncommented if your app change the font size in run time
MinimumSize = new Size(0, s.Height + 1); I added 1 to avoid any error of MeasureText
I just would like to know if it is possible to dock a windows form on top of the user screen? I have been trying to do this by manually setting the position of my form to the coordinates I want. But using this method, however, allows the user to change the position of the form just by dragging it. I want to make the form docked to the upper portion of the screen since this window form will server as a menu for the project I am making.
Thanks a lot. :)
I would consider using the Control.Dock property along with one of the DockStyle enumeration values.
You might need to play with the Layout too, so that you may layout your form's controls differently depending on the DockStyle selected.
You will need, in my point of view, to consider the Control.Location property so that you get to know which DockStyle value to dock your form with.
EDIT #1
Your Windows Form has a Dock property as it inherits from Control.
Let's consider the following :
Each time your form comes closer to your right-side of the screen, for example, or of the MDI container, you want to dock right, right ? (Little word play here... =P) So, you have to subscribe to the Control.LocationChanged event.
private void myForm_LocationChanged(object sender, EventArgs e) {
if (this.Location.X > 900) then
this.Dock = DockStyle.Right;
else if (this.Location.X < 150) then
this.Dock = DockStyle.Left;
else if (this.Location.Y > 600) then
this.Dock = DockStyle.Bottom;
else if (this.Location.Y < 150) then
this.Dock = DockStyle.Top;
else
this.Dock = DockStyle.None;
}
Indeed, instead of constant values, you should use the current desktop resolution and calculate a ratio from it where you want your docking to occur.
***Disclaimer:****This code is provided as-is and has not been tested. This algorithm is hopefully enough to guide you through the docking process as you need it. Further assistance may be brought upon request.* =)
It seems the Form.DesktopLocation property is the righter tool for the job as for your main window, meaning your MDI container, for instance. As for the other windows, I would go along with something that looks like the code sample provided.
Does this help?
EDIT #2
If you want to prevent Form's overlapping, perhaps the Control.BringToFront() method could do it before or after your call to the Control.Show() method, depending on what works best for you.
So after some tweaks I finally was able to get this code working.
this.DesktopLocation = new Point((Screen.PrimaryScreen.Bounds.Width / 2 - 420), 0);
I placed that line below the InitializeComponent() and it docks my form to the center of the screen with whatever resolution values.
By setting the FormBorderStyle of your form to None, you take the drag handle away from the user so they cannot move it via the mouse.
Then you just need to place it where you want.
If you really want to take away the users options you can also set the ShowInTaskbar property to false
.NET Framework / C# / Windows Forms
I'd like the FlowLayoutPanel to automatically adjust its width or height depending on number of controls inside of it. It also should change the number of columns/rows if there is not enough space (wrap its content). The problem is that if I set autosize then the flowlayoutpanel doesn't wrap controls I insert. Which solution is the best?
Thanks!
Set the FlowLayoutPanel's MaximumSize to the width you want it to wrap at. Set WrapContents = true.
Have you tried using the TableLayoutPanel? It's very useful for placing controls within cells.
There is no such thing like impossible in software development. Impossible just takes longer.
I've investigated the problem. If there is really need for Flow Layout, it can be done with a bit of work. Since FlowLayoutPanel lays out the controls without particularly thinking about the number of rows/columns, but rather on cumulative width/height, you may need to keep track of how many controls you've already added. First of all, set the autosize to false, then hook your own size management logic to the ControlAdded/ControlRemoved events. The idea is to set the width and height of the panel in such a way, that you'll get your desired number of 'columns' there
Dirty proof of concept:
private void flowLayoutPanel1_ControlAdded(object sender, ControlEventArgs e)
{
int count = this.flowLayoutPanel1.Controls.Count;
if (count % 4 == 0)
{
this.flowLayoutPanel1.Height = this.flowLayoutPanel1.Height + 70;
}
}
if the panel has initially width for 4 controls, it will generate row for new ones. ControlRemoved handler should check the same and decrease the panel height, or get all contained controls and place them again. You should think about it, it may not be the kind of thing you want. It depends on the usage scenarios. Will all the controls be of the same size? If not, you'd need more complicated logic.
But really, think about table layout - you can wrap it in a helper class or derive new control from it, where you'd resolve all the control placing logic. FlowLayout makes it easy to add and remove controls, but then the size management code goes in. TableLayout gives you a good mechanism for rows and columns, managing width and height is easier, but you'd need more code to change the placement of all controls if you want to remove one from the form dynamically.
If possible, I suggest you re-size the FlowLayoutPanel so that it makes use of all the width that is available and then anchor it at Top, Left and Right. This should make it grow in height as needed while still wrapping the controls.
I know this is an old thread but if anyone else wonders on here then here's the solution I produced - set autosize to true on the panel and call this extension method from the flow panel's Resize event:
public static void ReOrganise(this FlowLayoutPanel panel)
{
var width = 0;
Control prevChildCtrl = null;
panel.SuspendLayout();
//Clear flow breaks
foreach (Control childCtrl in panel.Controls)
{
panel.SetFlowBreak(childCtrl, false);
}
foreach (Control childCtrl in panel.Controls)
{
width = width + childCtrl.Width;
if(width > panel.Width && prevChildCtrl != null)
{
panel.SetFlowBreak(prevChildCtrl, true);
width = childCtrl.Width;
}
prevChildCtrl = childCtrl;
}
panel.ResumeLayout();
}
Are you adding the controls dynamically basing on the user's actions? I'm afraid you'd need to change the FlowLayout properties on the fly in code, when adding new controls to it, then refreshing the form would do the trick.
I am trying to right align a control in a StatusStrip. How can I do that?
I don't see a property to set on ToolStripItem controls that specifies their physical alignment on the parent StatusStrip.
How do I get Messages drop down to be right aligned? http://i.friendfeed.com/ed90b205f64099687db30553daa79d075f280b90
Found it via MSDN forums almost immediately after posting :)
You can use a ToolStripLabel to pseudo right align controls by setting the Text property to string.Empty and setting the Spring property to true. This will cause it to fill all of the available space and push all the controls to the right of the ToolStripLabel over.
For me it took two simple steps:
Set MyRightIntendedToolStripItem.Alignment to Right
Set MyStatusStrip.LayoutStyle to HorizontalStackWithOverflow
As an added note this is due to the fact that in the Win32 API a cell is either fixed width or fills the remaining space -1
int statwidths[] = {100, -1};
SendMessage(hStatus, SB_SETPARTS, sizeof(statwidths)/sizeof(int), (LPARAM)statwidths);
SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Hi there :)");
If memory serves me correctly you can have only one fill cell (-1) per statusbar.
You could also add a third middle cell and give this the fill property to get a more concistent looking StatusBar. Consistent because Messages has an inset to its left right where you'd expect it. A bit like the mspaint shot found on the MSDN page for StatusBars
I like the creative appreach though :D
You can display the Button at the end of the StatusStrip by using the logic below.
Add a ToolstripLabel to the StatusStrip
Set text as string.Empty
Set Padding for the ToolstripLabel
For example:
this.toolStripStatusLabel1.Padding = new Padding((int)(this.Size.Width - 75), 0, 0, 0);
Keep a Toolstrip label , set Spring property as true and for label align text in BottomLeft
I found that you can set the StatusStrip Layout to HorizontalStackWithOverflow.
Then, for each control on the StatusStrip that you want on the right side, set the control Alignment to Right.
I like this better since you don't need any extra or dummy controls to align.
If you set a status strip label control’s Spring property to true, then that label takes up any space not used by other controls in the StatusStrip.
Set the RightToLeft tool strip property to True.