Перейти к содержанию
    

Прошу помощи в написании простой тестовой программы

Здравствуйте!

 

Хочу сразу признаться - опыта не было в написании программ на VS (C++). Есть опыт в написании на C. Но по долгу службы приходится обучаться этому ремеслу. Летом в небольшие промежутки свободного времени проштудировала книжки предложенные здесь для прочтения - в голове сумбур. Для наведения порядка ... в моей голове и реального обучению, лучше начинать писать небольшую программу. Так, как рядом (на работе) спецов нет, хочу попросить вас, уважаемые форумчане, помочь в написании программы - примера. Я не прошу написать всю программу (хотя полный текст ее был более удобен для изучения и повторения), а хотя бы части, функциональные блоки программы. Мне будет удобно, изучая эти блоки, понять приемы визуального программирования и соответсвенно написать свою. Теперь к требованиям этой тестовой - учебной программе:

Программа или блоки программы дложны быть написаны нв Visual Studio желательно более старшей версии - 2010 (но не старше). Можно и в предыдущих вплоть до VC6.0. Гланое условие - без использования NET. После запуска программы, она должна работать (открыть порт COM1 со стандартной установкой: старт; 8бит; стоп скорость 9600 бод, если будет предварительный выбор порта с установкой параметров- то еще лучше) и принимать три байта: 1й байт всегда стартовая метка CA, второй - B1 отображается на панели светодиодов сменой картики светодиод зажен или нет, третий B2 отображается на графике ось ординат от 0 до 255. Ось абцисс - номер пакета от 0 до 255, при превышении номера пакета 255 - опять с нуля и стирается старый график. Программа так же должна уметь передавать по COM порту данные при нажатии кнопки send - два байта: первый - стартовый CA, второй - байт данных устанавливатся битовым полем Checkbox. При запуске программы должна открыться база SQL и внее должны записываться принимаемые данные соответственно по полям: N - номер пакета (long?), B1 байт данных (char), второй байт данных B2 (char). При выходе из программы база закрывается.

Из всего выше перечисленного хочется понять как работать:

1) Работа с COM портом. Прием и передача простых 2-х и 3-х байтовых пакетов.

2) Работа с базой данных SQL инициализация, открытие, запись (желательно чтение) полей, закрытие. Возможно что то я не учла.

3) Вывод форматированных данных в окно большим шрифтом (что то типа индикатора, дисплея).

4) Вывод бинарных данных в поле имитирующее светодиоды.

5) Опрос поля Checkbox (хотелось конечно, чтобы было поле выключателей OFF/ON).

6) Работа с Plot функцикей - вывод графика.

Дополнительно - этого нет выше:

7) Вывод принятых данных в виде лога (в скролинговое окно - забыла как оно точно называется) и в тектовый файл, который то же надо открыть или создать, если его нет, ну и закрыть после работы с ним.

 

Прошу, кто имеет немного свободного времени, помочь в написании этих блоков программы, желательно с небольшими комментариями. Пускай не сразу все, а по кусочкам.. Я думаю это многим поможет, не только мне, в написании своих первых программ на VS, да и не только.

Заранее Спасибо!

Далее в виде изображения требования к программе:

post-64146-1350000581_thumb.png

Изменено пользователем Alla_student

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну уж если так хочется на Visual C++ (на C# намного проще все)

 

Допустим класс CModem

CModem::CModem()
{
    m_hComm = INVALID_HANDLE_VALUE;
}

CModem::~CModem()
{
    UnInitialize();
}

BOOL CModem::Initialize(LPCTSTR lpCommPort)
{
    SECURITY_ATTRIBUTES sa;

    SECURITY_DESCRIPTOR sd;   

//--------------------------------------------------------------------

  if (IsWinNT())        // инициализация security для Windows NT
  {
    InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, true, NULL, false);
    sa.lpSecurityDescriptor = &sd;
  }

  else sa.lpSecurityDescriptor = NULL;

  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  sa.bInheritHandle = true;       // разрешаем наследование дескрипторов

//--------------------------------------------------------------------

    m_hComm = CreateFile(lpCommPort,
        GENERIC_READ | GENERIC_WRITE, 0, &sa, 
        OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

    if (m_hComm == INVALID_HANDLE_VALUE) 
    {
        
        CString strIntErrModem;
        
        strIntErrModem.Format(
            _T("%s %s"), 
            _T("Ошибка при создании указателя на "),
            lpCommPort);

        AfxMessageBox(strIntErrModem.GetBuffer(strIntErrModem.GetLength()),
            MB_OK | MB_ICONERROR );

        return FALSE; // fail to create

    }


    DCB dcb;

    GetCommState(m_hComm, &dcb);
    
    //BuildCommDCB(_T("baud=9600 parity=N data=8 stop=1"), &dcb);

    //BuildCommDCB("baud=19200 parity=N data=8 stop=1", &dcb);

    BuildCommDCB(
        _T("baud=1200 parity=N data=8 stop=1"),
        &dcb);

    dcb.fNull = false;

    SetCommState(m_hComm, &dcb);

    SetCommMask(m_hComm, EV_BREAK | EV_RXCHAR);

    EscapeCommFunction(m_hComm, CLRBREAK);

    //EscapeCommFunction(m_hComm, CLRDTR);

    PurgeComm(m_hComm, PURGE_TXABORT & PURGE_RXABORT);    

    return TRUE;
}

void CModem::UnInitialize()
{
    if (m_hComm != INVALID_HANDLE_VALUE)
    {
        EscapeCommFunction(m_hComm, CLRBREAK);//SETBREAK

        CloseHandle(m_hComm);

        m_hComm = INVALID_HANDLE_VALUE;
    }
}

BOOL CModem::IsWinNT()  //проверка запуска под WIN NT
{

    OSVERSIONINFO osv;

    osv.dwOSVersionInfoSize = sizeof(osv);

    GetVersionEx(&osv);

    return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);

}

 

кольцевой буфер для приема-передачи байт CBuffer

 

Buffer::CBuffer(int nLength, int nExtra)
{
    m_Length = nLength;

    m_Extra = nExtra;

    m_Head = m_Tail = 0;

    m_pBuffer = new CHAR[m_Length];
    
    if (IsWinNT())        // инициализация security для Windows NT
    {
    InitializeSecurityDescriptor(&sdBuffer,SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sdBuffer, true, NULL, false);
    saBuffer.lpSecurityDescriptor = &sdBuffer;
    }
    else saBuffer.lpSecurityDescriptor = NULL;

    saBuffer.nLength = sizeof(SECURITY_ATTRIBUTES);
    saBuffer.bInheritHandle = true;       //разрешаем наследование дескрипторов
      
    m_NotEmpty = new CEvent(FALSE, FALSE, NULL, &saBuffer);
    // объект "событие" изначально находится в состоянии "сброшен"                
    // объект "событие" с автоматическим сбрасыванием
}

CBuffer::~CBuffer()
{
    delete m_pBuffer;
}

BOOL CBuffer::ReadChar(CHAR& cChar)
{
    CSingleLock Lock(&m_Lock, TRUE);

    if (m_Tail == m_Head) return FALSE;

    cChar = m_pBuffer[m_Tail++];

    m_Tail %= m_Length;

    Lock.Unlock();

    return TRUE;
}

void CBuffer::WriteChar(CHAR cChar)
{

  CSingleLock Lock(&m_Lock, TRUE);

  m_pBuffer[m_Head++] = cChar;
  m_Head %= m_Length;

  // При необходимости размер буфера может быть увеличен

  if (m_Head == m_Tail)
  {

    CHAR *pBuffer = new CHAR[m_Length+m_Extra];

    memcpy(pBuffer, m_pBuffer, sizeof(CHAR) * m_Head);

    memcpy(pBuffer+m_Tail+m_Extra, m_pBuffer+m_Tail, 
        sizeof(CHAR) * (m_Length-m_Tail));

    m_Length += m_Extra;

    m_Tail += m_Extra;

    delete m_pBuffer;

    m_pBuffer = pBuffer;
  }

  // Разрешаем доступ к буферу до того, как просигнализируем
  // о поступлении нового символа, чтобы не потерять
  // ни одного такта процессора в случае, если после этого
  // сигнала процессор будет переключен на поток,
  // осуществляющий чтение, а доступ еще не будет разрешен

    Lock.Unlock();

    m_NotEmpty->SetEvent();
}

BOOL CBuffer::IsWinNT()  // проверка запуска под WIN NT
{
    OSVERSIONINFO osv;

    osv.dwOSVersionInfoSize = sizeof(osv);

    GetVersionEx(&osv);

    return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);

}

 

Создаем три потока

 

CWinThread *m_pOutThreadPort; // поток записи в последовательный порт

CWinThread *m_pInThreadPort; // поток чтения из последовательного порта

CWinThread *m_pDrawThreadPorе; // поток обработки принятых данных

 

ловим байты в потоке

 

DWORD InDataPort1(LPVOID lParam)
{
...

for (;;)
    {
        ResetEvent(o1.hEvent);

        if (!WaitCommEvent(pWnd->m_Port1.m_hComm, &dwEvtMask1, &o1))
        {
            if (WaitForMultipleObjects(2, Handles1, FALSE, INFINITE) ==
                WAIT_OBJECT_0+1) break;
        }

....

if (dwEvtMask1 & EV_RXCHAR)
        {        

            ClearCommError(pWnd->m_Port1.m_hComm, &dwError1, &csStat1);

            ResetEvent(o1.hEvent);

            if (!ReadFile(pWnd->m_Port1.m_hComm, szBuffer1, 
                csStat1.cbInQue, &dwBytes1, &o1))
            {
                if (WaitForMultipleObjects(2, Handles1, FALSE, INFINITE) ==
                    WAIT_OBJECT_0+1)
                    break;
            }


        
            for (UINT i1 = 0; i1 < csStat1.cbInQue; i1++)            
                pWnd->m_Port1.m_InBuffer.WriteChar(szBuffer1[i1]);            


            //Sleep(1);

        }

 

и так далее

 

в качестве графика рекомендую ZedGraph

если в устройстве присутствует MODBUS- так сразу NMODBUS

 

так же почитать

http://rln.nnov.ru/index.php?ind=reviews&a...iew&iden=44

 

на MSDN

 

http://msdn.microsoft.com/en-us/library/ff802693.aspx

 

 

 

 

Изменено пользователем fox1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Жуть.

Пляски с SecurityDescriptor не нужны - вы же не собираетесь ваши открытые порты и созданные события отдавать на сторону. Дублировать IsWinNT() в каждом классе нет никакой необходимости. Чтение из порта видимо запущенно в отдельном потоке. В таком случае Overlapped чтение вообще не нужно - пусть блокирует поток.

Кольцевой буфер лучше сделать на std::deque<char>, а не заниматься изобретением велосипедов.

 

К ТС - по поводу VS и NET. Если вам нужен GUI и не нужен .NET, то имеет смысл посмотреть в какую нибудь другую сторону - весь майнстрим у VS по поводу GUI направлен на .NET, все остальное умерло (у них). Либо смотрите в сторону Qt, либо какого нибудь Builder'а

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Жуть.

Пляски с SecurityDescriptor не нужны - вы же не собираетесь ваши открытые порты и созданные события отдавать на сторону. Дублировать IsWinNT() в каждом классе нет никакой необходимости. Чтение из порта видимо запущенно в отдельном потоке. В таком случае Overlapped чтение вообще не нужно - пусть блокирует поток.

Кольцевой буфер лучше сделать на std::deque<char>, а не заниматься изобретением велосипедов.

А вы бы не могли тогда пожалуйста прмеры привести, а то так меня совсем запутали :(

 

К ТС - по поводу VS и NET. Если вам нужен GUI и не нужен .NET, то имеет смысл посмотреть в какую нибудь другую сторону - весь майнстрим у VS по поводу GUI направлен на .NET, все остальное умерло (у них). Либо смотрите в сторону Qt, либо какого нибудь Builder'а

 

Я понимаю вас, что надо сменить компилятор и перейти на Builder или Qt. Но в то же время я вижу, что пишут программы под VS2010 с окнами и всеми фитчами описанными мной в топике без использования NET. Вопрос - как они это делают? Используют VS6.0 а потом проект переводят под VS2010? Используют MFC и не используют формы VS2010 (если вы говорите, что сразу это потянет "весь майнстрим у VS по поводу GUI направлен на .NET"?

 

Может все таки есть способ при написании программы с NET, этот весь весь майнстрим делать в виде библиотек dll-ок и вся эта "парадигма современного Microsoft" жила в одном каталоге с программой?

 

Ну уж если так хочется на Visual C++ (на C# намного проще все)

...

Спасибо.

Я понимаю разницу в программировании C++ без NET и C# , я прошу вас, если можно, привести два (желательно подробных) примера простых программ (полностью текст) открытия основного окна и в нем вывод в дополнительное окно значения переменной short или long как на рисунке:

post-64146-1350038667_thumb.png

Изменено пользователем Alla_student

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

SecurityDescriptor обязателен начиная с Windows XP.

Насчет дублирования IsWinNT() в каждом классе - вопрос спорный, можно конечно отдельную процедуру завести и глобальные флаги, но считаю это дело вкуса.

При использовании контейнера std::deque<char> надо синхронизировать доступ к этому контейнеру из потоков - проще свой завести, буфер стандартный, ни каких велосипедов.

На Builder переходить ... тоже вопрос спорный, многозадачность в нем своеобразная.

Последнии версии VS очень сильно ориентированы на FrameWork, но и MFC ни кто не отменял.

 

Синхронный и асинхронный ввод - вывод (I/O)

http://www.vsokovikov.narod.ru/New_MSDN_AP...asynchro_io.htm

Изменено пользователем fox1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

SecurityDescriptor обязателен начиная с Windows XP.

Насчет дублирования IsWinNT() в каждом классе - вопрос спорный, можно конечно отдельную процедуру завести и глобальные флаги, но считаю это дело вкуса.

При использовании контейнера std::deque<char> надо синхронизировать доступ к этому контейнеру из потоков - проще свой завести, буфер стандартный, ни каких велосипедов.

На Builder переходить ... тоже вопрос спорный, многозадачность в нем своеобразная.

Последнии версии VS очень сильно ориентированы на FrameWork, но и MFC ни кто не отменял.

 

Еще раз спасибо. Хотелось конечно чтобы здесь без "войн" - надо делать так, нет не так, а то у меня и без этого "крыша едет".

Я понимаю разницу в программировании C++ без NET и C# , я прошу вас, если можно, привести два (желательно подробных) примера простых программ (полностью текст) открытия основного окна и в нем вывод в дополнительное окно значения переменной short или long как на рисунке в предыдущем моем сообщении.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ок :)))

 

Начните с создания приложения Visual С++ MFC на основе диалога

 

http://msdn.microsoft.com/ru-ru/library/9e...v=vs.90%29.aspx

 

с использованием ActiveX

 

можно использовать activex serialport control и не заморачиваться

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

SecurityDescriptor обязателен начиная с Windows XP.
С чего бы это вдруг?

MSDN - CreateFile, описание параметра lpSecurityAttributes :

lpSecurityAttributes [in, optional]

 

A pointer to a SECURITY_ATTRIBUTES structure that contains two separate but related data members: an optional security descriptor, and a Boolean value that determines whether the returned handle can be inherited by child processes.

 

This parameter can be NULL.

 

If this parameter is NULL, the handle returned by CreateFile cannot be inherited by any child processes the application may create and the file or device associated with the returned handle gets a default security descriptor.

 

Насчет дублирования IsWinNT() в каждом классе - вопрос спорный, можно конечно отдельную процедуру завести и глобальные флаги, но считаю это дело вкуса.
Это не 'дело вкуса'. У вас N штук совершенно идентичных куска кода, которые к тому же совершенно не имеют отношения к тем классам, где они объявлены (в частности это видно по тому, что они не используют никаких членов классов, где они объявлены).

Нужно было просто сделать обычную процедуру (не в классе). Если С++ ООП язык, это еще не значит, что в ОО программах нельзя использовать обычные функции

 

При использовании контейнера std::deque<char> надо синхронизировать доступ к этому контейнеру из потоков - проще свой завести, буфер стандартный, ни каких велосипедов.
Да ну? Давайте сравним:

void CBuffer::WriteChar(CHAR cChar)
{

  CSingleLock Lock(&m_Lock, TRUE);

  m_pBuffer.push_back(cChar);

  // Разрешаем доступ к буферу до того, как просигнализируем
  // о поступлении нового символа, чтобы не потерять
  // ни одного такта процессора в случае, если после этого
  // сигнала процессор будет переключен на поток,
  // осуществляющий чтение, а доступ еще не будет разрешен

    Lock.Unlock();

    m_NotEmpty->SetEvent();
}

Несколько короче, не правда ли?

 

На Builder переходить ... тоже вопрос спорный, многозадачность в нем своеобразная.
Обычная, как везде в Windows. Но сам Bulder действительно вещь своеобразная (особенно последние версии) :cranky:

 

Последнии версии VS очень сильно ориентированы на FrameWork, но и MFC ни кто не отменял.
Это да, но изучать с нуля умершую архитектуру я бы ТС не посоветовал :rolleyes:

 

Синхронный и асинхронный ввод - вывод (I/O)

Угу, только асинхронный тут не нужен :biggrin:

 

я прошу вас, если можно, привести два (желательно подробных) примера простых программ (полностью текст) открытия основного окна и в нем вывод в дополнительное окно значения переменной short или long как на рисунке в предыдущем моем сообщении.
Если в вас будет Builder или Qt или WindowsForm с С#, то это пара строк. На MFC это займет пару сотен строк. На голом WinAPI - пару тысяч. Вам на чем примеры приводить? :rolleyes:

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

SecurityDescriptor обязателен начиная с Windows XP и Windows NT.

Попробуйте в XP SecurityDescriptor = NULL :)))) и работать перестанет.

Это код программы для связи с приборами я давно уже писал, начинал еще с Win98 - так в NT уже не работало пока не проинициализировал

SECURITY_ATTRIBUTES sa;

SECURITY_DESCRIPTOR sd;

не зря там введен анализ на ОСЬ :))))

можете проверить :)))

в MSDN явно про это ни где не говориться :))))

 

вот хороший примет MTTY

 

http://read.pudn.com/downloads8/sourcecode...1/MTTTY.C__.htm

Изменено пользователем fox1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это код программы для связи с приборами я давно уже писал, начинал еще с Win98 - так в NT уже не работало пока не проинициализировал

SECURITY_ATTRIBUTES sa;

SECURITY_DESCRIPTOR sd;

не зря там введен анализ на ОСЬ :))))

можете проверить :)))

Вы что-то путаете, нижепреведённый код прекрасно работает под XP (и под 7-ой будет работать), у Вас из-за чего другого не работало ;)

		//
	hCommPort = CreateFile(
		"COM1"
		, GENERIC_READ | GENERIC_WRITE
		, 0
		, 0
		, OPEN_EXISTING
		, 0
		, 0
		);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Угу, только асинхронный тут не нужен :biggrin:

Вообще то мы испльзуем асинхронный обмен по RS232!

 

Как автор топика, я хочу сделать вам замечание - я просила привести примеры, а не продолжать с апонентом кидаться "заплатками" кода, сложного для моего понимания.

 

Если в вас будет Builder или Qt или WindowsForm с С#, то это пара строк. На MFC это займет пару сотен строк. На голом WinAPI - пару тысяч. Вам на чем примеры приводить? :rolleyes:

 

Я бы попросила вас здесь не умничить на счет WinAPI, а привести примеры для C# и MFC - я об этом так выше и писала, если вы читаете внимательно весь топик. Если пару сотен строкдля вас сложно привести, а я думаю есть у вас какие нибудь наработки, а не все с нуля, то не приводите здесь - я писала выше, если вам не сложно и есть время.

 

По поводу QT и Bulder - не могу я их испльзовать, раньше об этом сообщала.

 

Вы что-то путаете, нижепреведённый код прекрасно работает под XP (и под 7-ой будет работать), у Вас из-за чего другого не работало ;)

...

 

Ко всем: Вы продолжаете извините мериться ... , а на мои ключевые вопросы не отвечаете, сожалею, но надеюсь ;)

Изменено пользователем Alla_student

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы что-то путаете, нижепреведённый код прекрасно работает под XP (и под 7-ой будет работать), у Вас из-за чего другого не работало ;)

Тоже так думаю - путает.

Под XP и 9x подключался так:

PortHandle:=CreateFile(PChar(p_sring), GENERIC_READ  or  GENERIC_WRITE,0,nil,OPEN_EXISTING,0,0);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот так выглядела моя программа, написанная по похожему как у Вас ТЗ. Только без базы.

MFC.

Интересуют исходники?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот так выглядела моя программа, написанная по похожему как у Вас ТЗ. Только без базы.

MFC.

Интересуют исходники?

Да, конечно, вы еще спрашиваете ;)

 

Но я вас помучаю после ;) В хорошем смысле

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообще то мы испльзуем асинхронный обмен по RS232!
Это никоим образом не мешает использовать синхронные вызовы ReadFile и WriteFile для ассинхронного обмена по RS232

 

Как автор топика, я хочу сделать вам замечание - я просила привести примеры, а не продолжать с апонентом кидаться "заплатками" кода, сложного для моего понимания.
Вам fox1 привел пример, правда он процентов на 80% избыточен и переусложнен, о чем я и написал

 

Я бы попросила вас здесь не умничить на счет WinAPI, а привести примеры для C# и MFC - я об этом так выше и писала, если вы читаете внимательно весь топик.
C# - это .NET, а он вас не устраивает, как вы сами писали. На MFC попросите fox1 - он похоже на нем писал (я не писал, и не собираюсь)

 

Если пару сотен строкдля вас сложно привести, а я думаю есть у вас какие нибудь наработки, а не все с нуля, то не приводите здесь - я писала выше, если вам не сложно и есть время.
Ваша задача - это не 'пара сотен срок кода', а где то ближе к десятку тысяч. GUI часть очень сильно зависит от библиотеки, о чем я вам и написал

 

По поводу QT и Bulder - не могу я их испльзовать, раньше об этом сообщала.
Qt - это библиотека, в том числе и под VS (в том числе и 2010), так что не вижу препядствий в ее использовании

 

Ко всем: Вы продолжаете извините мериться ... ,
Вообще то я пытаюсь уберечь вас от того, что fox1 написал - это не самый лучший вариант ответа на ваш вопрос :rolleyes:

а на мои ключевые вопросы не отвечаете, сожалею, но надеюсь ;)

Вы задали слишком общий вопрос - на него невозможно ответить. Конкретизируйте вопрос - получите ответ

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...