Четверг, Сентябрь 24, 2020

ComPort-CFrameWnd

#pragma once
#include "serialport.h"
#include "afxext.h"
#include "atltypes.h"


// Frame frame

class Frame : public CFrameWnd
{
    DECLARE_DYNCREATE(Frame)
public:
    Frame();           // protected constructor used by dynamic creation
    virtual ~Frame();
protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
private:
    CStatusBar m_wndStatusBar;
    CMenu m_wndMenu;
public:
    afx_msg void OnFileExit();
    afx_msg void OnPaint();
public:
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    afx_msg void OnSetFocus(CWnd* pOldWnd);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
protected:
    
    boolean CaretCreated;
    CPoint  CaretPosition;
    
public:
    afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
    CMetaFileDC* pMetaFileDC;
    afx_msg void OnStart();
protected:
    afx_msg LRESULT OnMess(WPARAM wParam, LPARAM lParam);
public:
    afx_msg void OnStop();
    afx_msg void OnClose();
    CList<CString> mList;
    afx_msg void OnClear();
    int mHowChar;
};
UINT __cdecl ReadSerial(LPVOID pParam);
char*   HexToASCII(char* sour, char* dest, int len);



// Frame.cpp : implementation file
//

#include "stdafx.h"
#include "Frame.h"
#include "resource.h"
#include "serialport.h"
char        buf[14]="\0";
char        dest[30]="\0";
CString     data="";
CSerialPort port;
int         x=0;
int         y=0;
boolean StartStopThread=false;

// Frame

IMPLEMENT_DYNCREATE(Frame, CFrameWnd)
Frame::Frame()
: mHowChar(0)
{
    Create(NULL,"FT232",WS_OVERLAPPEDWINDOW,rectDefault,
        NULL,NULL);    // Создать окно программы
    CaretCreated=false;
}

Frame::~Frame()
{
}


BEGIN_MESSAGE_MAP(Frame, CFrameWnd)
    ON_WM_CREATE()
    ON_COMMAND(ID_FILE_EXIT, &Frame::OnFileExit)
    ON_WM_PAINT()
    ON_WM_KILLFOCUS()
    ON_WM_SETFOCUS()
    ON_WM_LBUTTONDOWN()
    ON_WM_CHAR()
    ON_COMMAND(ID_TEST, &Frame::OnStart)
    ON_MESSAGE(MESS, &Frame::OnMess)
    ON_COMMAND(ID_STOP, &Frame::OnStop)
    ON_WM_CLOSE()
    ON_COMMAND(ID_CLEAR, &Frame::OnClear)
END_MESSAGE_MAP()


// Frame message handlers


int Frame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    m_wndStatusBar.Create(this);
    m_wndMenu.LoadMenu(IDR_MAIN_MENU);    // Загрузить меню из файла ресурса
    SetMenu(&m_wndMenu);                // Установить меню
    return 0;
}
char* HexToASCII(char* sour, char* dest, int len)
{
    int i;
    char tmp;
    int j=0;
    for(i=0;i<len;i++){
        tmp=((sour[i]>>4)&0x0f);
        if(tmp<=9){
            dest[j]=tmp+0x30;
        }
        else if(tmp>=0x0A && tmp<=0x0F){
            dest[j]=tmp+0x37;
        }
        j++;
        tmp=sour[i];
        tmp=tmp &= 0x0f;
        if(tmp<=9){
            dest[j]=tmp+0x30;
        }
        else if(tmp>=0x0A && tmp<=0x0F){
            dest[j]=tmp+0x37;
        }
        j++;
    }
    dest[j]=0;
    return dest;
}

void Frame::OnFileExit()
{
    StartStopThread=false;
    while(port.IsOpen());
    DestroyWindow();                   // Уничтожить окно
}


void Frame::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    if(!CaretCreated)
    {
        TEXTMETRIC textmetric;
        dc.GetTextMetrics(&textmetric);
        CreateSolidCaret(textmetric.tmAveCharWidth,textmetric.tmHeight);
        CaretPosition.x=CaretPosition.y=0;
        SetCaretPos(CaretPosition);
        CaretCreated=true;
    }
    
    CRect rect;
    GetWindowRect(rect);

    
    POSITION pos = mList.GetHeadPosition();
    if(pos)
    {
        for(int i=0;i<mList.GetSize();i++)
        {
            dc.TextOutA(x,y,mList.GetNext(pos));
            y+=16;
        }
        y=0;
    }
    HideCaret();
    CSize size=dc.GetTextExtent(data);
    CaretPosition.x=x+size.cx;
    CaretPosition.y=y;
    SetCaretPos(CaretPosition);
    ShowCaret();
}


void Frame::OnKillFocus(CWnd* pNewWnd)
{
    CFrameWnd::OnKillFocus(pNewWnd);
    HideCaret();
}


void Frame::OnSetFocus(CWnd* pOldWnd)
{
    CFrameWnd::OnSetFocus(pOldWnd);
    ShowCaret();
}


void Frame::OnLButtonDown(UINT nFlags, CPoint point)
{
    x=point.x;
    y=point.y;
    data.Empty();
    Invalidate();
    CFrameWnd::OnLButtonDown(nFlags, point);
}


void Frame::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    data+=(char)nChar;
    Invalidate();
    
    CFrameWnd::OnChar(nChar, nRepCnt, nFlags);
}


void Frame::OnStart()
{
    try
    {
        //Пробуем открыть порт для асинхронной передачи
        port.Open(2, 460800, CSerialPort::NoParity, 8, CSerialPort::OneStopBit, CSerialPort::NoFlowControl, TRUE);
        data="Устройство найдено...";
        mList.AddTail(data);
        Invalidate();
        //Флаг в проц для while()
        StartStopThread=true;
        //Для того, чтобы поток мог передать сообщение ему нужно знать HWND.
        HWND hWnd=GetSafeHwnd();
        //передадим ее в параметрах.
        AfxBeginThread(ReadSerial, hWnd);
    }
    catch (CSerialException* pEx)
    {
        AfxMessageBox("Не удалось найти ComPort");
        pEx->Delete();
    }
}

//Процесс чтения байтов из компорта
UINT ReadSerial(LPVOID pParam)
{
    //Событие
    CEvent event(FALSE, TRUE);
    //объявление асинхронной структуры
    OVERLAPPED overlapped;
    //чистим структуру
    ZeroMemory(&overlapped, sizeof(OVERLAPPED));
    //приладим событие
    overlapped.hEvent = event;
    //бесконечный цикл
    while(StartStopThread)
    {
        //асинхронное чтение порта
        if (!port.Read(buf, 13, overlapped))
        {    
            //сколько байт было принято
            DWORD dwBytesRead;
            //если нет передачи по компорту ждем минуту
            if (WaitForSingleObject(event, 10000) == WAIT_OBJECT_0)
            {
                //если всеже передача началась
                port.GetOverlappedResult(overlapped, dwBytesRead, FALSE);
                data="Data was read from the serial port";
                //Обновим окно
                ::PostMessage(HWND(pParam),MESS,0,0);
            }
            else
            {
                //передача за минуту не началась
                data="Нет данных ... попробуй еще раз !";
                //обновим окно
                ::PostMessage(HWND(pParam),MESS,0,0);
                //закрываем порт
                if(port.IsOpen())
                {
                    port.Close();
                }
                //останавливаем процесс
                return 1;
            }
        }
        //Преобразуем в строку полученные данные
        HexToASCII(buf,dest,13);
        //Скопируем в CString
        data=dest;
    }
    //Закрываем порт
    if(port.IsOpen())
    {
        port.Close();
    }
    // Terminate the thread
   ::AfxEndThread(0, FALSE);
    return 0;
}

//Свое сообщение из процесса ReadSerial сработало,обновим данные.
afx_msg LRESULT Frame::OnMess(WPARAM wParam, LPARAM lParam)
{
    mList.AddTail(data);
    Invalidate();
    return 0;
}


void Frame::OnStop()
{
    StartStopThread=false;
    Sleep(1000);
    //Закрываем порт
    if(port.IsOpen())
    {
        port.Close();
    }
}


void Frame::OnClose()
{
    StartStopThread=false;
    Sleep(1000);
    //Закрываем порт
    if(port.IsOpen())
    {
        port.Close();
    }
    CFrameWnd::OnClose();
}


void Frame::OnClear()
{
    mList.RemoveAll();
    Invalidate();
}


Back to Top