Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Delphi (до версии 2009) - часть 6

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

Открыть новую тему     Написать ответ в эту тему

ShIvADeSt



Moderator
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Продолжение темы Вопросы по Delphi (до версии 2009) - часть 5

Познаем сами, помогаем другим...
Обсуждаем вопросы, не связанные с юникоидными версиями Delphi - для этого есть соответствующая тема (см. ссылки ниже).


 
Правила топика:
    Прежде чем спрашивать:
  1. Желательно изучить вопрос, попытаться найти ответ в прилагаемых мануалах, хелпах и анализируя исходники.
  2. Выполнить поиск по топику (открыть "Версия для печати" и поискать ответ там).
  3. Применить фильтр по разделу "Прикладное программирование". Ответы на многие старые вопросы могли быть даны в отдельных темах.
  4. Продумайте вопрос. На поверхностные вопросы вы получите поверхностные ответы, или вообще ответов не получите.
  5. Желательно указывать версии используемого компилятора и операционной системы.
    Прежде чем отвечать:
  1. Если не можете помочь, не мешайте.
  2. Если уж вы отвечаете на вопрос, давайте ответ по сути.
  3. Если вы не уверены, так и говорите! Ошибочный, но авторитетно звучащий ответ хуже, чем отсутствие ответа.
  4. Задавайте дополнительные вопросы, чтобы получить больше информации.
  • Отсутствие ответа не равносильно игнорированию - иногда участники форума просто не знают ответ. Повторная посылка вопроса не приветствуется. Посты типа "неужели никто не знает ответа..." или "может мне все-таки кто-нибудь ответит" недопустимы.  
  • Все большие куски кода (более 5 строк) оформляем в тег [morе] дабы уменьшить размер поста. FAQ по тегу [morе].


    Некоторые "родственные" топики:
     
  • Вопросы по Delphi (версии 2009-2010 Weaver)
  • Вопросы по компонентам для Delphi, C++ Builder
  • Использование DevExpress
  • Вопросы по Ehlib
  • Компоненты и утилиты для Delphi/BCB/FreePascal/Lazarus - только Open Source
  • Коммерческие компоненты и утилиты для Delphi/BCB
  • кабак программистов :)
     
    См. также: Некоторые полезные ресурсы о Delphi
     
    И старайтесь, чтобы ваш код не попал сюда :)

  • Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 05:13 19-05-2010 | Исправлено: akaGM, 02:33 15-07-2020
    YuriyRR



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    EugeneBoss3

    Цитата:
    Использовал EMS Advanced Data Export VCL, но компонент перезаписывает существующую таблицу Excel. Как эксортировать данные?

    Предлагаю использовать компоненту XLSRadWriteII или NativeExcell они дают доступ к модификации любой ячейки. В цикле пробегаешься по датасету и пишешь куда надобно.

    Всего записей: 516 | Зарегистр. 07-06-2007 | Отправлено: 04:01 09-01-2011
    EugeneBoss3



    Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    YuriyRR
    Установил оба компонента, но в примерах не нашел как экспортировать данные из датасета на нужный лист. Может есть реализация? Пример, плиз.

    Всего записей: 247 | Зарегистр. 15-09-2009 | Отправлено: 08:48 09-01-2011
    konungster



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Вижу, тут с активностью получше чем в топике С++builder. Кто нибудь работал с отчетами crystal reports из delphi/cpp через Ole ?
    разобрался

    Всего записей: 959 | Зарегистр. 31-10-2005 | Отправлено: 21:17 09-01-2011 | Исправлено: konungster, 13:19 18-01-2011
    YuriyRR



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    EugeneBoss3

    Цитата:
    Может есть реализация? Пример, плиз.

    Код правда скриптового движка, но по сути такой-же как в Delphi
    Подробнее...




    Учим тег more

    Всего записей: 516 | Зарегистр. 07-06-2007 | Отправлено: 00:56 10-01-2011 | Исправлено: ShIvADeSt, 05:35 12-01-2011
    EugeneBoss3



    Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    YuriyRR
    Спасибо за участие. Попробовать можно, но хотелось бы узнать формат базы данных и описание полей таблицы.

    Всего записей: 247 | Зарегистр. 15-09-2009 | Отправлено: 03:13 10-01-2011
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Вы пытаетесь работать с указателями, но что то я нигде не вижу у вас необходимого при этом ручного управления распределением памяти. Почитайте для просвещения: http://www.transl-gunsmoker.ru/2009/09/pchars.html И по ссылкам там походить можно, это мега-полезный блог для делфина.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 14:00 10-01-2011
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Frodo_Torbins
    Спасибо. Вообще интересный блог. Перевел на строки возврат функции и все заработало, да и со строками проще работать.
     
    У меня ко всем вопрос кто разбирается хорошо в теме. Собственно приведу небольшой пример. Есть последовательность действий, выполняемая в отдельном потоке. Естественно поток нужен только лишь для того, чтобы не стопорить интерфейс приложения во время длительного действия. Этот поток должен быть всегда один и нужны проверки дабы не создавать вторичные потоки по глупости. Например, длительный расчет чего-то там, но с возможностью прервать действие. Сделано сейчас так:
     
    Глобальные переменные terminate: Boolean = TRUE и thread: DWORD = 0.
    Имеется структура для передачи этому потоку.
     

    Код:
    type
      TThreadParams = packed record
        Handle : THandle;
        pszAnsi: AnsiString;
      end;
      PThreadParams = ^TThreadParams;

     
    В колбэке для создания потока сделано так:
     

    Код:
      function ThreadCallback(LpParameter: PThreadParams): DWORD; stdcall;
      begin
        //
        Result := 0;
        //
        SetThreadPriority(thread, THREAD_PRIORITY_LOWEST);
        //
        repeat
          расчет
          Sleep(5);
        until
          (переменная > значение) or terminate
        //
        Dispose(LpParameter);
      end;

     
    Есть 3 кнопки пуск, стоп и прервать, ну типа того. Теперь надо бы организовать проверки.
     
    Код кнопки пуск:
     

    Код:
              if terminate then
                terminate := FALSE;
     
              if ((thread = 0) and (not terminate)) then
              begin
     
                New(params); // локальная переменная.
                params.Handle  := hWnd;
                params.pszAnsi := 'data';
     
                thread := CreateThread(
                  nil,
                  0,
                  @ThreadCallback,
                  params,
                  0,
                  ThreadID
                );
                if (thread <> 0) then
                begin
                  CloseHandle(thread);
                  thread := 0;
                end;

     
    Код кнопки стоп:
     

    Код:
              terminate := TRUE;
     
              if (thread <> 0) then
              begin
                GetExitCodeThread(thread, dwRet);
                TerminateThread(thread, dwRet);
                CloseHandle(thread);
                thread := 0;
              end;

     
    Ну и код кнопки прервать это просто terminate в TRUE устанавливаю. Если тыкать на пуск во время выполнения длительного колбэка, то создаются новые потоки, текущий не уничтожается, вероятно не успевает завершиться или не доходит до кода где Dispose. Может надо критические секции использовать или через WaitForSingleObject действовать? Информации по потокам масса, но ее так много, что я не в состоянии корректно переварить все. Везде масса вариантов и везде как мне кажется есть небольшие косяки. Ну и рекомендации с BeginThread раз в Делфи работаю. Но мне не надо ее. Как корректнее завершить поток и выполнить проверку?

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 23:57 11-01-2011 | Исправлено: Maks150988, 00:02 12-01-2011
    data man



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Хоть шапку уважайте:

    Цитата:
    Все большие куски кода (более 5 строк) оформляем в тег [morе] дабы уменьшить размер поста.


    ----------
    Любой достаточно развитый тролль неотличим от подлинно помешанного на какой-либо идее.
    Кекс. Антибиотики. Ламбада.

    Всего записей: 1696 | Зарегистр. 13-10-2005 | Отправлено: 00:12 12-01-2011
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Рекомендация с BeginThread на самом деле очень полезна, т к эта функция переводит менеджер памяти в многопоточный режим, чего вы не делаете в своем коде.
    Защиты от запуска нескольких копий потока я у вас вообще не вижу. Переменную thread вы сразу же обнуляете, а больше у вас никаких переменных нету.
    WaitForSingleObject могла бы пригодится в коде кнопки Стоп для корректного завершения работы потока. К примеру: установили terminate и ждем пока можно будет закрыть хендл. TerminateThread же лучше использовать только в самых крайних случаях. Еще функция WaitForSingleObject могла бы помочь если бы вы захотели организовать кнопку Пауза.
    Далее, если вы не будете закрывать хендл потока сразу же после старта, то после нажатия кнопки Прервать он у вас останется незакрытым. Один способ решить эту проблемму я только что описал. Второй способ - послать своему окну специальное сообщение (через PostMessage), и в его обработчике закрыть хендл.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 12:40 12-01-2011 | Исправлено: Frodo_Torbins, 12:41 12-01-2011
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Frodo_Torbins
    Ладно, впринципе можно и без BeginThread обойтись, сам выставлю IsMultiThread в TRUE перед CreateThread и код колбэка в try/except заключу.

    Цитата:
    Защиты от запуска нескольких копий потока я у вас вообще не вижу. Переменную thread вы сразу же обнуляете, а больше у вас никаких переменных нету.  

    А как бы вы тогда организовали защиту от запуска нескольких копий потока?
    Насчет WaitForSingleObject, непонятно сколько ставить таймаут, INFINITE или свое значение.

    Цитата:
    Далее, если вы не будете закрывать хендл потока сразу же после старта, то после нажатия кнопки Прервать он у вас останется незакрытым.

    А закрывать то его надо в самом колбэке или после CreateThread? Я после CreateThread проверяю хэндл на ноль и закрываю. Или вообще неправильно я сделал?

    Цитата:
    Второй способ - послать своему окну специальное сообщение (через PostMessage), и в его обработчике закрыть хендл.

    Забыл добавить, копируя куски кода сюда, в кнопке пуск такой код в самом начале:

    Код:
    SendMessage(hWnd, WM_COMMAND, MakeWParam(IDC_STOP, BN_CLICKED), 0);

     
    Сделал так чтобы было немножко понятливее наверное:
     
    Тынц
     
    Я так подумал, а хрен ли, все равно надо чистить указатель. Делаю диспос в начале колбэка, сохранив локально строку с хэндлом. Правилен ли такой подход? И правильно ли я сделал с WaitForSingleObject ожидание потока? Вроде бы память не течет и хэндлы потоков не прибавляются в процессе...

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 13:34 12-01-2011 | Исправлено: Maks150988, 14:30 12-01-2011
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Я бы в кнопке запуска хендл не закрывал. Тогда ваше условие "if ((thread = 0) and (not terminate)) then" автоматически становится защитой от повторного запуска. Тогда кнопку Прервать можно было бы удалить, а Стоп переделать под ожидание корректного завершения работы потока.

    Цитата:
    Насчет WaitForSingleObject, непонятно сколько ставить таймаут, INFINITE или свое значение.
    Можно INFINITE, но тогда использовать MsgWaitForMultipleObjects, чтобы не заблокировать интерфейс. Пример использования: http://www.transl-gunsmoker.ru/2010/04/blog-post_20.html

    Цитата:
    Забыл добавить, копируя куски кода сюда, в кнопке пуск такой код в самом начале:
    SendMessage(hWnd, WM_COMMAND, MakeWParam(IDC_STOP, BN_CLICKED), 0);
    Использование SendMessage для посылки сообщения текущему потоку равноценно прямому вызову соответствующего куска кода. Так что лучше просто выделить этот код в отдельную процедуру, и вызывать когда нужно.
     
    Добавлено:
    Вряд ли вам удастся закрыть хендл в калбеке, ведь его в этот момент будет использовать WaitForSingleObject. А если и закроете, то на вход TerminateThread попадет уже не корректный хендл. Проставьте всюду проверку ошибок - сами убедитесь.
    С освобождением памяти все было и так нормально.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 15:02 12-01-2011 | Исправлено: Frodo_Torbins, 15:10 12-01-2011
    zerofer



    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    может кто делал авторизацию на сайте с sunaps ssl+сертификат ,или подскажите что можно использовать,авторизацию то я сделал но дальше первой страницы никак так как в запросе передает ключ я так понимаю генерированный сертификатами.

    Всего записей: 124 | Зарегистр. 12-10-2008 | Отправлено: 15:39 12-01-2011
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Frodo_Torbins
    Так, давайте по порядку, что как исправить.

    Цитата:
    Я бы в кнопке запуска хендл не закрывал. Тогда ваше условие "if ((thread = 0) and (not terminate)) then" автоматически становится защитой от повторного запуска. Тогда кнопку Прервать можно было бы удалить, а Стоп переделать под ожидание корректного завершения работы потока.

    Кнопку прервать тогда убираю. Надо бы с пуском и стопом разобраться полностью. А если заместо SendMessage послать PostMessage? Я так понимаю вы это и имели ввиду как закрытие хэндла? Мне убрать? Раз вот это:

    Цитата:
    Использование SendMessage для посылки сообщения текущему потоку равноценно прямому вызову соответствующего куска кода. Так что лучше просто выделить этот код в отдельную процедуру, и вызывать когда нужно.

    И еще вот что.

    Цитата:
    С освобождением памяти все было и так нормально.

    Не знаю, я ради интереса проставлял пустой MessageBox после диспоса и до него дело не доходило, поэтому и подумалось.

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 15:44 12-01-2011
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Если у вас переменная thread одновременно является и хендлом и индикатором того, что поток запущен, то тогда вариант удаления хендла в ответ на сообщение вам не подойдет. Т к мы не знаем когда прийдет сообщение отправленное через PostMessage, то все это время не сможем запустить новый поток. Из корректных способов остается только вариант с ожиданием.

    Цитата:
    Не знаю, я ради интереса проставлял пустой MessageBox после диспоса и до него дело не доходило, поэтому и подумалось.
    Сложно что либо сказать не видя реального кода.
     
    Вообще очень тяжело обсуждать ваш код. Слишком уж сильно в нем перемешана логика работы и отображение интерфейса. Для простоты эти две задачи обычно разделяют. Но как только программист отделит интерфейс от логики в нескольких своих программах, он поймет, что всюду получился почти один и тот же код. Сразу возникает идея: "А не сделать ли мне отдельную небольшую библиотеку интерфейсных контролов, которую можно будет использовать во всех моих программах?". От этой идеи до VCL один шаг.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 16:35 12-01-2011 | Исправлено: Frodo_Torbins, 16:39 12-01-2011
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Frodo_Torbins
    Код не могу предоставить. Пока "играюсь" на этом примере. Переменная thread является хэндлом потока, по ее нулевости я и определяю существует ли поток в данный момент или нет. Остановлюсь на использовании WaitForSingleObject.
    А впринципе, а какая разница, WaitForSingleObject просто затормозит выполнение кода в основном потоке (именно код кнопки стоп), без разницы где уничтожится этот хэндл потока, даже если в колбэке будет корректно все "закрыто". Я же потом опять проверяю на нулевость перед TerminateThread.
    Я привык уже на апи делать, всл не люблю.

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 17:12 12-01-2011
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Если калбек успеет закрыть хендл, то код после WaitForSingleObject не нужен. А если не успеет, то у вас возможна ситуация когда одновременно работают два одинаковых потока, что может привести к попытке одновременно редактировать одни данные и глюкам. Или же, если вы решили оставить TerminateThread, то глюки может вызвать ее применение. Причем в обоих случаях это будут глюки из серии "100 отработало нормально, а на 101 упало непонятно почему".

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 20:56 12-01-2011 | Исправлено: Frodo_Torbins, 20:57 12-01-2011
    ShIvADeSt



    Moderator
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Frodo_Torbins
    Предлагаю сделать отдельную тему, все таки потоки это не типовая задача. И лучше обсуждать в отдельной теме, просто мне читать кусками то тут то там не удобно, смысл уходит.

    ----------
    И создал Бог женщину... Существо получилось злобное, но забавное...

    Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 02:25 13-01-2011
    XOBAH

    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Здравствуйте!
    Помогите пожалуйста: Мне надо чтобы при выборе\отмене чекбокса скрывались\отображались 2 компонента.  
    Пробовал так:
     

    Код:
     
    procedure TformMainMenu.checkGenerationClick(Sender: TObject);
    begin
    If edtName.Visible = True then
      Begin
    edtName.Visible := False;
    cobxGenNames.Visible := True;
      end;
    If edtName.Visible = False then
      Begin
    edtName.Visible := True;
    cobxGenNames.Visible := False;
      end;
    end;
    end.

     
    Но: При нажатии на чекбокс - едитБокс показан - и он делает его Скрытым - и во второй функции выполняется условие и делает его невидимым.
     
    Делал так:
     

    Код:
     
    procedure TformMainMenu.checkGenerationClick(Sender: TObject);
    begin
    If edtName.Visible = True then
    (edtName.Visible := False) AND (cobxGenNames.Visible := True)
    Else (edtName.Visible := True) AND (cobxGenNames.Visible := False);
    end;
    end.
     

     
    Ничего кроме: 2-ух [Error] Unit1.pas(117): Operator not applicable to this operand type не получил
     
    P.S. Юзаю Delphi 7
     
    Frodo_Torbins Спасибо, все работает. Вот код, может надо будет кому:

    Код:
    If checkGeneration.Checked  then
      Begin
    edtName.Visible := False;
    cobxGenNames.Visible := True;
      end
    else
     Begin

    edtName.Visible := True;
    cobxGenNames.Visible := False;
      end;

     
    marser, Ваш код не будет работать. При Неотмеченном чекбоксе, не покажется ни один компонентЮ а если чебокс будет отмечен - то покажутся сразу 2 компонента. А надо чтоб 1 из двух.

    Всего записей: 19 | Зарегистр. 04-12-2010 | Отправлено: 18:38 14-01-2011 | Исправлено: XOBAH, 20:42 14-01-2011
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    XOBAH
    У чекбокса есть свойство Checked вот его и надо проверять в if. Ошибка же у вас выскакивает потому, что вы не знаете основ языка делфи. Для объединения нескольких действий используются ключевые слова begin и end, как в первом вашем примере. Вот только точка с запятой ставится не всегда.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 18:48 14-01-2011 | Исправлено: Frodo_Torbins, 18:51 14-01-2011
    marser

    Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    XOBAH

    Код:
    procedure TformMainMenu.checkGenerationClick(Sender: TObject);  
    begin  
       edtName.Visible := checkGeneration.Checked
       cobxGenNames.Visible := checkGeneration.Checked;  
    end;

    Всего записей: 398 | Зарегистр. 29-03-2007 | Отправлено: 19:23 14-01-2011
    Открыть новую тему     Написать ответ в эту тему

    Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

    Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Delphi (до версии 2009) - часть 6


    Реклама на форуме Ru.Board.

    Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
    Modified by Ru.B0ard
    © Ru.B0ard 2000-2024

    BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

    Рейтинг.ru