Click here to Skip to main content
15,898,035 members
Home / Discussions / C#
   

C#

 
Questionneed help - A C# utility for a simple web query like application Pin
carl_em_200714-Oct-08 5:41
carl_em_200714-Oct-08 5:41 
AnswerRe: need help - A C# utility for a simple web query like application Pin
Simon P Stevens14-Oct-08 5:48
Simon P Stevens14-Oct-08 5:48 
AnswerRe: need help - A C# utility for a simple web query like application Pin
Ed.Poore14-Oct-08 6:07
Ed.Poore14-Oct-08 6:07 
GeneralRe: need help - A C# utility for a simple web query like application Pin
carl_em_200714-Oct-08 6:24
carl_em_200714-Oct-08 6:24 
GeneralRe: need help - A C# utility for a simple web query like application Pin
Ed.Poore14-Oct-08 8:03
Ed.Poore14-Oct-08 8:03 
Questionone question related to the memory and sources release Pin
Seraph_summer14-Oct-08 5:33
Seraph_summer14-Oct-08 5:33 
AnswerRe: one question related to the memory and sources release Pin
Simon P Stevens14-Oct-08 5:36
Simon P Stevens14-Oct-08 5:36 
GeneralRe: one question related to the memory and sources release Pin
Seraph_summer14-Oct-08 5:45
Seraph_summer14-Oct-08 5:45 
Hi,

the code is a little bit long, as follows:

simply speaking, I put several buttons in one panel, and each of them represents on function, then I just run the functions from the begining to the end.

private void toolStripButton_run_Click(object sender, EventArgs e)
{
Control[] control_panel = this.splitContainer1.Panel2.Controls.Find("panel_buffer", true);
DoubleBufferPanel double_panel = (DoubleBufferPanel)control_panel[0];

....


//////////////////////////////start normal simulaitons/////////////////////////////////////

this.toolStripStatusLabel_status.Text = "Overall simulation:";
this.toolStripStatusLabel_percent.Visible = true;
this.toolStripProgressBar1.Visible = true;
this.toolStripProgressBar1.Maximum = 10000;

textBox_simulation_output.Text += "Start the simulation ...";
textBox_simulation_output.Text += Environment.NewLine;
textBox_simulation_output.Text += Environment.NewLine;

//Application.DoEvents();


//bool parameter indicate simulation is done normally
bool b_done = true;

//double parameter indicate the simulation time for one loop
double d_time_loop = 0;


if (b_stop == true)
{
b_done = false;
}


//start the simulation
if (b_stop == false)
{
// splitContainer1.Enabled = false;//disable the container1 during simulaiton

this.toolStripButton_stop.Enabled = true;//enable the stop button
this.stopSimulationToolStripMenuItem.Enabled = true;

if (b_user_loop == false)
{
loop1_max = 1;
loop2_max = 1;
loop3_max = 1;
}

int progress_n = 0;
int loop_count = 0;

for (int loop = 0; loop < loopmax; loop++)//for each loop
{
for (int loop1 = 0; loop1 < loop1_max; loop1++)
{
loop1_no = loop1;

for (int loop2 = 0; loop2 < loop2_max; loop2++)
{
loop2_no = loop2;

for (int loop3 = 0; loop3 < loop3_max; loop3++)
{
Stopwatch sw = new Stopwatch();//start to calculate

sw.Reset();
sw.Start();

loop3_no = loop3;

if (b_stop == true)
{
b_done = false;

break;
}

Application.DoEvents();

/////////////////////////////////////////status information set///////////////////////////////


double f_loop = Convert.ToDouble(loop);
double f_loopmax = Convert.ToDouble(loopmax);

string str_estimated_time = "";
if (b_time == true)
{
double d_time_left = d_time_loop / 1000 *
(loopmax * loop1_max * loop2_max * loop3_max - loop_count);
if (loop_count == 0)
{
str_estimated_time = "Time: " + "unknow, ";
}
else
{
str_estimated_time = "Time: " + Convert.ToInt32(d_time_left).ToString() + "s, ";
}
}

string str_iteration = "";

if (b_iteration == true)
{
str_iteration = "";
if (loopmax > 1)
{
str_iteration += "Loop:" + (loop + 1).ToString() + ", ";
}
if (loop1_max > 1)
{
str_iteration += "Loop1:" + (loop1_no + 1).ToString() + ", ";
}
if (loop2_max > 1)
{
str_iteration += "Loop2:" + (loop2_no + 1).ToString() + ", ";
}
if (loop3_max > 1)
{
str_iteration += "Loop3:" + (loop3_no + 1).ToString() + ", ";
}

}


if ((b_time == true) || (b_iteration == true))
{
this.toolStripStatusLabel_percent.Text = str_iteration + " " + str_estimated_time;
}



loop_no = loop;//for each module's static parameters, such as Data.reg

dic_moudle_out.Clear();


/////////////////////////////////////////////////call the module function by reflection///////////////////



for (int i = 0; i < module_list.Count; i++)
{
//change the current running module color

textBox_simulation_output.Text +="current running module: "+ module_list[i];
textBox_simulation_output.Text += Environment.NewLine;

progress_n ++;

this.toolStripProgressBar1.Value = Convert.ToInt32(progress_n / (module_list.Count*f_loopmax * loop1_max * loop2_max * loop3_max)
* this.toolStripProgressBar1.Maximum);

Application.DoEvents();

string str_percent = "";
if (b_ratio == true)
{
str_percent =Convert.ToInt32(100*progress_n / (module_list.Count*f_loopmax * loop1_max * loop2_max * loop3_max)).ToString() + "%";
this.toolStripStatusLabel_percent.Text = str_percent + " " +
str_iteration + " " + str_estimated_time;
}

if (b_module == true)
{
for (int j = 0; j < double_panel.Controls.Count; j++)
{
if ((((MyButton)double_panel.Controls[j]).level == 1)
&& (((MyButton)double_panel.Controls[j]).Name.ToString() == module_list[i]))
{
((MyButton)double_panel.Controls[j]).BackColor = Color.Red;
}
else
{
((MyButton)double_panel.Controls[j]).BackColor = Color.White;
}
}
}

//check the moudle is labeled pass or not
bool b_pass = false;

for (int j = 0; j < double_panel.Controls.Count; j++)
{
if ((((MyButton)double_panel.Controls[j]).level == 1)
&& (((MyButton)double_panel.Controls[j]).Name.ToString() == module_list[i])
&& (((MyButton)double_panel.Controls[j]).b_pass == true))
{
b_pass = true;
}
}

string str_module = "";
if (b_module == true)
{
str_module = "Moudle: " + module_list[i].ToString()+", ";

this.toolStripStatusLabel_percent.Text = str_percent + ", " +
str_iteration + " " + str_estimated_time + " " + str_module;

this.toolStripStatusLabel_percent.Invalidate();
}


if (b_stop == true)
{
b_done = false;

break;
}
Application.DoEvents();


// for input parameter of module i
Dictionary<string,>> dic_in_temp = new Dictionary<string,>>();

//for those modules with input, i.e. in_no!=0
if (list_in[i] != 0)
{
List<string> path_in = new List<string>();//save all the in path string for module i
//for each module, check the input path
foreach (KeyValuePair<string,> kvp in path)
{
if (kvp.Key.Contains(module_list[i].ToString() + "*in*no*"))
{
path_in.Add(kvp.Key.ToString());
}
}
//list the path_in in the right order according to the input no 0,1,2...
for (int m = 0; m < path_in.Count; m++)//loop in order to list all the path_in in the right order
{
for (int j = 0; j < path_in.Count - 1; j++)
{
string str_in_no_1 = path_in[j].Substring(path_in[j].IndexOf("*in*no*") + 7, 1);//the no of input and output is assumed to be less than 10
string str_in_no_2 = path_in[j + 1].Substring(path_in[j + 1].IndexOf("*in*no*") + 7, 1);//the no of input and output is assumed to be less than 10
if (Convert.ToInt16(str_in_no_1) > Convert.ToInt16(str_in_no_2))//exchange
{
string str_temp = path_in[j];
path_in[j] = path_in[j + 1];
path_in[j + 1] = str_temp;
}
}
}

//obtain the module out and the out no for each path_in,
//save the input parameters for module i

for (int m = 0; m < path_in.Count; m++)
{
string str_module_out = path_in[m].Substring(0, path_in[m].IndexOf("*out*no*"));
string str_out_no = path_in[m].Substring(path_in[m].IndexOf("*out*no*") + 8, 1);

Dictionary<string,>> dic_out_temp = new Dictionary<string,>>();
dic_moudle_out.TryGetValue(str_module_out, out dic_out_temp);
List<para_in_out> list_out_temp = new List<para_in_out>();
dic_out_temp.TryGetValue(str_out_no, out list_out_temp);
dic_in_temp.Add(m.ToString(), list_out_temp);

}

}

//get the module name without the no "_0"
string str = module_list[i].ToString();
string str_function = str.Substring(0, str.IndexOf("*"));

#region reflection functions
//for the modules without input
object out_temp = new object();
if (list_in[i] == 0)
{
try
{
bool b_module_non_dll = false;

for (int k = 0; k < str_module_list.Count; k++)
{
if (str_function == str_module_list[k])
{
b_module_non_dll = true;
}
}

if (b_module_non_dll == true)
{
//directly call the functions:olkd
out_temp = this.GetType().InvokeMember(str_function, BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, this, new object[] { module_list[i] });
}

else
{

string str_dll = str_module_dll_path;
str_dll = str_dll + "\\" + str_function + ".dll";

AssemblyName name = new AssemblyName();
name.CodeBase = "file://" + str_dll;
Assembly asm = AppDomain.CurrentDomain.Load(name);

// Instantiate the class
string str_namespace_class = "NS_" + str_function + "." + "Class_" + str_function;
object remoteObject =
asm.CreateInstance(str_namespace_class);
Type remoteType =
asm.GetType(str_namespace_class);

// Call the method
MethodInfo method = remoteType.GetMethod(str_function + "_fun");
out_temp = method.Invoke(remoteObject, new object[] { module_list[i], module_value, loop_no, b_stop });
}
}
catch (TargetInvocationException ex)
{
MessageBox.Show(ex.InnerException.ToString());
splitContainer1.Enabled = true;//enable the container1 during simulaiton
return;

}
}
else
{
try
{
bool b_module_non_dll = false;

for (int k = 0; k < str_module_list.Count; k++)
{
if (str_function == str_module_list[k])
{
b_module_non_dll = true;
}
}



if (b_module_non_dll == true)
{
if (b_pass == true)

out_temp = this.GetType().InvokeMember(str_function + "_pass",
BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
null, this, new object[] { module_list[i], dic_in_temp });

else

out_temp = this.GetType().InvokeMember(str_function,
BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
null, this, new object[] { module_list[i], dic_in_temp });

}

else
{
string str_dll = str_module_dll_path;
str_dll = str_dll + "\\" + str_function + ".dll";

AssemblyName name = new AssemblyName();
name.CodeBase = "file://" + "\\" + str_dll;
Assembly asm = AppDomain.CurrentDomain.Load(name);

// Instantiate the class
string str_namespace_class = "NS_" + str_function + "." + "Class_" + str_function;
object remoteObject =
asm.CreateInstance(str_namespace_class);
Type remoteType =
asm.GetType(str_namespace_class);

// Call the method
MethodInfo method = remoteType.GetMethod(str_function + "_fun");
out_temp = method.Invoke(remoteObject, new object[] { module_list[i], module_value, dic_in_temp, loop_no, b_stop });


}
}
catch (TargetInvocationException ex)
{
MessageBox.Show(ex.InnerException.ToString());
splitContainer1.Enabled = true;//enable the container1 during simulaiton
return;

}

}

#endregion reflection functions

//save output for each module with output

Dictionary<string,>>> dic_moudle_out_temp = new Dictionary<string,>>>();
dic_moudle_out_temp = (Dictionary<string,>>>)out_temp;

if (out_temp != null) //avoid for the modules without output
{

foreach (KeyValuePair<string,>>> kvp in dic_moudle_out_temp)
{
dic_moudle_out.Add(kvp.Key, kvp.Value);
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////// modules loop: start ////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////

#region modules loop

//check whether current module belongs to the end module of some module loops:

List<mybutton> list_loop_modules = new List<mybutton>();
int loop_modules_no = 0;
string str_current_loop_name = "";
foreach (KeyValuePair<string,>> kvp in dic_module_loop)
{

if (module_list[i] == kvp.Value[kvp.Value.Count - 1].Name)
{
dic_module_loop.TryGetValue(kvp.Key, out list_loop_modules);
dic_module_loop_no.TryGetValue(kvp.Key, out loop_modules_no);
str_current_loop_name = kvp.Key;
}
}

//if so, then loop these modules
if (list_loop_modules.Count != 0)
{
textBox_simulation_output.Text += Environment.NewLine;
textBox_simulation_output.Text += "current running loop: " + str_current_loop_name;
textBox_simulation_output.Text += Environment.NewLine;


for (int ii = 1; ii < loop_modules_no; ii++) //start from 1 not 0 because one loop has calculated
{
textBox_simulation_output.Text += Environment.NewLine;
textBox_simulation_output.Text += "current running loop no: " + ii.ToString();
textBox_simulation_output.Text += Environment.NewLine;


for (int i_loop = 0; i_loop < list_loop_modules.Count; i_loop++)
{
textBox_simulation_output.Text += "current running module : " + list_loop_modules[i_loop].Name;
textBox_simulation_output.Text += Environment.NewLine;

//change the current running module color
for (int j = 0; j < double_panel.Controls.Count; j++)
{

if ((((MyButton)double_panel.Controls[j]).level == 1)
&& (((MyButton)double_panel.Controls[j]).Name.ToString() == list_loop_modules[i_loop].Name))
{
((MyButton)double_panel.Controls[j]).BackColor = Color.Red;
}
else
{
((MyButton)double_panel.Controls[j]).BackColor = Color.White;
}
}

//check the moudle is labeled pass or not
bool b_pass_loop = false;
for (int j = 0; j < double_panel.Controls.Count; j++)
{
if ((((MyButton)double_panel.Controls[j]).level == 1)
&& (((MyButton)double_panel.Controls[j]).Name.ToString() == list_loop_modules[i_loop].Name)
&& (((MyButton)double_panel.Controls[j]).b_pass == true))
{
b_pass_loop = true;
}
}

string str_module_loop_modules = "";
if (b_module == true)
{
str_module_loop_modules = "Moudle: " + list_loop_modules[i_loop].Name.ToString();
string str_modules_loop_current = "loop:" + str_current_loop_name + " #" + (ii + 1).ToString();
this.toolStripStatusLabel_percent.Text = str_percent + " "
+ str_iteration + " " + str_estimated_time + " "
+ str_modules_loop_current + " " + str_module_loop_modules;
}

if (b_stop == true)
{
b_done = false;
break;
}
Application.DoEvents();



//for the first module in the loop, the input is assigned by the output,i.e., the last module


// for input parameter of module i
Dictionary<string,>> dic_in_temp_loop = new Dictionary<string,>>();

//for those modules with input, i.e. in_no!=0
if (list_loop_modules.Count != 0)
{
List<string> path_in = new List<string>();//save all the in path string for module i
//for each module, check the input path
foreach (KeyValuePair<string,> kvp in path)
{
if (kvp.Key.Contains(list_loop_modules[i_loop].Name.ToString() + "*in*no*"))
{
path_in.Add(kvp.Key.ToString());
}
}
//list the path_in in the right order according to the input no 0,1,2...
for (int m = 0; m < path_in.Count; m++)//loop in order to list all the path_in in the right order
{
for (int j = 0; j < path_in.Count - 1; j++)
{
string str_in_no_1 = path_in[j].Substring(path_in[j].IndexOf("*in*no*") + 7, 1);//the no of input and output is assumed to be less than 10
string str_in_no_2 = path_in[j + 1].Substring(path_in[j + 1].IndexOf("*in*no*") + 7, 1);//the no of input and output is assumed to be less than 10
if (Convert.ToInt16(str_in_no_1) > Convert.ToInt16(str_in_no_2))//exchange
{
string str_temp = path_in[j];
path_in[j] = path_in[j + 1];
path_in[j + 1] = str_temp;
}
}
}

//obtain the module out and the out no for each path_in,
//save the input parameters for module i

if (i_loop == 0) //the input into the first module: the output of the last module
{
string str_module_out = list_loop_modules[list_loop_modules.Count - 1].Name;
string str_out_no = "0";

Dictionary<string,>> dic_out_temp_loop = new Dictionary<string,>>();
dic_moudle_out.TryGetValue(str_module_out, out dic_out_temp_loop);
List<para_in_out> list_out_temp_loop = new List<para_in_out>();
dic_out_temp_loop.TryGetValue(str_out_no, out list_out_temp_loop);
dic_in_temp_loop.Add(str_out_no, list_out_temp_loop);
}

else //the input into the other modules: the output from the previous ones
{
for (int m = 0; m < path_in.Count; m++)
{
string str_module_out = path_in[m].Substring(0, path_in[m].IndexOf("*out*no*"));
string str_out_no = path_in[m].Substring(path_in[m].IndexOf("*out*no*") + 8, 1);

Dictionary<string,>> dic_out_temp_loop = new Dictionary<string,>>();
dic_moudle_out.TryGetValue(str_module_out, out dic_out_temp_loop);
List<para_in_out> list_out_temp_loop = new List<para_in_out>();
dic_out_temp_loop.TryGetValue(str_out_no, out list_out_temp_loop);
dic_in_temp_loop.Add(m.ToString(), list_out_temp_loop);

}
}
}

//get the module name without the no "_0"
string str_loop = list_loop_modules[i_loop].Name.ToString();
string str_function_loop = str_loop.Substring(0, str_loop.IndexOf("*"));


//for the modules without input
object out_temp_loop = new object();

//call reflection functions
try
{
bool b_module_non_dll = false;

for (int k = 0; k < str_module_list.Count; k++)
{
if (str_function == str_module_list[k])
{
b_module_non_dll = true;
}
}

if (b_module_non_dll == true)
{
if (b_pass_loop == true)

out_temp_loop = this.GetType().InvokeMember(str_function_loop + "_pass",
BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
null, this, new object[] { list_loop_modules[i_loop].Name, dic_in_temp_loop });

else

out_temp_loop = this.GetType().InvokeMember(str_function_loop,
BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
null, this, new object[] { list_loop_modules[i_loop].Name, dic_in_temp_loop });

}

else
{
string str_dll = str_module_dll_path;
str_dll = str_dll + "\\" + str_function + ".dll";

AssemblyName name = new AssemblyName();
name.CodeBase = "file://" + "\\" + str_dll;
Assembly asm = AppDomain.CurrentDomain.Load(name);

// Instantiate the class
string str_namespace_class = "NS_" + str_function_loop + "." + "Class_" + str_function_loop;
object remoteObject =
asm.CreateInstance(str_namespace_class);
Type remoteType =
asm.GetType(str_namespace_class);

// Call the method
MethodInfo method = remoteType.GetMethod(str_function_loop + "_fun");
out_temp = method.Invoke(remoteObject, new object[] { list_loop_modules[i_loop].Name,
module_value, dic_in_temp_loop, loop_no, b_stop });

}
}
catch (TargetInvocationException ex)
{
MessageBox.Show(ex.InnerException.ToString());
splitContainer1.Enabled = true;//enable the container1 during simulaiton
return;

}

//update the output for each module in the loop

Dictionary<string,>>> dic_moudle_out_temp_loop = new Dictionary<string,>>>();
dic_moudle_out_temp_loop = (Dictionary<string,>>>)out_temp_loop;

if (out_temp_loop != null) //avoid for the modules without output
{
foreach (KeyValuePair<string,>>> kvp in dic_moudle_out_temp_loop)
{
dic_moudle_out.Remove(kvp.Key);
dic_moudle_out.Add(kvp.Key, kvp.Value);
}
}

}
}

}

#endregion modules loop

}//end: for each module

if (loop_count == 0) //only calculate one time for time estimation
{
sw.Stop();
d_time_loop = sw.ElapsedMilliseconds;
}

loop_count++;


}//end: loop 3
}//end: loop 2
}//end: loop 1
}//end: loop
}//end: for b_stop==false
if (b_done == true)
{
sw_total.Stop();
double d_time_total = sw_total.ElapsedMilliseconds / 1000;

this.toolStripStatusLabel_status.Text = "Simulation is done, total time is:"
+ (Convert.ToInt32(d_time_total)).ToString() + "s";

textBox_simulation_output.Text += Environment.NewLine;
textBox_simulation_output.Text += this.toolStripStatusLabel_status.Text;
textBox_simulation_output.Text += Environment.NewLine;


this.toolStripButton_output_observer.Enabled = true;
this.outputWindowToolStripMenuItem.Enabled = true;

b_simulation_complete = true;
}
else
{
this.toolStripStatusLabel_status.Text = "Simulation is stopped";

textBox_simulation_output.Text += Environment.NewLine;
textBox_simulation_output.Text += "Simulation is stopped";
textBox_simulation_output.Text += Environment.NewLine;
textBox_simulation_output.ScrollToCaret();
}

//splitContainer1.Enabled = true;//enable the container1 during simulaiton

this.toolStripProgressBar1.Visible = false;
this.toolStripStatusLabel_percent.Visible = false;

this.toolStripButton_stop.Enabled = false;//disable the stop button
this.stopSimulationToolStripMenuItem.Enabled = false;

//close all figures button
if ((dic_form.Count > 0) || (dic_form_single.Count > 0))
{
toolbutton_close_all_figure.Enabled = true;
Menu_Close_all_Figure.Enabled = true;
}


}
GeneralRe: one question related to the memory and sources release Pin
Simon P Stevens14-Oct-08 5:59
Simon P Stevens14-Oct-08 5:59 
GeneralRe: one question related to the memory and sources release Pin
Seraph_summer14-Oct-08 5:59
Seraph_summer14-Oct-08 5:59 
GeneralRe: one question related to the memory and sources release Pin
Simon P Stevens14-Oct-08 6:04
Simon P Stevens14-Oct-08 6:04 
QuestionWindows Forms Action Framework [modified] Pin
Donkey Master14-Oct-08 5:17
Donkey Master14-Oct-08 5:17 
AnswerRe: Windows Forms Action Framework Pin
Simon P Stevens14-Oct-08 5:34
Simon P Stevens14-Oct-08 5:34 
GeneralRe: Windows Forms Action Framework Pin
Donkey Master14-Oct-08 5:56
Donkey Master14-Oct-08 5:56 
GeneralRe: Windows Forms Action Framework Pin
Simon P Stevens14-Oct-08 6:07
Simon P Stevens14-Oct-08 6:07 
QuestionHow To discover websevices Method Pin
shames(Sam)14-Oct-08 4:39
shames(Sam)14-Oct-08 4:39 
AnswerRe: How To discover websevices Method Pin
led mike14-Oct-08 4:49
led mike14-Oct-08 4:49 
GeneralRe: How To discover websevices Method Pin
shames(Sam)14-Oct-08 6:03
shames(Sam)14-Oct-08 6:03 
Questiona way to execute the file on list view by doubleclick Pin
Gianpaolo Barci14-Oct-08 4:37
Gianpaolo Barci14-Oct-08 4:37 
QuestionRe: a way to execute the file on list view by doubleclick Pin
led mike14-Oct-08 4:46
led mike14-Oct-08 4:46 
AnswerRe: a way to execute the file on list view by doubleclick Pin
Gianpaolo Barci14-Oct-08 5:10
Gianpaolo Barci14-Oct-08 5:10 
AnswerRe: a way to execute the file on list view by doubleclick Pin
DaveyM6914-Oct-08 5:31
professionalDaveyM6914-Oct-08 5:31 
GeneralRe: a way to execute the file on list view by doubleclick Pin
Gianpaolo Barci14-Oct-08 5:48
Gianpaolo Barci14-Oct-08 5:48 
GeneralRe: a way to execute the file on list view by doubleclick Pin
Gianpaolo Barci14-Oct-08 6:44
Gianpaolo Barci14-Oct-08 6:44 
GeneralRe: a way to execute the file on list view by doubleclick Pin
DaveyM6914-Oct-08 9:09
professionalDaveyM6914-Oct-08 9:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.