How to reproduce a forum/twitter-like UI on Winform - c#

As a classic forum, threads and replys are displayed on a page, with dark and light and dark and light backcolor.
I am trying to write a client of a forum on windows using winform. It is
At first, I have tried this way:
Add a big panel to the form, let's call it the PARENT PANEL.
Add small panels to the big panel like this:
panel1.Visible = false;
for (int i=0; i<5;i++)
{
Panel parent = new Panel();
parent.Height = 800;
Random ra = new Random();
TextBox p = new TextBox();
p.Text = "fehsuifq";
p.Multiline = true;
p.WordWrap = true;
p.Dock = DockStyle.Fill;
parent.BackColor = Color.FromArgb(ra.Next(0, 254), ra.Next(0, 254), ra.Next(0, 254));
p.BorderStyle = BorderStyle.None;
p.ReadOnly = true;
p.TabStop = false;
p.BackColor = this.BackColor;
parent.Controls.Add(p);
parent.Dock = DockStyle.Top;
panel1.Controls.Add(parent);
}
panel1.Visible = true;
Every panel(tenicially, a control) displays a thread's text and images and others details(like authors or avator).
Images are not shown until it is clicked.
when the image is clicked, it is loaded and the controls's height will change as result.
The PARENT PANEL will contains hundreds of these controls since there will be so many threads. It is and have to be scrollable, obviously.
But if I put a textbox in the control, the scroll wheel no longer work on the PARENT PANEL.If I use a label, it is not selectable.
I think this way can't be more stupid, completely.
So I am looking for a better to do this job, to display hundreds or even thousands threads/replys on winform, which is:
the height is dynamic, because the images inside will not load until it is clicked.
The text inside is selectable (I edited this just to disambiguate)
the PARENT PANEL can response to the mouse's wheel, just like twitter, forums.
So that I can use my scroll wheel to browse all the replys at one time. The loading is a background work.
Look at the picture, when the text is selected, the whole panel is still response to the wheel(just like normal webPage). This is a uwp app and I am not sure if winform can do this.

Related

User Control c# Add Dynamically

I create a user control dynamically in my code
UserControl myobject = new UserControl();
myObject contains a button etc.
when I add this control to my picturebox
picturebox.Controls.Add(myobject);
my picturebox's backgorund image is dissappeared.
Why?
note: the button can be seen however. I want picturebox to be seen also
Set transparent basckground color of your user control. This will make picturebox visible:
UserControlDisplay myobject = new UserControlDisplay();
myobject.BackColor = Color.Transparent;
picturebox.Controls.Add(myobject);
BTW I believe you have different name of user control. And yes, as #samjudson stated, PictureBox should not be used this way: try to use Panel with background image instead (approach will stay same - use transparent color to see parent control):
panel.BackgroundImage = // your image
UserControlDisplay myobject = new UserControlDisplay();
myobject.BackColor = Color.Transparent;
panel.Controls.Add(myobject);
Try this:
UserControl myobject = new UserControl();
Button but = new Button();
but.BackColor = Color.Gray
pic.BackColor = Color.Green;
myobject.Controls.Add(but);
pic.Visible = true;
pic.Controls.Add(myobject);
The PictureBox control is not meant to be used as a container. Try adding a parent Panel or similar and the adding the PictureBox and your custom control to the Panel control.

How to add scrollbar to groupbox? C# 4.0

So... did someone know how to make it?...
In a panel is easy, because we can set the "AutoScroll" property, to true... but groupbox doesn't have it.
Anyways... exists some way for it?, thanks in advance ;-).
Quite simple... Add a panel inside a group box.
Declare Group box object and Panel object which will contain the scroll bar by default and some of my Check box objects;I read somewhere that Group box's don't have scroll bar for aesthetic reasons(i hope it's not true, why not let the user make that call). Solution is simple, once you know that you will create a panel that will lay on top of your group box just to get your scroll bar.
private System.Windows.Forms.GroupBox grpDR;//GROUPBOX IN WHICH PANEL WILL OVERLAY
private System.Windows.Forms.Panel grpScrlDR;//PANEL WHICH WILL HAVE SCROLL BAR AND CONTAIN CHECK BOXES
private System.Windows.Forms.CheckBox chkDr2;
private System.Windows.Forms.CheckBox chkDr1;
private void InitializeComponent()
{
this.grpScrlDR = new System.Windows.Forms.Panel();
this.chkDr2 = new System.Windows.Forms.CheckBox();
this.chkDr1 = new System.Windows.Forms.CheckBox();
this.grpDR = new System.Windows.Forms.GroupBox();
this.grpScrlDR.SuspendLayout();
this.grpDR.SuspendLayout();
//
// grpScrlDR
// PANEL DETAILS ADDING CHECKBOX CONTROLS AND ENABLING AUTO SCROLL
this.grpScrlDR.AutoScroll = true;
this.grpScrlDR.Controls.Add(this.chkDr2);
this.grpScrlDR.Controls.Add(this.chkDr1);
this.grpScrlDR.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpScrlDR.Location = new System.Drawing.Point(5, 336);
this.grpScrlDR.Name = "grpScrlDR";
this.grpScrlDR.Size = new System.Drawing.Size(175, 230);
this.grpScrlDR.TabIndex = 0;
//
// chkDr2
//
this.chkDr2.AutoSize = true;`
this.chkDr2.Location = new System.Drawing.Point(13, 45);
this.chkDr2.Name = "chkDr2";
this.chkDr2.Size = new System.Drawing.Size(54, 20);
this.chkDr2.TabIndex = 1;
this.chkDr2.Text = "Permit#";
this.chkDr2.UseVisualStyleBackColor = true;
this.chkDr2.CheckedChanged += new System.EventHandler(this.chkDr_CheckedChanged);
//
// chkDr1
//
this.chkDr1.AutoSize = true;
this.chkDr1.Checked = true;
this.chkDr1.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkDr1.Location = new System.Drawing.Point(13, 22);
this.chkDr1.Name = "chkDr1";
this.chkDr1.Size = new System.Drawing.Size(54, 20);
this.chkDr1.TabIndex = 0;
this.chkDr1.Text = "Account";
this.chkDr1.UseVisualStyleBackColor = true;
this.chkDr1.CheckedChanged += new System.EventHandler(this.chkDr_CheckedChanged);
//
// grpDR
// GROUP BOX DETAILS - GROUP BOX IS ADDING PANEL CONTROLS
this.grpDR.Controls.Add(this.grpScrlDR);
this.grpDR.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.grpDR.Location = new System.Drawing.Point(5, 336);
this.grpDR.Name = "grpDR";
this.grpDR.Size = new System.Drawing.Size(175, 230);
this.grpDR.TabIndex = 46;
this.grpDR.TabStop = false;
this.grpDR.Text = "Report by";
this.grpDR.Visible = false;
}
The GroupBox cannot display a scroll bar. If you need a control similar to a GroupBox that can contain a scroll bar, see the Panel control
Read This Article - Find (The GroupBox cannot display a scroll bar) Text
If you need to add a panel inside of your GroupBox, Dock a Panel inside of the GroupBox and set the AutoScroll property on the docked Panel to true. You can then place any controls you need inside of the GroupBox on the Panel, which will scroll when necessary.
If you don't like the way that looks as you stated above, then you have two possible options:
There may be a way to hack (more like "abuse" in this situation) the GroupBox control by making calls into the native Win32 API to add a scrollbar. I rarely use native calls on managed controls, but I've done this in situations where, for instance, I need to disable the scroll bar on a ListView as ListView doesn't expose this property. Below I expose the native Win32 function for use in C#, just call SetScrollBarVisible to enable or disable the scrollbar as needed from your code (I have not tested this on a GroupBox):
If aesthetics is THAT important to you (not a bad thing, user experience is greatly underappreciated in many areas of the application development world) and adding a scroll bar to the GroupBox doesn't work/look good to you, you will need to find another solution. I would imagine the best solution would be to make your own control from the ground up that meets your expectations (or modify the scrollbar itself, no idea how to do this), though this is can be a lot more work than it might be worth.
Here is how I expose and call the Win32 function SetScrollBar from my C# code (sorry, the DllImport won't format as a code block for some reason):
[DllImport ("user32")]
private static extern long ShowScrollBar (long hwnd , long wBar, long bShow);
long SB_HORZ = 0;
long SB_VERT = 1;
long SB_BOTH = 3;
private static void SetScrollBarVisible (Control control, long sb, bool enable)
{
if (control != null) return;
if (enable)
ShowScrollBar(control.Handle.ToInt64(), sb, 1);
else
ShowScrollBar(control.Handle.ToInt64(), sb, 0);
}
To do this you would have to add 1 panel to the groupbox and set the autoscroll property to true.
Then you would add a second panel which would be large then the first panel.
On this second panel (StringPanel in the beleow code) you would add controls.
System.Windows.Forms.GroupBox StringsGroup;
System.Windows.Forms.Panel StingPanel;
System.Windows.Forms.Panel StringPanel2;
StringsGroup = new System.Windows.Forms.GroupBox();
StingPanel = new System.Windows.Forms.Panel();
StringPanel2 = new System.Windows.Forms.Panel();
//Add your controls to StringPanel
StingPanel.Size = new System.Drawing.Size(300, 800);
StringPanel2.Size = new System.Drawing.Size(325, 345);
StringPanel2.AutoScroll = true;
this.StringPanel2.Controls.Add(StingPanel);
this.StringsGroup.Controls.Add(this.StringPanel2);
Horizontal Scroll Bar Tip
If you have a panel where all the controls contained within it are anchored to the top (so that they are centered) you will never see the horizontal scroll bar. You need to have at least one control that is anchored left & top that disappears when the panel is too small to show it in order for the horizontal scroll bar to appear. I put a label with hidden text on the panel to accomplish this.
This little tidbit took me quite a while to discover! Hope it's helpful!
If you dont want scrollbars, but want your GroupBox to grow, you can edit these below properties from the Layout section as shown below.
AutoSize = true;
AutoSizeMode = GrowOnly;

Scrollbar location is moving visible/nonvisible changing controls

I have a form with a scrollable panel and two controls sitting right on top of each other - one visible one not. Based on a certain condition when that form is activated I might swap the visible properties of the two controls. These controls are at the bottom of the scrollable panel. If when I leave that form I leave it scrolled to the bottom, go change the condition that will cause the controls' visibility to swap and go back to that form the visible control will have dropped about 200px down the page leaving a large gap. Anyone know what could be causing this? I tried resetting the scrollbar position to the top on form close but that just causes a smaller gap and sometimes the control to move higher into other controls. Any ideas?
Here is an example that reproduces the problem. If the mouse is moved over the red label, the visibility of button2 is changed to true which causes the scroll jumps back up to Button1.
public class Form123456 : Form {
public Form123456() {
Controls.Add(new UC1());
}
public class UC1 : UserControl {
Button b1 = new Button { Text = "Button1" };
Label lb = new Label { Text = "_", AutoSize = true, BackColor = Color.Red };
Button b2 = new Button { Text = "Button2", Visible = false };
Button b2b = new Button { Text = "x" };
Button b3 = new Button { Text = "Button3" };
public UC1() {
AutoScroll = true;
Dock = DockStyle.Fill;
b1.Location = new Point(0, 200);
b2.Location = new Point(0, 600);
lb.Location = new Point(70, 600);
b2b.Location = new Point(90, 600);
b3.Location = new Point(0, 800);
Controls.Add(b1);
Controls.Add(b2);
Controls.Add(lb);
Controls.Add(b2b);
Controls.Add(b3);
lb.MouseEnter += delegate {
b2.Visible = true;
};
lb.MouseLeave += delegate {
b2.Visible = false;
};
}
}
}
To fix it, one solution is to add this code:
protected override Point ScrollToControl(Control activeControl) {
return this.AutoScrollPosition;
}
Solution from:
Why does clicking in a text box cause an AutoScroll panel to scroll back to the top?
No repro. Sounds to me that you are doing more than just changing the Visible property. Whenever you assign the Location property, you have to add the AutoScrollPosition to compensate for the scroll state. Post code if this doesn't help.
Have you verified the order that you change visibility of the two controls?
The scroll bars on a container with auto scroll set to true will appear and disappear depending on the position of controls that are outside of the visible area of the control. Controls that are invisible do not count.
So in your case if you make both controls invisible at anytime, the scroll bars will disappear. They will come back when one control is made visible. So to make sure you don't have a jump in scroll bar position and controls position you should make sure that at no time are both controls invisible. Another solution is to have a pseudo-visible control on the container. That is a control that has its visibility set to true but it is not actually visible for the user (for example a dot of the color of the background, a label with no text ...). Position this control in the furthest position x,y and the scroll bars will never disappear..

Winforms, creating padding when using Dock properties

How do I add padding, or some space between the textboxes when using dockstyle.top property?
for(int i =0; i< 10; i++) {
textboxes[i] = new TextBox();
textboxes[i].Dock = DockStyle.Top;
mypanel.Controls.Add(textboxes[i]);
}
The code above puts textboxes right beneath each other. Can't figure this out without using mass panels or fixed positioning. How to do the following?
1) I would like to add around 10-20pixels between boxes.
2) How to change size (height,width) of the textboxes, since when using dockstyle.top it ignores the size commands ?
With DockStype.Top you can't change the width of your TextBoxes, cause they are docked. You can only change the height. But to change the height of a TextBox you have to set the Multiline = true beforehand.
To get the space between the different boxes you have to put each TextBox within a panel, set the TextBox.Dock = Fill, the Panel.Dock = Top and the Panel.Padding = 10. Now you have some space between each TextBox.
Sample Code
for (int i = 0; i < 10; i++)
{
var panelTextBox = CreateBorderedTextBox();
this.Controls.Add(panelTextBox);
}
private Panel CreateBorderedTextBox()
{
var panel = CreatePanel();
var textBox = CreateTextBox();
panel.Controls.Add(textBox);
return panel;
}
private Panel CreatePanel()
{
var panel = new Panel();
panel.Dock = DockStyle.Top;
panel.Padding = new Padding(5);
return panel;
}
private TextBox CreateTextBox()
{
var textBox = new TextBox();
textBox.Multiline = true;
textBox.Dock = DockStyle.Fill;
return textBox;
}
What i forgot, you can also give a try to the FlowLayoutPanel. Just remove the DockStyle.Top from the panels and put them into the FlowLayoutPanel. Also you should set the FlowDirection to TopDown. Maybe this can also help you to solve your problem, too.
Another work around that suits smaller layouts is to just add a Label control afterwards also docked to the Top, which is not AutoSized, Text=" ", Height=your padding. This is quite useful for the odd bit of padding when using the designer.
I know where you're coming from, this is especially frustrating after returning to WinForms from WPF.
I would suggest using a TableLayoutPanel, in which each TextBox would get its own cell, and adjusting the properties of the cells. This should solve both your padding and size problems.
Another alternative would be to use some more complex layout controls, such as the DevExpress ones (not free).

event when the scroll bars appear C#

How can you detect exactly when the scroll bar appears in a UserControl? Is there an event for this?
They can only appear when the control is resized or the amount of data in the control increases. Since you get notifications of resize, and adding data is up to you. It's easy to add code to test for the scrollbar in the few places where their visibility can change. There's really no need to have a special notification.
I ended up using the Layout event, and checking if the scrollbars were currently shown or not. A Layout event is sent when the scroll bar visibility changes.
This is more reliable than listening to the size of the window, because the size of the window is not the only thing that can cause the scrollbars to appear.
https://msdn.microsoft.com/en-us/library/system.windows.forms.control.layout(v=vs.110).aspx
Scroll bars are finicky
Working with scroll bars is often arduous. The Layout event solution is correct but I want to add my additional research to the knowledgebase.
I'm attempting to automatically change the width of multiple UserControl inside a custom UserControl that inherits from FlowLayoutPanel. I want a vertical scroll bar to appear only when the list is longer than the panel size. No horizontal scroll bar ever. Your implementation may differ slightly but the bulk of code will be similar and face similar issues.
ScrollableControl
In order for a UserControl to have a scroll bar appear, it must inherit from ScrollableControl. Both Panel and ContainerControl fit this criteria.
ScrollableControl only contains the Scroll event. This event occurs when scrolling but not upon appearance of the scroll bar.
Rather, the Layout Event found inside Control will occur when a control should reposition its child controls. This includes resizing, child resizing, and parent resizing. I would recommend using this event rather than manually checking for resize to avoid unwanted and inconsistent behavior.
Detecting a scroll bar
To detect when the scroll bar should appears, I count the number of controls in the FlowLayoutPanel and compare it against the number of "visible controls". Visible controls are those which intersect the border area of the panel.
private void RichFlowPanel_Layout(object sender, LayoutEventArgs e)
{
var controls = Controls.Cast<Control>().OrderBy(x => x.Top);
var visibles = controls.Where(l => ClientRectangle.IntersectsWith(l.Bounds));
if (visibles.Count() <= Controls.Count)
{
// A scrollbar exists
}
else
{
// A scrollbar does not exist
}
}
Derived from this answer.
Controlling a scroll bar
A scroll bar can automatically show/hide by setting AutoScroll=true. This will also display the horizontal scrollbar if there isn't space for the vertical scrollbar. AutoScroll opens a Pandora's box of scrollbar issues & bugs. In order to keep the horizontal scrollbar hidden, AutoScroll must be false. This answer outlines a work around for keeping the horizontal hidden.
Specifically
panel.HorizontalScroll.Maximum = 0;
HScroll = false;
panel.VerticalScroll.Visible = false;
will hide the horizontal scroll bar.
The usage and odd behavior of HScroll is covered in this answer.
Combining what we've learned
The following event method is attached to the Layout event inside my custom user control extending FlowLayoutPanel.
Point prevPosition;
private void RichFlowPanel_Layout(object sender, LayoutEventArgs e)
{
var controls = Controls.Cast<Control>().OrderBy(x => x.Top);
var visibles = controls.Where(l => ClientRectangle.IntersectsWith(l.Bounds));
prevPosition = AutoScrollPosition;
if (visibles.Count() <= Controls.Count)
{
Console.WriteLine("showing scroll bar" + " V: " + visibles.Count() + " C: " + Controls.Count);
VerticalScroll.Visible = true;
// Insert method here to tell children controls to resize
HorizontalScroll.Maximum = 0;
HScroll = false;
HorizontalScroll.Visible = false;
}
else
{
Console.WriteLine("hiding scroll bar" + " V: " + visibles.Count() + " C: " + Controls.Count);
VScroll = false;
VerticalScroll.Visible = false;
// Insert method here to tell children controls to resize
HorizontalScroll.Maximum = 0;
HScroll = false;
HorizontalScroll.Visible = false;
}
AutoScrollPosition = new Point(Math.Abs(AutoScrollPosition.X), Math.Abs(prevPosition.Y));
}
Additionally, InitalializeComponents() of the FlowLayoutPanel for completeness and because docking, AutoSize, etc. can often bring confusing behavior.
this.SuspendLayout();
//
// RichFlowPanelUserControl
//
this.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.AutoSize = true;
this.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
this.Padding = new System.Windows.Forms.Padding(3);
this.WrapContents = false;
this.Layout += new System.Windows.Forms.LayoutEventHandler(this.RichFlowPanel_Layout);
this.ResumeLayout(false);
I understand this is slightly off-topic but the combination of this information should help users on their scroll bar adventures.
Why not use the "ClientSizeChanged" event?
This event gets fired if the client size has changed, which is the case if a scrollbar is added.

Categories

Resources