I have this C# winform with tabs on toolstrip. I need to place that plus button on extreme right "+" besides the latest tab on toolstrip. I have tried for location, but couldn't get it. Is there any other way to do this. The button should shift its position based on the new tab added or deleted
Here is a solution that uses a workaround: It owner-draws the Tab control in order to get the Bounds of each Tab..:
private void tabControl_DrawItem(object sender, DrawItemEventArgs e)
{
var page = tabControl.TabPages[e.Index];
e.DrawBackground();
e.DrawFocusRectangle();
TextRenderer.DrawText(e.Graphics, page.Text, page.Font, e.Bounds, e.ForeColor);
if (e.Index == tabControl.TabCount - 1)
button6.Left = tabControl.Left + e.Bounds.Right + 3;
}
private void buttonAdd_Click(object sender, EventArgs e)
{
tabControl.TabPages.Add("new page " + tabControl.TabCount);
}
private void buttonRemoveLast_Click(object sender, EventArgs e)
{
tabControl.TabPages.RemoveAt(tabControl.TabCount - 1);
}
You may want to change the owner-drawing to suit your application.. There a are quite a few examples around.
Related
Ehm, umm, this means some lines should be two-lined in size. My boss think this is more simple solution, than limit displayed text to fit width and don't like horizontal scroll bar >_<
lst.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
lst.MeasureItem += lst_MeasureItem;
lst.DrawItem += lst_DrawItem;
private void lst_MeasureItem(object sender, MeasureItemEventArgs e)
{
e.ItemHeight = (int)e.Graphics.MeasureString(lst.Items[e.Index].ToString(), lst.Font, lst.Width).Height;
}
private void lst_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
e.DrawFocusRectangle();
e.Graphics.DrawString(lst.Items[e.Index].ToString(), e.Font, new SolidBrush(e.ForeColor), e.Bounds);
}
private void lst_MeasureItem(object sender, MeasureItemEventArgs e)
{
e.ItemHeight = (int)e.Graphics.MeasureString(lst.Items[e.Index].ToString(), lst.Font, lst.Width).Height;
}
private void lst_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
e.DrawFocusRectangle();
e.Graphics.DrawString(lst.Items[e.Index].ToString(), e.Font, new SolidBrush(e.ForeColor), e.Bounds);
}
To get the right display member to show up when data binding, replace
lst.Items[e.Index].ToString()
with a casted version of the property. So if your binding source is class object Car it would look like
((Car)lst.Items[e.Index]).YourDisplayProperty
Then the above functions can appropriately measure the string and draw it. :)
Helpful link
Check out this answer. It overrides the template of the listbox with a textblock which wraps the text. Hope it's useful. To solve your problem I think you shold add : ScrollViewer.HorizontalScrollBarVisibility="Disabled" . Found it here
To make binding correct, be sure to add check "lst.Items.Count > 0" to lst_MeasureItem function. Here is my example:
if (lst.Items.Count > 0)
{
e.ItemHeight = (int)e.Graphics.MeasureString(lst.Items[e.Index].ToString(), lst.Font, lst.Width).Height;
}
Everything else seems to work nicely after that.
I'm building an application in which I'd like a user to be able to reorder pictures in a form in two columns. I've got a flowLayoutPanel of a set width, and pictures are added via the OpenFileDialog and scaled to half the width (minus an allowance for a scroll bar) of the flow layout panel.
This is where I'm stuck - I've tried adding the images as Labels, Buttons, and now PictureBoxes and I can't work out how to actually move them around. I gave up on labels because CanSelect is false - although I didn't know if that would have made a difference - and I moved on from buttons because I realised picture boxes existed. I'm open to switching out which controls I use but the images will always need to be in two columns.
Here's the code I currently have for the DragEnter and DragDrop events:
private void flowLayoutPanel_6_Cards_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.All;
}
private void flowLayoutPanel_6_Cards_DragDrop(object sender, DragEventArgs e)
{
MessageBox.Show("dropped");
}
How can I implement this? What controls should I use and what properties should I be looking at to make this possible?
So thanks to #TaW's comment I now know that you have to add a DoDragDrop call to the MouseDown event on whatever you're dragging. My now-working code is below (thanks mostly to this tutorial):
private void flowLayoutPanel_6_Cards_DragDrop(object sender, DragEventArgs e)
{
PictureBox picture = (PictureBox)e.Data.GetData(typeof(PictureBox));
FlowLayoutPanel _source = (FlowLayoutPanel)picture.Parent;
FlowLayoutPanel _destination = (FlowLayoutPanel)sender;
if (_source != _destination)
{
//where did you even get this from?
}
else
{
Point p = _destination.PointToClient(new Point(e.X, e.Y));
var item = _destination.GetChildAtPoint(p);
int index = _destination.Controls.GetChildIndex(item, false);
_destination.Controls.SetChildIndex(picture, index);
_destination.Invalidate();
}
}
private void flowLayoutPanel_6_Cards_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.All;
}
void p_MouseDown(object sender, MouseEventArgs e)
{
PictureBox p = (PictureBox)sender;
p.DoDragDrop(p, DragDropEffects.All);
}
I'm working on a C# project using WPF. In my MainWindow I just got rid of the default windows border and made an own border instead with a png file. I just set this as the background of the MainWindow.
Now I made some kinda tricky way to make my window move:
private void Window_MouseDown(object sender, MouseButtonEventArgs e) {
mouseDown = true;
lastX = (int)e.GetPosition(this).X;
lastY = (int)e.GetPosition(this).Y;
}
private void Window_MouseUp(object sender, MouseButtonEventArgs e) {
mouseDown = false;
}
private void Window_MouseMove(object sender, MouseEventArgs e) {
if (mouseDown) {
int xDiff = (int)e.GetPosition(this).X - lastX;
int yDiff = (int)e.GetPosition(this).Y - lastY;
this.Left += xDiff;
this.Top += yDiff;
}
}
private void Window_MouseLeave(object sender, MouseEventArgs e) {
mouseDown = false;
}
Now this doesn't really work properly. This way the user can move the window at all clear spaces, even on Labels and TextBlocks. Is there a way to give the background or a border these kind of events? Or is there a better way to integrate borders?
Thanks in advance!
As you said, behavior is erratic when done manually but there's a fix for it.
This is the method in the framework that is specially for doing that :
http://msdn.microsoft.com/en-us/library/system.windows.window.dragmove(v=vs.110).aspx
I'm in the stages of making a program which will require a tabpage to flash when an event happens
I've googled around, and i came across this: Blink tab header on receiving event. This is similar, but uses WPF, and i'm using WinForms, and i'm not even sure that does what i want :L
I've also found this: C#: Flash Window in Taskbar via Win32 FlashWindowEx. This is what i want, but obvious for the whole form, and in the taskbar, not 'in form'
Anyone got any ideas?
I'm not saying this is the best way or even a great way to accomplish this, but it does work. I've used code similar to this when I needed to something similar.
The tabControl1 has two tabs and I blink tab 1 (the second tab).
For my example that I threw together, I set tabControl1's DrawMode property to "OwnerDrawFixed" and then a couple of buttons which start/stop the timer. The interval was something like 750ms but you could choose whatever, of course. On a timer1_Tick event, I swap out the current color and tell the tabControl1 to refresh itself. That'll make the DrawItem event get raised and then I either draw the rectangle the current color if it is tab page 1 or the backcolor if not. Then I draw the tabpage's text.
It works. Could use some tweaking for sure. Give it a whirl!
public partial class Form1 : Form
{
Color currentColor = Color.Green;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (currentColor == Color.Yellow)
currentColor = Color.Green;
else
currentColor = Color.Yellow;
tabControl1.Refresh();
}
private void button2_Click(object sender, EventArgs e)
{
timer1.Stop();
}
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
if (timer1.Enabled && e.Index == 1)
{
e.Graphics.FillRectangle(new SolidBrush(currentColor), e.Bounds);
}
else
{
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), e.Bounds);
}
Rectangle paddedBounds = e.Bounds;
paddedBounds.Inflate(-2, -2);
e.Graphics.DrawString(tabControl1.TabPages[e.Index].Text, this.Font, SystemBrushes.HighlightText, paddedBounds);
}
}
I have a custom control and I want the user to be able to drag it. So I put in the following code in the custom control:
void MoveableStackPanel_MouseMove(object sender, MouseEventArgs e)
{
if (IsMoving)
{
Point newLoc = e.GetPosition(null);
MainWindow.Instance.Title = newLoc.ToString(); // Debug
Margin = new Thickness(newLoc.X - 48, newLoc.Y - 48, 0, 0);
}
}
Note the "-48" in the code.
When the mouse is moved up or left then the mouse is not in the controls area anymore and thus does no longer trigger the MouseMove event. So I added the -48 twice to work around that. But when the user moves the mouse faster than the framework can update then the mouse will get outside the controls area and the control also won't move anymore.
I was thinking about assigning an IMovableInterface and keep lists of controls that are moving in the main form and such but that is all such a hassle and such... What is the proper solution?
P.S.: the controls are generated dynamically so I need the solution in C# code and not in XML.
Try using the CaptureMouse Method.
See if something like this works for you.:
void moveableStackPanel1_MouseUp(object sender, MouseButtonEventArgs e)
{
ReleaseMouseCapture();
}
void moveableStackPanel1_MouseDown(object sender, MouseButtonEventArgs e)
{
if (IsEnabled && IsVisible)
CaptureMouse();
}
void moveableStackPanel1_MouseMove(object sender, MouseEventArgs e)
{
if (IsMouseCaptured)
{
Point newLoc = e.GetPosition(null);
Margin = new Thickness(newLoc.X, newLoc.Y, 0, 0);
}
}