Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.17.64.47] |
|
Страницы: (8) « Первая ... 3 4 [5] 6 7 ... Последняя » все ( Перейти к последнему сообщению ) |
Сообщ.
#61
,
|
|
|
Спасибо. Работает. Сделал так:
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 числе - очевидно из-за построчного обновления пропускаются первые несколько данных Как можно устранить эти нюансы? |
Сообщ.
#62
,
|
|
|
Цитата Acvarif @ В MFC некоторые нюансы - не прописывает один 0 в HEX числе Это ни к MFC, ни к Билдеру отношения не имеет. Это форматный вывод в "С". Попробуй так: temp_str.Format(_T(" %02X"), bufrd[i]); Или даже так: TCHAR buf[128]; _sntprintf_s(buf,ARRAYSIZE(buf),_TRUNCATE,_T(" %02X"),bufrd[i]); Почитай про printf/sprintf. тут, например |
Сообщ.
#63
,
|
|
|
Да. Зарапортовался с форматированием. Спасибо.
В билдере было так stroka = stroka + IntToHex(bufrd[i], 2) + ' '; Все же остался один непонятный нюанс - Похоже каждая новая строка записывается на место старой. Все выводится в одну едиственную строку. Как с этим бороться? |
Сообщ.
#64
,
|
|
|
Цитата Acvarif @ Все же остался один непонятный нюанс - Похоже каждая новая строка записывается на место старой. Все выводится в одну едиственную строку. Как с этим бороться? Эти "технологии" я тебе уже показывал: www.ya.ru, ищем "CEdit MFC" и находим описание тут. Цитата ... CEdit наследует значительные возможности из CWnd. Для установки и извлечения текста из объекта CEdit, используйте функции-члены SetWindowText и GetWindowTextCWnd, устанавливающие или получающие все содержимое элемента управления "Поле ввода", даже если многострочный элемент управления. Линии многополосном текста в элементе управления разделены последовательности символов "\r\n". Кроме того, если элемент управления "Поле ввода" многополосн, получение и установка часть текста элемента управления путем вызова функции-члены GetLine, SetSel, GetSel и ReplaceSelCEdit. ... |
Сообщ.
#65
,
|
|
|
Эта ссылка у меня открыта. Но всеравно не врубаюсь.
Цитата Линии многополосном текста в элементе управления разделены последовательности символов "\r\n". Это что означает? На практике получается, что каждый новый вызов кода // Перенос буфера в строку. 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); стирает предыдущую строку и печатает новую на ее место. Что в коде нужно добавить, отнять, изменить, чтобы просто каждый новый его вызов печатал строку с новой строки? |
Сообщ.
#66
,
|
|
|
Цитата Acvarif @ Эта ссылка у меня открыта. Но всеравно не врубаюсь. я не использую MFC. Но судя по этому описанию - как-то так: // ... for (DWORD i = 0; i < btr; i++) { temp_str.Format(_T(" %02X"), bufrd[i]); stroka = stroka + temp_str + ' '; } stroka += "\r\n"; //... |
Сообщ.
#67
,
|
|
|
Спасибо. Мысль неплохая.
Но все оказалось круто закручено. Итак понятно, что каждое выполнение кода 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 (так какраз и выполняется вышеприведенный код) будет вызываться многократно. Все заложено в функции потока чтения //--------------------------------------------------------------------------- // Поток чтения 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 отобразится нужное количество принятых данных. Пока помогла не вдаваться в такие дебри небольшая задержка if((mask & EV_RXCHAR)!=0) { ::Sleep(100); Теперь вход в if(btr) { осуществляется один раз при непрерывном пакете данных на COM (порядка 800 байт с перидом в 1 сек) Функция ReadPrinting(btr, lpParam); выполняется один раз - окно Edit Control отображает корректно весь пакет принятых данных. Если у кого есть по этому поводу еще какие мысли, буду признателен. |
Сообщ.
#68
,
|
|
|
Цитата Acvarif @ Но все оказалось круто закручено. Итак понятно, что каждое выполнение кода ... приводит к новому выводу строки в Edit Control Вообще непонятно, что ты хочешь. Если ты получаешь не строки, а байт - так и выводи байты. Поставь непрерывный счётчик байт, равный размеру строки. По достижению максимального значения - сбрасывай счётчик и добавляй два байта в Эдит '\r','\n'. Дополнительные операции со строками только время тратят. |
Сообщ.
#69
,
|
|
|
Цитата Acvarif @ Все же остался один непонятный нюанс - Похоже каждая новая строка записывается на место старой. Все выводится в одну едиственную строку. Как с этим бороться? Цитата Acvarif @ Что в коде нужно добавить, отнять, изменить, чтобы просто каждый новый его вызов печатал строку с новой строки? Вместо CEdit::SetWindowText: int len = pEdit->GetWindowTextLength(); pEdit->SetSel(len, len); pEdit->ReplaceSel(_T("\r\nНовая строка")); |
Сообщ.
#70
,
|
|
|
Цитата Вообще непонятно, что ты хочешь. Если ты получаешь не строки, а байт - так и выводи байты. Поставь непрерывный счётчик байт, равный размеру строки. По достижению максимального значения - сбрасывай счётчик и добавляй два байта в Эдит '\r','\n'. Может я сразу не написал почему используется асинхронный прием - прием по событию прихода каждого байта. Все дело в том, что пакеты данных переменной длины (от 800 до 4000 байт). Каждый новый пакет - другая длина. Поэтому подсчитать что-то конкретное невозможно. Вот и выкручиваюсь... Кроме того, ответная передача пакета управления (128 байт информации) должна быть по времени (разрыв не более 10 мс)жестко привязана к концу приема. Конец к счастью можно определить по конкретным конечным символам в пакете прима. Пока в MFC прием работает не хуже чем в Builder. В Builder имеется возможность выводить строку в Label, Panel типа Form1->Panel3->Caption = "Всего принято байт: " + IntToStr(counterRX); sprintf(Buffer,"Дистанция: %d м", Distm); Form1->Label16->Caption = Buffer; В MFC имеется Text Control. Можно-ли в Text Control выводить текст примерно как Panel3->Caption =.. или Label16->Caption = ..? |
Сообщ.
#71
,
|
|
|
Цитата Acvarif @ В Builder имеется возможность выводить строку в Label, Panel типа Form1->Panel3->Caption = "Всего принято байт: " + IntToStr(counterRX); sprintf(Buffer,"Дистанция: %d м", Distm); Form1->Label16->Caption = Buffer; В MFC имеется Text Control. Можно-ли в Text Control выводить текст примерно как Panel3->Caption =.. или Label16->Caption = ..? Естестно CStatic* pText = (CStatic*)GetDlgItem(IDC_STATIC1); pText->SetWindowText(_T("Hello")); также имеется возможность определить объект соотвествующего класса и обращаться непросредствено через него: 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")); } |
Сообщ.
#72
,
|
|
|
Цитата Acvarif @ Может я сразу не написал почему используется асинхронный прием - прием по событию прихода каждого байта. Все дело в том, что пакеты данных переменной длины (от 800 до 4000 байт). Каждый новый пакет - другая длина. 1. Или выводи по-байтно. 2. Или принимай по-одному, но накапливай в выводной буфер число байт, равное длине строки твоего "виртуального" дисплея, и выводи. 3. Или читай из буфера порта операцией чтения максимальный размер (допустим 4000 байт). С указанным тайм-аутом по приходу байт. Почитай подробнее про тайм-ауты и выбери подходящий. Будешь принимать или по максимальному количеству или по тайм-ауту некоторое количество байт. Получишь - выводи. --- Все 3 способа будут работать - 100%. Единственное требование - чтобы твой компьютер мог в принципе справится с таким потоком байт. |
Сообщ.
#73
,
|
|
|
Цитата Так и делаю. Вроде работает.Или принимай по-одному.. Цитата CStatic* pText = (CStatic*)GetDlgItem(IDC_STATIC1); pText->SetWindowText(_T("Hello")); Понятно. Спасибо. По ходу разобрался со сменой фонта в IDC_EDIT1 // фонт для 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 код выбора работает с опозданием на строку. 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 Как сделать так чтобы срабатывало то, что выбрано в настоящий момент? |
Сообщ.
#74
,
|
|
|
Цитата Acvarif @ В билдере элемент выбора типа ComboBox работает непосредственно с выбранным в окне текстом. В MFC код выбора работает с опозданием на строку. Как сделать так чтобы срабатывало то, что выбрано в настоящий момент? дело в том что событие OnCbnSelchangeCombo3 срабатывает до замены текста в редакторе комбо, поэтому вызов GetDlgItemText считывает предыдущее значение. Выход считывать текущее значение на основе выбранного пункта из списка значений комбо с помощью GetLBText. void CMFCtestDlg::OnCbnSelchangeCombo3() { CString strCombo3; CComboBox* pCombo = (CComboBox*)GetDlgItem(IDC_COMBO3); pCombo->GetLBText(pCombo->GetCurSel(),strCombo3); } |
Сообщ.
#75
,
|
|
|
Спасибо. Работает.
В билдере имеется функция закрытия формы типа void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) В ней обычно останавливаются потоки, закрывается порт и т. п. Как можно сделать то-же в MFC? |