I'm wondering if it is possible somehow locate popup of ToolTip outside of application form in the fixed point over the empty desktop with MouseHover event, of course if event is useful for ToolTip, not sure. Or any other way if it is possible
I'm not asking for how to display another form as an option for this goal.
You can use either of these options:
Handle showing and hiding the ToolTip yourself. You can use MouseHover show the ToolTip in desired location and using MouseLeave hide it.
Using MoveWindow Windows API method, force the tooltip to show in a specific location instead of default location.
Option 1
You can handle MouseHover and MouseLeave event of your control(s) and show ToolTip in specific location of desktop window this way:
private void control_MouseHover(object sender, EventArgs e)
{
var control = (Control)sender;
var text = toolTip1.GetToolTip(control);
if (!string.IsNullOrEmpty(text))
toolTip1.Show(text, control, control.PointToClient(new Point(100, 100)));
}
private void control_MouseLeave(object sender, EventArgs e)
{
var control = (Control)sender;
toolTip1.Hide(control);
}
Option 2
As another option which I previously offered for align right edges of a control and ToolTip, you can set OwnerDraw property of ToolTip to true and handle Draw event of the control and use MoveWindow Windows API method to move ToolTip to desired location:
[System.Runtime.InteropServices.DllImport("User32.dll")]
static extern bool MoveWindow(IntPtr h, int x, int y, int width, int height, bool redraw);
private void toolTip1_Draw(object sender, DrawToolTipEventArgs e) {
e.DrawBackground();
e.DrawBorder();
e.DrawText();
var t = (ToolTip)sender;
var h = t.GetType().GetProperty("Handle",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var handle = (IntPtr)h.GetValue(t);
var location = new Point(100,100);
MoveWindow(handle, location.X, location.Y, e.Bounds.Width, e.Bounds.Height, false);
}
It sounds like ultimately what you want is a box to display some information whenever you hover over some particular items on your GUI. You also say that you want the information to display at a fixed point.
As opposed to achieving this with the tool-tip, I would do the following:
Create some fixed label or text-box to display information and put it somewhere on your Windows form.
Create a subscriber to the mouse hover event.
Based on the sender (which control you're hovering) from the mouse hover event, choose what information to display in the fixed location.
I've seen people doing this in some other programs... Take, RealTerm for example. Try it out if you want and see how it feels before you try this solution.
On the other hand, if you must do this with a tool-tip. You can choose the position using overloads of ToolTip.Show.
Related
I am trying to create a Bitmap from a RichTextBox and set it as the background image for a panel, but unfortunately the text is not shown.
Bitmap l_bitmap = new Bitmap(m_control.Width, m_control.Height);
m_control.DrawToBitmap(l_bitmap, new Rectangle(0, 0, l_bitmap.Width, l_bitmap.Height));
m_panel.BackgroundImage = l_bitmap;
m_panel.Refresh();
m_control is my RichTextBox. When I debug, I can see that the control contains the text I wrote, but the bitmap just shows an empty RichTextBox.
I use the same code for other types of controls (Button, CheckBox, TextBox...). The text is shown with no problems.
Well you are trying to create a bitmap from the control. The text you put in there isn't the control, so it won't bother to chow it as bitmap. Try to create a picture from screen (like a screenshot).
Example:
Graphics gr = Graphics.FromImage(l_bitmap);
gr.CopyFromScreen(m_control.PointToScreen(Point.Empty), point.Empty, m_control.Size);
This will make a bitmap from your given points. This will additional show you the text.
EDIT
Maybe you can use this instead. In addition to your idea, I simply put a label onto my panel. (L for Label and P for Panel)
As you can see, the label is empty because I cleared the Text property. Now, when you click one of the buttons below the panel, it will update the label.Text propertie and there will be the text you gave the control.
Here is some example:
As you can see, the label shows the Name of the control. Completly custom as you can see on my source code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public RichTextBox tmpRtf = new RichTextBox();
//Poor button name incoming...
private void button1_Click(object sender, EventArgs e)
{
if (tmpRtf == null)
tmpRtf = new RichTextBox();
//You can add any text here and it will be shown on the label.
this.tmpRtf.Text = "Richtextbox";
this.UpdatePanel(this.tmpRtf);
}
//Custom method to update the panel for any control. Can pobably be done way better than this, but hey.
private void UpdatePanel(object pControl)
{
//Checks if control is a rtf
if(pControl is RichTextBox)
{
//This is your code! Ay.
Bitmap l_bitmap = new Bitmap(this.panel1.Width / 2, this.panel1.Height / 2);
(pControl as RichTextBox).DrawToBitmap(l_bitmap, new Rectangle(0, 0, l_bitmap.Width, l_bitmap.Height));
this.tmpRtf.BackColor = Color.LightGray;
this.panel1.BackgroundImage = l_bitmap;
this.panel1.BackgroundImageLayout = ImageLayout.Center;
this.labelControlName.Text = this.tmpRtf.Text;
this.panel1.Refresh();
}
}
}
Its not possible to show text on a control thats not visualized. But you can build a workaround! Or, instead of taking a picture you can simply create the control on top of it, that will also show the Text and maybe the user can test it (e.g. click on buttons, look at the control behaviour).
Hopefully this is something to get you inspired that there are always more ways to accomplish.
I wonder if it's possible to customize my C# application (winforms) to get a better design, I made a PSD (photoshop document) so I can generate png jpeg... pictures if I need them.
Example of a form like the one I want :
Indeed as it was pointed out in the comments, it is easy to use WPF (indows Presentation Foundation) to achieve that result, but if you really need that it must be made in windows forms I can help you with that...
ControlBox and Border
It seens that your form does not have a control box (minimize, maximize and close buttons)
to achieve that you can set
form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None
I'm not sure if that galaxy behind your form is part of the application so i'll be considering that it is not
To achieve that irregular shape of the form we have to do a workaround here
Irregular Shape of the Form
we are going to set a Color to TransparentKey, so everything in the form in that specific color will be transparent, like it does not exists (if you click in that part it will go into de desktop or whatever application you have behind in your form)
So let's use a specific color which we will probably dont use in the form
form.TransparencyKey = Color.FromArgb(111, 111, 111); //You can do it by the editor
So in order to make that white part we are going to use an Panel and a PictureBox outsite of the Panel trying to copy the shape of your image
Stylized Inputs
To make it easier and reusable I'm going to make a userControl in this one
the usercontrol will have
a Panel called HighLightPanel, its dock property will be set to Fill
a Panel called BackColorPanel, it will be inside the HighLightPanel
a PictureBox called InputPicture, its dock property will be set to Left, it will be inside BackColorPanel and its acessor will be public
a TextBox called TextBox, its dock property wil be set to fill, it will be inside BackColorPanel, the BorderStyle Property set to None, you should set the size and font you most desize in this one, I'm going to use Segoe UI; 15,75pt and its acessor will be public
Now we have to make some properties in our UserControl to make it work without work in other controls
First in the SizeChanged event of the HighLightPanel we will make the BackColorPanel be exacly two points smaller in every direction and its position to 1;1 so we can see the HighLightPanel
private void HighlightPanel_SizeChanged(object sender, EventArgs e)
{
this.BackColorPanel.Size = new Size(
HighlightPanel.Width - 2,
HighlightPanel.Height - 2);
}
Now we will create two propertys to handle the Highlight Color
public Color HighlightBorderColor { get; set; }
public Color NonHighlightBorderColor { get; set; }
And in the Enter and Leave Property of our TextBox we are going to change the HighlightPanel
private void TextBox_Enter(object sender, EventArgs e)
{
HighlightPanel.BackColor = HighlightBorderColor;
}
private void TextBox_Leave(object sender, EventArgs e)
{
HighlightPanel.BackColor = NonHighlightBorderColor;
}
So now every time the user enter the Input it will appear that the Input has an Border in the specified Color
Now to enhance its usability to developers we will make some wrappers in its controls to be easier change property of child controls in the editor
public Image InputImage
{
get { return InputPicture.Image; }
set { InputPicture.Image = value; }
}
public PictureBoxSizeMode InputImageLayout
{
get { return InputPicture.SizeMode; }
set { InputPicture.SizeMode = value; }
}
public char PasswordCharacter
{
get { return TextBox.PasswordChar; }
set { TextBox.PasswordChar = value; }
}
public bool ShowInputImage
{
get { return InputPicture.Visible; }
set { InputPicture.Visible = value; }
}
In the InputImage set the picture you want for the User and the Key
Insert the two controls in the position you like
Position of the Form
if you want your form to be moveable without the border you will have to use this snippet, it is more easy in WPF
#region MoveForm
Point LastPoint;
bool ShouldMove;
private void form_MouseDown(object sender, MouseEventArgs e)
{
LastPoint = e.Location;
ShouldMove = true;
this.TransparencyKey = Color.FromArgb(111, 111, 111);
}
private void form_MouseUp(object sender, MouseEventArgs e)
{
ShouldMove = false;
}
private void form_MouseMove(object sender, MouseEventArgs e)
{
if (ShouldMove)
{
this.Location = new Point(
this.Location.X - LastPoint.X + e.X,
this.Location.Y - LastPoint.Y + e.Y);
}
}
#endregion
If you need a lot of special graphics effects learning WPF will indeed be a sound investement.
If all you want is that login screen, it is trivial in Winforms and doesn't take any horrible hacks as you've been told..
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.BackColor = System.Drawing.Color.LavenderBlush;
this.TransparencyKey = System.Drawing.Color.LavenderBlush;
this.ControlBox = false;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Text= "";
These seven lines are all it takes for a form to be transparent. I copied them from the Designer code; you can simply set the 7 Properties in the property grid.
Now add a panel, dock it to the bottom and give it the right color; add a picturebox and your other controls and you are set.
To create the two input groups you also need just a few regular controls and only a few simple lines of code:
You place one Panel, BorderStyle = FixedSingle; and add a Label and a TextBox to it. The Label has AutoSize = False; and both ImageAlign and TextAlign are set to MiddleLeft. You assign an image to the Label's Image and prefix the Text with enough blanks to not overlap. Obviously you should define a PasswordChar for the 2nd TextBox. Now all you need is to script the Enter and Leave events to change the BackColor of the respective Panels between, say SystemColors.Control and SystemColors.MenuHighlight. Size the Labels to almost fill the Panels and you are done. Less code than the WPF version, I'd bet.
If you need such input an controls again and again, simply create Usercontrols for each type you need!
Here is an example of the limits you will hit: Wouldn't it be nice to add a dropshadow effect to the image? It is doable in Winforms. But it would involve painting that effect; this would take at least 15 or 20 lines of involved code instead of simply turning the effect on with (estimated) 1-3 simple lines.
Do you need any nice hover effects? Not easy, to say the least..
These limits will be all over the place, so it really depends on how fancy your requirements will get.
Maybe you should use this example as a starter to compare the two techniques and to warm you up to WPF?
I have a form with three panels.
I want the top two to be a fixed height, and bottom one to fill the rest of the space.
The dialog is resizable, so all should change width on resixze, and bottom one should change height.
This is important, the user must be able to stretch the form, as well as the program through code.
If I set a panel to visible = false, I want the form height to shrink so the others stay the same height.
If I set a panel to visible = true, I want the form height to grow by the height of the panel.
I will control the hiding/showing of the panels with buttons. The idea is I show certain panels for "advanced" mode in my form, and hide them for "simple" mode. I cannot have a bunch of blank space if I hide a panel, and I want the form to shrink a bunch for simple mode.
I tried doing this with panels docked to top, but a form resize by the user will not change a panel height. So that is the main trick I am asking for help on.
Anyone in this kind of situation can use the below styling:
Use 2-3 Panel to Group different Controls and place them in a single parent control say a GroupBox.
Make all the child panels Dock to the same side say "Top".
if any of the panel is jumping over another due to similar docking. In Visual Studio, go to menu View > Other Windows > Document Outline and Set the display order. (https://msdn.microsoft.com/en-us/library/46xf4h0w%28v=vs.80%29.aspx)
Set the Panel property as follows:
AutoSize: true
AutoSizeMode: GrowAndShrink
Once the panel is not visible, other panel will take away the empty space.
Hope this helps!!!
the other posts are close, there is a detail missing that I included in the solution I came up with. Its a flag to tell if the sized event was caused by a user form resize, or the program doing it when a panel is shown or hidden.
For this solution, make a form with 4 panels.
Set dock to top for all panels. Do not set any autosizing for panels or form.
Also make two buttons and place on top panel, or any panel that you will not be hiding.
The code below shows how to handle the resized event, and the showing hiding buttons.
I made them hide/show panel 2, but the code should work for any panel.
namespace ProgTesting {
public partial class Form5 : Form {
private bool doNothing = false;
public Form5() {
InitializeComponent();
cmdAdvanced.Visible = false;
}
private void cmdSimple_Click(object sender, EventArgs e) {
if (panel2.Visible) {
panel2.Visible = false;
doNothing = true;
this.MinimumSize = new Size(this.Width, this.Height - panel2.Height);
this.Height = this.Height - panel2.Height;
doNothing = false;
cmdSimple.Visible = false;
cmdAdvanced.Visible = true;
}
}
private void cmdAdvanced_Click(object sender, EventArgs e) {
if (!panel2.Visible) {
panel2.Visible = true;
doNothing = true;
this.Height = this.Height + panel2.Height;
this.MinimumSize = new Size(this.Width, this.Height);
doNothing = false;
cmdAdvanced.Visible = false;
cmdSimple.Visible = true;
}
}
private void Form5_SizeChanged(object sender, EventArgs e) {
if (!doNothing)
if (panel2.Visible)
panel3.Height = this.ClientSize.Height - panel1.Height - panel2.Height - panel4.Height;
else
panel3.Height = this.ClientSize.Height - panel1.Height - panel4.Height;
}
}
}
You do have to manage the heights going on, which is a pain but gives you control. Some shots of it working:
It sounds like what you are looking for is an Expander. Essentially a control that consists of a header and a content area, where clicking on the header toggles the content area between visible and collapsed.
I'm not 100% certain if an Expander control will automatically adjust the height of a form when it expands/collapses though. You may need to hook up an event handler to the Expander to manually adjust the height of your form when the Expander collapses.
Try looking at the Stack Overflow Question Add an expander (collapse/expand) to a Panel WinForm. There are a number of links from that question about implementing an Expander in Windows Forms, including some that provide full source code.
Update:
I've knocked up a quick demo that will accomplish what you want, in a very primitive way, not using any of the various Expander controls out there. I think that while you will find the Expanders useful, I doubt they will adjust the size of the container they are inside, unless you write some adjustment code like I have below.
Create a form that looks like this:
The two text boxes are anchored Left, Top, Right.
The toggle button is anchored Left, Top, named btnTogglePanel.
The magenta panel is anchored Left, Top, Right, Bottom, named pnlToggled.
The bottom button is anchored Right, Bottom.
Then in the code behind for the form:
public partial class ToggleableExpanderForm : Form
{
public ToggleableExpanderForm()
{
InitializeComponent();
SizeChanged += (s, args) =>
{
if (_LastSize.HasValue)
{
var diff = Size - _LastSize.Value;
if (_LastHeight.HasValue
&& !IgnoreNextResizeForLastHeightAdjustment)
{
_LastHeight += diff.Height;
}
}
_LastSize = Size;
};
}
private Size? _LastSize;
private bool IgnoreNextResizeForLastHeightAdjustment = true;
private int? _LastHeight;
private void btnTogglePanel_Click(object sender, EventArgs e)
{
var newVisibility = !pnlToggled.Visible;
int heightAdjustment = 0;
if (newVisibility)
{
if (_LastHeight.HasValue)
{
heightAdjustment = _LastHeight.Value;
_LastHeight = null;
}
}
else
{
_LastHeight = pnlToggled.Height;
heightAdjustment = -pnlToggled.Height;
}
pnlToggled.Visible = newVisibility;
IgnoreNextResizeForLastHeightAdjustment = true;
Height += heightAdjustment;
}
}
Essentially you adjust the height of the form manually when the toggle button is clicked, based on whether or not the panel is hiding/showing. You also need to take into account of what will happen when the user resizes the form when the panel is invisible, which is where the cruft around listening to the SizeChanged event comes in. You need the answer to "how MUCH has the size changed" and then you adjust your previously stored panel height as appropriate.
I don't imagine the above code is perfect, and I haven't tested it in every use case, but it gets the basic job done.
One way to go about it is to use a TableLayoutPanel for the top two panels.
The steps below will give you the resizing desired when the user resizes the form.
Start by created a TableLayoutPanel (TLP) and shrink it down from the default 2 columns, 2 rows to just 2 columns, 1 row.
Anchor it to Top, Left, and Right
Now size the TLP to fit your top two panels and place each panel in a cell of the TLP.
Anchor these two panels to all sides.
Position the 3rd panel (Panel3) below the TLP to your liking and anchor it to all sides.
To handle the hiding of Panel3 some logic will need to be added to the appropriate button_Click event. Determine what size you would like the "minimized" height to be and then just store the form size when Panel3 is visible and restore the height when it's clicked again. It should look something like this.
private void button1_Click(object sender, EventArgs e)
{
if (panel3.Visible)
{
// make invisible
panel3.Visible = false;
// storedHeight is a private member of the Form
storedHeight = Form1.ActiveForm.Height;
Form1.ActiveForm.Height = minimumHeight; // Set to predetermined minimum height
}
else
{
// make visible
panel3.Visible = true;
Form1.ActiveForm.Height = storedHeight;
}
}
Now when you hide Panel3 the form will shrink to the size of the TLP, then grow again when Panel3 is visible. Also the top panels will expand in width, but not height. You will need to change the MinSize properties of the form and its value will have to be dynamically adjusted depending on whether Panel3 is visible or not.
I have downloaded Kinect SDK 1.7, toolkit and have played with following samples.
ControlBasics WPF
InteractionGallery WPF.
I figured out that Kinect Toolkit internally uses the interaction frame to detect the hand position/gesture and accordingly maps it with the Kinect Controls.
I have a requirement where I want to capture a grip event on a Kinect Tile Button. Since the default KinectTileButton does not provide a Grip event. I added a grip event handler on my button.
KinectRegion.AddHandPointerGripHandler(kinectButton, OnHandPointerCaptured);
private void OnHandPointerCaptured(object sender, HandPointerEventArgs handPointerEventArgs)
{
// Add code here
}
I placed a debug breakpoint inside the OnHandPointerCaptured method and was able to receive proper hits when I grip on the KinectTileButton. But for some reason I do not see the KinectCursor image change to a grip as it happens on the KinectScrollViewer control.
I tried setting up the isGripTarget property in the KinectButtonBase class but it doesn't help.
private void InitializeKinectButtonBase()
{
KinectRegion.AddHandPointerPressHandler(this, this.OnHandPointerPress);
KinectRegion.AddHandPointerGotCaptureHandler(this, this.OnHandPointerCaptured);
KinectRegion.AddHandPointerPressReleaseHandler(this, this.OnHandPointerPressRelease);
KinectRegion.AddHandPointerLostCaptureHandler(this, this.OnHandPointerLostCapture);
KinectRegion.AddHandPointerEnterHandler(this, this.OnHandPointerEnter);
KinectRegion.AddHandPointerLeaveHandler(this, this.OnHandPointerLeave);
// Use the same OnHandPointerPress handler for the grip event
KinectRegion.AddHandPointerGripHandler(this, this.OnHandPointerPress);
//Set Kinect button as Grip target
// KinectRegion.SetIsPressTarget(this, true);
KinectRegion.SetIsGripTarget(this, true);
}
How do I change the KinectCursor image from openhand icon to grip, and also the size.
Here's what i found-
1) Cursor Image and Size - Both these samples use Microsoft.Kinect.Toolkit.Controls project that defines the Custom Controls (KinectTileButton,KinectScrollViwer,KinectRegion etc.) used in these samples. The Kinect Cursor image and size is defined as a resource in
Microsoft.Kinect.Toolkit.Controls ->Themes->Generic.xaml. Search for following in the file -
<Style TargetType="{x:Type local:KinectCursor}">
You can modify this as per your need. Wasn't able to find any properties/hooks exposed to control this directly from the UI.
2) Grip event on Tile Button - Kinect Button Supports various events which can be subsribed to and acted upon on your desire. see this
Hand over button event in Kinect SDK 1.7
3) Change Cursor image to Grip on Tile Button -
Microsoft.Kinect.Toolkit.Controls project uses KinectCursorVisualizer.cs and KinectCursor.cs to render the virtual hand cursor on the UI. The Open Hand/Grip visual state is controlled via this Dependency Property defined in KinectCursor.cs.
public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register(
"IsOpen",
typeof(bool),
typeof(KinectCursor),
new UIPropertyMetadata(true, (o, args) => ((KinectCursor)o).EnsureVisualState()));
A quick find all references on the property IsOpen tells that the only place where this property is set is in KinectCursorVisualizer.cs-> OnHandPointersUpdated method. Line- 229
// Set open state
cursor.IsOpen = !pointer.IsInGripInteraction;
And this pointer.IsInGripInteraction property is set at KinectAdapter.cs Line 678
handPointer.IsInGripInteraction = newIsInGripInteraction;
If you look at the code just above this line you'll find that this property is only set to true if the target element has a QueryInteractionStatusHandler defined and it sets
args.Handled , args.IsInGripInteraction property to true.
Since KinectScrollViewer has this handler defined you see a grip image.
private void InitializeKinectScrollViewer()
{
KinectRegion.AddHandPointerGotCaptureHandler(this, this.OnHandPointerCaptured);
KinectRegion.AddHandPointerLostCaptureHandler(this, this.OnHandPointerLostCapture);
KinectRegion.AddHandPointerEnterHandler(this, this.OnHandPointerEnter);
KinectRegion.AddHandPointerMoveHandler(this, this.OnHandPointerMove);
KinectRegion.AddHandPointerPressHandler(this, this.OnHandPointerPress);
KinectRegion.AddHandPointerGripHandler(this, this.OnHandPointerGrip);
KinectRegion.AddHandPointerGripReleaseHandler(this, this.OnHandPointerGripRelease);
//This is the QueryInteractionStatusHandler
KinectRegion.AddQueryInteractionStatusHandler(this, this.OnQueryInteractionStatus);
KinectRegion.SetIsGripTarget(this, true);
this.scrollMoveTimer.Tick += this.OnScrollMoveTimerTick;
this.scrollViewerInertiaScroller.SlowEnoughForSelectionChanged += this.OnSlowEnoughForSelectionChanged;
// Create KinectRegion binding
this.kinectRegionBinder = new KinectRegionBinder(this);
this.kinectRegionBinder.OnKinectRegionChanged += this.OnKinectRegionChanged;
}
but KinectTileButton (extends KinectButtonBase) does not have this handler defined
private void InitializeKinectButtonBase()
{
KinectRegion.AddHandPointerPressHandler(this, this.OnHandPointerPress);
KinectRegion.AddHandPointerGotCaptureHandler(this, this.OnHandPointerCaptured);
KinectRegion.AddHandPointerPressReleaseHandler(this, this.OnHandPointerPressRelease);
KinectRegion.AddHandPointerLostCaptureHandler(this, this.OnHandPointerLostCapture);
KinectRegion.AddHandPointerEnterHandler(this, this.OnHandPointerEnter);
KinectRegion.AddHandPointerLeaveHandler(this, this.OnHandPointerLeave);
KinectRegion.SetIsPressTarget(this, true);
}
How to define this handler ? - Simple add following to your UI. Can be added to constructor
//Add the handler
KinectRegion.AddQueryInteractionStatusHandler(kinectButton, OnQuery);
Define the Handler
//Variable to track GripInterationStatus
bool isGripinInteraction = false;
private void OnQuery(object sender, QueryInteractionStatusEventArgs handPointerEventArgs)
{
//If a grip detected change the cursor image to grip
if (handPointerEventArgs.HandPointer.HandEventType == HandEventType.Grip)
{
isGripinInteraction = true;
handPointerEventArgs.IsInGripInteraction = true;
}
//If Grip Release detected change the cursor image to open
else if (handPointerEventArgs.HandPointer.HandEventType == HandEventType.GripRelease)
{
isGripinInteraction = false;
handPointerEventArgs.IsInGripInteraction = false;
}
//If no change in state do not change the cursor
else if (handPointerEventArgs.HandPointer.HandEventType == HandEventType.None)
{
handPointerEventArgs.IsInGripInteraction = isGripinInteraction;
}
handPointerEventArgs.Handled = true;
}
You may have to tweak this as per your requirement. Happy Kinecting :)
For my C# Windows Form Application, I have created a flowlayoutpanel that contains several panels. Inside the panel, I have a button "Clear" for each and every single panel.
How do I write the event handler for the code for the button "Clear" such that once I have click the button, the panel would sort of be "Removed" from the flowlayoutpanel.
This is a short part of the code of the adding of panels to the flowlayoutpanel.
nFlowPanel.Controls.Add(createNotificationPanel());
nFlowPanel.Controls.Add(createNotificationPanel());
nFlowPanel.Controls.Add(createNotificationPanel());
nFlowPanel.Controls.Add(createNotificationPanelImpt());
nFlowPanel.Controls.Add(createNotificationPanelImpt());
and this is the code for the button "Clear"
Button btnClear = new Button
{
Text = "Clear",
Name = "btnClear",
Location = new Point(416, 17)
};
p.Controls.Add(btnClear);
btnClear.Click += new EventHandler(buttonClear_Click);
So what should i write in the following method to have the effect of removing e.g. the second panel that was added in the first part of code I have written?
void buttonClear_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
EDIT
the code for creating my panel is
var p = new Panel
{
BorderStyle = BorderStyle.FixedSingle ,
Size = new Size(506,100),
Name = "notifyPanel"
};
and the code for creating my FlowLayoutPanel is
var nFlowPanel = new FlowLayoutPanel
{
FlowDirection = FlowDirection.TopDown,
WrapContents = false,
AutoScroll = true,
Size = new Size(530, 377),
Location = new Point(13, 145)
};
and the code for my button clear is
void buttonClear_Click(object sender, EventArgs e)
{
var button = (Control)sender;
var panel = button.Parent.Controls["notifyPanel"];
panel.Dispose();
}
however it gives the error
Object reference not set to an instance of an object.
on the panel.Dispose() line.
anyone can help?
The Controls.Remove() method is very dangerous, it doesn't dispose the control. Which will live on, moved to the so-called parking window, using up both Windows and managed resources. After a bit less than 10,000 times doing this it crashes your program when Windows is no longer willing to let you create any more windows.
Call the control's Dispose() method instead. That also automatically removes the control from its container.
void buttonClear_Click(object sender, EventArgs e)
{
var panel = nFlowPanel.Controls["notifyPanel"];
panel.Dispose();
}
You can do it like this:
nFlowPanel.Controls.Remove((sender as Button).Parent);
I will suggest you to use List for this. Before adding Panels in the FlowLayoutpanel, add them in the List. Then just remove the indexed panel from the flowlayoutpanel.
Panel pnlTemp = (panel)list[index];
nFlowPanel.Controls.Remove(pnlTemp);
To get the index of the button you have to add your buttons also to your list and after clicking any button, search the button in the list and get the index of the button where it is saved in the list. If my code is unclear, let me know. but I feel your task is that complex. I am not sure but this link may be of some help.
Hope it helps.