You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
517 lines
15 KiB
C#
517 lines
15 KiB
C#
10 years ago
|
//-----------------------------------------------------------------------------
|
||
|
// File: DPlayConnect_JoinForm.cs
|
||
|
//
|
||
|
// Desc: Application class for the DirectPlay samples framework.
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Windows.Forms;
|
||
|
using System.Threading;
|
||
|
using System.Timers;
|
||
|
using Microsoft.DirectX;
|
||
|
using Microsoft.DirectX.DirectPlay;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// This form will search for existing running samples and allow you to join them or will
|
||
|
/// allow you to create your own session as a host
|
||
|
/// </summary>
|
||
|
public class CreateJoinForm : System.Windows.Forms.Form
|
||
|
{
|
||
|
private System.Windows.Forms.Button btnJoin;
|
||
|
private System.Windows.Forms.Label label1;
|
||
|
private System.Windows.Forms.Button btnCreate;
|
||
|
private System.Windows.Forms.ListBox lstSession;
|
||
|
private System.Windows.Forms.Button btnCancel;
|
||
|
private System.Windows.Forms.Button btnSearch;
|
||
|
private const int EnumExpireThreshold = 2000;
|
||
|
private bool amJoining = false;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Hold our information of hosts we found
|
||
|
/// </summary>
|
||
|
private struct FindHostsResponseInformation
|
||
|
{
|
||
|
public int LastFoundTime;
|
||
|
public ApplicationDescription ApplicationDesc;
|
||
|
public int RoundTripLatencyMs;
|
||
|
public Address sender;
|
||
|
public Address device;
|
||
|
public override string ToString()
|
||
|
{
|
||
|
if (ApplicationDesc.MaxPlayers > 0)
|
||
|
return ApplicationDesc.SessionName + " (" + ApplicationDesc.CurrentPlayers + "/" + ApplicationDesc.MaxPlayers + ") (" + RoundTripLatencyMs + "ms)";
|
||
|
else
|
||
|
return ApplicationDesc.SessionName + " (" + ApplicationDesc.CurrentPlayers + ") (" + RoundTripLatencyMs + "ms)";
|
||
|
}
|
||
|
};
|
||
|
|
||
|
private Peer peer;
|
||
|
private ConnectWizard connectionWizard;
|
||
|
private Address deviceAddress;
|
||
|
private Address hostAddress = null;
|
||
|
private bool isSearching = false;
|
||
|
private int findHostHandle = 0;
|
||
|
private CreateSessionForm createSessionForm = null;
|
||
|
private ResultCode resultCode;
|
||
|
private ArrayList foundHosts = new ArrayList();
|
||
|
private bool isConnected = false;
|
||
|
private ManualResetEvent connectEvent = null;
|
||
|
private System.Timers.Timer updateListTimer = null;
|
||
|
private System.Timers.Timer connectTimer = null;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Constructor
|
||
|
/// </summary>
|
||
|
public CreateJoinForm(Peer peerObject, Address addressObject, ConnectWizard connectionWizard)
|
||
|
{
|
||
|
//
|
||
|
// Required for Windows Form Designer support
|
||
|
//
|
||
|
InitializeComponent();
|
||
|
peer = peerObject;
|
||
|
this.connectionWizard = connectionWizard;
|
||
|
this.Text = connectionWizard.SampleName + " - " + this.Text;
|
||
|
deviceAddress = addressObject;
|
||
|
|
||
|
//Set up the event handlers
|
||
|
peer.FindHostResponse += new FindHostResponseEventHandler(FindHostResponseMessage);
|
||
|
peer.ConnectComplete += new ConnectCompleteEventHandler(ConnectResult);
|
||
|
peer.AsyncOperationComplete += new AsyncOperationCompleteEventHandler(CancelAsync);
|
||
|
|
||
|
//Set up our timer
|
||
|
updateListTimer = new System.Timers.Timer(300); // A 300 ms interval
|
||
|
updateListTimer.Elapsed += new System.Timers.ElapsedEventHandler(this.UpdateTimer);
|
||
|
updateListTimer.SynchronizingObject = this;
|
||
|
updateListTimer.Start();
|
||
|
//Set up our connect timer
|
||
|
connectTimer = new System.Timers.Timer(100); // A 100ms interval
|
||
|
connectTimer.Elapsed += new System.Timers.ElapsedEventHandler(this.ConnectTimer);
|
||
|
connectTimer.SynchronizingObject = this;
|
||
|
// Set up our connect event
|
||
|
connectEvent = new ManualResetEvent(false);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// An asynchronous operation was cancelled
|
||
|
/// </summary>
|
||
|
private void CancelAsync(object sender, AsyncOperationCompleteEventArgs e)
|
||
|
{
|
||
|
if (e.Message.AsyncOperationHandle == findHostHandle)
|
||
|
{
|
||
|
findHostHandle = 0;
|
||
|
btnSearch.Text = "Start Search";
|
||
|
isSearching = false;
|
||
|
btnCreate.Enabled = true;
|
||
|
btnSearch.Enabled = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// A host was found and responded to our query
|
||
|
/// </summary>
|
||
|
private void FindHostResponseMessage(object sender, FindHostResponseEventArgs dpMessage)
|
||
|
{
|
||
|
// Now we need to add this to our list of available sessions
|
||
|
SessionAdd(dpMessage.Message);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Add this session to our list
|
||
|
/// </summary>
|
||
|
/// <param name="dpMessage"></param>
|
||
|
private void SessionAdd(FindHostsResponseMessage dpMessage)
|
||
|
{
|
||
|
FindHostsResponseInformation dpInfo = new FindHostsResponseInformation();
|
||
|
|
||
|
dpInfo.ApplicationDesc = dpMessage.ApplicationDescription;
|
||
|
dpInfo.device = dpMessage.AddressDevice;
|
||
|
dpInfo.sender = dpMessage.AddressSender;
|
||
|
dpInfo.RoundTripLatencyMs = dpMessage.RoundTripLatencyMs;
|
||
|
dpInfo.LastFoundTime = Environment.TickCount;
|
||
|
|
||
|
// Let's check the items first and see if this one already exists
|
||
|
bool isFound = false;
|
||
|
|
||
|
lock (foundHosts)
|
||
|
{
|
||
|
for (int i = 0; i < lstSession.Items.Count; i++)
|
||
|
{
|
||
|
if (dpInfo.ApplicationDesc.GuidInstance == ((FindHostsResponseInformation)lstSession.Items[i]).ApplicationDesc.GuidInstance)
|
||
|
{
|
||
|
foundHosts[i] = dpInfo;
|
||
|
lstSession.Items[i] = dpInfo;
|
||
|
isFound = true;
|
||
|
}
|
||
|
}
|
||
|
if (!isFound)
|
||
|
{
|
||
|
lstSession.Items.Add(dpInfo);
|
||
|
foundHosts.Add(dpInfo);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Clean up any resources being used.
|
||
|
/// </summary>
|
||
|
protected override void Dispose(bool Disposing)
|
||
|
{
|
||
|
base.Dispose(Disposing);
|
||
|
|
||
|
if (isSearching)
|
||
|
{
|
||
|
if (findHostHandle != 0)
|
||
|
peer.CancelAsyncOperation(findHostHandle);
|
||
|
isSearching = !isSearching;
|
||
|
}
|
||
|
if (connectTimer != null)
|
||
|
connectTimer.Dispose();
|
||
|
|
||
|
if (updateListTimer != null)
|
||
|
updateListTimer.Dispose();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#region Windows Form Designer generated code
|
||
|
/// <summary>
|
||
|
/// Required method for Designer support - do not modify
|
||
|
/// the contents of this method with the code editor.
|
||
|
/// </summary>
|
||
|
private void InitializeComponent() {
|
||
|
this.btnSearch = new System.Windows.Forms.Button();
|
||
|
this.btnCancel = new System.Windows.Forms.Button();
|
||
|
this.lstSession = new System.Windows.Forms.ListBox();
|
||
|
this.btnCreate = new System.Windows.Forms.Button();
|
||
|
this.label1 = new System.Windows.Forms.Label();
|
||
|
this.btnJoin = new System.Windows.Forms.Button();
|
||
|
this.SuspendLayout();
|
||
|
//
|
||
|
// btnSearch
|
||
|
//
|
||
|
this.btnSearch.Location = new System.Drawing.Point(319, 7);
|
||
|
this.btnSearch.Name = "btnSearch";
|
||
|
this.btnSearch.Size = new System.Drawing.Size(86, 27);
|
||
|
this.btnSearch.TabIndex = 2;
|
||
|
this.btnSearch.Text = "Start Search";
|
||
|
this.btnSearch.Click += new System.EventHandler(this.btnSearch_Click);
|
||
|
//
|
||
|
// btnCancel
|
||
|
//
|
||
|
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||
|
this.btnCancel.Location = new System.Drawing.Point(333, 227);
|
||
|
this.btnCancel.Name = "btnCancel";
|
||
|
this.btnCancel.Size = new System.Drawing.Size(74, 27);
|
||
|
this.btnCancel.TabIndex = 3;
|
||
|
this.btnCancel.Text = "Cancel";
|
||
|
//
|
||
|
// lstSession
|
||
|
//
|
||
|
this.lstSession.Location = new System.Drawing.Point(5, 37);
|
||
|
this.lstSession.Name = "lstSession";
|
||
|
this.lstSession.Size = new System.Drawing.Size(400, 186);
|
||
|
this.lstSession.TabIndex = 1;
|
||
|
this.lstSession.DoubleClick += new System.EventHandler(this.btnJoin_Click);
|
||
|
this.lstSession.SelectedValueChanged += new System.EventHandler(this.SelectedChange);
|
||
|
//
|
||
|
// btnCreate
|
||
|
//
|
||
|
this.btnCreate.DialogResult = System.Windows.Forms.DialogResult.Yes;
|
||
|
this.btnCreate.Location = new System.Drawing.Point(84, 227);
|
||
|
this.btnCreate.Name = "btnCreate";
|
||
|
this.btnCreate.Size = new System.Drawing.Size(74, 27);
|
||
|
this.btnCreate.TabIndex = 2;
|
||
|
this.btnCreate.Text = "Create";
|
||
|
this.btnCreate.Click += new System.EventHandler(this.btnCreate_Click);
|
||
|
//
|
||
|
// label1
|
||
|
//
|
||
|
this.label1.Location = new System.Drawing.Point(5, 13);
|
||
|
this.label1.Name = "label1";
|
||
|
this.label1.Size = new System.Drawing.Size(312, 16);
|
||
|
this.label1.TabIndex = 0;
|
||
|
this.label1.Text = "Select session to join, or click Create to start a new session.";
|
||
|
//
|
||
|
// btnJoin
|
||
|
//
|
||
|
this.btnJoin.Enabled = false;
|
||
|
this.btnJoin.Location = new System.Drawing.Point(7, 227);
|
||
|
this.btnJoin.Name = "btnJoin";
|
||
|
this.btnJoin.Size = new System.Drawing.Size(74, 27);
|
||
|
this.btnJoin.TabIndex = 2;
|
||
|
this.btnJoin.Text = "Join";
|
||
|
this.btnJoin.Click += new System.EventHandler(this.btnJoin_Click);
|
||
|
//
|
||
|
// CreateJoinForm
|
||
|
//
|
||
|
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
|
||
|
this.CancelButton = this.btnCancel;
|
||
|
this.ClientSize = new System.Drawing.Size(411, 264);
|
||
|
this.ControlBox = false;
|
||
|
this.Controls.Add(this.btnCreate);
|
||
|
this.Controls.Add(this.btnJoin);
|
||
|
this.Controls.Add(this.btnSearch);
|
||
|
this.Controls.Add(this.btnCancel);
|
||
|
this.Controls.Add(this.lstSession);
|
||
|
this.Controls.Add(this.label1);
|
||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||
|
this.MaximizeBox = false;
|
||
|
this.MinimizeBox = false;
|
||
|
this.Name = "CreateJoinForm";
|
||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||
|
this.Text = "Join or create a session";
|
||
|
this.ResumeLayout(false);
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// The selected session was changed.
|
||
|
/// </summary>
|
||
|
private void SelectedChange(object sender, System.EventArgs e)
|
||
|
{
|
||
|
if (amJoining)
|
||
|
return; // Do nothing if we are already joining a session
|
||
|
|
||
|
btnJoin.Enabled = (lstSession.SelectedItem != null);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// We either want to start or stop searching
|
||
|
/// </summary>
|
||
|
private void btnSearch_Click(object sender, System.EventArgs e)
|
||
|
{
|
||
|
if (!isSearching)
|
||
|
{
|
||
|
if( hostAddress != null )
|
||
|
hostAddress.Dispose();
|
||
|
|
||
|
hostAddress = new Address();
|
||
|
hostAddress.ServiceProvider = deviceAddress.ServiceProvider;
|
||
|
|
||
|
// See if we should prompt the user for the remote address
|
||
|
if (ConnectWizard.ProviderRequiresPort(hostAddress.ServiceProvider))
|
||
|
{
|
||
|
AddressForm addressDialog = new AddressForm(connectionWizard.DefaultPort);
|
||
|
addressDialog.ShowDialog(this);
|
||
|
|
||
|
// If the user cancelled the address form, abort the search
|
||
|
if (addressDialog.DialogResult != DialogResult.OK)
|
||
|
return;
|
||
|
|
||
|
// If a port was specified, add the component
|
||
|
if (addressDialog.Hostname != "")
|
||
|
hostAddress.AddComponent(Address.KeyHostname, addressDialog.Hostname);
|
||
|
|
||
|
// If a hostname was specified, add the component
|
||
|
if (addressDialog.Port > 0)
|
||
|
hostAddress.AddComponent(Address.KeyPort, addressDialog.Port);
|
||
|
}
|
||
|
|
||
|
//Time to enum our hosts
|
||
|
ApplicationDescription desc = new ApplicationDescription();
|
||
|
desc.GuidApplication = connectionWizard.ApplicationGuid;
|
||
|
|
||
|
// If the user was not already asked for address information, DirectPlay
|
||
|
// should prompt with native UI
|
||
|
FindHostsFlags flags = 0;
|
||
|
if (!ConnectWizard.ProviderRequiresPort(deviceAddress.ServiceProvider))
|
||
|
flags = FindHostsFlags.OkToQueryForAddressing;
|
||
|
|
||
|
peer.FindHosts(desc,hostAddress,deviceAddress,null,Timeout.Infinite,0,Timeout.Infinite, flags, out findHostHandle);
|
||
|
isSearching = true;
|
||
|
btnCreate.Enabled = false;
|
||
|
btnSearch.Text = "Stop Search";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
btnSearch.Text = "Stopping...";
|
||
|
btnSearch.Enabled = false;
|
||
|
if (findHostHandle != 0)
|
||
|
peer.CancelAsyncOperation(findHostHandle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// A form was disposed
|
||
|
/// </summary>
|
||
|
/// <param name="sender"></param>
|
||
|
/// <param name="e"></param>
|
||
|
public void FormDisposed(object sender, EventArgs e)
|
||
|
{
|
||
|
if (sender == createSessionForm)
|
||
|
createSessionForm = null;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// We should create a new session. Display a dialog allowing the user to set
|
||
|
/// certain options
|
||
|
/// </summary>
|
||
|
private void btnCreate_Click(object sender, System.EventArgs e)
|
||
|
{
|
||
|
this.DialogResult = DialogResult.None;
|
||
|
((Button)sender).DialogResult = DialogResult.None;
|
||
|
if (createSessionForm == null)
|
||
|
{
|
||
|
createSessionForm = new CreateSessionForm(peer,deviceAddress,connectionWizard);
|
||
|
createSessionForm.Disposed += new System.EventHandler(this.FormDisposed);
|
||
|
}
|
||
|
if (createSessionForm.ShowDialog(this) != DialogResult.Cancel)
|
||
|
{
|
||
|
((Button)sender).DialogResult = DialogResult.Yes;
|
||
|
this.DialogResult = DialogResult.Yes;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Determine if we need to expire any of our currently listed servers
|
||
|
/// </summary>
|
||
|
private void UpdateTimer(object sender, System.Timers.ElapsedEventArgs e)
|
||
|
{
|
||
|
lock (foundHosts)
|
||
|
{
|
||
|
for (int i = 0; i< foundHosts.Count; i++)
|
||
|
{
|
||
|
// First check to see if this session has expired
|
||
|
if (Environment.TickCount - ((FindHostsResponseInformation)foundHosts[i]).LastFoundTime > EnumExpireThreshold)
|
||
|
{
|
||
|
foundHosts.RemoveAt(i);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
for (int i = 0; i< lstSession.Items.Count; i++)
|
||
|
{
|
||
|
// First check to see if this session has expired
|
||
|
if (Environment.TickCount - ((FindHostsResponseInformation)lstSession.Items[i]).LastFoundTime > EnumExpireThreshold)
|
||
|
{
|
||
|
lstSession.Items.RemoveAt(i);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Wait for a connect to complete
|
||
|
/// </summary>
|
||
|
private void ConnectTimer(object sender, System.Timers.ElapsedEventArgs e)
|
||
|
{
|
||
|
if (connectEvent.WaitOne(0,false)) // Wait for the Connect event to be fired
|
||
|
{
|
||
|
if (isConnected) // Are we connected?
|
||
|
{
|
||
|
// Get rid of the timer
|
||
|
if (updateListTimer != null)
|
||
|
updateListTimer.Stop();
|
||
|
|
||
|
if (connectTimer != null)
|
||
|
connectTimer.Stop();
|
||
|
|
||
|
this.DialogResult = DialogResult.OK;
|
||
|
this.Close();
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MessageBox.Show(this,"Failed to connect. The error code was: \n" + resultCode.ToString() ,"Failed to connect",MessageBoxButtons.OK,MessageBoxIcon.Information);
|
||
|
// Restart our timer
|
||
|
updateListTimer.Start();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Fired when a connect complete message is received from DirectPlay. Fire
|
||
|
/// our event to notify the sample we've connected
|
||
|
/// </summary>
|
||
|
private void ConnectResult(object sender, ConnectCompleteEventArgs e)
|
||
|
{
|
||
|
if (e.Message.ResultCode == 0)
|
||
|
{
|
||
|
isConnected = true;
|
||
|
}
|
||
|
else
|
||
|
isConnected = false;
|
||
|
|
||
|
resultCode = e.Message.ResultCode;
|
||
|
// Notify the timer that we've connected.
|
||
|
connectEvent.Set();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Join an existing session
|
||
|
/// </summary>
|
||
|
private void btnJoin_Click(object sender, System.EventArgs e)
|
||
|
{
|
||
|
FindHostsResponseInformation dpInfo;
|
||
|
if (lstSession.SelectedItem == null)
|
||
|
{
|
||
|
MessageBox.Show(this,"Please select a session before clicking join.","No session",MessageBoxButtons.OK,MessageBoxIcon.Information);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Turn off all buttons
|
||
|
btnCreate.Enabled = false;
|
||
|
btnCancel.Enabled = false;
|
||
|
btnJoin.Enabled = false;
|
||
|
btnSearch.Enabled = false;
|
||
|
amJoining = true;
|
||
|
// Stop our secondary timer
|
||
|
updateListTimer.Stop();
|
||
|
dpInfo = ((FindHostsResponseInformation)lstSession.SelectedItem);
|
||
|
connectionWizard.SetUserInfo();
|
||
|
peer.Connect(dpInfo.ApplicationDesc,dpInfo.sender, dpInfo.device,null,ConnectFlags.OkToQueryForAddressing);
|
||
|
// Now start our 'Connect' timer
|
||
|
connectTimer.Start();
|
||
|
}
|
||
|
}
|