Posted
Filed under .NET/C#
몇 달만에 포스팅 인지 모르겠습니다.....
이전 포스팅에 USB 장치 인식시 자동으로 Comport를 찾아주는 소스를... (윈폼)
올려 드렸습니다..

이번 포스팅은 WPF에서 USB인식시 Comport를 찾아주는 소스 입니다.

using System;
using System.Windows;
using System.IO.Ports;
using System.Windows.Threading;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace Wpf_Serial
{
    /// 
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// 
    public partial class MainWindow : Window
    {
        decimal LineNumber = 1;

        SerialPort SP = new SerialPort();

        public MainWindow()
        {
            InitializeComponent();
        }

        IntPtr WndProc(IntPtr hWnd, int nMsg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            UInt32 WM_DEVICECHANGE = 0x0219;
            UInt32 DBT_DEVTUP_VOLUME = 0x02;
            UInt32 DBT_DEVICEARRIVAL = 0x8000;
            UInt32 DBT_DEVICEREMOVECOMPLETE = 0x8004;

            //디바이스 연결시
            if ((nMsg == WM_DEVICECHANGE) && (wParam.ToInt32() == DBT_DEVICEARRIVAL))
            {
                int devType = Marshal.ReadInt32(lParam, 4);

                if (devType == DBT_DEVTUP_VOLUME)
                {
                    GetSerialPort();
                }
            }

            //디바이스 연결 해제시...
            if((nMsg == WM_DEVICECHANGE) && (wParam.ToInt32() == DBT_DEVICEREMOVECOMPLETE))
            {
                int devType = Marshal.ReadInt32(lParam,4);
                if(devType == DBT_DEVTUP_VOLUME)
                {
                    GetSerialPort();
                }
            }

            return IntPtr.Zero;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            WindowInteropHelper helper = new WindowInteropHelper(this);
            HwndSource source = HwndSource.FromHwnd(helper.Handle);
            source.AddHook(new HwndSourceHook(this.WndProc));

            SP.DataReceived += new SerialDataReceivedEventHandler(SP_DataReceived);
        }

        private void SP_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
            {
                string str = SP.ReadLine();
                textBox1.AppendText("[" + LineNumber++.ToString() + "] : " + str);
                textBox1.ScrollToEnd();
            }));
        }

        private void btnPortSearch_Click(object sender, RoutedEventArgs e)
        {
            GetSerialPort();
        }

        private void GetSerialPort()
        {
            lst_ComPort.Items.Clear();
            foreach (string comport in SerialPort.GetPortNames())
            {
                lst_ComPort.Items.Add(comport);
            }

            if (lst_ComPort.Items.Count <= 0)
            {
                lst_ComPort.Items.Add("찾을 수 없음");
            }
        }

        private void btnPortOpen_Click(object sender, RoutedEventArgs e)
        {
            if (SP.IsOpen)
            {

            }
            else
            {
                SP.Open();
            }
        }

        private void lst_ComPort_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            SP.PortName = lst_ComPort.SelectedItem.ToString();
        }

        private void btnPortClose_Click(object sender, RoutedEventArgs e)
        {
            if (SP.IsOpen)
            {
                SP.Close();
            }
        }
    }
}
음 WPF에서 요 코드를 사용하기 전에 WindowsBase 항목을 참조를 해주어야 했던걸로 기억이 납니다..
2012/08/20 14:44 2012/08/20 14:44
Posted
Filed under .NET/C#
요즘 대충 시리얼 통신을 USB를 이용해서 하는 경우가 더러 있는거 같더라구요.....
저도 GPS 모듈 가지고 놀때 USB를 통하여 시리얼 통신을 하곤 하였는데.
그래서 USB장치 인식 하는 법을 응용해서 USB가 인식이 되었을때 자동으로 COM Port를 찾도록 하는 방법을 알려 드리겠습니다.

아래 화면은 대충의 결과물.....
예전에는 버튼을 눌러서 새로고침을 시도 했는데... 지금은
USB인식을 통해 바로 검색하도록 하였습니다..

※인식하는데 다소 3~4초 가량 걸리더라구요
사용자 삽입 이미지

public partial class Form1 : Form
    {
        SerialPort sp = new SerialPort();

        public Form1()
        {
            InitializeComponent();
            GetSerialPort();
        }

        protected override void WndProc(ref Message m)
        {
            UInt32 WM_DEVICECHANGE = 0x0219;
            UInt32 DBT_DEVTUP_VOLUME = 0x02;
            UInt32 DBT_DEVICEARRIVAL = 0x8000;
            UInt32 DBT_DEVICEREMOVECOMPLETE = 0x8004;

            if ((m.Msg == WM_DEVICECHANGE) && (m.WParam.ToInt32() == DBT_DEVICEARRIVAL))//디바이스 연결
            {
                //int m_Count = 0;
                int devType = Marshal.ReadInt32(m.LParam, 4);

                if (devType == DBT_DEVTUP_VOLUME)
                {
                    GetSerialPort();
                }
            }

            if((m.Msg == WM_DEVICECHANGE) &&(m.WParam.ToInt32()  == DBT_DEVICEREMOVECOMPLETE))  //디바이스 연결 해제
            {
                int devType = Marshal.ReadInt32(m.LParam, 4);
                if (devType == DBT_DEVTUP_VOLUME)
                {
                    GetSerialPort();
                }
            }

            base.WndProc(ref m);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                GetSerialPort();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void GetSerialPort()
        {
            listBox1.Items.Clear();

            try
            {
                foreach (string str in SerialPort.GetPortNames())
                {
                    listBox1.Items.Add(str);
                }
                if (listBox1.Items.Count <= 0)
                {
                    listBox1.Items.Add("연결 장치 없음");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
연결/연결해제가 되면 이를 감지하여 시리얼 포트 장치를 재 검색해주도록 하고 있습니다. 예제는 소스 코드를 가지고 응용해 보시면 될듯 합니다...
2012/04/06 16:28 2012/04/06 16:28