I have a Custom panel which contains 4 labels (in example pasted, I have erased definition of those 2 I didn't used).
This custom panel is added to a panel dynamically, as many records I have in an array.
The parent panel, has the Horizontal scroll enabled = false, as I should scroll only vertically.
Everything works fine, as I can use mouse on vertical scrollbar and I can scroll the panel container. But when I want to use mouse wheel to scroll all the custom panels (child objects) it does not do anything.
I have tried many of the solutions that works for other on this site, but none of them works for me and I don't know why.
I read about the panel has to have focus to be able to scroll, and I will have to pass the OnMouseWheel event to parent, in child. But I am not able to do it, I don't know how to do it.
my custom panel (child):
public class PlaylistRecords : Panel
{
public Label lblRecordNumber { get; private set; }
private Label lblRecordName;
public static int RecordNumber { get; set; }
public static String RecordName { get; set; }
public PlaylistRecords(
int RecordNumber,
String RecordName
)
{
InitializeComponent();
this.Size = new System.Drawing.Size(800,50);
this.BackColor = System.Drawing.Color.FromArgb(20,20,20);
PlaylistRecords.RecordNumber = RecordNumber;
PlaylistRecords.RecordName = RecordName;
this.lblRecordNumber.Text = PlaylistRecords.RecordNumber.ToString()+".";
this.lblRecordName.Text = PlaylistRecords.RecordName;
this.lblRecordNumber.Location = new System.Drawing.Point(2, (int)(this.Height - this.lblRecordNumber.Height) / 2);
this.lblRecordName.Location = new System.Drawing.Point(
this.lblRecordNumber.Location.X+ this.lblRecordNumber.Width+2,
(int)(this.Height - this.lblRecordName.Height) / 2);
}
private void InitializeComponent()
{
this.lblRecordNumber = new myLabel();
this.lblRecordName = new myLabel();
this.lblRegistPath = new myLabel();
this.SuspendLayout();
//
// lblRecordNumber
//
this.lblRecordNumber.Name = "lblRecordNumber";
this.lblRecordNumber.Size = new System.Drawing.Size(50, 23);
//
// lblRecordName
//
this.lblRecordName.Name = "lblRecordName";
this.lblRecordName.Size = new System.Drawing.Size(150, 23);
//
// PlaylistRecords
//
this.Controls.Add(this.lblRecordNumber);
this.Controls.Add(this.lblRecordName);
this.ResumeLayout(false);
}
}
this.SetStyle(ControlStyles.Selectable, true);
this.TabStop = true;
These two lines of code written in constructor of child control (panel) is doing the job.
Thank you #Hans Passant for your comment. :)
Well if a control is not accepting events then they would be passed to parent
lblRecordNumber.Enabled = false;
lblRecordName.Enabled = false;
alternatively you can pass the scroll event to containing control referred to as Parent
internal class myLabel : Label
{
const int WM_MOUSEWHEEL = 0x020A;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEWHEEL)
m.HWnd = this.Parent.Handle;
base.WndProc(ref m);
}
}
and use that control instead.
Related
I´m using WindowsForm and working with flat design. In the program there are 6 buttons, these buttons are made of a label and a panel. The label controls all the actions that the button can do. when i started writing the program i made one function for each button, now i like to use one function that controls all buttons. I have tried to make that work but I´m stuck and can´t find a way to solve it.
Been looking around at the forum for solutions but i think that i might not know what i´m looking for.
This is what i made so far.
Buttons[] cobra = new Buttons[5];
private class Buttons
{
private bool position;
private string name;
public bool Position
{
get { return position; }
set { position = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
}
private void SetButtons()
{
cobra[0].Name = "label3";
cobra[0].Position = false;
cobra[1].Name = "label4";
cobra[1].Position = false;
}
private void CheckStatusButtons(object import)
{
for (int i = 0; i < cobra.Length; i++)
{
}
}
private class ToggelFunction
{
private bool hawk;
public bool Hawk
{
get { return hawk; }
set { hawk = value; }
}
}
ToggelFunction tiger = new ToggelFunction();
private void label3_Click(object sender, EventArgs e)
{
if (tiger.Hawk == false)
{
button1.BackColor = Color.PaleGreen;
label3.Text = "ON";
if (myport.IsOpen)
{
send(new byte[] { 16, 128, 32, 16, 1 });
}
tiger.Hawk = true;
return;
}
if (tiger.Hawk == true)
{
button1.BackColor = Color.DarkSeaGreen;
label3.Text = "2";
if (myport.IsOpen)
{
send(new byte[] { 16, 128, 32, 8, 1 });
}
tiger.Hawk = false;
return;
}
}
"label3_Click" this is my function for button 1, all buttons look the same just different variables.
As I found on the forum, you can use object sender to i identify which button that made the click and from there use that in the function to make action.
So all buttons will use this functions, i´m not sure how to compare values in the if statement, if button 1 is click then it should check what values button 1 has.
My idea was to make a class "Buttons" and an array to store all the values of each button, it´s not completed yet. When a button is clicked it checks
with the array what values that button has and compare that in the function depending on what the action is. The first action would be to check if the button is on or off. If it´s off then it enters that if statement and there some actions will happen, change of color and the text, these values also have to be stored in the array i guess.
I have tried to compare the array with object sender, but i get some error saying that you can´t compare bool with object i think.
So i wonder if some one might have a solution or suggestions?
I have made a simple example of what i think you want to do. bare in mind this does not abide by all coding best practises but its not a mess either. You will need to put your safety null checks in.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public class ButtonVariables
{
public int value1 { get; set; }
public int value2 { get; set; }
}
Dictionary<string, ButtonVariables> bv = new Dictionary<string, ButtonVariables>();
private void ProcessClick(object sender, EventArgs e)
{
ButtonVariables vars = GetVariables(sender);
//Do stuff with your variable set here
}
private ButtonVariables GetVariables(object sender)
{
ButtonVariables returnValue = new ButtonVariables();
switch (((Button)sender).Name.ToLower())
{
case "buttona":
return bv["A"];
case "buttonb":
return bv["B"];
case "buttonc":
return bv["C"];
default:
break;
}
return null;
}
private void ButtonA_Click(object sender, EventArgs e)
{
ProcessClick(sender, e);
}
private void ButtonB_Click(object sender, EventArgs e)
{
ProcessClick(sender, e);
}
private void ButtonC_Click(object sender, EventArgs e)
{
ProcessClick(sender, e);
}
}
I've basically added two methods to handle your method. One to identify the button and get its related values from a dictionary that you will have to populate with your Buttons class. and one to carry out the logic.
EDIT
As requested in the comments here's an easy (but not the only way) to point your event listeners towards the same method.
Initially you need to set up with one button and double click it or do some other way to create the forms Button_Click() Event Method. At this point an event listener delegate has been added to your Form.Designer.cs File. Open that file and you will see something like this:
//
// ButtonA
//
this.ButtonA.Location = new System.Drawing.Point(12, 12);
this.ButtonA.Name = "ButtonA";
this.ButtonA.Size = new System.Drawing.Size(75, 23);
this.ButtonA.TabIndex = 0;
this.ButtonA.Text = "button1";
this.ButtonA.UseVisualStyleBackColor = true;
this.ButtonA.Click += new System.EventHandler(this.ButtonA_Click);
What you need to do is create your other buttons and add this code in for them with a change to the last line new System.EventHandler(this.ButtonA_Click); This line basically states which method to call when the ButtonA.Click event is invoked. At this point you can add what ever method you want (as long as you name is nicely for good convention). So your example would be this :
//
// ButtonA
//
this.ButtonA.Location = new System.Drawing.Point(12, 12);
this.ButtonA.Name = "ButtonA";
this.ButtonA.Size = new System.Drawing.Size(75, 23);
this.ButtonA.TabIndex = 0;
this.ButtonA.Text = "button1";
this.ButtonA.UseVisualStyleBackColor = true;
this.ButtonA.Click += new System.EventHandler(this.ProcessClick);
//
// ButtonB
//
this.ButtonB.Location = new System.Drawing.Point(12, 12);
this.ButtonB.Name = "ButtonB";
this.ButtonB.Size = new System.Drawing.Size(75, 23);
this.ButtonB.TabIndex = 0;
this.ButtonB.Text = "B";
this.ButtonB.UseVisualStyleBackColor = true;
this.ButtonB.Click += new System.EventHandler(this.ProcessClick);
//
// ButtonC
//
this.ButtonC.Location = new System.Drawing.Point(12, 12);
this.ButtonC.Name = "ButtonC";
this.ButtonC.Size = new System.Drawing.Size(75, 23);
this.ButtonC.TabIndex = 0;
this.ButtonC.Text = "C";
this.ButtonC.UseVisualStyleBackColor = true;
this.ButtonC.Click += new System.EventHandler(this.ProcessClick);
Remember you need to physically create the buttons on the form itself.
Lets say you have three labels and a panel for each label. You can add the event handler to all of them and whenever that event fires the event handler will use that label as the sender. To keep the panel associated with the label, you could add the panel to the label's tag property. Then, in the event handler you can then get the panel from the label.
label1.Click += label_Click;
label2.Click += label_Click;
label3.Click += label_Click;
label1.Tag = panel1;
label2.Tag = panel2;
label3.Tag = panel3;
In the event handler, just cast sender to Label and there you have your label object to do whatever you want with and like I said, the panel is in the Tag property. I did a little refactoring to your code to make it cleaner looking.
private void label_Click(object sender, EventArgs e)
{
// this is what itsme86 was suggesting in the comments
var label = (Label)sender;
var panel = (Panel)label.Tag;
label.BackColor = tiger.Hawk ? Color.DarkSeaGreen : Color.PaleGreen;
label.Text = tiger.Hawk ? "2" : "ON";
if (myport.IsOpen)
send(new byte[] { 16, 128, 32, 8, 1 });
tiger.Hawk = !tiger.Hawk;
}
Let me know if you have any questions about this.
Created a custom intellisense textbox (textbox with listbox a child).
As shown in below image, the listbox pops up when i enter a char which all works fine and good but when i am at the end of textbox the listbox is partially visible, is there anyway i can show the whole listbox content?
Tried this "Show control inside user control outside the boundaries of its parent
But when the popup window opens the text box looses focus and i cannot type anything further, my intellisense textbox keeps giving better results based on what they type but in this situation i am not able to type anymore.
FYI tried to add pParentControl.Focus() into show method defined in other article as shown below, missing something?
public void Show(Control pParentControl)
{
if (pParentControl == null) return;
// position the popup window
var loc = pParentControl.PointToScreen(new Point(0, pParentControl.Height));
pParentControl.Focus();
m_tsdd.Show(loc);
}
Here is the complete code
class TextBox_AutoComplete : TextBox
{
#region Class Members
List<string> dictionary;
ListBox listbox = new ListBox();
#endregion
private PopupHelper m_popup;
#region Extern functions
[DllImport("user32")]
private extern static int GetCaretPos(out Point p);
#endregion
#region Constructors
public TextBox_AutoComplete() : base()
{
this.Margin = new Padding(0, 0, 0, 0);
this.Multiline = true;
this.Dock = DockStyle.Fill;
this.KeyDown += Textbox_KeyDown;
this.KeyUp += Textbox_KeyUp;
listbox.Parent = this;
listbox.KeyUp += List_OnKeyUp;
listbox.Visible = false;
this.dictionary = new List<string>();
}
#endregion
#region Properties
public List<string> Dictionary
{
get { return this.dictionary; }
set { this.dictionary = value; }
}
#endregion
#region Methods
private static string GetLastString(string s)
{
Regex rgx = new Regex("[^a-zA-Z0-9_.\\[\\]]");
s = rgx.Replace(s, " ");
string[] strArray = s.Split(' ');
return strArray[strArray.Length - 1];
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
Point cp;
GetCaretPos(out cp);
List<string> lstTemp = new List<string>();
List<string> TempFilteredList = new List<string>();
string LastString = GetLastString(this.Text.Substring(0, SelectionStart));
//MessageBox.Show(LastString);
/*seperated them so that column name matches are found first*/
TempFilteredList.AddRange(dictionary.Where(n => n.Replace("[", "").ToUpper().Substring(n.IndexOf(".") > 0 ? n.IndexOf(".") : 0).StartsWith(LastString.ToUpper())
).Select(r => r)
.ToList());
TempFilteredList.AddRange(dictionary.Where(n => n.Replace("[", "").ToUpper().StartsWith(LastString.ToUpper())
|| n.ToUpper().StartsWith(LastString.ToUpper()))
.Select(r => r)
.ToList());
lstTemp = TempFilteredList.Distinct().Select(r => r).ToList();
/*Getting max width*/
int maxWidth = 0, temp = 0;
foreach (var obj in lstTemp)
{
temp = TextRenderer.MeasureText(obj.ToString(), new Font("Arial", 10, FontStyle.Regular)).Width;
if (temp > maxWidth)
{
maxWidth = temp;
}
}
listbox.SetBounds(cp.X + 20, cp.Y + 20, maxWidth, 60);
if (lstTemp.Count != 0 && LastString != "")
{
listbox.DataSource = lstTemp;
// listbox.Show();
if (m_popup == null)
m_popup = new PopupHelper(listbox);
m_popup.Show(this);
}
else if (m_popup != null)
{
//listbox.Hide();
m_popup.Hide();
}
}
protected void Textbox_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Down)
{
if (listbox.Visible == true)
{
listbox.Focus();
}
e.Handled = true;
}
else if (e.KeyCode == Keys.Escape)
{
listbox.Visible = false;
e.Handled = true;
}
}
protected void Textbox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space && listbox.Visible == true)
{
listbox.Focus();
List_OnKeyUp(listbox, new KeyEventArgs(Keys.Space));
e.Handled = true;
}
if (e.KeyCode == Keys.Down && listbox.Visible == true)
{
listbox.Focus();
e.Handled = true;
}
}
private void List_OnKeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space || e.KeyCode == Keys.Enter)
{
int Selection_Start = this.SelectionStart;
string StrLS = GetLastString(this.Text.Substring(0, Selection_Start));
this.Select(Selection_Start - StrLS.Length, StrLS.Length);
// MessageBox.Show(this.Selection_Start.ToString() + " Last string" + StrLS);
this.SelectedText=((ListBox)sender).SelectedItem.ToString();
listbox.Hide();
this.Focus();
}
}
#endregion
}
public sealed class PopupHelper : IDisposable
{
private readonly Control m_control;
private readonly ToolStripDropDown m_tsdd;
private readonly Panel m_hostPanel; // workarround - some controls don't display correctly if they are hosted directly in ToolStripControlHost
public PopupHelper(Control pControl)
{
m_hostPanel = new Panel();
m_hostPanel.Padding = Padding.Empty;
m_hostPanel.Margin = Padding.Empty;
m_hostPanel.TabStop = false;
m_hostPanel.BorderStyle = BorderStyle.None;
m_hostPanel.BackColor = Color.Transparent;
m_tsdd = new ToolStripDropDown();
m_tsdd.CausesValidation = false;
m_tsdd.Padding = Padding.Empty;
m_tsdd.Margin = Padding.Empty;
m_tsdd.Opacity = 0.9;
m_control = pControl;
m_control.CausesValidation = false;
m_control.Resize += MControlResize;
//m_hostPanel.Controls.Add(m_control);
m_tsdd.Padding = Padding.Empty;
m_tsdd.Margin = Padding.Empty;
m_tsdd.MinimumSize = m_tsdd.MaximumSize = m_tsdd.Size = pControl.Size;
m_tsdd.Items.Add(new ToolStripControlHost(m_control));
}
private void ResizeWindow()
{
m_tsdd.MinimumSize = m_tsdd.MaximumSize = m_tsdd.Size = m_control.Size;
m_hostPanel.MinimumSize = m_hostPanel.MaximumSize = m_hostPanel.Size = m_control.Size;
}
private void MControlResize(object sender, EventArgs e)
{
ResizeWindow();
}
/// <summary>
/// Display the popup and keep the focus
/// </summary>
/// <param name="pParentControl"></param>
public void Show(Control pParentControl)
{
if (pParentControl == null) return;
// position the popup window
var loc = pParentControl.PointToScreen(new Point(0, pParentControl.Height));
pParentControl.Focus();
m_tsdd.Show(loc);
}
public void Hide()
{
m_tsdd.Hide();
}
public void Close()
{
m_tsdd.Close();
}
public void Dispose()
{
m_control.Resize -= MControlResize;
m_tsdd.Dispose();
m_hostPanel.Dispose();
}
}
Firstly, I personally don't see any benefit in having a control inside another. Yes, the child control is locked inside its parent's boundaries automatically for you, but this benefit is negated by the issue that you're facing, and solving that issue requires the same work as when the two controls have no relation. In both cases, you'll have to do the calculations manually to keep the child visible inside its parent. In the second case the parent is the app's window.
Secondly, I don't recommend using hacks like the one mentioned in the comments to show the child outside its parent's boundaries. The hack creates more issues than it solves, as you found out. And what's the point of that hack anyway? If you want to show the child outside the parent, then don't make it a child control in the first place, and you don't need any hack.
The best solution is the one that you find in any well designed app, and in Windows itself. Open any app, let's say Notepad, and right-click near the upper-left corner. You'll see the context menu pulling to lower-right direction. Now right-click near the other three corners and you'll see the context menu pulling in different direction each time, so it will always be visible inside the app. Now if you resize the app window too small and right-click, the context menu will choose the best direction but some of it will be outside the app because the window is too small. That's why you need your list not to be a child, but it's up to you, and it's only about these edge cases. The solution will be similar in both cases.
You're displaying the list in this line:
listbox.SetBounds(cp.X + 20, cp.Y + 20, maxWidth, 60);
The key is cp.X and cp.Y. This is what decides where the list will appear. You need to make this point dynamic and responsive to the boundaries of the parent. You fixed the width to maxWidth and height to 60, so I will use those values in the calculation.
To make sure the list will not go beyond the bottom:
var y = this.Height < cp.Y + 60 ? this.Height - 60 : cp.Y;
To make sure the list will not go beyond the right:
var x = this.Width < cp.X + maxWidth ? this.Width - maxWidth : cp.X;
Now you can show your list at the calculated point:
listbox.SetBounds(x, y, maxWidth, 60);
Notes:
I didn't include the 20 gap that you used. I think it looks better without the gap and I haven't seen any app that has a gap. If you prefer the gap, add it to the calculation of x and y. Don't add it in the SetBounds() or that will screw up the calculation.
The calculation above doesn't take into account when the parent size is too small to show the child inside. If you want to support that edge case, you need to make the child a separate control and add some checks to the calculation.
This question already has answers here:
How to move and resize a form without a border?
(7 answers)
Closed 7 years ago.
I have created a border-less form using c# but could make the custom title bar movable so I search the internet and found this code:
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_NCHITTEST)
m.Result = (IntPtr)(HT_CAPTION);
}
private const int WM_NCHITTEST = 0x84;
private const int HT_CLIENT = 0x1;
private const int HT_CAPTION = 0x2;
After applying this code can click and drag my form in every inch of the form except for the title bar .
This is a good example of the movable title bar.
This is a full example
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Custom_Title_Bar
{
public partial class MainForm : Form
{
private PictureBox title = new PictureBox(); // create a PictureBox
private Label minimise = new Label(); // this doesn't even have to be a label!
private Label maximise = new Label(); // this will simulate our this.maximise box
private Label close = new Label(); // simulates the this.close box
private bool drag = false; // determine if we should be moving the form
private Point startPoint = new Point(0, 0); // also for the moving
public MainForm()
{
this.FormBorderStyle = FormBorderStyle.None;// get rid of the standard title bar
this.title.Location = this.Location; // assign the location to the form location
this.title.Width = this.Width; // make it the same width as the form
this.title.Height = 50; // give it a default height (you may want it taller/shorter)
this.title.BackColor = Color.Black; // give it a default colour (or load an image)
this.Controls.Add(this.title); // add it to the form's controls, so it gets displayed
// if you have an image to display, you can load it, instead of assigning a bg colour
// this.title.Image = new Bitmap(System.Environment.CurrentDirectory + "\\title.jpg");
// if you displayed an image, alter the SizeMode to get it to display as you want it to
// examples:
// this.title.SizeMode = PictureBoxSizeMode.StretchImage;
// this.title.SizeMode = PictureBoxSizeMode.CenterImage;
// this.title.SizeMode = PictureBoxSizeMode.Zoom;
// etc
// you may want to use PictureBoxes and display images
// or use buttons, there are many alternatives. This is a mere example.
this.minimise.Text = "Minimise"; // Doesn't have to be
this.minimise.Location = new Point(this.Location.X + 5, this.Location.Y + 5); // give it a default location
this.minimise.ForeColor = Color.Red; // Give it a colour that will make it stand out
// this is why I didn't use an image, just to keep things simple:
this.minimise.BackColor = Color.Black; // make it the same as the PictureBox
this.Controls.Add(this.minimise); // add it to the form's controls
this.minimise.BringToFront(); // bring it to the front, to display it above the picture box
this.maximise.Text = "Maximise";
// remember to make sure it's far enough away so as not to overlap our minimise option
this.maximise.Location = new Point(this.Location.X + 60, this.Location.Y + 5);
this.maximise.ForeColor = Color.Red;
this.maximise.BackColor = Color.Black; // remember, we want it to match the background
this.maximise.Width = 50;
this.Controls.Add(this.maximise); // add it to the form
this.maximise.BringToFront();
this.close.Text = "Close";
this.close.Location = new Point(this.Location.X + 120, this.Location.Y + 5);
this.close.ForeColor = Color.Red;
this.close.BackColor = Color.Black;
this.close.Width = 37; // this is just to make it fit nicely
this.Controls.Add(this.close);
this.close.BringToFront();
// now we need to add some functionality. First off, let's give those labels
// MouseHover and MouseLeave events, so they change colour
// Since they're all going to change to the same colour, we can give them the same
// event handler, which saves time of writing out all those extra functions
this.minimise.MouseEnter += new EventHandler(Control_MouseEnter);
this.maximise.MouseEnter += new EventHandler(Control_MouseEnter);
this.close.MouseEnter += new EventHandler(Control_MouseEnter);
// and we need to do the same for MouseLeave events, to change it back
this.minimise.MouseLeave += new EventHandler(Control_MouseLeave);
this.maximise.MouseLeave += new EventHandler(Control_MouseLeave);
this.close.MouseLeave += new EventHandler(Control_MouseLeave);
// and lastly, for these controls, we need to add some functionality
this.minimise.MouseClick += new MouseEventHandler(Control_MouseClick);
this.maximise.MouseClick += new MouseEventHandler(Control_MouseClick);
this.close.MouseClick += new MouseEventHandler(Control_MouseClick);
// finally, wouldn't it be nice to get some moveability on this control?
this.title.MouseDown += new MouseEventHandler(Title_MouseDown);
this.title.MouseUp += new MouseEventHandler(Title_MouseUp);
this.title.MouseMove += new MouseEventHandler(Title_MouseMove);
}
private void Control_MouseEnter(object sender, EventArgs e)
{
if (sender.Equals(this.close))
this.close.ForeColor = Color.White;
else if (sender.Equals(this.maximise))
this.maximise.ForeColor = Color.White;
else // it's the minimize label
this.minimise.ForeColor = Color.White;
}
private void Control_MouseLeave(object sender, EventArgs e)
{
// return them to their default colors
if (sender.Equals(this.close))
this.close.ForeColor = Color.Red;
else if (sender.Equals(this.maximise))
this.maximise.ForeColor = Color.Red;
else // it's the minimise label
this.minimise.ForeColor = Color.Red;
}
private void Control_MouseClick(object sender, MouseEventArgs e)
{
if (sender.Equals(this.close))
this.Close(); // close the form
else if (sender.Equals(this.maximise))
{
// maximise is more interesting. We need to give it different functionality,
// depending on the window state (Maximise/Restore)
if (this.maximise.Text == "Maximise")
{
this.WindowState = FormWindowState.Maximized; // maximise the form
this.maximise.Text = "Restore"; // change the text
this.title.Width = this.Width; // stretch the title bar
}
else // we need to restore
{
this.WindowState = FormWindowState.Normal;
this.maximise.Text = "Maximise";
}
}
else // it's the minimise label
this.WindowState = FormWindowState.Minimized; // minimise the form
}
void Title_MouseUp(object sender, MouseEventArgs e)
{
this.drag = false;
}
void Title_MouseDown(object sender, MouseEventArgs e)
{
this.startPoint = e.Location;
this.drag = true;
}
void Title_MouseMove(object sender, MouseEventArgs e)
{
if (this.drag)
{
// if we should be dragging it, we need to figure out some movement
Point p1 = new Point(e.X, e.Y);
Point p2 = this.PointToScreen(p1);
Point p3 = new Point(p2.X - this.startPoint.X,
p2.Y - this.startPoint.Y);
this.Location = p3;
}
}
} // end of the class
} // end of the namespace
If you want you can extract just the moving code and integrate it with your code, the movable Title code is just in the following Event Handlers
Title_MouseUp
Title_MouseDown
Title_MouseMove
Here is the original article for this code, you can read it for more explanation about the code
http://www.dreamincode.net/forums/topic/64981-designing-a-custom-title-bar/
The link to original article is broken
I have created a custom close image label, added it to a larger label, and added that to my panel. I have a bunch of these panels all over. I created a function to make this label collection which I then adds it to the panel. How do I create an event that closes the panel (Parent of Parent?) when a small close-style label is clicked? Here's what I have so far.
public void MakePanel1(string panel_name)
{
Panel MyPanel = new Panel();
Label TitleLabel = AddTitleLabel(panel_name);
MyPanel.Controls.Add(TitleLabel);
this.Controls.Add(MyPanel);
}
public Label AddTitleLabel(string title)
{
Label TitleLabel = new Label();
TitleLabel.Size = new Size(231, 20);
TitleLabel.BorderStyle = BorderStyle.FixedSingle;
TitleLabel.TextAlign = ContentAlignment.MiddleLeft;
TitleLabel.Text = title;
Label CloseLabel = new Label();
CloseLabel.Size = new Size(16, 16);
CloseLabel.Location = new Point(212, 2);
CloseLabel.Image = Image.FromFile(#"..\..\pics\x.png");
CloseLabel.Click += new System.EventHandler(this.DoStuffAndClosePanel);
TitleLabel.Controls.Add(CloseLabel);
return TitleLabel;
}
private void DoStuffAndClosePanel(object sender, EventArgs e)
{
// Do some stuff
// Close the panel -- sender.Close() ?????
}
thanks in advance
If you really want to do what you described you should know the panel control doesn't have a close method and you can:
private void DoStuffAndClosePanel(object sender, EventArgs e)
{
//Do Stuff
//...
//Close Panel
var parent=((Control)sender).Parent;
parent.Visible = false;
parent.Dispose();
parent = null;
}
As another option you can use a Form instead of such panel. You can hide title bar of form and use your close button instead.
For example if you want to have such form:
public class PanelForm:Form
{
protected override void WndProc(ref Message message)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_MOVE = 0xF010;
switch (message.Msg)
{
case WM_SYSCOMMAND:
int command = message.WParam.ToInt32() & 0xfff0;
if (command == SC_MOVE)
return;
break;
}
base.WndProc(ref message);
}
}
And the for showing such panel:
var f= new PanelForm();
f.TopLevel=false;
f.FormBorderStyle= System.Windows.Forms.FormBorderStyle.FixedSingle;
f.MinimizeBox=false;
f.MaximizeBox=false;
this.Controls.Add(f);
f.Show();
Or add it to a TableLayoutPanel, or FlowLayoutPanel
Another option could be using a TabControl and remove unwanted tabs.
I have a class that generates a listview dynamically and placed it in a tab control. When the user resizes the form, I want to capture that event and resize the listview. I can set the dock property but directly on top of the grid there is a panel with a combo box ( allows user to sort of filter the data). And when I set the docking the grid docks to the top of the tab and doesn't realize there is a combo there. Maybe i am doing something wrong.
Here is a sample code:
public class KI_Tab_Items_ListviewControl : KI_Tab_Items, IDisposable
{
private ListView m_Listview = new ListView();
private ComboBox m_ComboBox = new ComboBox();
public ListView ListViewControl { get { return m_Listview; } set { m_Listview = value; } }
public ComboBox ComboBoxControl { get { return m_ComboBox; } set { m_ComboBox = value; } }
public override void ClearItems()
{
ListViewControl.Items.Clear();
}
public override void PopulateControls()
{
base.PopulateControls();
}
public virtual void AddColumnHeaders()
{
ListViewControl.Columns.Clear();
}
public KI_Tab_Items_ListviewControl(TabControl m_TabControl, int lIndex, bool DisplayComboBox = true)
{
if (m_TabControl.TabPages[lIndex].Controls.Count == 0)
{
int ListviewTop = 0;
m_TabControl.TabPages[lIndex].Controls.Clear();
if (DisplayComboBox)
{
m_TabControl.TabPages[lIndex].Controls.Add(ComboBoxControl);
ComboBoxControl.Dock = DockStyle.Top;
ComboBoxControl.Visible = true;
ComboBoxControl.Left = 0;
ComboBoxControl.Top = 0;
ListviewTop = ComboBoxControl.Top + ComboBoxControl.Height;
}
m_TabControl.TabPages[lIndex].Controls.Add(ListViewControl);
ListViewControl.Anchor = AnchorStyles.Top;
ListViewControl.Dock = DockStyle.Bottom;
ListViewControl.Visible = true;
ListViewControl.Top = ListviewTop;
ListViewControl.Height = m_TabControl.TabPages[lIndex].Height - ListviewTop;
}
}
void System.IDisposable.Dispose()
{
Tab_Control.Controls.Clear();
m_Listview = null;
m_ComboBox = null;
}
}
Set the ComboBox docked to Top. If it hides the top of your Full docked ListView you have to open the Document Outline window and swap ComboBox and ListView order.
As alternative you can set the Anchor property of the ListView (for example if you add the Right anchor it'll will keep its distance from the right border when resizing the form).
Add ListView FIRST. Set ListViewControl.Dock = DockStyle.Fill.
Add ComboBox LAST. Sett ComboBoxControl.Dock = DockStyle.Top.
public void KI_Tab_Items_ListviewControl( TabControl m_TabControl, int lIndex, bool DisplayComboBox = true )
{
if ( m_TabControl.TabPages[ lIndex ].Controls.Count == 0 )
{
int ListviewTop = 0;
m_TabControl.TabPages[ lIndex ].Controls.Clear();
m_TabControl.TabPages[ lIndex ].Controls.Add( ListViewControl );
// Add ListView FIRST.
// NOTE: set ListViewControl.Dock = DockStyle.Fill;
//
ListViewControl.Anchor = AnchorStyles.Top;
ListViewControl.Dock = DockStyle.Fill;
ListViewControl.Visible = true;
ListViewControl.Top = ListviewTop;
ListViewControl.Height = m_TabControl.TabPages[ lIndex ].Height - ListviewTop;
// Add ComboBox last.
// NOTE: set ComboBoxControl.Dock = DockStyle.Top;
//
if ( DisplayComboBox )
{
m_TabControl.TabPages[ lIndex ].Controls.Add( ComboBoxControl );
ComboBoxControl.Dock = DockStyle.Top;
ComboBoxControl.Visible = true;
ComboBoxControl.Left = 0;
ComboBoxControl.Top = 0;
ListviewTop = ComboBoxControl.Top + ComboBoxControl.Height;
}
}
}