I want to display the form before the speech output - c#

My problem is that the program speaks before the form gets displayed.
Here's the load block:
/********************
* *
* Start Game *
* *
********************/
private void Battleship_Load(object sender, EventArgs e)
{
// Interface housekeeping
lblStatus.Font = new Font("HandelGotDLig", 18);
// fill computer board
game.buildBoards();
human = game.Human;
computer = game.Computer;
shot = game.Initialize(ref human, ref shot);
//set up displays
gbComputerHistory.Visible = false;
gbHumanHistory.Visible = false;
gbShot.Visible = false;
lblStatus.Text = "Choose who starts";
gbStart.Visible = true;
// display human board
DisplayBoard(picHuman, human, false);
// display computer ships
DisplayBoard(picComputer, computer, false);
this.Refresh();
#if SPEECH
Say("Welcome to BATTLESHIP! Prepare to Lose!");
Say("Choose who starts first.");
#endif
}
I suspect I could bury it in the paint event, but then I'd have to keep track of whether it has spoken already.
I don't want it speaking every time the form is repainted.

Try adding the speech code to the Form_Shown event. This event is raised whenever the form is shown to the user (when they can actually see it). From MSDN:
The Shown event is only raised the first time a form is displayed; subsequently minimizing, maximizing, restoring, hiding, showing, or invalidating and repainting will not raise this event.

Related

pause rich text box and then resume again

What I am doing:
I am receiving a string of data every second constantly from a serial port. I am processing it and also displaying this string on the rich text box.
Problem:
I want the user to go through the old strings and copy any, but user can't do it because data is coming every second and auto-scrolling occurs.
My desired solution:
I am thinking to have a check-box 'pause'. when user checks it updating of rich text box stops. and user can go in history and copy a string. but in the mean while I don't want to stop the incoming strings from the serial port as I am doing other things as well with the incoming strings.
So when user uncheck 'pause' checkbox, all the strings which had arrived earlier while user had checked' pause' checkbox also appear on rich text box along with new ones.
is there a way to do it ?
Suppose that when you check the Pause button then every incoming text is appended to a StringBuilder instead of the RichTextBox. When the user uncheck the Pause button you copy everything from the StringBuilder to the RichTextBox
// Assume that these are somewhere globals of your forms
RichTextBox rtb = new RichTextBox();
CheckBox chkPause = new CheckBox();
StringBuilder sb = new StringBuilder();
protected void chkPause_CheckedChanged(object sender, EventArgs e)
{
if(!chkPause.Checked)
{
rtb.AppendText = sb.ToString();
// Do not forget to clear the buffer to avoid errors
// if the user repeats the stop/go cycle.
sb.Clear();
}
else
{
// Start a timer to resume normal flow after a timer elapses.
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = GetSuspensionMilliseconds();
t.Tick += onTick;
t.Start();
}
}
protected void onTick(object sender, EventArgs e)
{
if (chkPause.Checked)
{
// Set to false when the timing elapses thus triggering the CheckedChanged event
chkPause.Checked = false;
System.Windows.Forms.Timer t = sender as System.Windows.Forms.Timer;
t.Stop();
}
}
now in the point where the incoming data is passed to the RichTextBox you could add
....
string incomingData = ReceiveDataFromSerialPort();
if(chkPause.Checked)
sb.AppendLine(incomingData);
else
rtb.AppendText = incomingData;

Timer doesn't seem to tick ( until I minimize window )

This is the image of the design window:
Here is the MainForm.Designer.cs file:
namespace SamsCSharp24
{
partial class ImeObrasca
{
// irrelavent code is omitted, only event subscriptions are left
private void InitializeComponent()
{
// irrelavent code is omitted for brewity
//
// SelectPicture
//
this.SelectPicture.Paint += new System.Windows.Forms.PaintEventHandler(this.SelectPicture_Paint);
this.SelectPicture.Click += new System.EventHandler(this.SelectPicture_Click);
//
// Quit
//
this.Quit.Click += new System.EventHandler(this.Quit_Click);
//
// PictureBox
//
this.PictureBox.MouseLeave += new System.EventHandler(this.PictureBox_MouseLeave);
this.PictureBox.MouseEnter += new System.EventHandler(this.PictureBox_MouseEnter);
//
// btnOptions
//
this.btnOptions.Click += new System.EventHandler(this.btnOptions_Click);
//
// timerClock
//
this.timerClock.Tick += new System.EventHandler(this.timerClock_Tick);
}
#endregion
}
}
Here is the MainForm.cs file:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace SamsCSharp24
{
public partial class ImeObrasca : Form
{
public ImeObrasca()
{
InitializeComponent();
// when uncommenting below line, window is not seen in taskbar
// this.ShowInTaskbar = false;
}
// other code is omitted for brewity
private void SelectPicture_Paint(object sender, PaintEventArgs e)
{
// just for fun, change color of a button to light blue
SelectPicture.BackColor = Color.Azure;
}
private void timerClock_Tick(object sender, EventArgs e)
{
// when timer ticks, change label's text into current time of day
staticClock.Text = "Current time of day: " +
DateTime.Now.Hour.ToString() + " : " +
DateTime.Now.Minute.ToString() + " : " +
DateTime.Now.Second.ToString();
}
}
}
Timer control has following properties set via designer:
Enabled = true;
Interval = 1000
Name = timerClick
Tick (event) = timerClock_Tick
As for label, here are the properties also set with designer:
BorderStyle = FixedSingle
Name = staticClock
Autosize = false
Text =
Other properties are default or irrelevant ( like Location or Size )
PROBLEM:
When I run the application ( in Debug mode ), window appears with properly placed controls and with proper look. Every other part of the code works successfully ( picture opening / drawing etc ) but the label remains empty, as initially set in the designer.
After I minimize / maximize the window, the label text is set correct. I have tried to move the part of the window with label "out" of the screen and get it back to see what happens. The text in the label was changed sometimes -> it didn't update correct.
MY EFFORTS TO SOLVE THE PROBLEM:
This is my first time trying out C# and WinForms so I have tried to find some online documentation on timers.
After examining .Designer.cs file I have found out that the timer from toolbox belongs to System.Windows.Forms.Timer class. I found nothing there to help me, since in Remarks section is stated that setting property Enabled to true starts the timer, and setting it to false stops it.
I have tried to put simple message box, and it started popping properly when the window was minimized. When window is in normal state nothing showed, but other parts of the program worked well ( picture opening / drawing / etc ).
After trying to Google for solution / searching here on SO, I have found no concrete solution ( although some suggestions were made, but as I said, they weren't helpful to me ).
QUESTION:
How to modify timer's tick handler, so label's text can be modified every second?
What am I doing wrong?
As Hans Passant stated in one of the comments, "Paint event handlers should only paint, they should never change properties that cause the Paint event to be fired again. Such shenanigans cause the UI thread to burn 100% core, never getting to dispatch the low-priority synthesized messages. Like WM_TIMER. Minimizing the window stops that, temporarily."

How to instantly change label text during a method at runtime?

I've searched through stackoverflow but cannot find the answer. I don't know if I could make this question clearly. I'm not an English-speaking person anyway =.=
I'm using c# and visual studio 2010 to develop.
I'm making a Form for user to login, I would like this form test sql server connection during load event.
It seems easy, the code is:
private void testDBconnection()
{
label3.Text = "Connecting to Database Server......";
SqlServerConnection ssc = new SqlServerConnection();
bool conOK = ssc.isConnectable(ssc.makeConnectionString(
SqlServerConnParamters.SqlServerIPAddress,
SqlServerConnParamters.AccountValidationDatabaseName,
SqlServerConnParamters.SqlServerUserName,
SqlServerConnParamters.SqlServerPassword,
5));
if (conOK)
{
label3.Text = "";
}
else
{
label3.Text = "Database connection failed";
button1.Enabled = false;
}
}
I put this method in Form_Load event.
But in runtime, this process start even before this form shows. And the validation could last for 15 seconds by default(I set it to 5 but it also takes time). If the connection has some problem, it will display like the programe failed to open, but it will shown after it failed to connect to database.
My intention is tell the user by Label3 displaying "Connecting to Database Server......", and tell user if connection failed.
I was trying to find Form Event like "Loaded_Complete", or "Loaded"(I found Form_Closed though), but I couldn't.
I guess it has something to do with thread, programe sleeping, or else. I hope someone could help me on this. Thanks a lot guys!
I would use a BackgroundWorker this way. That will defer the database check operation, and the form load will not be locked by it.
label3.Text = "Connecting...";
button1.Enabled = false;
var bkw = new BackgroundWorker();
bkw.DoWork += (s, ev) =>
{
SqlServerConnection ssc = new SqlServerConnection();
ev.Result = ssc.isConnectable(ssc.makeConnectionString(
SqlServerConnParamters.SqlServerIPAddress,
SqlServerConnParamters.AccountValidationDatabaseName,
SqlServerConnParamters.SqlServerUserName,
SqlServerConnParamters.SqlServerPassword, 5));
};
bkw.RunWorkerCompleted += (s, ev) =>
{
if ((bool)ev.Result == true)
{
label3.Text = "Connected";
button1.Enabled = true;
}
else
{
label3.Text = "Database connection failed";
}
bkw.Dispose();
};
bkw.RunWorkerAsync();
However, this would require some exception handling. If an exception occurs in the DoWork event, then you can check in the RunWorkerCompleted event wether ev.Error is null or not (it contains the exception) and react accordingly.
Use timer.
In form load event start the timer(set interval to 2 sec or what ever you want). As timer ticks call your connection method. At the starting of your testDBconnection() method, stop the timer and dispose it because you don't need it any more.
You should not be using the Form_Load event to fire events when a form loads, you should override the OnLoad() method instead, that way you control when the code gets fired (it's possible for multiple subscribers to be listening to Form_Load and you don't know what order they will run in).
The quickest and dirtiest way of getting the screen to refresh is to Add
Application.DoEvents();
After changing the label, this forces the screen to update. In general though this is bad practice and the background thread above would be a better solution long term.

Is there anyway to know when the screen has been updated/refreshed (OpenGL or DirectX maybe?)

I currently have an application I'm writing in c# (using .NET) that requires me to start a timer as soon as a user sees an image on screen up until they respond with a key press.
Now I realise that practically this is very difficult given the monitor input lag and response time, the time the keyboard takes to physically send the message, the OS to process it, etc.
But I'm trying my best to reduce it down to mostly a constant error (the response time results will be used to compare one user to the next so a constant error isn't really an issue). However annoying hurdle is the variable caused by the monitor refresh rate, as I gather when my onPaint message is called and done with, it doesn't mean the image has actually been processed and sent from the graphics buffer?
Unfortunately time restrictions and other commitments would realistically restrict me to continuing this task in c# for windows.
So what I was wondering was if either handling all the drawing in OpenGL or DirectX or better still for me if it is possible to just using either OpenGL or DirectX to create an event when the screen is updated?
Another suggestion given to me previously was regarding V-Sync, if I switch this off is the image sent as soon as it is drawn? as opposed to sending images at a set rate synchronised to the monitor refresh rate?
You must render your graphic in a separate thread in order to:
Use vertical synchronisation to have a precise timing of the effective display of your image.
Get the precise timing of your user input (since user interface is not on the same thread than the render loop.
Initialise Direct3D to enable the VSync during render :
// DirectX example
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.BackBufferCount = 1;
presentParams.PresentationInterval = PresentInterval.One;
device = new Device(...
Perform the render in a separate thread:
Thread renderThread = new Thread(RenderLoop);
renderThread.Start();
shouldDisplayImageEvent = new AutoResetEvent();
Then use the following render loop:
void RenderLoop()
{
while(applicationActive)
{
device.BeginScene();
// Other rendering task
if (shouldDisplayImageEvent.WaitOne(0))
{
// Render image
// ...
userResponseStopwatch = new Stopwatch();
userResponseStopwatch.Start();
}
device.EndScene();
device.Present();
}
}
Then handle the user input :
void OnUserInput(object sender, EventArgs e)
{
if (userResponseStopwatch != null)
{
userResponseStopwatch.Stop();
float userResponseDuration = userResponseStopwatch.ElapsedMillisecond - 1000 / device.DisplayMode.RefreshRate - displayDeviceDelayConstant;
userResponseStopwatch = null;
}
}
You now use the shouldDisplayImageEvent.Set() event trigger to display the image as needed and start the stop watch.
First enable the VSync on your application idle loop :
// DirectX example
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.BackBufferCount = 1;
presentParams.PresentationInterval = PresentInterval.One;
device = new Device(...
Application.Idle += new EventHandler(OnApplicationIdle);
// More on this here : http://blogs.msdn.com/tmiller/archive/2005/05/05/415008.aspx
internal void OnApplicationIdle(object sender, EventArgs e)
{
Msg msg = new Msg();
while (true)
{
if (PeekMessage(out msg, IntPtr.Zero, 0, 0, 0))
break;
}
// Clearing render
// ...
if (displayImage)
{
// Render image
// ...
renderTime = DateTime.now();
}
device.Present();
}
With the vsync enabled, the device.Present function block until the next frame synchronisation, so if you compute the time between renderTime and the user input time and remove the display device delay + 16.67ms you should get your user response delay.

Make visible baloonTipText until it is clicked

I have a NotifyIcon in my program which displays a baloon tip in the taskbar. I wrote code as
notifyIcon1.Icon = new Icon(SystemIcons.Application, 40, 40);
notifyIcon1.Visible = true;
notifyIcon1.Text = "Test Notify Icon Demo";
notifyIcon1.BalloonTipText =count+ " Alerts";
notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
notifyIcon1.BalloonTipTitle = "Alert!";
notifyIcon1.ShowBalloonTip(999999999);
The baloon tip is invisible after the set time (999999999). But I want to show the baloon tip until it is clicked as I have baloontipclicked event.
How to make baloontip visible forever?
from MSDN:
Minimum and maximum timeout values are enforced by the operating
system and are typically 10 and 30 seconds, respectively, however this
can vary depending on the operating system. Timeout values that are
too large or too small are adjusted to the appropriate minimum or
maximum value. In addition, if the user does not appear to be using
the computer (no keyboard or mouse events are occurring) then the
system does not count this time towards the timeout.
it seems not be possible to override the maximum timeout (eventually adjusted by Windows and limited to 30 seconds even if you specify a longer one) so the Notification will fade away, will not wait for you to click on it after 2 minutes.
if you want to really have a different behavior you should probably use something else, other objects or simulate something similar with forms where you have the full control on the behavior and you can show, hide and close as you wish from your code.
You can show it again if it hasn't been clicked.
You have the close event (BalloonTipClosed), if user hasn't ckicked it just show it again.
private void ShowBalloonTip(int minutes) {
notifyIcon.BalloonTipIcon = ToolTipIcon.Error;
notifyIcon.BalloonTipText = "Text";
notifyIcon.BalloonTipTitle = "Title";
notifyIcon.ShowBalloonTip(minutes* 60 * 1000);
m_showUntil = DateTime.Now.AddMinutes(minutes);
}
private void notifyIcon_BalloonTipClosed(object sender, EventArgs e) {
if (m_showUntil > DateTime.Now)
notifyIcon.ShowBalloonTip(60 * 1000);
}
private void notifyIcon_BalloonTipClicked(object sender, EventArgs e) {
m_showUntil = DateTime.MinValue;
(..)
}

Categories

Resources