I get this very annoying border when pressing tab and the clicking the button
I've tried
foreach (Control x in this.Controls)
{
if (x is Button)
{
Button newbut = (Button)x;
newbut.FlatStyle = FlatStyle.Flat;
newbut.FlatAppearance.BorderColor = Color.FromArgb(0, 255, 255, 255);
newbut.FlatAppearance.BorderSize = 0;
newbut.TabStop = false;
}
}
And I've also tried doing adding an event on Keydown and not allowing to press the tab key but nothing has worked so far.
this is example of the border that keeps popping up
Fixed by generating own button class and editing the designer.cs file
If you do not want custom buttons, you can shift focus to another control once finished, this prevents the rectangle from showing. You could place a dummy control out of view and shift fucus to this.
private void btnDoSomething_Click(object sender, EventArgs e)
{
myDummyControl.Focus();
MessageBox.Show("This still executes even though we have lost focus");
// If you are decoupling your code from the UI, this becomes second nature quickly as it becomes part of your control handling.
}
Also you can stop the control from getting Tab focus my setting it's TabStop property tp false, do this in the buttons Paint event.
If you have many buttons, you can just point them to the same event handler (On_Paint).
private void On_Paint(object sender, PaintEventArgs e)
{
Button thisButton = sender as Button;
thisButton.TabStop = false;
}
Related
I have a form with a picturebox docked to fill the whole thing. On this form, I have a panel that is normally invisible and another picturebox; on the panel, I have a label and another panel with a label.
Here is what SHOULD happen when the user hovers over the second picturebox:
The picturebox's image changes and the first panel becomes visible, making the second panel and both labels visible too
The user clicks on the second label
The second label's OnClick handler makes the first label's text change and the second panel becomes invisible
A timer ticks for a few seconds
A code segment in the timer's OnTick handler causes the image in the second picturebox to change and the first panel to become invisible
Here is what DOES happen:
The picturebox's image changes and the first panel becomes visible, making the second panel and both labels visible too
The user clicks on the second label
The second label's OnClick handler sets the first label's text to a new string and sets the second panel's Visible property to false, BUT the second panel stays visible (although you can't interact with it) and the first label's text gets written on top of the old text
A timer ticks for a few seconds
A code segment in the timer's OnTick handler causes the image in the second picturebox to change and the first panel to become invisible
I've tried everything I can think of. I've called Invalidate, Update, and Refresh on every control in the form, I've called Application.DoEvents, I've reset the image in the background PictureBox to itself, nothing. The REALLY weird part is that in step 5, when the front picturebox resets itself and all panels are set invisible, nothing gets left behind - it's just for that brief few seconds between the OnClick handler terminating and the timer's OnTick cleaning up that there are problems. I can edit this for more information if needed, but does anyone have any ideas of what to do?
Edit: It's been pointed out to me that I should probably upload the code for this. Well, that code is a hacked-together mess, but okay. Also: there are some weird extra bits (in the enum types among others), they're for later parts of the project and irrelevant right now.
bool CountingHoverTime = false;
int HoverTime = 0;
int MasterTick = 0;
enum GhostState { Stand, Speak, Pet, Ask };
GhostState curState;
public enum TalkType { HoverGen, Petted, Spont, TimerMsg, Response };
private void Form1_Load(object sender, EventArgs e)
{
FormBorderStyle = FormBorderStyle.None;
ShowInTaskbar = false;
TopMost = true;
ControlBox = false;
Text = String.Empty;
WindowState = FormWindowState.Maximized;
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent;
this.TransparencyKey = Color.Transparent;
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//base.OnPaintBackground(e);
}
private void pictureBox2_MouseHover(object sender, EventArgs e)
{
if(curState == GhostState.Stand)
{
CountingHoverTime = true;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if((curState != GhostState.Ask) && (curState != GhostState.Stand))
{
MasterTick++;
if(MasterTick > 10)
{
SetToBasic();
}
}
else
{
MasterTick = 0;
}
if (CountingHoverTime)
{
HoverTime++;
if (HoverTime > 4)
{
HoverTime = 0;
curState = GhostState.Ask;
Say("What can I do for you?", TalkType.HoverGen);
}
}
}
public void SetToBasic()
{
curState = GhostState.Stand;
ghostBox.Image = Properties.Resources.stickStand1;
TalkPanel.Visible = false;
}
public void Say(String speak, TalkType type)
{
mainText.Text = speak;
if(type == TalkType.Response || type == TalkType.Spont)
{
curState = GhostState.Speak;
}
else
{
curState = GhostState.Ask;
}
ghostBox.Image = Properties.Resources.stickTalk;
if (type == TalkType.HoverGen)
OptionPanel.Visible = true;
else
OptionPanel.Visible = false;
TalkPanel.Visible = true;
backBox.Image = Properties.Resources.background;
ghostBox.Invalidate();
TalkPanel.Invalidate();
mainText.Invalidate();
backBox.Invalidate();
ghostBox.Update();
TalkPanel.Update();
mainText.Update();
backBox.Update();
Application.DoEvents();
}
private void op1label_Click(object sender, EventArgs e)
{
curState = GhostState.Speak;
OptionPanel.Visible = false;
Say("No can do yet.", TalkType.Response);
}
Edit 2: I've put together a gif visualization of what's happening, thank you HandbagCrab.
I've approached this from a different direction. I think the issue is to do with the picturebox you have docked on the form causing some issues.
To fix it and still keep the transparency, get rid of the backBox. Set the background colour of the form to a colour you're not going to use then set the transparency key to that colour. This will make those areas of the form transparent. Now you just need your hidden panel and your labels and whatever control it is that hosts your stick man image.
I've left the backgrounds of the labels as pink here but you should change them to your background colour so that they're not transparent.
When I run the form I get the transparency still and when clicking on the grey panel (I've used a panel to simulate your stick man) shows the hidden panel with the labels. Clicking label2 updates the text on label1 (the one that contains the text "longish text"), completely replacing the text.
Here it is in use (I've not done a gif as I wanted each step to be clearly visible)
Here's the application when open:
Here it is after clicking the grey box:
Here's the updated text when clicking label2:
I've left the application border style as Sizeable just so you can see where the border lies. I also took the screenshots over a black background so there was no visual clutter.
Here's me right clicking the desktop through the transparent section:
As the title suggests i am having trouble getting a DragOver event to function correctly. I have over 100 buttons on a form and i want their colour to change when a picturebox is dragged over them. I have set all buttons AllowDrop = true and have included the code below in the method.
private void ShipOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.None;
Button b = (Button)sender;
b.BackColor = Color.Green;
label22.Text = "";
}
I do not see why this will not work. I also have a DragLeave method which simply changes the colour to a different one.
One thing to note is that the item i am dragging over the button is larger than the button itself. Not sure whether this will have an effect.
You need to wire up the events to your method. If all of the buttons are in a single panel, you can do something like this in your form's constructor:
foreach (Button b in panel1.Controls.OfType<Button>()) {
b.DragOver += ShipOver;
}
Same principle applies to the DragLeave event.
I'm working on a C# WinForms application in which I have a number of processes that are all managed by a 'master' application.
In this master application, each process is visualized by its own FlowLayoutPanel which contains a number of buttons for various function. I call these panels the 'process blocks'.
However, when many of these processes are made, not all blocks easily fit on the screen. For this reason I am implementing a 'compact mode', which hides all the buttons of all the process blocks, leaving only their name, their status and the start/stop button visible. I then assign a ContextMenuStrip to each process block, in which I show all the buttons listed as a ToolStripMenuItem so I can access all the functions of the process block that way. I am clearing these ContextMenuStrips dynamically and add the items when the menu is opened.
I do this by iterating over all the child controls of the FlowLayoutPanel, see if they are of type Button, and if so, I add them to the ContextMenuStrip. See the code snippet below:
private void PanelCmsOpened(object sender, EventArgs e) {
try {
ContextMenuStrip cMenuStrip = (ContextMenuStrip) sender;
// Clear all items from the context menu
cMenuStrip.Items.Clear();
// Loop over all controls in the FlowLayoutPanel
foreach (var c in CPanel.Controls) {
Button btn = c as Button;
if (btn == null) continue; // Not a button, continue
// Get the text from the button
string lbl = btn.Text;
if (string.IsNullOrEmpty(lbl)) {
try {
// The button has no text (only an icon), so we get the tooltip text of the button
lbl = PanelTooltip.GetToolTip(btn);
}
catch {
// We can't get any text to display, so skip this button
continue;
}
}
// Add a new item to the ContextMenuStrip
cMenuStrip.Items.Add(new ToolStripMenuItem(lbl,
btn.BackgroundImage,
(s, ea) => btn.PerformClick() // Perform a click on the button
)
{
Enabled = btn.Enabled
});
}
}
catch (Exception Ex) {
MessageBox.Show("Fout bij openen van context menu: " + Ex.Message, "Fout", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
The problem:
Now this is all working fine, as long as the buttons are visible. However, when going to compact mode, I hide the buttons by setting their Button.Visible property. In that case, nothing happens. I've tried putting a try-catch block around the PerformClick, but no exception is thrown. Just nothing happens. Does anyone know how to make this work for hidden buttons?
PerformClick checks if button available for clicking before performing click. Hidden buttons are considered unavailable. You can simply show button just before performing click, and hide it after clicking:
cMenuStrip.Items.Add(
new ToolStripMenuItem(lbl, btn.BackgroundImage, (s, ea) => {
var size = btn.Size;
btn.Size = Size.Empty; // button still will be invisible
btn.Show(); // make it clickable
btn.PerformClick();
btn.Hide(); // hide again
btn.Size = size; // restore original size
});
NOTE: If you also need to add some visible buttons, then you should handle them separately to avoid flickering
cMenuStrip.Items.Add(new ToolStripMenuItem(
lbl, btn.BackgroundImage, (s, ea) => ClickButton(btn)));
Where ClickButton is a method which performs different logic depending whether button is visible or not:
private void ClickButton(Button button)
{
if (button.Visible)
{
button.PerformClick();
return;
}
var size = button.Size;
button.Size = Size.Empty;
button.Show();
button.PerformClick();
button.Hide();
button.Size = size;
}
The only thing you can't do is setting visible = false;
Other than that yu can use any trick to hide the buttons: You can stack them behind another control, you can move them out of sight in any direction or even move them into a different parent:
To hide them:
panel1.Size = Size.Empty;
button1.Parent = panel1;
//..
To show them again:
button1.Parent = this;
//..
Assuming they sit on the Form.
Note that they will have kept their original locations and sizes; watch for changes in the tab-order and z-order!
If the button is not visible the Click event won't be raised.
One option is to take the code which is in the button click event and add it as a separate method. Then call the method instead of the PerformClick row. This will work though if you do identical things on every button click.
Another options it to make the buttons transparent. This will make them invisible to the client and the PerformClick event will work fine. You can see that in the following link :Drawing a transparent button.
Hope this helps.
I'm making a settings form, where user can assign custom hotkeys for the application. There's a TextBox, and by clicking it with mouse, it focuses and waits for one keypress and then defocuses (by focusing another label):
private void txtKey_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
}
private void txtKey_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
TextBox textBox = (TextBox)sender;
textBox.Text = e.KeyCode.ToString();
label1.Focus();
}
Is there a way to defocus focused TextBox (and cancel the key assinging process), by either clicking it again with mouse, or by clicking the GroupBox around it? I can't figure out how to check if TextBox was already focused when clicked (because when clicked, it gets focused before I can test if it's focused). Of course I can add a button "Cancel" next to the TextBox, but that's not what I want.
There is no Click-event for GroupBox, so I can't defocus TextBox by clicking GroupBox around it. Or can I somehow?
You can set/remove the Focus with
Keyboard.Focus = null;
You can also register to the following event:
public event MouseButtonEventHandler PreviewMouseLeftButtonDown
This event fires every time you click on the TextBox, thus you can set the Focus there if you want to.
For Winforms there is a way as well. I'm not proficient in it, but here would be a way:
Make a textBox (e.g. named textBoxFocus) that lies outside your window. Size it 1, 1 and move it to -10,-10 for example. Then you can register to the Click event and write
textBoxFocus.Focus();
It's a bit of a roundabout way, but should achieve what you want.
Thanks to private_meta for getting me to right direction (in comments)! I set the flag with click event, and before setting the flag, testing if flag is set. So first click does not find the flag, but second will. And flag is cleared within textbox Enter-event (which fires before Click-event). Now every other click focuses and every other defocuses textbox, as I wanted.
private void txtKey_Enter(object sender, EventArgs e)
{
TextBox textBox = (TextBox)sender;
textBox.Tag = null;
}
private void txtKey_Click(object sender, EventArgs e)
{
TextBox textBox = (TextBox)sender;
if (textBox.Tag != null) label1.Focus();
textBox.Tag = "clicked";
}
One of the simple way is that, you may use a bool flag here.
Algorithm:
By default, the bool value is 0;
If(Textbox Selected && flag = 0)
Do your task; and flag = 1;
I hope I could satisfy your query and you can follow this algorithm.
I have a button and on click of that i show a popup which has a listbox.
popup named - popComboList
Listbox named - lstComboBoxResult
I am giving a focus to a listbox but at initial on a click of a button the listbox doesn't get focus-(this happens only once at initial, when i first time click button) After the second click it works.
private void bnOpen_Click(object sender, RoutedEventArgs e)
{
if (IsDesignTime)
return;
lstComboBoxResult.Width = tbComboValue.ActualWidth + bnOpen.ActualWidth;
if (!popComboList.IsOpen)
{
SetPopupPosition(popComboList);
popComboList.IsOpen = true;
lstComboBoxResult.Focus();
}
else
{
popComboList.IsOpen = false;
}
}
This is a bit of a guess, but try calling UpdateLayout() after opening the pop-up, but before calling Focus(). It's possible that the listbox is not fully initialized and therefore unable to accept focus until it has become visible for the first time.