|
Kev, I think I told you to use a flag. Application.Exit() will still try to close the window hense call the handler.
Let me elaborate:
In Form1_SessionEnding()
Here you will do a SaveSchedules() and set a flag called bShutdownStarted=true
In Form1_Closing()
Here you will first check <br />
if(bShutdownStarted==true)<br />
else<br />
I am assuming that Form1_SessionEnding() will always be called before Form1_Closing() because logically it should happen so. Correct me if I am wrong. Kudos to Heath for the delegate example.
[A look at SystemEvents.SessionEnding MSDN page tells me what gets called first is not deterministic unless you override the WndProc function as per the example on the page]
|
|
|
|
|
Salil,
2 things, firstly, Application.Exit() doesn't fire the form_closing event.
I tried calling Application.Exit from a button click and it just shut the app down without asking me for the password.
Secondly, Session Ending is called after Form_Closing so i can't simply set a flag.
Cheers
Kev
|
|
|
|
|
No, Application.Exit doesn't fire the Form.Closing event, nor should it. Calling Application.Exit is the same as sending WM_QUIT to your message pump. When you close a form, you're essentially sending WM_CLOSE .
The fact that the events happen in the wrong order means you're not doing something right. You add a handler for the SystemEvents.SessionEnding in your form's instance (not in Main - your default entry point - since Application.Run is a blocking call). Set a flag then call Close . This sends WM_CLOSE to your window proc and your Closing event handler is called.
The previous post is correct then, and recommended was I was going to: use state variables. A simple bool would do.
The SystemEvents.SessionEnding event (not to be confused with SystemEvents.SessionEnded ; if that's fired there's nothing you can do, really, at least as far as prompting for user input) handles the WM_QUERYENDSESSION message which is sent to application message pumps. This has nothing to do with WM_CLOSE or WM_QUIT . It simply notifies the window proc that a request to end the interactive session has been posted.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles]
|
|
|
|
|
Heath, just to check i've got things right and we are both going along the same lines of thought.
I have a bool called closing in the form instance.
My forms constructor
public Form1()
{
InitializeComponent();
closing = false;
SystemEvents.SessionEnding += new SessionEndingEventHandler(OnSessionEnding);
}
Form1_Closing
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
SaveSchedules();
if (!(closing))
{
if (!(CheckPassword()))
e.Cancel = true;
}
}
OnSessionEnding
private void OnSessionEnding(object sender, SessionEndingEventArgs e)
{
SaveSchedules();
closing = true;
}
Thats it, all the relevant code as far as i'm aware.
If the user closes the form manually then i want checkpassword to be called.
This works OK.
If the user enters the correct password, CheckPassword returns true and
e.Cancel remains false, the application exits nicely.
If the user logs off of the machine or shuts it down i don't want checkpassword to be called. To accomplish this, as i was advised in the previous posts i am using the state variable closing.
The closing variable is set to true in the OnSessionEnding method.
This is what i believe has been suggested but the CheckPassword function is still called. If i've misunderstood whats been said in the previous posts then please let me know so i can make the relevant changes.
Thanks for all your help and patience
Kev
|
|
|
|
|
Again, you should call Close in your SystemEvents.SessionEnding event handler, after setting the state variable.
The problem is that canceling the WM_CLOSING notification message (setting CancelEventArgs.Cancel to true in your Form.ClosingEvent ) won't affect the WM_QUERYENDSESSION notification message (your SystemEvents.SessionEnding handler). I would recommend implementing the same logic into both handlers:
private void OnSessionEnding(object sender, SessionEndingEventArgs e)
{
e.Cancel = !CheckPassword();
} The big problem here is that prompting the user takes time (mostly for the user to type their password, unless you're authenticating the password across some wire format or against a slow database; hardcoding it into the assembly is a bad idea since even a tool that comes with the free SDK can read it easily) - more time than Windows is willing to give it when shutting down. The application will appear hung and the user will be prompted to end the task (process) or cancel the shutdown. Inevitably, the user will blame your program.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles]
|
|
|
|
|
I think we've still got our wires crossed, a little background might help.
This app is going to be run on PC's in the back offices of our shops around the UK. The staff in the shops are very limited to what they can do on the PC's and most of them don't know the difference between a monitor and a computer so the password being hard coded is safe enough.
The app will run in the system tray while the PC is on but, in certain cases one of our support guys might need to shut the app down manually. So they will restore the app from the system tray, click the cross and enter the password. This is all done without shutting the pc down.
In certain cases, i.e. when the support person in question can't dial into the box to take remote control they may just ask the user to shut down the pc. The way i have the app coded at the minute it prompts for the password when the PC is being shut down, this is what i'm trying to stop. The password is only there to stop the shop user from shutting down the application while they are logged in.
Hope that makes sense
Kev
|
|
|
|
|
exhaulted wrote:
I think we've still got our wires crossed, a little background might help.
I didn't know they were crossed to begin with. You asked for help and we gave it to you. The suggestions are sound if implemented correctly. What and why you need to do isn't really relevent. As I mentioned about hard-coding passwords, if it's for anything serious it's a bad idea. That implies that if it's not important, then hard-coding it may be fine. It was only a suggestion.
Again, though, what I mentioned before for implementation does work. Shutting down the machine posts WM_QUERYENDSESSION to the application before sending WM_CLOSE or WM_QUIT (it actually doesn't even send WM_CLOSE , IIRC). It wouldn't even make sense to do it any other way. I mean, why give applications a chance to cancel the shutdown if you close the main window (which in most applications terminates the main message pump) first?
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles]
|
|
|
|
|
FYI:
.NET Framework 2.0 supplies a "FormClosing" event, which sends a "CloseReason" enum which seems to contain exactly what you need.
Alas, it's a beta
there are no facts, only interpretations
|
|
|
|
|
That does indeed sound like exactly what i need, guess i'll have to try Salil's OnEndSession idea.
Kev
|
|
|
|
|
You could look for the OnSessionEnd Message by over riding WinProc. Then programticly cause the application to close.
Hope this helps....
Forever Developing
|
|
|
|
|
Thanks for that, seems like a possible solution but....
I've been looking at an example for overriding the WinProc and it seems
easy enough. The message ID is stored in the .Msg property.
Is there somewhere that lists all of the different windows messages and their equivelant .Msg values?
Cheers
Kev
|
|
|
|
|
|
I think you should forget what I told you and follow the advice posted by Heath Stewart. His solution is a "More Managed Solution"
Anyway...
Forever Developing
|
|
|
|
|
hi,
I am executing a select() method agnest a data table. I got result as DataRow[]. Here i got collection of datarow.
My question is how can i create a table from this DataRow[] without executing all unwanted iteration(iterating through individual datarow or something).
Specifically : How can i create a table from a DataRow collection.
**************************
S r e e j i t h N a i r
**************************
|
|
|
|
|
Hi
If the result is the type of 'DataRowsCollection' then you can directly assign it to DataTable's Rows property.
If it is a collection of DataRows then you have to iterate one by one
M.Sendilkumar
TVS Infotech Ltd
Chennai
|
|
|
|
|
hi,
I think you didn't understood my question. See i don't want to iterate through any row hell. Do you have any other solution for this ?
**************************
S r e e j i t h N a i r
**************************
|
|
|
|
|
Hi Sreejith
There is no other way.But we can minimize the work in iteration.
SqlConnection con=new SqlConnection(@"Data Source=YOURSERVER\INSTANCENAME;Initial Catalog=Northwind;UID=sa; PWD=sa;");
con.Open();
SqlDataAdapter adpt=new SqlDataAdapter("select OrderID,CustomerID,EmployeeID from orders",con);
DataTable dt1=new DataTable();
adpt.Fill(dt1);
DataRow[] dr=dt1.Select("customerid='vinet'");
DataTable dt2=new DataTable();
for(int i=0;i<dr.GetLength(0);i++)
{
dt2.ImportRow(dr[i]);
}
int a=dt2.Rows.Count;
------------------------------------
try this.
---------------------------
M.Sendilkumar
TVS Infotech Ltd
Chennai
|
|
|
|
|
Right now I am working with DataGrid.CurrentRowIndex
how to do if I have to select multiple rows.
Thank you,
======
Yo need a brain to code.
|
|
|
|
|
hi,
What is your real requirement ?. We can select more than one record in a datagrid. Select() method is used to select a perticular row. And Unselect() method doing the reverse of Select(). you can check whether a perticular row is selected or not by using IsSelected() method. I recommand you to read the DataGrid Class description in MSDN.;)
**************************
S r e e j i t h N a i r
**************************
|
|
|
|
|
Hello Sreejit,
I have used DataGrid_MouseUp() event and then used DataGrid.CurrentRowIndex to get the current row.
private void DataGrid_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)<br />
{<br />
int i = DataGrid.CurrentRowIndex;<br />
}
But how can I get multiple rows index if I have selected multiple rows.
like this>>
private void DataGrid_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)<br />
{<br />
for (int i = 0; i <= DataGrid.CurrentRowIndexes:confused:; i++)<br />
{<br />
int j = DataGrid.CurrentRowIndexes[i];<br />
}<br />
}
======
Yo need a brain to code.
|
|
|
|
|
//For collecting the index of selected records
ArrayList Ar=new ArrayList();
private void DataGrid_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
for (int i = 0; i <= DataGrid.CurrentRowIndexes; i++)
{
/*this line will help you to deside whether row is selected or not. If yes then it will return a bool value. Else will return a false value.*/
if(DataGrid.IsSelected(i)
Ar.Add(DataGrid.CurrentRowIndexes[i].ToString());
else
continue;
}
}
So finally you will get all index of selected row in your ArrayList.
Remaing is upto you to design based on your requirement.;)
**************************
S r e e j i t h N a i r
**************************
|
|
|
|
|
Sreeji, Thank you very much. I appreciate your help.
======
code proj. rocks!
|
|
|
|
|
Hi, I wonder if it is possible to detect somehow (from C# app) when the Windows plays some specific .wav file?
What I wanna do is to "subscribe" for that event and do my job when some specific .wav file gets played.
Any ideas?
thanks!
|
|
|
|
|
You're most likely going to be able to do this simply by a mechanism that watches if a file is read, as opposed to played specifically.
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|