/// <summary> /// Handles the selection of the company logo to accept the negotiation. /// </summary> /// <param name="sender">The object that originated this event.</param> /// <param name="e">The event arguments.</param> void logoButton_Click(object sender, EventArgs e) { // Immediately close the notification window. this.animationState = AnimationState.Closing; // Advise any listeners that the negotiation has been rejected. if (this.Accept != null) { this.Accept(this, new MatchEventArgs(this.matchId)); } }
/// <summary> /// Event handler for a match. /// </summary> /// <param name="sender">The object that originated the event.</param> /// <param name="e">The event arguments.</param> void Match_MatchRowChanging(object sender, DataSetMarket.MatchRowChangeEvent e) { // When a new, pending match record has been added to the data mode, start a thread that will // display the notification window. if (e.Action == DataRowAction.Commit) { if (e.Row.MatchId == this.matchId && e.Row.StatusCode != Status.Active) { this.animationState = AnimationState.Closing; } } }
/// <summary> /// Animate the window on opening and closing. /// </summary> /// <param name="sender">The object that originated this event.</param> /// <param name="e">The event arguments.</param> private void timer_Tick(object sender, EventArgs e) { // The animation is driven by the periodic timer and a series of states. switch (this.animationState) { case AnimationState.Initial: // This initializes the animation and plays the opening sound. this.Visible = true; this.startTime = DateTime.Now; this.animationState = AnimationState.Opening; this.soundPlayerType.LoadAsync(); break; case AnimationState.Opening: // This will calculate by how much the window is to grow on this cycle. int increment = this.Height + NotificationWindow.increment > this.size.Height ? this.size.Height - this.Height : NotificationWindow.increment; // Grow the window. this.SuspendLayout(); this.Top -= increment; this.Height += increment; this.ResumeLayout(false); // If the window has reached its potential height, then go into the waiting state. if (this.Height >= this.size.Height) { this.animationState = AnimationState.Waiting; } break; case AnimationState.Closing: // This will calculate by how much this window is to shrink on this cycle. int decrement = this.Height - NotificationWindow.increment < 0 ? -this.Height : -NotificationWindow.increment; // Shrink the window. this.SuspendLayout(); this.Height += decrement; this.Top -= decrement; this.ResumeLayout(false); // If the window has shrunk to nothing, move on to closing it. if (this.Height == 0) { this.animationState = AnimationState.Closed; } break; case AnimationState.Closed: // This will close and dispose the window. this.Visible = false; ThreadPool.QueueUserWorkItem(new WaitCallback(UninitializeData)); this.timer.Stop(); this.Dispose(); break; } }
/// <summary> /// Show the notification window with an accompanying sound. /// </summary> public new void Show() { // This window is animated, so there's the actual size that appears on the screen, and there's the potential size. That // is, the size the window will be when it is fully displayed. The 'size' parameter contains the window's potential // size. It is initially dislayed with no height and grows vertically until the desired height is obtained. base.Size = new Size(this.size.Width, 0); // If a company logo hasn't been provided, the symbol name is used in large, distinctive letters. if (this.imageCompanyLogo == null) { this.imageCompanyLogo = new Bitmap(NotificationWindow.defaultLogoWidth, NotificationWindow.defaultLogoHeight); Graphics graphicsBitmap = Graphics.FromImage(this.imageCompanyLogo); Font font = new Font("Tahoma", 20.0f, FontStyle.Bold | FontStyle.Italic); Rectangle rectangle = new Rectangle(Point.Empty, this.imageCompanyLogo.Size); StringFormat stringFormat = StringFormat.GenericDefault; stringFormat.Alignment = StringAlignment.Center; stringFormat.LineAlignment = StringAlignment.Center; stringFormat.FormatFlags = StringFormatFlags.NoWrap; graphicsBitmap.DrawString(this.symbol, font, this.textBrush, rectangle, stringFormat); graphicsBitmap.Dispose(); } // A large button in the center of the window will hold either the symbol of the company or the comany logo. When it // is pressed, the negotiation is accepted. this.logoButton.Image = this.imageCompanyLogo; // I believe there is a better way to maintain the client rectangle than this one, but it works for now. This defines // the area where the non-frame elements are displayed. The values have been reverse-engineered from the MSN // notification window. this.clientRectangle = new Rectangle(2, 24, this.size.Width - 5, this.size.Height - 27); // This is the working area of the screen that has the system task bar. It is used to calculate the position of the // notification window so it pops up in the lower, right hand corner. That is, it should pop up in the same location // and with the same animiation effects as Micrsoft Instant Messaging. Rectangle workingArea = Screen.PrimaryScreen.WorkingArea; // Lay the elements out in the window. this.SuspendLayout(); // This is 'slot' where the notification window is displayed. this.Location = new Point(workingArea.Right - (this.Width + NotificationWindow.defaultGap), workingArea.Bottom - (this.size.Height * this.slotNumber)); // This is where the "Cancel" button is displayed. this.cancelButton.Location = new Point(this.size.Width - this.cancelButton.Image.Width - 6, 6); // This is where the "Options" label is displayed. this.labelOptions.Location = new Point(this.clientRectangle.Right + 2 - this.labelOptions.Width, this.clientRectangle.Top); // This is where the company name of logo is displayed. this.logoButton.Location = new Point((this.clientRectangle.Width - this.logoButton.Image.Width) / 2 + this.clientRectangle.Left, (this.clientRectangle.Height - this.logoButton.Image.Height) / 2 + this.clientRectangle.Top); this.logoButton.Size = new Size(this.logoButton.Image.Width, this.logoButton.Image.Height); // All the elements have been placed in the window. this.ResumeLayout(false); // The animation is driven by a series of states and a timer. This will start the process that will make the // notification window grow. this.animationState = AnimationState.Initial; this.timer.Interval = NotificationWindow.popUpTime / NotificationWindow.popUpSteps; this.timer.Start(); // This works like a dialog box in that it has it's own message thread to handle the timer messages. Application.Run(); }