Конференция "Компоненты" » PasswordChar для компонента [D5, WinXP]
 
  • harisma © (13.10.09 18:13) [0]
    Достался мне в наследство от предыдущих разработчиков компонент, наследник от TCustomEdit, но несколько универсализированый. Другими словами он может иметь 10 разных стилей, а также в него интегрировано свойство Mask, которое есть у стандартного дельфийского компонента TMaskEdit.

    Проблема в том, что на некоторых компьютерах (на моем компьютере все отрабатывает корректно) почему-то не отрабатывает установка для этого компонента свойства PasswordChar - текст как отображался читаемыми символами  -так и отображается дальше, не зависимо от того, установлено свойство PasswordChar = '*' или нет.

    Я создал специальный тестовый проект. В него поместил 10 экземпляров этого компонента (на каждый из стилей по одному). Кнопки возле экземпляров компонента отвечают за установку/снятие свойства PasswordChar.

    Я выложил тестовый проект и модуль самого компонента вот по этому адресу: http://depositfiles.com/files/fpv64b1bb

    У кого проявится такое же поведение (отсутствие всякой реакции экземпляра компонента на установку свойства PasswordChar при нажатии на кнопку), прошу помочь найти проблему в модуле компонента. Очень подозреваю, что проблема кроется в отрисовке компонента, но где именно - мне трудно определить.
  • DimaBr © (14.10.09 08:58) [1]
    PasswordChar унаследован от TCustomEdit, никакого вмешательства в отрисовку не замечено.
    Как ведёт себя обыкновенный TEdit на присловутых машинах
  • harisma © (14.10.09 11:27) [2]
    То что PasswordChar унаследован от TCustomEdit я знаю. Обычный дельфийский TEdit нормально показывает звездочки, а этот не хочет почему-то. По крайней мере я знаю у нас на фирме 3 компьютера, на которых эти звездочки не показываются. :(
  • DimaBr © (14.10.09 13:58) [3]
    Как ведёт себя Edit с установленным PasswordChar на этих машинах ?
  • harisma © (14.10.09 15:08) [4]

    > Как ведёт себя Edit с установленным PasswordChar на этих
    > машинах ?

    Отображается как надо - звездочками.
  • DimaBr © (14.10.09 16:23) [5]
    Вызывает подозрение строка
    Style := Style and not ES_WANTRETURN or ES_MULTILINE

    Что значит not ES_WANTRETURN ?
  • harisma © (14.10.09 16:40) [6]
    Вот нарытая мною информация из Инета о стилях для эдита:


    Ниже перечисленные стили поля редактирования текста (в классе EDIT) могут быть определены в параметре dwStyle:

       * ES_AUTOHSCROLL - Автоматически прокручивает текст вправо на 10 символов, когда пользователь напечатает символ в конце строчки. Когда пользователь нажимает клавишу ENTER, управление прокручивает весь текст обратно, чтобы установить нуль.
       * ES_AUTOVSCROLL - Автоматически перемещает текст вверх на одну страницу, когда пользователь нажимает клавишу ENTER на последней строчке.
       * ES_CENTER - Выравнивает по центру текст в многостроковом поле редактирования текста.
       * ES_LEFT - Выравнивание текста слева.
       * ES_LOWERCASE - Преобразовывает все символы в нижний регистр, поскольку они печатаются внутри поля редактирования текста.
       * ES_MULTILINE - Обозначает многостроковое окно редактирования текста. Значение по умолчанию - одностроковое окно редактирования текста. Когда многостроковое поле редактирования находится в диалоговом окне, заданная по умолчанию ответная реакция на нажим клавиши ENTER должна активизировать кнопку по умолчанию. Чтобы использовать клавишу ENTER для перевода строки, стиль используйте ES_WANTRETURN. Когда многостроковое окно редактирования не в диалоговом окне и определен стиль ES_AUTOVSCROLL, поле редактирования показывает столько строчек, сколько это возможно и прокручивает вертикально, когда пользователь нажимает клавишу ENTER. Если Вы не определяете ES_AUTOVSCROLL, окно редактирования показывает столько строчек, сколько это возможно и подает звуковой сигнал, если пользователь нажимает клавишу ENTER, но больше ни строчки не может отобразиться в окне. Если Вы определяете стиль ES_AUTOHSCROLL, многостроковое окно редактирования автоматически горизонтально прокручивается, когда каретка проходит за правый край элемента управления. Чтобы запустить новую строку, пользователь должен нажать клавишу ENTER. Если Вы не определяете ES_AUTOHSCROLL, элемент управления, когда это необходимо, автоматически переносит без разрыва слова в начало следующей строки. Новая строка образуется и тогда, если пользователь нажимает клавишу ENTER. Размер окна определяет позицию перехода слова на новую строку. Если размер окна изменяется, изменяется позиция перехода на новую строку, а текст восстанавливается. Многостроковое окно редактирования текста может иметь линейки прокрутки . Окно редактирования с линейками прокрутки обрабатывают свои собственные сообщения от линейки прокрутки. Обратите внимание, что окно редактирования без линеек прокрутки, прокручивают текст, как описано в предыдущих параграфах и обрабатывают любые сообщений прокрутки, посланные родительским окном.
       * ES_NOHIDESEL - Отрицает заданное по умолчанию поведение для поля редактирования текста. Заданное по умолчанию поведение скрывает выбор, когда элемент управления теряет фокус ввода и инвертирует выбор, когда панель управления принимает фокус ввода. Если Вы определяете ES_NOHIDESEL, выбранный текст инвертируется, даже если панель управления не имеет фокуса.
       * ES_NUMBER - Позволяет ввести в поле редактирования только цифры.
       * ES_OEMCONVERT - Преобразует текст, введенный в окно редактирования. Текст преобразуется из набора символов Windows - в набор символов OEM, а затем обратно - в набор Windows. Это гарантирует соответствующее символьное преобразование, когда из прикладной программы вызывается функция CharToOem, чтобы преобразовать строку Windows в окне редактирования в символы OEM. Этот стиль наиболее полезен для окон редактирования текста, которые содержат имена файлов.
       * ES_PASSWORD - Отображает звездочку (*) вместо каждого символа, введенного с клавиатуры в окно редактирования. Вы можете использовать сообщение EM_SETPASSWORDCHAR, чтобы заменить ею символ, который отображается.
       * ES_READONLY - Не допускает пользователя к вводу или редактированию текста в окне редактирования.
       * ES_RIGHT - Выравнивает по правому краю текст в многострочном окне редактирования.
       * ES_UPPERCASE - Преобразует все символы в символы верхнего регистра, когда они вводятся в окно редактирования.
       * ES_WANTRETURN - Определяет, чтобы служебный код возврата каретки был вставлен тогда, когда пользователь нажимает клавишу ENTER при вводе текста в многострочное поле редактирования текста в диалоговом окне. Если Вы не определяете этот стиль, нажимая клавишу ENTER, вы получите тот же самый эффект, словно нажали заданную по умолчанию командную кнопку диалогового окна. Этот стиль не имеет никакого влияния в однострочном окне редактирования.

  • Игорь Шевченко © (14.10.09 17:32) [7]
    (c) MSDN
    ES_PASSWORD
    Displays an asterisk (*) for each character typed into the edit control. This style is valid only for single-line edit controls.

    Так как в коде принудительно устанавливается ES_MULTILINE, то ES_PASSWORD выключается.

    Предлагаю исправить

    procedure TUniversalCustomEdit.CreateParams(var Params: TCreateParams);

    на

    procedure TUniversalCustomEdit.CreateParams(var Params: TCreateParams);
    const
     Alignments: array[Boolean, TAlignment] of DWORD =
     ((ES_LEFT, ES_RIGHT, ES_CENTER), (ES_RIGHT, ES_LEFT, ES_CENTER));
    begin
     inherited CreateParams(Params);
     with Params do
     begin
       Style := Style and not ES_WANTRETURN {or
           Alignments[UseRightToLeftAlignment, FAlignment]}
    ;
       if (Style and ES_PASSWORD) = 0 then
          Style := Style or ES_MULTILINE;
     end;
    end;

  • harisma © (14.10.09 17:40) [8]
    Это не помогает, поскольку CreateParams вызывается только при создании компонента и больше не вызывается в процессе работы с ним. :(
  • Игорь Шевченко © (14.10.09 17:51) [9]
    Читаем MSDN дальше:

    EM_SETPASSWORDCHAR:
    Edit controls: Multiline edit controls do not support the password style or messages.

    То есть, проблема в том, что компонент всегда устанавливает стиль ES_MULTILINE. Можно сделать свою реакцию на сообщение EM_SETPASSWORDCHAR, если PasswordChar не нулевой, сбрасывать ES_MULTILINE и вызывать обработку этого сообщения в предке.
  • harisma © (14.10.09 18:07) [10]

    > Можно сделать свою реакцию на сообщение EM_SETPASSWORDCHAR

    А можно подробнее? Дело в том, что даже в родном TCustomEdit реакция на это сообщение отсутствует. И вообще нигде в Дельфе нет реакции на такое сообщение. Оно обрабатывается где-то глубоко-глубоко в недрах Винды.

    Игорь, а у вас вообще описанная проблема этим компонентом проявляется на вашей машине?
  • Игорь Шевченко © (14.10.09 18:25) [11]

    > Игорь, а у вас вообще описанная проблема этим компонентом
    > проявляется на вашей машине?


    А у меня на машине приложению не удалось запуститься, поскольку vcl50.bpl не был найден.


    > А можно подробнее?


    Можно подробнее (не пробовал, но где-то так, сама идея)

     TCustomUniversalMaskEdit = class(TCustomEdit)
     private
       procedure EmSetpasswordChar (var Message: TMessage); message EM_SETPASSEORDCHAR;
     .....
     end;

    procedure TCustomUniversalMaskEdit.EmSetpasswordChar (var Message: TMessage);
    var
     OldStyle: ULONG;
    begin
     if PasswordChar <> #0 then { Он к этому времени уже должен быть установлен }
     begin
        OldStyle := GetWindowLong(Handle, GWL_STYLE);
        if (OldStyle and ES_MULTILINE) <> 0 then
          SetWindowLong(Handle, GWL_STYLE, OldStyle and not ES_MULTILINE);
     end;
     inherited;
    end;



    Это первый способ. Второй способ - замаскировать свойство, объявив
    у TCustomUniversalMaskEdit public-свойство PasswordChar

     public
       property PasswordChar: Char read GetPasswordChar write SetPasswordChar;

    function TCustomUniversalMaskEdit.GetPasswordChar: Char;
    begin
     Result := inherited PasswordChar;
    end;

    procedure TCustomUniversalMaskEdit.SetPasswordChar(const Value: Char);
    begin
     RecreateWnd;
     if Value <> #0 then
       { Убрать es_multiline из стиля }
     inherited PasswordChar := Value;
    end;

  • harisma © (14.10.09 19:08) [12]
    Игорь, я выложил другую версию моего проекта, где он скомпилирован без галочки "Build with runtime packages".
    Ее можно взять тут:
    http://depositfiles.com/files/0jwvwf11z

    Пробуйте ее запустить.
  • Игорь Шевченко © (14.10.09 19:39) [13]

    > Пробуйте ее запустить.


    Запустил, при нажатии на кнопки ничего не меняется.
    Windows XP Professional Russian, SP3
  • harisma © (14.10.09 19:55) [14]

    > при нажатии на кнопки ничего не меняется.

    Вот и у нас такая же проблема. :(

    Кстати, попробовал я реализовать ваши предложения на предмет замаскировать свойство PasswordChar - результат к сожалению нулевой. :(

    Теперь у вас есть исходник компонента и пример его неработоспособности. Можете попробовать его исправить, раз у вас этот эффект проявляется?
  • Игорь Шевченко © (14.10.09 20:08) [15]
    harisma ©   (14.10.09 19:55) [14]

    Попробовать могу, если мне будет выслан (дана ссылка на выложенный) готовый проект (dpr+pas+dfm и ничего более), чтобы я смог его сразу скомпилировать на D2006, не устанавливая никаких компонентов (то есть, в проекте должно быть динамическое создание сторонних компонентов)
  • Игорь Шевченко © (14.10.09 20:13) [16]
    А еще лучше, чтобы не тратить ничье время, поступить так:
    Известно, что PasswordChar гарантировано не будет работать на компонентах с кнопками, унаследованных от TCustomEdit.
    Поэтому, если необходим PasswordChar именно на таких компонентах, от этой идеи отказаться сразу, а контролы, где нужен PasswordChar, сделать на обычных TEdit.
  • harisma © (14.10.09 20:30) [17]
    Хорошо, Я выложил проект здесь:
    http://depositfiles.com/files/blifqwpeq
    Берите, пробуйте.
  • Игорь Шевченко © (14.10.09 20:56) [18]
    harisma ©   (14.10.09 20:30) [17]

    То есть, мой совет [16] не подошел ?

    Я ведь его не просто так дал: компоненты с кнопками внутри окна редактирования используют посылку сообщения EM_SETRECTNP для того, чтобы отсечь область реактирования от области, где будет нарисована кнопка. А это сообщение имеет смысл только если у контрола стоит стиль ES_MULTILINE.

    Поэтому от идеи использовать PasswordChar в таких компонентах лучше сразу отказаться.
    А Edit-ы простого вида можно ведь и с помощью стандартного TEdit сделать.

    Вот и вопрос - стоит ли пробовать ?
  • harisma © (15.10.09 11:33) [19]

    > Поэтому от идеи использовать PasswordChar в таких компонентах
    > лучше сразу отказаться.

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

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

    Кстати, в контролах с кнопками сам смысл прятания текста за звездочками теряется, поскольку допустим у стиля fesInteger текст можно набрать на выпадающем калькуляторе, у стиля fesListBox все варианты выбора отображаются в выпадающем ListBox (типа как стандартный ComboBox) и т. д.

    Соответственно задача сводится только к обеспечению поддержки PasswordChar для стиля fesSimple.
 
Конференция "Компоненты" » PasswordChar для компонента [D5, WinXP]
Есть новые Нет новых   [134427   +26][b:0][p:0.005]