⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 formmain.cs

📁 kuiMsg是一款用.net C# 开发的即时消息开源软件,适合.net即时消息软件开发者用。 主要功能: 支持文件传输(p2p); 支持GIF动画表情( 彻底消除闪屏 :) );
💻 CS
📖 第 1 页 / 共 4 页
字号:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using IMLibrary;
using System.Security.Cryptography;

namespace LanMsg
{
    public sealed partial class FormMain : DevComponents.DotNetBar.Office2007RibbonForm   //Form 
    {

        #region Main函数
        public FormMain()
        {
            InitializeComponent();
           
            this.Left = Screen.PrimaryScreen.WorkingArea.Width - this.Width;
            this.Top = 200;

            this.loginIcon  = (System.Drawing.Icon) FormAccess.resourceManager.GetObject("community1");
            LanMsg.FormAccess.formMain = this;

            FormAccess.sockUDP = this.sockUDP1;
        }
        #endregion

        #region 用户变量申明区
        /// <summary>
        /// 
        /// </summary>
        FormHide fHide = new FormHide();

        /// <summary>
        /// 确定当用户是否退出应用程序
        /// </summary>
        private bool isExitApp = false;//确定当用户是否退出应用程序
  
        /// <summary>
        /// 记录当前用户是否设置自动登录
        /// </summary>
        private bool  selfAutoLogin = false;

        /// <summary>
        /// 登录图标
        /// </summary>
        private System.Drawing.Icon loginIcon;
         
        #endregion

        #region  FormMain_Load事件
        private void FormMain_Load(object sender, EventArgs e)
        {
            ///初始化表情
            for (int i = 0; i < 195; i++)
                FormAccess.formMain.imageListFace.Images.Add(i.ToString(), (System.Drawing.Image)FormAccess.resourceManager.GetObject("_" + i.ToString()));

            this.fHide.Show();//将显示隐藏窗口,用于关闭或重新启动计算机时退出程序
            this.Hide();

            BeginListen();//选择服务端口并开始侦听服务
            readyLogin(true );

            FormAccess.selfInfo.userNameChanged +=new UserInfo.userNameChangedEventHandler(selfInfo_userNameChanged);
            FormAccess.selfInfo.userStateChanged += new UserInfo.userStateChangedEventHandler(selfInfo_userNameChanged);
            this.tabSelfInfo.TextChanged += new EventHandler(tabSelfInfo_TextChanged);
        }

        private void tabSelfInfo_TextChanged(object sender, EventArgs e)
        {
            this.NotifyIcon.Text = tabSelfInfo.Text;
        }
       

        private void selfInfo_userNameChanged(object sender)
        {
            IMLibrary.UserInfo user =sender as IMLibrary.UserInfo;
            this.tabSelfInfo.Text = user.userName + user.StateInfo;
            this.tabSelfInfo.Refresh();
        }
        #endregion

        #region 窗口启动时准备登录readyLogin()
     /// <summary>
        /// 窗口启动时准备登录
     /// </summary>
        /// <param name="IsFirstLogin">是否首次登录</param>
        private void readyLogin(bool IsFirstLogin)
        {
            if (FormAccess.selfInfo.State == 0)//输入用户与密码
            {
                FormLogin f = new FormLogin();
                if (!IsFirstLogin)
                {
                    f.checkBoxAoutLogin.Checked = false;
                    f.Update1.Dispose();
                }
                f.ShowDialog();
                if (f.isExitApp)
                {
                    f.Dispose();
                    this.ExitApp();
                }
                
                FormAccess.selfInfo.UserID = f.textUserID.Text.Trim();
                FormAccess.selfPassword = f.textPassword.Text;

                this.selfAutoLogin = f.checkBoxAoutLogin.Checked;
                f.Dispose();


                FormAccess.dbDepToDeps();//将数据库中组织机构表加载到Deps集合
                FormAccess.dbUserToUsers();//将数据库中用户表加载到Users集合

                if (LanMsg.dataAccess.IsCorrectPassword(FormAccess.selfInfo.UserID, FormAccess.selfPassword))//如果密码正确,则用户可以加载基础数据 
                {
                    FormAccess.usersToTreeView(this.TreeUsers);//将用户表填充至TreeView控件
                    FormAccess.depsToTreeView(this.TreeUsers);//将组织机构填充至TreeView控件
                    this.NotifyIcon.ContextMenuStrip = this.contextMenuNotify;
                }
                
                this.Login();//开始登录
                this.timerLogin.Enabled = true; //开始检测登录
            }
        }
        
        #endregion

        #region 应用退出程序函数 ExitApp()
        /// <summary>
        /// 应用退出程序函数
        /// </summary>
        public void ExitApp()
        {
            ////////告诉服务器,自己已经离线 
            byte[] buffer = new byte[1];
            buffer[0] = 0;
            IMLibrary.ServerMsg msg = new IMLibrary.ServerMsg(FormAccess.selfInfo.ID, buffer);
            FormAccess.sendMsgToServer(2, msg);

            //////////告诉其它用户自己已经离线
            FormAccess.sendMsgToAllUser(12, IMLibrary.TextEncoder.textToBytes(FormAccess.selfInfo.UserID));

            ///
            this.NotifyIcon.Dispose();

            System.Threading.Thread.Sleep(100);
            this.sockUDP1.CloseSock();
            System.Threading.Thread.Sleep(100);

            this.isExitApp = true;
            System.Diagnostics.Process.GetCurrentProcess().Kill();//强制杀进程结束程序
            try
            { Application.Exit(); }
            catch { }
        }
        #endregion

        #region 数据到达事件
        private void sockUDP1_DataArrival(byte[] Data, System.Net.IPAddress Ip, int Port)
        {
            DataArrivaldelegate outdelegate = new DataArrivaldelegate(DataArrival);
            this.BeginInvoke(outdelegate, new object[] { Data, Ip, Port });
        }
        #endregion

        #region 选择服务端口并开始侦听服务BeginListen()
        /// <summary>
        /// 选择服务端口并开始侦听服务
        /// </summary>
        private void BeginListen()
        {
            System.Random i = new Random();

        resetPort:
            int j = i.Next(2000, 60000);//端口取值范围
            try
            {
                this.sockUDP1.Listen(j);//UDP开始侦听来自外部的消息
            }
            catch
            {
                goto resetPort;
            }

            System.Net.IPAddress[] ip  =   System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName());//获得本机局域网地址
            FormAccess.selfInfo.IP = ip[ip.Length-1];//获得本机局域网地址
            FormAccess.selfInfo.Port = j;//获得本机局域网端口
            FormAccess.LocalIp = ip[ip.Length - 1];//获得本机局域网地址
            FormAccess.LocalPort = j;//获得本机局域网端口

            //System.Net.IPAddress[] ipServer  = System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName());//获得服务器IP地址
            //FormAccess.ServerIP = ipServer[0];//获得服务器IP地址
        }

        #endregion

        #region 数据达到事件处理过程DataArrival(byte[] Data, System.Net.IPAddress Ip, int Port)
        private delegate void DataArrivaldelegate(byte[] Data, System.Net.IPAddress Ip, int Port);
        private void DataArrival(byte[] Data, System.Net.IPAddress Ip, int Port)
        {

            int cnt = 0;//记录接收到的数据包大小
            cnt = Data.Length;//获取接收到的数据包大小
            if (cnt < 3) return;//如果收到的数据小于3个字节则视为非法用户,抛弃

            if (Data[0] != 255) return;//将非法用户的数据抛弃

            try
            {
                byte[] buffer = new byte[cnt - 2];//申明一个字节数组,用于保存去除第一个字节码(即LanMsg协议编码)的其它数据(即消息实体)
                Buffer.BlockCopy(Data, 2, buffer, 0, cnt - 2);//去除前两个字节码(即LanMsg协议编码)的其它数据为消息实体,将其保存于Buffer字节数组

                switch (Data[1])// 取得第一个字节码,即LanMsg协议编码,根据编码判断用户发过来的请求为何种类型
                {
                    case 0://服务器告诉用户密码错误
                        this.onErrorPassword(new DataArrivalEventArgs(buffer));
                        break;
                    case 5://服务器告诉用户登录成功 
                        this.onUserScuccessLogin(new DataArrivalEventArgs(buffer));//触发用户成功登录事件 
                        break;
                    case 6://服务器告诉用户与服务器处于联接状态 
                        this.onUserOnlineChanageState(new DataArrivalEventArgs(buffer));//触发联接状态事件
                        break;
                    case 7://服务器返回“部分组织机构信息”
                        this.onGetDepartmentCollections(new DataArrivalEventArgs(buffer));//触发部门信息接收事件
                        break;
                    case 8://服务器返回“部分组织用户信息”
                        this.onGetUserCollections(new DataArrivalEventArgs(buffer));
                        break;
                    case 9://服务器通知有用户上线
                        this.onUserOnline(new DataArrivalEventArgs(buffer));//触发用户上线事件
                        break;
                    case 10://收到用户对话消息
                        this.onUserReceiveMsg(new DataArrivalEventArgs(buffer,Ip,Port ));//触发收到用户对话消息事件 
                        break;
                    case 11://用户收到消息并回复
                        this.onUserReceiveMsgReturn(new DataArrivalEventArgs(buffer));//触发收到消息回复事件 
                        break;
                    case 12://用户离线 
                        this.onUserIsNotOnline(new DataArrivalEventArgs(buffer));//触发用户离线事件
                        break;
                    case 13://服务器通知用户已经在别处登录
                        this.onUserElseLogin();//触发用户别处登录事件
                        break;
                    case 14://用户发送文件请求事件
                        this.onUserFileSendRequest(new DataArrivalEventArgs(buffer, Ip, Port));//触发用户发送文件请求事件 
                        break;
                    case 15://收到群发通知消息
                        this.onGroupMsg(new DataArrivalEventArgs(buffer));//处理群发通知消息
                        break;
                    case 16://对方要求打洞
                        this.onUdpPenetrate(new DataArrivalEventArgs(buffer, Ip, Port));
                        break;
                    case 17://用户UDP打洞成功
                        this.onUdpPenetrateSuccess(new DataArrivalEventArgs(buffer, Ip, Port));
                        break;
                    case 18://用户要求发送局域网IP地址与端口
                        this.onRecUserLocalIpPort(new DataArrivalEventArgs(buffer, Ip, Port));
                        break;
                    case 20://对方告诉自己向对方打洞成功
                        this.onAVRequest(new DataArrivalEventArgs(buffer, Ip, Port));
                        break;
                    case 21://对方告诉可以开始视频
                        this.onBeginAV(new DataArrivalEventArgs(buffer, Ip, Port));
                        break;
                    case 22://对方取消视频对话
                        this.onCancelAV(new DataArrivalEventArgs(buffer));
                        break;
                    case 23://服务器返回部分上线用户的信息
                        this.onGetOnlineUserCollections(new DataArrivalEventArgs(buffer));
                        break;
                    case 24://服务器告诉用户,密码修改成功
                        this.onChangePasswordSuccessful();
                        break;
                    case 25://对方桌面切图发送请求
                        this.onUserImageSendRequest(new DataArrivalEventArgs(buffer, Ip, Port));//触发用户发送文件请求事件 
                        break;
                }
            }
            catch { return; }//抛掉非法数据
        }
        #endregion

        #region 服务器告诉用户,密码修改成功
        /// <summary>
        /// 密码修改成功
        /// </summary>
        private void  onChangePasswordSuccessful( )
        {
            FormAccess.isChangePasswordSuccessful = true;
        }

        #endregion

        #region  对方要求发送自己的本地局域网IP与端口
        /// <summary>
        /// 对方要求发送自己的本地局域网IP与端口
        /// </summary>
        /// <param name="e"></param>
        private void onRecUserLocalIpPort(DataArrivalEventArgs e)
        {
            MessageBox.Show("用户发来本地局域网IP与端口:");

            UserInfo tempUser=IMLibrary.Serializers.ByteToObj(e.Data) as UserInfo ;
            if (tempUser == null) return;//非法数据则返回

            exUser user = FormAccess.findUser(tempUser.UserID);
            if (user == null) return;//非法数据则返回

            user.IP = tempUser.IP;//将用户Internet IP设置为局域网IP
            user.Port = tempUser.Port;//将用户Internet Port设置为局域网端口
            user.isInLan = true;//将用户设置为局域网用户 

            MessageBox.Show("用户发来本地局域网IP与端口:" + user.IP.ToString() +"-"+ user.Port.ToString());
        }
        #endregion

        #region 处理用户UDP打洞数据包
        /// <summary>
        /// 处理用户UDP打洞数据包
        /// </summary>
        /// <param name="e"></param>
        private void onUdpPenetrate(DataArrivalEventArgs e)
        {
            string mtuValue = e.Data.Length.ToString();
            string[] userStr = IMLibrary.TextEncoder.bytesToText(e.Data).Split('|');
            //MessageBox.Show(userStr[0] +"要求打洞(" + mtuValue + ")") ;
            exUser user = FormAccess.findUser(userStr[0]);
            if (user == null) return;//如果用户不存在则返回
            FormAccess.sendMsgToOneUser(17, IMLibrary.TextEncoder.textToBytes(FormAccess.selfInfo.UserID + "|" + mtuValue), user);//告诉对方打洞成功
        }

        /// <summary>
        /// 处理打洞成功
        /// </summary>
        /// <param name="e"></param>
        private void onUdpPenetrateSuccess(DataArrivalEventArgs e)
        {
            string[] userUdpPenInfo = IMLibrary.TextEncoder.bytesToText(e.Data).Split('|');
            exUser user = FormAccess.findUser(userUdpPenInfo[0]);
            if(user == null) return;//如果用户不存在则返回
            user.isDirectCon = true;//表明用户与自己网络位置上处于直联,用户能够直接收到自己发送的任何消息,消息不需要服务器转发
            try 
            {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -