Newer
Older
WifiScan / WifiScan / Form1.cs
@XWolf Override XWolf Override on 23 Apr 2023 9 KB License!
// MIT License
//
// Copyright (c) 2023 XWolf Override
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace WifiScan
{
    public partial class Form1 : Form
    {
        // Create a Font object for the node tags.
        Font tagFont = new Font("Helvetica", 7, FontStyle.Bold);

        public Form1()
        {
            InitializeComponent();
            AutoScaleDimensions = new SizeF(96F, 96F);
            AutoScaleMode = AutoScaleMode.Dpi;
            PopulateTree();
            DblBuf();
            ShowWifi(null);
        }

        private void DblBuf()
        {
            var objMethodInfo = typeof(Control).GetMethod("SetStyle", BindingFlags.NonPublic | BindingFlags.Instance);

            var objArgs = new object[] { ControlStyles.AllPaintingInWmPaint |
                             ControlStyles.UserPaint |
                             ControlStyles.OptimizedDoubleBuffer, true };

            objMethodInfo.Invoke(scMain.Panel1, objArgs);
            objMethodInfo.Invoke(scMain.Panel2, objArgs);
            objArgs = new object[] { ControlStyles.AllPaintingInWmPaint |
                             ControlStyles.OptimizedDoubleBuffer, true };
            objMethodInfo.Invoke(tvTree, objArgs);
        }

        #region Tree Management

        private TreeNode GetNodeFor(WifiDevice dev)
        {
            foreach (TreeNode node in tvTree.Nodes)
                if (dev == node.Tag)
                    return node;
            TreeNode nnode = tvTree.Nodes.Add(dev.Name);
            nnode.Tag = dev;
            return nnode;
        }

        private TreeNode GetNodeFor(Wifi wifi, TreeNodeCollection nodes)
        {
            foreach (TreeNode node in nodes)
                if (wifi.BSSID == ((Wifi)node.Tag).BSSID)
                {
                    node.Tag = wifi;
                    return node;
                }
            TreeNode nnode = nodes.Add(wifi.DisplayName);
            nnode.Tag = wifi;
            return nnode;
        }

        private TreeNode[] GetNodesFor(Wifi wifi)
        {
            List<TreeNode> result = new List<TreeNode>();
            foreach (TreeNode nodeHW in tvTree.Nodes)
            {
                TreeNodeCollection nodes = nodeHW.Nodes;
                foreach (TreeNode node in nodes)
                    if (wifi.BSSID == ((Wifi)node.Tag).BSSID)
                        result.Add(node);
            }
            return result.ToArray();
        }

        private void PopulateTree()
        {
            tvTree.BeginUpdate();
            ArrayList nodesToDelete = new ArrayList(tvTree.Nodes);// Fill with all (discard found later)
            foreach (WifiDevice dev in WifiDevice.List())
            {
                TreeNode node = GetNodeFor(dev);
                bool wasEmpty = node.Nodes.Count == 0;
                nodesToDelete.Remove(node);
                Wifi[] wifis = dev.Networks;
                ArrayList disabledNetNodes = new ArrayList(node.Nodes);// Fill with all (discard found later)
                foreach (Wifi wifi in wifis)
                {
                    TreeNode nwnode = GetNodeFor(wifi, node.Nodes);
                    if (nwnode.Text != wifi.DisplayName)
                        nwnode.Text = wifi.DisplayName; // Update network name (for configuration changes)
                    int ico = wifi.Signal > 70 ? 1 : wifi.Signal > 35 ? 2 : 3;
                    nwnode.ImageIndex = nwnode.SelectedImageIndex = ico;
                    disabledNetNodes.Remove(nwnode);
                }
                foreach (TreeNode nwdel in disabledNetNodes)
                {
                    nwdel.ImageIndex = nwdel.SelectedImageIndex = 4;
                }
                if (wasEmpty && node.Nodes.Count > 0)
                    node.Expand();
            }
            // remove old
            foreach (TreeNode ndel in nodesToDelete)
                tvTree.Nodes.Remove(ndel);
            tvTree.EndUpdate();
        }

        #endregion

        private void ShowWifi(Wifi w)
        {
            pwinfo.Tag = w;
            if (w == null)
                pwinfo.Visible = false;
            else
            {
                WifiApi.HighlightBSSID = w.BSSID;
                lbInfo.Text = w.SSID;
                lbInfo2.Text = w.Active ? w.BSSID + ", Ch:" + w.Channel + ", Power:" + w.Signal : w.BSSID;
                pbSignal.Value = w.Active ? (int)w.Signal : 0;
                btColor.BackColor = w.Conf.Color;
                cbVisible.Checked = w.Conf.Visible;
                pwinfo.Visible = true;
            }
            scMain.Panel2.Invalidate();
        }

        private void UpdateNode(Wifi w)
        {
            if (w == null)
                return;
            TreeNode[] ns = GetNodesFor(w);
            foreach (TreeNode n in ns)
            {
                n.StateImageIndex = w.Conf.Visible ? -1 : 5;
            }
            scMain.Panel2.Invalidate();
        }

        private void WifiTimer_Tick(object sender, EventArgs e)
        {
            WifiApi.Snapshoot();
            PopulateTree();
            scMain.Panel2.Invalidate();
        }

        private void splitContainer1_Panel2_Paint(object sender, PaintEventArgs e)
        {
            WifiApi.Paint(e.Graphics, scMain.Panel2.ClientSize);
        }

        private void tvTree_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (tvTree.SelectedNode == null)
                return;
            ShowWifi(tvTree.SelectedNode.Tag as Wifi);
        }

        private void btColor_Click(object sender, EventArgs e)
        {
            Wifi w = pwinfo.Tag as Wifi;
            if (w == null)
                return;
            ColorDialog cd = new ColorDialog();
            cd.Color = w.Conf.Color;
            if (cd.ShowDialog() == DialogResult.OK)
            {
                w.Conf.Color = cd.Color;
                ShowWifi(w);
                UpdateNode(w);
            }
        }

        private void cbVisible_CheckedChanged(object sender, EventArgs e)
        {
            Wifi w = pwinfo.Tag as Wifi;
            if (w == null)
                return;
            w.Conf.Visible = cbVisible.Checked;
            ShowWifi(w);
            UpdateNode(w);
        }

        private void tvTree_DoubleClick(object sender, EventArgs e)
        {
            if (tvTree.SelectedNode == null)
                return;
            Wifi w = tvTree.SelectedNode.Tag as Wifi;
            if (w == null)
                return;
            w.Conf.Visible = !w.Conf.Visible;
            UpdateNode(w);
        }

        private void tvTree_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == ' ')
            {
                if (tvTree.SelectedNode == null)
                    return;
                Wifi w = tvTree.SelectedNode.Tag as Wifi;
                if (w == null)
                    return;
                w.Conf.Visible = !w.Conf.Visible;
                UpdateNode(w);
            }
        }

        private void tvTree_DrawNode(object sender, DrawTreeNodeEventArgs e)
        {
            if (imageListDevices.Images.Count == 0)
                return;
            if (e.Node.Tag is Wifi w)
            {
                bool focused = (e.State & TreeNodeStates.Focused) != 0;
                using (Brush color = new SolidBrush(w.Conf.Color))
                using (Brush bbg = new SolidBrush(focused ? SystemColors.Highlight : tvTree.BackColor))
                using (Brush bfont = new SolidBrush(focused ? SystemColors.HighlightText : tvTree.ForeColor))
                {
                    Font nodeFont = e.Node.NodeFont ?? tvTree.Font;
                    e.Graphics.FillRectangle(bbg, e.Bounds);
                    int x = e.Bounds.X + 10;
                    int y = e.Bounds.Y;
                    if (e.Node.StateImageIndex >= 0)
                        e.Graphics.DrawImage(imageListDevices.Images[e.Node.StateImageIndex], x, y + 8, 17, 17);
                    x += 8;
                    imageListDevices.Draw(e.Graphics, x, y, e.Node.ImageIndex);
                    x += 27;
                    y++;
                    e.Graphics.FillRectangle(color, new Rectangle(x, y, 7, e.Bounds.Height - 2));
                    x += 9;
                    e.Graphics.DrawString(e.Node.Text, nodeFont, bfont, x, y);
                    x += 5;
                    y += 13;
                    e.Graphics.DrawString($"{w.RangeName}, Ch: {w.Channel}, Power: {w.Signal}%", tagFont, Brushes.Gray, x, y);

                }
            }
            else
                e.DrawDefault = true;

        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("https://github.com/XWolfOverride/WifiScan");
        }

    }
}