На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
Дорогие друзья! Поздравляем вас с днём Победы!
msm.ru
! Правила раздела Visual C++ / MFC / WTL (далее Раздела)
1) На Раздел распространяются все Правила Форума.
2) Перед тем, как создать новый топик, убедитесь, что Вы читали Правила создания тем в Разделе.
3) Вопросы, не связанные с программированием (настройки MS Visual Studio, книги, библиотеки и т.д.),
обсуждаются в разделе C/C++: Прочее
4) Вопросы разработки .NET (Windows Form, C++/CLI и т.п.) приложений на Visual C++/C# обсуждаются в разделе .NET.
5) Нарушение Правил может повлечь наказание со стороны модераторов.

Полезные ссылки:
user posted image FAQ Раздела user posted image Обновления для FAQ Раздела user posted image Поиск по Разделу user posted image MSDN Library Online
Модераторы: ElcnU
Страницы: (8) « Первая ... 3 4 [5] 6 7 ... Последняя » все  ( Перейти к последнему сообщению )  
> Visual Studio 2008 + COM Port
    Спасибо. Работает. Сделал так:
    ExpandedWrap disabled
          for (int i = 0; i < btr; i++)
          {
              temp_str.Format(_T(" %X"), bufrd[i]);
              stroka = stroka + temp_str + ' ';
          }
       
          CWnd* pWnd = CWnd::FromHandle((HWND)lpParam);
          CEdit* pEdit = (CEdit*)pWnd->GetDlgItem(IDC_EDIT1);
          pEdit->SetWindowText(stroka);

    Выводит данные так
    Прикреплённая картинка
    Прикреплённая картинка

    В билдере так
    Прикреплённая картинка
    Прикреплённая картинка

    В MFC некоторые нюансы
    - не прописывает один 0 в HEX числе
    - очевидно из-за построчного обновления пропускаются первые несколько данных
    Как можно устранить эти нюансы?
    Сообщение отредактировано: Acvarif -
      Цитата Acvarif @
      В MFC некоторые нюансы
      - не прописывает один 0 в HEX числе

      Это ни к MFC, ни к Билдеру отношения не имеет.
      Это форматный вывод в "С".
      Попробуй так:
      ExpandedWrap disabled
        temp_str.Format(_T(" %02X"), bufrd[i]);

      Или даже так:
      ExpandedWrap disabled
        TCHAR buf[128]; _sntprintf_s(buf,ARRAYSIZE(buf),_TRUNCATE,_T(" %02X"),bufrd[i]);

      Почитай про printf/sprintf.
      тут, например
        Да. Зарапортовался с форматированием. Спасибо.
        В билдере было так
        ExpandedWrap disabled
          stroka = stroka + IntToHex(bufrd[i], 2) + ' ';

        Все же остался один непонятный нюанс - Похоже каждая новая строка записывается на место старой. Все выводится в одну едиственную строку. Как с этим бороться?
        Сообщение отредактировано: Acvarif -
          Цитата Acvarif @
          Все же остался один непонятный нюанс - Похоже каждая новая строка записывается на место старой. Все выводится в одну едиственную строку. Как с этим бороться?

          Эти "технологии" я тебе уже показывал:
          www.ya.ru, ищем "CEdit MFC" и находим описание
          тут.
          Цитата

          ...
          CEdit наследует значительные возможности из CWnd. Для установки и извлечения текста из объекта CEdit, используйте функции-члены SetWindowText и GetWindowTextCWnd, устанавливающие или получающие все содержимое элемента управления "Поле ввода", даже если многострочный элемент управления. Линии многополосном текста в элементе управления разделены последовательности символов "\r\n". Кроме того, если элемент управления "Поле ввода" многополосн, получение и установка часть текста элемента управления путем вызова функции-члены GetLine, SetSel, GetSel и ReplaceSelCEdit.
          ...
          Сообщение отредактировано: ЫукпШ -
            Эта ссылка у меня открыта. Но всеравно не врубаюсь.
            Цитата
            Линии многополосном текста в элементе управления разделены последовательности символов "\r\n".

            Это что означает? На практике получается, что каждый новый вызов кода
            ExpandedWrap disabled
                  // Перенос буфера в строку.
                  for (DWORD i = 0; i < btr; i++)
                  {
                      temp_str.Format(_T(" %02X"), bufrd[i]);
                      stroka = stroka + temp_str + ' ';
                  }
               
                  CWnd* pWnd = CWnd::FromHandle((HWND)lpParam);
                  CEdit* pEdit = (CEdit*)pWnd->GetDlgItem(IDC_EDIT1);
                  pEdit->SetWindowText(stroka);

            стирает предыдущую строку и печатает новую на ее место.
            Что в коде нужно добавить, отнять, изменить, чтобы просто каждый новый его вызов печатал строку с новой строки?
              Цитата Acvarif @
              Эта ссылка у меня открыта. Но всеравно не врубаюсь.

              я не использую MFC.
              Но судя по этому описанию - как-то так:
              ExpandedWrap disabled
                // ...
                for (DWORD i = 0; i < btr; i++)
                {
                 temp_str.Format(_T(" %02X"), bufrd[i]);
                 stroka = stroka + temp_str + ' ';
                }
                stroka += "\r\n";
                //...
                Спасибо. Мысль неплохая.
                Но все оказалось круто закручено. Итак понятно, что каждое выполнение кода
                ExpandedWrap disabled
                  CString stroka, temp_str;
                  // Перенос буфера в строку.
                      for (DWORD i = 0; i < btr; i++)
                      {
                          temp_str.Format(_T(" %02X"), bufrd[i]);
                          stroka = stroka + temp_str + ' ';
                      }
                   
                      CWnd* pWnd = CWnd::FromHandle((HWND)lpParam);
                      CEdit* pEdit = (CEdit*)pWnd->GetDlgItem(IDC_EDIT1);
                      pEdit->SetWindowText(stroka);

                приводит к новому выводу строки в Edit Control
                Это значит, что если непрерывный пакет данных в буфере приемника COM будет появляться с некоторыми временными разрывами то это уже будет не непрерывный пакет данных и функция ReadPrinting(btr, lpParam); вывода данных в Edit Control (так какраз и выполняется вышеприведенный код) будет вызываться многократно. Все заложено в функции потока чтения
                //---------------------------------------------------------------------------
                ExpandedWrap disabled
                  // Поток чтения
                   
                  DWORD WINAPI ReadThread( LPVOID lpParam )
                  {
                    // структура текущего состояния порта,
                    // используется для определения количества принятых в порт байт
                    COMSTAT comstat;
                    // переменная temp используется в качестве заглушки
                    DWORD btr, temp, mask, signal;
                    // создать сигнальный объект-событие для асинхронных операций
                    overlapped.hEvent = CreateEvent(NULL, true, true, NULL);
                    // установить маску на срабатывание по событию приёма байта в порт
                    SetCommMask(COMport, EV_RXCHAR);
                    // пока поток не будет прерван, выполняем цикл
                    while(1)
                    {
                      //ожидать события приёма байта (это и есть перекрываемая операция)
                      WaitCommEvent(COMport, &mask, &overlapped);
                      //приостановить поток до прихода байта
                      signal = WaitForSingleObject(overlapped.hEvent, INFINITE);
                      //если событие прихода байта произошло
                      if(signal == WAIT_OBJECT_0)
                      {
                        //проверяем, успешно ли завершилась перекрываемая операция WaitCommEvent
                        if(GetOverlappedResult(COMport, &overlapped, &temp, true))
                        {
                          //если произошло именно событие прихода байта
                          if((mask & EV_RXCHAR)!=0)
                          {
                      ::Sleep(100);
                            // нужно заполнить структуру COMSTAT
                            ClearCommError(COMport, &temp, &comstat);
                            // и получить из неё количество принятых байтов
                            btr = comstat.cbInQue;
                            // если действительно есть байты для чтения
                            if(btr)
                            {
                              // прочитать байты из порта в буфер программы
                              ReadFile(COMport, bufrd, btr, &temp, &overlapped);
                              // вызываем функцию для вывода данных на экран
                              ReadPrinting(btr, lpParam);
                            }
                          }
                        }
                      }
                    Sleep(1);
                    }
                    return 1;
                  }

                Собственно, чтобы избежать повторений нужно или задержать вход в if(btr) или CString stroka, temp_str; сделать глобальными, чтобы очищать их как-то, когда в Edit Control отобразится нужное количество принятых данных.
                Пока помогла не вдаваться в такие дебри небольшая задержка
                ExpandedWrap disabled
                  if((mask & EV_RXCHAR)!=0)
                          {
                      ::Sleep(100);

                Теперь вход в
                ExpandedWrap disabled
                  if(btr)
                            {

                осуществляется один раз при непрерывном пакете данных на COM (порядка 800 байт с перидом в 1 сек) Функция ReadPrinting(btr, lpParam); выполняется один раз - окно Edit Control отображает корректно весь пакет принятых данных.
                Если у кого есть по этому поводу еще какие мысли, буду признателен.
                Сообщение отредактировано: Acvarif -
                  Цитата Acvarif @
                  Но все оказалось круто закручено. Итак понятно, что каждое выполнение кода
                  ...
                  приводит к новому выводу строки в Edit Control

                  Вообще непонятно, что ты хочешь.
                  Если ты получаешь не строки, а байт - так и выводи байты.
                  Поставь непрерывный счётчик байт, равный размеру строки.
                  По достижению максимального значения - сбрасывай счётчик и добавляй
                  два байта в Эдит '\r','\n'.
                  Дополнительные операции со строками только время тратят.
                    Цитата Acvarif @
                    Все же остался один непонятный нюанс - Похоже каждая новая строка записывается на место старой. Все выводится в одну едиственную строку. Как с этим бороться?

                    Цитата Acvarif @
                    Что в коде нужно добавить, отнять, изменить, чтобы просто каждый новый его вызов печатал строку с новой строки?

                    Вместо CEdit::SetWindowText:
                    ExpandedWrap disabled
                      int len = pEdit->GetWindowTextLength();
                      pEdit->SetSel(len, len);    
                      pEdit->ReplaceSel(_T("\r\nНовая строка"));

                    :D
                    Сообщение отредактировано: Cfon -
                      Цитата
                      Вообще непонятно, что ты хочешь.
                      Если ты получаешь не строки, а байт - так и выводи байты.
                      Поставь непрерывный счётчик байт, равный размеру строки.
                      По достижению максимального значения - сбрасывай счётчик и добавляй
                      два байта в Эдит '\r','\n'.

                      Может я сразу не написал почему используется асинхронный прием - прием по событию прихода каждого байта.
                      Все дело в том, что пакеты данных переменной длины (от 800 до 4000 байт). Каждый новый пакет - другая длина. Поэтому подсчитать что-то конкретное невозможно. Вот и выкручиваюсь... Кроме того, ответная передача пакета управления (128 байт информации) должна быть по времени (разрыв не более 10 мс)жестко привязана к концу приема. Конец к счастью можно определить по конкретным конечным символам в пакете прима.
                      Пока в MFC прием работает не хуже чем в Builder.
                      В Builder имеется возможность выводить строку в Label, Panel типа
                      ExpandedWrap disabled
                        Form1->Panel3->Caption = "Всего принято байт: " + IntToStr(counterRX);

                      ExpandedWrap disabled
                        sprintf(Buffer,"Дистанция: %d м", Distm);
                              Form1->Label16->Caption = Buffer;

                      В MFC имеется Text Control. Можно-ли в Text Control выводить текст примерно как Panel3->Caption =.. или Label16->Caption = ..?
                      Сообщение отредактировано: Acvarif -
                        Цитата Acvarif @
                        В Builder имеется возможность выводить строку в Label, Panel типа
                        ExpandedWrap disabled
                          Form1->Panel3->Caption = "Всего принято байт: " + IntToStr(counterRX);

                        ExpandedWrap disabled
                          sprintf(Buffer,"Дистанция: %d м", Distm);
                                Form1->Label16->Caption = Buffer;

                        В MFC имеется Text Control. Можно-ли в Text Control выводить текст примерно как Panel3->Caption =.. или Label16->Caption = ..?

                        Естестно :D
                        ExpandedWrap disabled
                          CStatic* pText = (CStatic*)GetDlgItem(IDC_STATIC1);
                          pText->SetWindowText(_T("Hello"));

                        также имеется возможность определить объект соотвествующего класса и обращаться непросредствено через него:
                        ExpandedWrap disabled
                          class CDialog1 : public CDialog
                          {
                          public:
                              CStatic label1;
                          };
                           
                          void CDialog1::DoDataExchange(CDataExchange* pDX)
                          {
                              CDialog::DoDataExchange(pDX);
                              DDX_Control(pDX, IDC_STATIC1, label1);
                          }
                           
                          BOOL CDialog1::OnInitDialog()
                          {
                              CDialog::OnInitDialog();
                              label1.SetWindowText(_T("Hello"));
                          }
                        Сообщение отредактировано: Cfon -
                          Цитата Acvarif @
                          Может я сразу не написал почему используется асинхронный прием - прием по событию прихода каждого байта.
                          Все дело в том, что пакеты данных переменной длины (от 800 до 4000 байт). Каждый новый пакет - другая длина.

                          1. Или выводи по-байтно.
                          2. Или принимай по-одному, но накапливай в выводной буфер число байт, равное длине строки
                          твоего "виртуального" дисплея, и выводи.
                          3. Или читай из буфера порта операцией чтения максимальный размер (допустим 4000 байт).
                          С указанным тайм-аутом по приходу байт.
                          Почитай подробнее про тайм-ауты и выбери подходящий.
                          Будешь принимать или по максимальному количеству или по тайм-ауту
                          некоторое количество байт. Получишь - выводи.
                          ---
                          Все 3 способа будут работать - 100%.
                          Единственное требование - чтобы твой компьютер мог в принципе справится
                          с таким потоком байт.
                            Цитата
                            Или принимай по-одному..
                            Так и делаю. Вроде работает.

                            Цитата
                            ExpandedWrap disabled
                                 CStatic* pText = (CStatic*)GetDlgItem(IDC_STATIC1);
                                  pText->SetWindowText(_T("Hello"));

                            Понятно. Спасибо. По ходу разобрался со сменой фонта в IDC_EDIT1
                            ExpandedWrap disabled
                              // фонт для IDC_EDIT1
                                  CFont *font = new CFont;
                                  CEdit* pEditFont = (CEdit*)pWnd->GetDlgItem(IDC_EDIT1);
                                  font->CreateFont (
                                  20,                        // nHeight
                                  0,                         // nWidth
                                  0,                         // nEscapement
                                  0,                         // nOrientation
                                  FW_NORMAL,                 // nWeight
                                  FALSE,                     // bItalic
                                  FALSE,                     // bUnderline
                                  0,                         // cStrikeOut
                                  ANSI_CHARSET,              // nCharSet
                                  OUT_DEFAULT_PRECIS,        // nOutPrecision
                                  CLIP_DEFAULT_PRECIS,       // nClipPrecision
                                  DEFAULT_QUALITY,           // nQuality
                                  DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
                                  L"Arial");                 // lpszFacename
                                  pEditFont->SetFont(font);

                            Похоже удастся весь процесс приема передачи сделать в одном потоке.


                            В билдере элемент выбора типа ComboBox работает непосредственно с выбранным в окне текстом.
                            В MFC код выбора работает с опозданием на строку.
                            ExpandedWrap disabled
                              void CMFCtestDlg::OnCbnSelchangeCombo3()
                              {
                                  CString strCombo3;
                                  GetDlgItemText(IDC_COMBO3, strCombo3);
                               
                                if(strCombo3 == "откл.")
                                {
                                  bufwr[1] &= ~(1 << 0);
                                  bufwr[1] &= ~(1 << 1);
                                }
                                else if(strCombo3 == "мин.")
                                {
                                  bufwr[1] |= (1 << 0);
                                  bufwr[1] &= ~(1 << 1);
                                }
                                else if(strCombo3 == "макс.")
                                {
                                  bufwr[1] &= ~(1 << 0);
                                  bufwr[1] |= (1 << 1);
                                }
                              }

                            При выборе в bufwr[1] записываются данные соответствующие предыдущему состоянию окна IDC_COMBO3
                            Как сделать так чтобы срабатывало то, что выбрано в настоящий момент?
                            Сообщение отредактировано: Acvarif -
                              Цитата Acvarif @
                              В билдере элемент выбора типа ComboBox работает непосредственно с выбранным в окне текстом.
                              В MFC код выбора работает с опозданием на строку.

                              Как сделать так чтобы срабатывало то, что выбрано в настоящий момент?

                              дело в том что событие OnCbnSelchangeCombo3 срабатывает до замены текста в редакторе комбо, поэтому вызов GetDlgItemText считывает предыдущее значение. Выход считывать текущее значение на основе выбранного пункта из списка значений комбо с помощью GetLBText.
                              ExpandedWrap disabled
                                void CMFCtestDlg::OnCbnSelchangeCombo3()
                                {
                                    CString strCombo3;
                                    CComboBox* pCombo = (CComboBox*)GetDlgItem(IDC_COMBO3);
                                    pCombo->GetLBText(pCombo->GetCurSel(),strCombo3);
                                 
                                }
                              Сообщение отредактировано: Cfon -
                                Спасибо. Работает.
                                В билдере имеется функция закрытия формы типа
                                ExpandedWrap disabled
                                  void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)

                                В ней обычно останавливаются потоки, закрывается порт и т. п.
                                Как можно сделать то-же в MFC?
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0782 ]   [ 18 queries used ]   [ Generated: 9.05.24, 20:51 GMT ]