I am using this code to check if the form is minimized:
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_SYSCOMMAND:
int command = m.WParam.ToInt32() & 0xfff0;
if (command == SC_MINIMIZE)
MessageBox.Show("Minimized");
Variaveis.telaMinimizada = true;
else
Variaveis.telaMinimizada = false;
MessageBox.Show("Maximized");
break;
}
base.WndProc(ref m);
}
This code works like a charm. When I click on minimize button, appear the message "minimized", and when I reopen the application, appear the message "maximized"
But there is a problem. Not always people minimize the form by clicking on minimize button. I mean, if I click on screen OUT the form, the form will also minimize, and when this happens, the code I have do not detect that the form got minimized.
How can I check if the form is minimized (or is invisible on screen) when the form gets minimized after clicking OUT the form?
Ideas? Thanks!
Edit: I already tried doing what is recommended on this post, but do not work:
How to detect when a windows form is being minimized?
this might work for you
//we create a variable to store our window's last state
FormWindowState lastState;
public Form2()
{
InitializeComponent();
//then we create an event for form size changed
//i did use lambda for creating event but you can use ordinary way.
this.SizeChanged += (s, e) =>
{
//when window size changed we check if current state
//is not the same with the previous
if (WindowState != lastState)
{
//i did use switch to show all
//but you can use if to get only minimized status
switch (WindowState)
{
case FormWindowState.Normal:
MessageBox.Show("normal");
break;
case FormWindowState.Minimized:
MessageBox.Show("min");
break;
case FormWindowState.Maximized:
MessageBox.Show("max");
break;
default:
break;
}
//and at the and of the event we store last window state in our
//variable so we get single message when state changed.
lastState = WindowState;
}
};
}
Edit:
and to check if form is not on top anymore you can override OnLostFocus like so
protected override void OnLostFocus(EventArgs e)
{
MessageBox.Show("form not on top anymore");
base.OnLostFocus(e);
this.Focus();
}
Related
I have a application that opens some child windows with the parameterless Show()-Methode. So the child-windows have no owner, which enabled them to be behind or in front of the main window.
Now I would like to know if the whole application gets or losts focus. Is there a single event to do this?
I tried OnActivate/OnDeactivate and OnGotFocus/OnLostFocus which only reports events for a single form. This means the OnLostFocus-event is fired when the application lost focus, but also if another form is focused.
You can handle WM_ACTIVATEAPP in your main form and get notified about activation or deactivation of your app:
private const int WM_ACTIVATEAPP = 0x1C;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_ACTIVATEAPP)
{
if (m.WParam == IntPtr.Zero)
BeginInvoke(new Action(() => { Text = "Deactivated"; }));
else
BeginInvoke(new Action(() => { Text = "Activated"; }));
}
base.WndProc(ref m);
}
Note: As it's already mentioned in the comments by Hans, when using above option, you should be careful to not fall into a deadlock and infinite loop. Make sure you read the comments.
As another option, you also can detect activation or deactivation of every form by handling Activate and Deactivate event. When a form deactivates, you can check if the app is still foreground, by checking check if Form.ActiveForm has value:
private void f_Deactivate(object sender, EventArgs e)
{
BeginInvoke(new Action(() =>
{
if (Form.ActiveForm == null)
Text = "App Deactivated"; //App deactivated
else
Text = "Still Active"; //App is still active
}));
}
I am developing a Windows Forms application in C# in which I have a form which must start in a maximized state and not allow users to restore or resize it. I have already configured the form to start in maximized mode, disable the restore and maximize button and locked the borders of the form but when the title bar is double clicked, the form restores to a smaller size which is unexpected. The following are the properties I set to achieve the required behaviour:
FormBorderStyle = FixedSingle
MaximizeBox = False
WindowState = Maximized
Can someone please help me solve this problem and explain me the solution?
Thanks in advance.
You have to remember that your form starts with some default size values and double click is just toggling between 2 states.
Within your normal state the form will retrieve it's last ( in your case default ) size which you can override :
Width = Screen.PrimaryScreen.Bounds.Width;
Height = Screen.PrimaryScreen.Bounds.Height;
Another thing is that your application has something called start position which ( from what I remember ) defaults to the center of the screen and you can change it using :
Form.StartPosition = new Point(0, 0); // top-left corner
Now all you have to do in your applicaiton is to check for the toggle between window states. Easiest way would be to use WndProc and wait for messages listed in this msdn page :
protected override void WndProc(ref Message m)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_MAXIMIZE = 0xF030;
const int SC_RESTORE = 0xF120;
if (m.Msg == WM_SYSCOMMAND)
{
switch((int)m.WParam)
{
case SC_RESTORE:
// your window was restored ( double clicked on the command bar )
// set it's window state back to maximize or do whatever
break;
case SC_MAXIMIZE:
// your window was maximized .. no actions needed, just for debugging purpose
break;
}
}
base.WndProc(ref m);
}
This can be accomplished by catching the event and overriding it:
private void Form_Load(object sender, EventArgs e)
{
this.FormBorderStyle = FormBorderStyle.FixedSingle;
this.WindowState = FormWindowState.Maximized;
this.MaximizeBox = false;
this.MinimumSize = Screen.GetWorkingArea(this.Location).Size;
}
private const int WM_NCLBUTTONDBLCLK = 0x00A3;
//double click on a title bar
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_NCLBUTTONDBLCLK)
{
m.Result = IntPtr.Zero;
return;
}
base.WndProc(ref m);
}
I have a Leave Event for a TextEditor in which I perform a validation that an entry is required and display an error message.
Before I perform the validation, I check if the form is disposing, or the Cancel button was clicked. In that case I exit the leave event.
But if the user clicks the X button, these two checks do not capture that and the error message is displayed. I do not want the error message to display if the user clicks the X button. How can I achieve that?
private void TitleTextEditor_Leave(object sender, EventArgs e)
{
UltraTextEditor _currentControl = sender as UltraTextEditor;
if (this.CancelUButton.Focused || this.Disposing)
{
return;
}
if (_currentControl.Text.IsNullOrStringEmpty())
{
MessageBox.Show("Title is required.");
}
}
This is a cruddy problem if you want to suppress the validation error message you display. The only decent way to get ahead of it is by detecting the WM_CLOSE message before the Winforms code sees it and generates the Validating event on the control with the focus.
Paste this code to solve your problem:
protected override void WndProc(ref Message m) {
// Prevent validation on close:
if (m.Msg == 0x10) this.AutoValidate = AutoValidate.Disable;
base.WndProc(ref m);
}
Do consider that you are yelling too loud. The ErrorProvider component is a very decent way to display validation errors and be subtle about it. And nothing drastic goes wrong when the form validates itself on closure, you only have to do this:
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
e.Cancel = false;
}
In the FormClosingEventArgs you have a CloseReason property, you can probably use it.
How to find out if a control's Form has closed or not. I have listened to the VisibleChanged event in order to divine the Form because ParentChanged can happen before the control is added to a Form (e.g. if it is in a Panel). You might also want to unsubscribe from VisibleChanged events after the first one.
//put this at class level
bool _parentClosed;
//put this in controls constructor
//when control first becomes visible
this.VisibleChanged += (s1, a1) =>
{
//find parent Form (not the same as Parent)
Form form = this.FindForm();
//If we are on a Form
if (form != null)
//subscribe to it's closing event
form.Closing += (s2, a2) => { _parentClosed = true; };
else
throw new Exception("How did we become visible without being on a Form?");
};
I'd like a context menu on the caption bar right click
any tips/samples pref in c# ?
UPDATE - for various reasons, right click on the form won't work because the form is not empty and the form is composited dynamically so....
You can do this by trapping the WM_NCRBUTTONDOWN notification that Windows sends when the user right-clicks the title bar. The control class does not have an event for it, you'll need to override WndProc(). Here's an example form, you'll need to add a ContextMenuStrip:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
protected void OnTitlebarClick(Point pos) {
contextMenuStrip1.Show(pos);
}
protected override void WndProc(ref Message m) {
const int WM_NCRBUTTONDOWN = 0xa4;
if (m.Msg == WM_NCRBUTTONDOWN) {
var pos = new Point(m.LParam.ToInt32());
OnTitlebarClick(pos);
return;
}
base.WndProc(ref m);
}
}
MSDN explains how to handle right-clicks on Windows Forms controls. Controls, including Forms, inherit the MouseClick event.
MouseEventArgs will tell you what button was clicked through the Button property. Have a look at the MouseButtons Enumeration.
if you handle the form mouse-click, you can then use the following code:
private void Dialog_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
this.Text = "new caption text";
}
}
But you'll have to make sure that you generate this event for the top-level control on a form. For instance if you have a group box on the form, it will receive the mouse-click events rather than the form itself, for the areas of the form that are under the group box.
There is already a menu managed by Windows when you right-click the titlebar.
Do you want to replace it completely?
If you want to add to it you will have to use the Win32 API and interop and you will have to subclass the form.
See the AppendMenu() function.
Basically you need to use p-invoke to do this. There is a really great example at Here
You can see from the example you will need to manually mimic the event handlers, but this is pretty straight forward.
You can override WndProc of the form and capture the WM_NCRBUTTONDOWN message:
protected override void WndProc(ref Message m)
{
const int WM_NCRBUTTONDOWN = 0xA4;
if (m.Msg == WM_NCRBUTTONDOWN)
{
MessageBox.Show("Caption right clicked!");
}
else
{
base.WndProc(ref m);
}
}
This code will suppress the window's context menu, however. You may not wish this. The WM_NCRBUTTONDOWN message will also be sent if you right click the window borders as well. You may not desire this either.
I'm using Microsoft Visual C# 2008 Express.
In my main form, there's that X button to close the form at the top right. How do I add code to this button? In my menu, I have an "Exit" item and it has code that cleans up and closes my databases. How do I add the same code to this button if the user chooses that as a way to exit?
Thanks!
-Adeena
Using the FormClosing Event should catch any way of closing the form.
In the Design view for your form, within the Properties window, select the Events button and scroll down to the "FormClosed" and "FormClosing" events.
FormClosed is called after the form is closed.
FormClosing is called before the form is closed and also allows you to cancel the close, keeping the form open:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
}
If you want to ask the user "Are you sure you want do close this form?", then use FormClosing, where you can set Cancel = True and the form would remain open.
If you want to close some resource only when the form is definitely closed, then you use FormClosed event.
If you are in control of the whole code, then it kind of does not matter. But what you do not want to happen is to clean-up the resources using FormClosing when the the other handler of the event will keep the form open.
FormClosing/FormClosed lets you watch the event for that form which may coincide with the application exiting. However, there is another event you can wire up called Application.ApplicationExit.
In your Main method:
Application.ApplicationExit += Application_ApplicationExit;
...
private static void Application_ApplicationExit(object sender, EventArgs e) {
// do stuff when the application is truly exiting, regardless of the reason
}
Use the Closed-Event of your winform.
This code will capture the user clicking on the 'X' or using Alt-F4 on a form to allow you to do something. I had to use this because the I needed the action to call my closing event, and it wouldn't call it when using the FormClosing Event due to racing events.
/// <summary>
/// This code captures the 'Alt-F4' and the click to the 'X' on the ControlBox
/// and forces it to call MyClose() instead of Application.Exit() as it would have.
/// This fixes issues where the threads will stay alive after the application exits.
/// </summary>
public const int SC_CLOSE = 0xF060;
public const int WM_SYSCOMMAND = 0x0112;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
MyClose();
base.WndProc(ref m);
}
double click the exit button in form'design then
simply call the Dispose() method
Form action method
//
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (e.CloseReason == CloseReason.WindowsShutDown) return;
switch (MessageBox.Show(this, "Are you sure you want to exit?", "Exit", MessageBoxButtons.YesNo))
{
case DialogResult.No:
e.Cancel = true;
break;
default:
break;
}
}
You can use form closing events choose or set closing event in properties window
You can add dialog conditions based on what task you want to perform before closing form
private void Form1_FormClosing(object sender,FormClosingEventArgs e)
{
Application.Exit();
//you can also use Application.ExitThread();
}