Prevent a form from coming to the front - c#

I have two TopMost forms quite close together (form A and B). If I click on A it comes to the front and put's itself over form B. I tried to overwrite the WndProc method:
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0201 || m.Msg == 0x0202 || m.Msg == 0x0203)
{
return;
}
base.WndProc(ref m);
}
Nevertheless the form A still overlays form B if I click on it so I guess it must be some other Msg code. Hopefully someone knows how to do it.

you have BringToFront/BringToBack functions available under ActiveForm. I suggest you look into those. Off the top of my head, I'd probably override one of those and make sure when Form A has focus, to bring form B to front.
However, the problem you're having can be solved without code.

Related

Preventing WindowState.Normal

I have an application that I am working on (for myself), and I want to prevent the Window from showing at all.
So far, what I have got is WindowState.Minimized so that the Form's initial state is Minimized. And when I click the app's icon in the Taskbar, I want it to remain minimized - not just Hide() it when it has shown. So I thought that something like this might work:
protected override void OnGotFocus(EventArgs e)
{
this.WindowState = WindowState.Minimized;
}
But I was wrong. So what I am thinking is that I need something that happends before OnGotFocus. The reason that just hiding it when it gets focused is not enough, is because you can see, very faintly, that it does actually show itself when you click the icon in the taskbar before this.WindowState = WindowState.Minimize gets called.
My only requirement is that the application must not be shown when it's icon is clicked on the Taskbar. I will need to show the window programatically, at some point, though.
How can I make sure that clicking its icon never shows the window?
This seemed to work for me with no "hint" of it coming and going:
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0112) //WM_SYSCOMMAND
{
if ((m.WParam.ToInt32() & 0xFFF0) == 0xF030 ||
(m.WParam.ToInt32() & 0xFFF0) == 0xF120)
m.WParam = new IntPtr(0xF020);
}
base.WndProc(ref m);
}
Just override the WndProc and this will catch both SC_MAXIMIZE (0xF030) and SC_RESTORE (0x0F120). SC_MINIMIZE is 0xF020.
As Hans has suggested, I have edited my post to mask out the low-order bits used by the system per this MSDN section: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646360(v=vs.85).aspx
Hi you can use the form_resize event to trigger windowstate to minimized
private void Form1_Resize ( object sender , EventArgs e )
{
if ( WindowState == FormWindowState.Maximized )
{
// minimize it here
}
}

WM_MOUSEWHEEL message does not propagate to parent

I have a RichTextBox with ScrollBars set to None. According to MSDN
The DefWindowProc function propagates the message to the window's
parent. There should be no internal forwarding of the message, since
DefWindowProc propagates it up the parent chain until it finds a
window that processes it.
I interpret this as, I should not need to hook into the message pump (IMessageFilter) and manually forward WM_MOUSEWHEEL events to the parent Form containing the richtextbox. When I am inside of RichTextBox and perform a mouse scroll, the Form does not scroll. Why not? How can I get the Form to scroll?
Keep in mind that scrollbars are set to none for RichTextBox and enabled for the Form. So why isn't the form getting the scroll event?
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
this.AutoScroll = true;
richTextBox1.ScrollBars = RichTextBoxScrollBars.None;
}
}
For my derived TextBox, rather than ignore the mouse wheel as the above does, I instead wanted to pass it on up to my Parent control... which is what the TextBox SHOULD do in any case, in my opinion. Here's what I put in my derived TextBox's WndProc:
switch (m.Msg)
{
case 0x020A: // WM_MOUSEWHEEL
case 0x020E: // WM_MOUSEHWHEEL
if (this.ScrollBars == ScrollBars.None && this.Parent != null)
m.HWnd = this.Parent.Handle; // forward this to your parent
base.WndProc(ref m);
break;
default:
base.WndProc(ref m);
break;
}
The form doesn't scroll because the RichTextBox handles the WM_MOUSEWHEEL itself and doesn't call DefWindowProc to forward it to its parent. Apparently that doesn't change when disabling the scroll bars.
So you either need to implement an IMessageFilter or create a subclass of RichTextEdit that will forward the WM_MOUSEWHEEL as shown here:
public class NoScrollRichTextBox : RichTextBox
{
const int WM_MOUSEWHEEL = 0x020A;
protected override void WndProc(ref Message m)
{
// This will completely ignore the mouse wheel, which will disable zooming as well
if (m.Msg != WM_MOUSEWHEEL)
base.WndProc(ref m);
}
}

Activate a form and process button click at the same time?

I'm using Windows Forms in C#.
I have a main form with a couple of toolbars that contain toolStripButtons. After working with another form that contains data, the main form loses focus and clicking on a toolStripButton does not trigger OnClick event: the first click activates the main form, and only the second click actually pushes the button. I need the user to click a button only once to trigger a Click event, any ideas on how to do that? Thanks.
Notes:
I was using MDI and there were no problems clicking on the parent's form buttons. But now the paramount is to have forms freely floating across multiple displays.
The worker forms have the main form as the Owner property, this way they stay on top of the main form.
When I click on the button of an inactive form, none of MouseHover, MouseEnter, MouseDown nor MouseUp fires. It's just main form's Activate event that fires.
There is a treeView (inside a tabControl, inside a splitContainer, inside a panel), on the main form. Its items are selected upon a first mouse click, even if the main form is inactive. I guess not all controls are equal!
What you need to do is create a class that inherits ToolStrip and handles the WndProc. This is one way to do it. There are others.
private class MyToolStrip : ToolStrip
{
private const uint WM_LBUTTONDOWN = 0x201;
private const uint WM_LBUTTONUP = 0x202;
private static bool down = false;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_LBUTTONUP && !down)
{
m.Msg = (int)WM_LBUTTONDOWN;
base.WndProc(ref m);
m.Msg = (int)WM_LBUTTONUP;
}
if (m.Msg == WM_LBUTTONDOWN) down = true;
if (m.Msg == WM_LBUTTONUP) down = false;
base.WndProc(ref m);
}
}
I've also seen this solution:
protected override void WndProc(ref Message m)
{
// WM_MOUSEACTIVATE = 0x21
if (m.Msg == WM_MOUSEACTIVATE && this.CanFocus && !this.Focused)
this.Focus();
base.WndProc(ref m);
}
I ran into this at the last place I worked, I think the solution I came up with worked more like the latter, but I don't have access to the exact code I used.
if u have Form without borders, so this logic was working for you built in :)
form.FormBorderStyle = FormBorderStyle.None

Form changes size between constructor exit and begining of Load C#

I am rather baffled at the moment, I have a form which I show as a dialog (although non dialog is the same) in response to a menu item click.
var createUser = new FrmCreateUser();
createUser.ShowDialog();
Somewhere between the constructor exiting, and when the load event is fired the size is being changed.
I have overloaded WndProc in the 'parent' form, although it just falls though to the base implementation so I find it hard to believe that's the cause.
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)WindowsMessages.WM_SYSCOMMAND)
{
if (m.WParam.ToInt32() == (int)WindowsMessages.SC_MINIMIZE)
{
foreach (Form f in Application.OpenForms)
if (f != this)
f.Hide();
}
else if (m.WParam.ToInt32() == (int)WindowsMessages.SC_RESTORE)
{
foreach (Form f in Application.OpenForms)
if (f != this && f.GetType() != typeof (Controls.DockLocation) )
f.Show();
}
}
base.WndProc(ref m);
}
I can restore the size to what is should be in the load event handler, but I remain confused as to the cause.
private void FrmCreateUser_Load(object sender, EventArgs e)
{
Size = new Size(RestoreBounds.Width, RestoreBounds.Height);
}
If anyone can shed some light on this it would be much appreciated.
Edit
Removing the WndProc override has no effect.
SizeChanged is only invoked once (inside the createUser.ShowDialog() call) which occurs before OnHandleCreated(EventArgs e) is called.
Edit 2
Here are some pictures to show the effect.
designer:
Designer http://www.free.nodespot.com/designer.jpg
runtime:
Runtime http://www.free.nodespot.com/runtime.jpg
I found it - much by a happy fluke of where the PropertyGrid positioned itself as to anything else. StartPosition had been set to WindowsDefaulBounds rather than the default of WindowsDefaultLocation.

Is it possible to disable animation when minimizing / restoring window?

When I click minimize button in my Windows Forms application, I don't want it to perform the classic Windows minimize animation (window going down to taskbar).
As far as I know, there's no Minimize event, I can just use Resize, but I have no clue how to detect if I clicked minimize button. I tried to use if ( WindowState = FormWindowState.Minimized ) { ... }, but that does the animation anyway and triggers the code after.
Is there any way to detect minimize button click? Is there any way to disable animations or is that triggered by Windows settings?
This works, but it has an unpleasant side-effect on the taskbar button. I can't think of another way, animation isn't even accessible from SystemParametersInfo().
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
protected override void WndProc(ref Message m) {
// Catch WM_SYSCOMMAND, SC_MINIMIZE
if (m.Msg == 0x112 && m.WParam.ToInt32() == 0xf020) {
this.Hide();
this.WindowState = FormWindowState.Minimized;
this.BeginInvoke(new Action(() => this.Show()));
return;
}
base.WndProc(ref m);
}
}
Update: disabling animation on Aero is possible by pinvoking DwmSetWindowAttribute() with the DWMWA_TRANSITIONS_FORCEDISABLED attribute. See this answer.

Categories

Resources