Standalone scroll bar in C# Text box - c#

In my project, I need a stand alone scroll bar for my text box. So I have created a customized scroll bar. Any idea How to use my customized scroll bar(both Horizontal and Vertical) in the text box instead of built-in scroll bar?
Please find my sample code below. (In original code the textbox and the scrollbar is skinnable. I cannot post the actual code here...)
public partial class EditControl : Control
{
int BORDERWIDTH = SystemInformation.Border3DSize.Width;
int SCROLLBARWIDTH = SystemInformation.VerticalScrollBarWidth;
CustomTextBox editCtrl;
VScrollBar vScrollBar = null;
public EditControl()
{
InitializeComponent();
editCtrl = new CustomTextBox();
this.Width = 200 + SCROLLBARWIDTH;
this.Height = 140;
editCtrl.Width = this.Width - SCROLLBARWIDTH;
editCtrl.Height = this.Height;
editCtrl.Multiline = true;
editCtrl.Left = Left;
vScrollBar = new VScrollBar();
vScrollBar.Height = this.Height;
vScrollBar.Location = new Point(editCtrl.Width, 1);
vScrollBar.Scroll += new ScrollEventHandler(vScrollBar_Scroll);
this.Controls.Add(editCtrl);
this.Controls.Add(vScrollBar);
}
private void vScrollBar_Scroll(object sender, ScrollEventArgs e)
{
//Code to scroll the text box
//editCtrl.ScrollTo(position);
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
editCtrl.Width = this.Width - SCROLLBARWIDTH;
editCtrl.Height = this.Height;
}
public partial class CustomTextBox : TextBox
{
public CustomTextBox()
{
//InitializeComponent();
}
public void ScrollTo(int Position)
{
//Code to scroll the contents.
}
}
}
}

The problem is solved. I have masked the original scrollbar of textbox by my customized scrollbar. GetScrollInfo API is used to synch the scrollbars.

Related

How can we pop-up picture boxes in c# forms like bing images search do

I am trying to make my dynamic generated picture boxes acts on a mouse hover like the "bing" do. Below is the picture attached of what bing search looks like on mouse hover :
Now this is my search results of a project I am working on, what i really want to do is that I want to make picture pop-up as the way which is shown above in bing search.
Please note that all of the picture boxes are generated dynamically on the run time.
if you are using picture boxes.
then you can enhance the current picture box like this
and use it.
//extending the picture box
public class PicControl : PictureBox
{
// variables to save the picture box old position
private int _OldWidth;
private int _OldHeight;
private int _OldTop;
private int _OldLeft;
public PicControl()
{
}
protected override void OnLoadCompleted(System.ComponentModel.AsyncCompletedEventArgs e)
{
_OldTop = this.Top;
_OldLeft = this.Left;
_OldWidth = this.Width;
_OldHeight = this.Height;
base.OnLoadCompleted(e);
}
protected override void OnMouseEnter(EventArgs e)
{
//once mouse enters
// take the backup of height width top left
//so we can restore once mouse leaves
_OldTop = this.Top;
_OldLeft = this.Left;
_OldWidth = this.Width;
_OldHeight = this.Height;
//decrease the control top left to show hover effect
this.Top = this.Top - 10;
this.Left = this.Left - 10;
// same increase the height width
this.Height = this.Height + 20;
this.Width = this.Width + 20;
// show to control on top of all
this.BringToFront();
//trigger the base event
base.OnMouseEnter(e);
}
protected override void OnMouseLeave(EventArgs e)
{
// mouse leaves now we have to restore
//picture box to its original position
this.Height = _OldHeight;
this.Width = _OldWidth;
this.Left = _OldLeft;
this.Top = _OldTop;
base.OnMouseLeave(e);
}
}
Now when you add this class in your project and build it,it will
show you PicControl in your toolbox you can replace pictureBox with PicContorl
in order get that effect.
hope it will helps you.
Here is some example how you could make very trivial popup for such images.
//Sample object representing one of your pictures
PictureBox pb1 = new PictureBox();
List<PictureBox> images = new List<PictureBox>();
images.Add(pb1);
int frameSize = 5;
PictureBox popup = new PictureBox();
popup.Visible = false;
popup.MouseLeave += (s, a) =>
{
popup.Visible = false;
};
foreach (var pb in images)
{
pb.MouseEnter += (s, a) =>
{
var sender = (PictureBox)s;
popup.Image = sender.Image;
popup.Left = sender.Left - frameSize;
popup.Top = sender.Top - frameSize;
popup.Width = sender.Width + (2 * frameSize);
popup.Height = sender.Height + (2 * frameSize);
popup.Visible = true;
popup.BringToFront();
};
}
Let's assume your picture boxes are in "images" collection. We have one more picture box which is hidden that will work as popup.
Next for each of them we bind to MouseEnter event. On MouseEnter we position popup picturebox above the hovered image and we set there same image but we make it slightly bigger and centered over underlying picture and we show the popup.
We are also bound to MouseLeave event of popup so when mouse leaves the popup it will dissapear.
Of course it's just a concept to inspire you for further development. Remember to mark as answer if helps you and you like it :)
Use this code in style sheet
.image:hover {
-webkit-transform:scale(1.2); transform:scale(1.2);
}
.image {
-webkit-transition: all 0.7s ease; transition: all 0.7s ease;
}
and pass this class to the image
<img alt="" src="../Sample%20Pictures/Chrysanthemum.jpg"
style="width: 301px; height: 196px" class="image " />
input:-
Output:-

Painting a TextBox

I'm in need of a way to make TextBox appear like a parallelogram but i can't figure out how to do so. I currently have this code:
private void IOBox_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Point cursor = PointToClient(Cursor.Position);
Point[] points = { cursor, new Point(cursor.X + 50, cursor.Y), new Point(cursor.X + 30, cursor.Y - 20),
new Point(cursor.X - 20, cursor.Y - 20) };
Pen pen = new Pen(SystemColors.MenuHighlight, 2);
g.DrawLines(pen, points);
}
But apparently it's not working. Either i misplaced/misused it or i'm not doing something right.
This is the method that i use to add it.
int IOCounter = 0;
private void inputOutput_Click(object sender, EventArgs e)
{
IOBox box = new IOBox();
box.Name = "IOBox" + IOCounter;
IOCounter++;
box.Location = PointToClient(Cursor.Position);
this.Controls.Add(box);
}
Any idea how i can fix it? IOBox is a UserControl made by me which contains a TextBox. Is that rightful to do?
If its possible, you should make your application using WPF. WPF is designed to do exactly what you are trying to do.
However, it can be done in WinForms, though not easily. You will need to make a new class that inherits the TextBox WinForm control. Here is an example that makes a TextBox look like a circle:
public class MyTextBox : TextBox
{
public MyTextBox() : base()
{
SetStyle(ControlStyles.UserPaint, true);
Multiline = true;
Width = 130;
Height = 119;
}
public override sealed bool Multiline
{
get { return base.Multiline; }
set { base.Multiline = value; }
}
protected override void OnPaintBackground(PaintEventArgs e)
{
var buttonPath = new System.Drawing.Drawing2D.GraphicsPath();
var newRectangle = ClientRectangle;
newRectangle.Inflate(-10, -10);
e.Graphics.DrawEllipse(System.Drawing.Pens.Black, newRectangle);
newRectangle.Inflate(1, 1);
buttonPath.AddEllipse(newRectangle);
Region = new System.Drawing.Region(buttonPath);
base.OnPaintBackground(e);
}
}
Keep in mind that you will still have to do other things, such as clipping the text, etc. But this should get you started.

OnFontChange method

I have my control MyLabel and when I change the Font Size must perform this code in the constructor. How to make this code worked?
protected override void OnFontChanged(EventArgs e)
{
if (AutoSize_)
{
this.AutoSize = true;
remember_size = this.Size;
this.AutoSize = false;
this.Size = new Size(remember_size.Width, remember_size.Height);
remember_size = this.Size;
}
...
this.Invalidate();
}
But don't work. For example this code work:
protected override void OnFontChanged(EventArgs e)
{
if (AutoSize_)
{
this.AutoSize = true;
}
...
this.Invalidate();
}
If your goal is to resize the label so the text is visible, regardless of the font size, the AutoSize property will do this for you.. However if you for some reason wish to handle this with your own code, you could try setting the AutoSize property to false (and not change it..)
The following code method can be called from any Form, UserControl, or Control. It will return the size of the specified text in the specified font.
public static Size MeasureText(Graphics graphicsDevice, String text, Font font)
{
System.Drawing.SizeF textSize = graphicsDevice.MeasureString(text, font);
int width = (int)Math.Ceiling(textSize.Width);
int heigth = (int)Math.Ceiling(textSize.Height);
Size size = new Size(width, heigth);
return size;
}
Now you will need to check that the label has not outgrown the parent container, which would cause some of the labels text to be cut off. Something like the following will accomplish this:
private void ResizeParentAccordingToLabelSize(Label resizedLabel)
{
int necessaryWidth = resizedLabel.Location.X + resizedLabel.Width;
int necessaryHeight = resizedLabel.Location.Y + resizedLabel.Height;
if (necessaryWidth > this.Width)
{
this.Width = necessaryWidth;
}
if (necessaryHeight > this.Height)
{
this.Height = necessaryHeight;
}
}

How to scroll in flowlayout panel without showing scrollbar in windows form

I am working on a touch screen POS in WinForms.
I have a flowlayoutpanel and add buttons dynamically but I dont want to show a scrollbar.
I use 2 buttons to scroll instead, so please help me how to scroll without showing a scrollbar
Try placing the FlowLayoutPanel inside another panel with these properties:
flowLayoutPanel1.AutoScroll = false;
flowLayoutPanel1.AutoSize = true;
flowLayoutPanel1.AutoSizeMode = AutoSizeMode.GrowAndShrink;
From here, you have to control yourself the location of the FlowLayoutPanel1 inside your panel (which should also have AutoScroll = false;) based on your two buttons.
Take two buttons btnLeft and btnRight and try this code :
private void btnLeft_Click(object sender, EventArgs e)
{
if (flowPanelItemCategory.Location.X <= xpos)
{
xmin = flowPanelItemCategory.HorizontalScroll.Minimum;
if (flowPanelItemCategory.Location.X >= xmin)
{
xpos -= 100;
flowPanelItemCategory.Location = new Point(xpos, 0);
}
}
}
private void btnRight_Click(object sender, EventArgs e)
{
if (flowPanelItemCategory.Location.X <= xpos)
{
xmax = flowPanelItemCategory.HorizontalScroll.Maximum;
if (flowPanelItemCategory.Location.X < xmax)
{
xpos += 100;
flowPanelItemCategory.Location = new Point(xpos, 0);
}
}
}

Change the borderColor of the TextBox

How can I change the BorderColor of the Textbox when a user Clicks on it or focuses on it?
You can handle WM_NCPAINT message of TextBox and draw a border on the non-client area of control if the control has focus. You can use any color to draw border:
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class ExTextBox : TextBox
{
[DllImport("user32")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);
private const int WM_NCPAINT = 0x85;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_NCPAINT && this.Focused)
{
var dc = GetWindowDC(Handle);
using (Graphics g = Graphics.FromHdc(dc))
{
g.DrawRectangle(Pens.Red, 0, 0, Width - 1, Height - 1);
}
}
}
}
Result
The painting of borders while the control is focused is completely flicker-free:
BorderColor property for TextBox
In the current post I just change the border color on focus. You can also add a BorderColor property to the control. Then you can change border-color based on your requirement at design-time or run-time. I've posted a more completed version of TextBox which has BorderColor property:
in the following post:
BorderColor property for TextBox
try this
bool focus = false;
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (focus)
{
textBox1.BorderStyle = BorderStyle.None;
Pen p = new Pen(Color.Red);
Graphics g = e.Graphics;
int variance = 3;
g.DrawRectangle(p, new Rectangle(textBox1.Location.X - variance, textBox1.Location.Y - variance, textBox1.Width + variance, textBox1.Height +variance ));
}
else
{
textBox1.BorderStyle = BorderStyle.FixedSingle;
}
}
private void textBox1_Enter(object sender, EventArgs e)
{
focus = true;
this.Refresh();
}
private void textBox1_Leave(object sender, EventArgs e)
{
focus = false;
this.Refresh();
}
This is an ultimate solution to set the border color of a TextBox:
public class BorderedTextBox : UserControl
{
TextBox textBox;
public BorderedTextBox()
{
textBox = new TextBox()
{
BorderStyle = BorderStyle.FixedSingle,
Location = new Point(-1, -1),
Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
AnchorStyles.Left | AnchorStyles.Right
};
Control container = new ContainerControl()
{
Dock = DockStyle.Fill,
Padding = new Padding(-1)
};
container.Controls.Add(textBox);
this.Controls.Add(container);
DefaultBorderColor = SystemColors.ControlDark;
FocusedBorderColor = Color.Red;
BackColor = DefaultBorderColor;
Padding = new Padding(1);
Size = textBox.Size;
}
public Color DefaultBorderColor { get; set; }
public Color FocusedBorderColor { get; set; }
public override string Text
{
get { return textBox.Text; }
set { textBox.Text = value; }
}
protected override void OnEnter(EventArgs e)
{
BackColor = FocusedBorderColor;
base.OnEnter(e);
}
protected override void OnLeave(EventArgs e)
{
BackColor = DefaultBorderColor;
base.OnLeave(e);
}
protected override void SetBoundsCore(int x, int y,
int width, int height, BoundsSpecified specified)
{
base.SetBoundsCore(x, y, width, textBox.PreferredHeight, specified);
}
}
WinForms was never good at this and it's a bit of a pain.
One way you can try is by embedding a TextBox in a Panel and then manage the drawing based on focus from there:
public class BorderTextBox : Panel {
private Color _NormalBorderColor = Color.Gray;
private Color _FocusBorderColor = Color.Blue;
public TextBox EditBox;
public BorderTextBox() {
this.DoubleBuffered = true;
this.Padding = new Padding(2);
EditBox = new TextBox();
EditBox.AutoSize = false;
EditBox.BorderStyle = BorderStyle.None;
EditBox.Dock = DockStyle.Fill;
EditBox.Enter += new EventHandler(EditBox_Refresh);
EditBox.Leave += new EventHandler(EditBox_Refresh);
EditBox.Resize += new EventHandler(EditBox_Refresh);
this.Controls.Add(EditBox);
}
private void EditBox_Refresh(object sender, EventArgs e) {
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e) {
e.Graphics.Clear(SystemColors.Window);
using (Pen borderPen = new Pen(this.EditBox.Focused ? _FocusBorderColor : _NormalBorderColor)) {
e.Graphics.DrawRectangle(borderPen, new Rectangle(0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1));
}
base.OnPaint(e);
}
}
Using OnPaint to draw a custom border on your controls is fine. But know how to use OnPaint to keep efficiency up, and render time to a minimum. Read this if you are experiencing a laggy GUI while using custom paint routines: What is the right way to use OnPaint in .Net applications?
Because the accepted answer of PraVn may seem simple, but is actually inefficient. Using a custom control, like the ones posted in the answers above is way better.
Maybe the performance is not an issue in your application, because it is small, but for larger applications with a lot of custom OnPaint routines it is a wrong approach to use the way PraVn showed.
set Text box Border style to None
then write this code to container form "paint" event
private void Form1_Paint(object sender, PaintEventArgs e)
{
System.Drawing.Rectangle rect = new Rectangle(TextBox1.Location.X,
TextBox1.Location.Y, TextBox1.ClientSize.Width, TextBox1.ClientSize.Height);
rect.Inflate(1, 1); // border thickness
System.Windows.Forms.ControlPaint.DrawBorder(e.Graphics, rect,
Color.DeepSkyBlue, ButtonBorderStyle.Solid);
}
With PictureBox1
.Visible = False
.Width = TextBox1.Width + 4
.Height = TextBox1.Height + 4
.Left = TextBox1.Left - 2
.Top = TextBox1.Top - 2
.SendToBack()
.Visible = True
End With
Here is my complete Flat TextBox control that supports themes including custom border colors in normal and focused states.
The control uses the same concept mentioned by Reza Aghaei https://stackoverflow.com/a/38405319/5514131 ,however the FlatTextBox control is more customizable and flicker-free.
The control handles the WM_NCPAINT window message in a better way to help eliminate flicker.
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WindowMessage.WM_NCPAINT AndAlso _drawBorder AndAlso Not DesignMode Then 'Draw the control border
Dim w As Integer
Dim h As Integer
Dim clip As Rectangle
Dim hdc As IntPtr
Dim clientRect As RECT = Nothing
GetClientRect(Handle, clientRect)
Dim windowRect As RECT = Nothing
GetWindowRect(Handle, windowRect)
w = windowRect.Right - windowRect.Left
h = windowRect.Bottom - windowRect.Top
clip = New Rectangle(CInt((w - clientRect.Right) / 2), CInt((h - clientRect.Bottom) / 2), clientRect.Right, clientRect.Bottom)
hdc = GetWindowDC(Handle)
Using g As Graphics = Graphics.FromHdc(hdc)
g.SetClip(clip, CombineMode.Exclude)
Using sb = New SolidBrush(BackColor)
g.FillRectangle(sb, 0, 0, w, h)
End Using
Using p = New Pen(If(Focused, _borderActiveColor, _borderNormalColor), BORDER_WIDTH)
g.DrawRectangle(p, 0, 0, w - 1, h - 1)
End Using
End Using
ReleaseDC(Handle, hdc)
Return
End If
MyBase.WndProc(m)
End Sub
I have removed the default BorderStyle property and replaced it with a simple boolean DrawBorder property that controls whether to draw a border around the control or not.
Use the BorderNormalColor property to specify the border color when the TextBox has no focus, and the BorderActiveColor property to specify the border color when the control receives focus.
The FlatTextBox comes with two themes VS2019 Dark and VS2019 Light, use the Theme property to switch between them.
Complete FlatTextBox control code written in VB.NET
https://gist.github.com/ahmedosama007/37fe2004183a51a4ea0b4a6dcb554176

Categories