Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Как сделать, чтобы компоненты были активными?


Автор: SerK 7.12.2016, 21:39
Проблема такая:

При нажатии на Кнопку (выполняется фукнция обработки строк), все компоненты перестают реагировать пока функция не выполнится.
А мне нужно выводить данные в Прогресс бар - как функция выполняется: какая строка обрабатывается, какая позиция искомого слова, время выполнения. Словом отображать весь ход работы функции. 

Как это реализовать?

Автор: vol4ek 8.12.2016, 05:53
По нажатию кнопки создавайте отдельный поток и в нем ыыполняйте всю обработку строк.

Автор: feodorv 8.12.2016, 10:58
Можно и в одном потоке, главное - периодически очищать очередь сообщений. Например, после обновления данных в прогресс баре (через различные SendMessage) можно вызвать такую функцию:
Код

BOOL ustpHelloDialogMessageLoop( HWND dialog )
{
  MSG msg;

  for( ;; )
  {
    BOOL bRet;

    if( !PeekMessage( &msg, 0, 0, 0, PM_NOREMOVE) ) break;
    if( (bRet = GetMessage( &msg, 0, 0, 0)) == 0 ) break;

    if( bRet < 0 )
    {
      /* system error */
      return FALSE;
    }

    if( !IsWindow( dialog ) || !IsDialogMessage( dialog, &msg) )
    {
      TranslateMessage( &msg );
      DispatchMessage( &msg );
    }
  }

  return TRUE;
}

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

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Kak-sdelat-chtoby-komponenty-byli-aktivnymi-id584857f927bb7e167838cce3#findElement_E7045_584912a720a8ef0e663b3f11_0

Автор: feodorv 8.12.2016, 10:58
Можно и в одном потоке, главное - периодически очищать очередь сообщений. Например, после обновления данных в прогресс баре (через различные SendMessage) можно вызвать такую функцию:
Код

BOOL DialogMessageLoop( HWND dialog )
{
  MSG msg;

  for( ;; )
  {
    BOOL bRet;

    if( !PeekMessage( &msg, 0, 0, 0, PM_NOREMOVE) ) break;
    if( (bRet = GetMessage( &msg, 0, 0, 0)) == 0 ) break;

    if( bRet < 0 )
    {
      /* system error */
      return FALSE;
    }

    if( !IsWindow( dialog ) || !IsDialogMessage( dialog, &msg) )
    {
      TranslateMessage( &msg );
      DispatchMessage( &msg );
    }
  }

  return TRUE;
}

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

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Kak-sdelat-chtoby-komponenty-byli-aktivnymi-id584857f927bb7e167838cce3#findElement_E7045_584912a720a8ef0e663b3f11_0

Автор: feodorv 8.12.2016, 10:58
Можно и в одном потоке, главное - периодически очищать очередь сообщений. Например, после обновления данных в прогресс баре (через различные SendMessage) можно вызвать такую функцию:
Код

BOOL DialogMessageLoop( HWND dialog )
{
  MSG msg;

  for( ;; )
  {
    BOOL bRet;

    if( !PeekMessage( &msg, 0, 0, 0, PM_NOREMOVE) ) break;
    if( (bRet = GetMessage( &msg, 0, 0, 0)) == 0 ) break;

    if( bRet < 0 )
    {
      /* system error */
      return FALSE;
    }

    if( !IsWindow( dialog ) || !IsDialogMessage( dialog, &msg) )
    {
      TranslateMessage( &msg );
      DispatchMessage( &msg );
    }
  }

  return TRUE;
}

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

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Kak-sdelat-chtoby-komponenty-byli-aktivnymi-id584857f927bb7e167838cce3#findElement_E7045_584912a720a8ef0e663b3f11_0

Автор: feodorv 8.12.2016, 10:58
Можно и в одном потоке, главное - периодически очищать очередь сообщений. Например, после обновления данных в прогресс баре (через различные SendMessage) можно вызвать такую функцию:
Код

BOOL DialogMessageLoop( HWND dialog )
{
  MSG msg;

  for( ;; )
  {
    BOOL bRet;

    if( !PeekMessage( &msg, 0, 0, 0, PM_NOREMOVE) ) break;
    if( (bRet = GetMessage( &msg, 0, 0, 0)) == 0 ) break;

    if( bRet < 0 )
    {
      /* system error */
      return FALSE;
    }

    if( !IsWindow( dialog ) || !IsDialogMessage( dialog, &msg) )
    {
      TranslateMessage( &msg );
      DispatchMessage( &msg );
    }
  }

  return TRUE;
}

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

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Kak-sdelat-chtoby-komponenty-byli-aktivnymi-id584857f927bb7e167838cce3#findElement_E7045_584912a720a8ef0e663b3f11_0

Автор: feodorv 8.12.2016, 10:58
Можно и в одном потоке, главное - периодически очищать очередь сообщений. Например, после обновления данных в прогресс баре (через различные SendMessage) можно вызвать такую функцию:
Код

BOOL DialogMessageLoop( HWND dialog )
{
  MSG msg;

  for( ;; )
  {
    BOOL bRet;

    if( !PeekMessage( &msg, 0, 0, 0, PM_NOREMOVE) ) break;
    if( (bRet = GetMessage( &msg, 0, 0, 0)) == 0 ) break;

    if( bRet < 0 )
    {
      /* system error */
      return FALSE;
    }

    if( !IsWindow( dialog ) || !IsDialogMessage( dialog, &msg) )
    {
      TranslateMessage( &msg );
      DispatchMessage( &msg );
    }
  }

  return TRUE;
}

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

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Kak-sdelat-chtoby-komponenty-byli-aktivnymi-id584857f927bb7e167838cce3#findElement_E7045_584912a720a8ef0e663b3f11_0

Автор: SerK 8.12.2016, 12:02
Цитата(feodorv @  8.12.2016,  10:58 Найти цитируемый пост)
Можно и в одном потоке, главное - периодически очищать очередь сообщений. Например, после обновления данных в прогресс баре (через различные SendMessage) можно вызвать такую функцию


Спасибо за ответ. Ещё вопрос: как вызывать эту функцию BOOL DialogMessageLoop( HWND dialog )?  HWND dialog - что это?

Добавлено через 1 минуту и 58 секунд
Цитата(vol4ek @  8.12.2016,  05:53 Найти цитируемый пост)
По нажатию кнопки создавайте отдельный поток и в нем ыыполняйте всю обработку строк.


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

Автор: xvr 8.12.2016, 13:44
Цитата(SerK @  8.12.2016,  12:02 Найти цитируемый пост)
Спасибо за ответ.

В Builder'е есть специальный метод для такой обработки - Application->ProcessMessages();

Цитата(SerK @  8.12.2016,  12:02 Найти цитируемый пост)
Создал поток, но это не повлияло на главную форму - она как была заторможенной во время выполнения функции, так и осталась.

В поток надо было вынести выполнение этой самой функции, а вы что туда поместили?

Автор: SerK 8.12.2016, 21:49
Цитата(xvr @  8.12.2016,  13:44 Найти цитируемый пост)
В поток надо было вынести выполнение этой самой функции, а вы что туда поместили?


Поместил в файл потока:
Код

void __fastcall MyT::Execute()
{
    Synchronize(Process);
}
//---------------------------------------------------------------------------
void __fastcall MyT::Process()
{
    chictovprover(Form1->SynMemo2->Text,"");
}


а вызов в файле главной формы:
Код

MyT *Thread;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Thread = new MyT(false);
Thread->FreeOnTerminate= 0;
}


Добавлено через 4 минуты и 19 секунд
Цитата(xvr @  8.12.2016,  13:44 Найти цитируемый пост)
В Builder'е есть специальный метод для такой обработки - Application->ProcessMessages();


Как им пользоваться в данном случае? 

Автор: xvr 9.12.2016, 19:12
Цитата(SerK @  8.12.2016,  21:49 Найти цитируемый пост)
Поместил в файл потока:

А где собственно вычисления? Если внутри MyT::Process, то это неправильно. Реальные вычисления должны вызываться вне метода Synchronize

Цитата(SerK @  8.12.2016,  21:49 Найти цитируемый пост)
Как им пользоваться в данном случае? 

Периодически вызывать в процессе длительных вычислений. Интервал между вызовами напрямую влияет на 'отзывчивость' интерфейса

Автор: SerK 10.12.2016, 09:55
Вычисления вызываются вне метода Synchronize

Цитата(xvr @  9.12.2016,  19:12 Найти цитируемый пост)
А где собственно вычисления? Если внутри MyT::Process, то это неправильно. Реальные вычисления должны вызываться вне метода Synchronize



Код

void __fastcall MyT::Execute()
{
    Synchronize(Process);
}
//---------------------------------------------------------------------------
void __fastcall MyT::Process()
{
    chictovprover(Form1->SynMemo2->Text,"");
}
//---------------------------------------------------------------------------
String __fastcall MyT::chictovprover(String text1,String text2)
{
// код
}


Цитата(xvr @  9.12.2016,  19:12 Найти цитируемый пост)
Периодически вызывать в процессе длительных вычислений.


Спасибо - разобрался с Application->ProcessMessages();

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)