Почему EM_SETMARGINS не работает под Windows 7? - PullRequest
3 голосов
/ 18 ноября 2010

У меня есть сложный визуальный элемент управления, который состоит из поля редактирования и кнопки выпадающего меню. Выпадающая кнопка не является оконным элементом управления и отображается над окном редактирования. Я ограничиваю ширину редактирования следующим вызовом:

SendMessage(Handle, EM_SETMARGINS, EC_RIGHTMARGIN, 
  (DropDownButtonWidth + 2) shl 16);

Он отлично работает в Windows XP, но не работает в Windows 7. В последнем случае, когда фокусированный блок редактирования перекрывает выпадающую кнопку и стирает ее изображение.

Какой будет правильный способ ограничения прямоугольника редактирования в обеих операционных системах?

PS: я тоже попробовал другой подход:

  SendMessage(Handle, EM_GETRECT, 0, LongInt(@Loc));
  Loc.Bottom := ClientHeight + 1;  
  Loc.Right := ClientWidth - FButton.Width - 2;
  Loc.Top := 0;
  Loc.Left := 0;
  SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@Loc));

Но это не работает и для Windows 7.

Ответы [ 2 ]

2 голосов
/ 21 января 2013

Ваш первый код для установки полей верен.

Однако все становится сложно, из-за того, как работает VCL, базовое окно, созданное для данного элемента управления VCL, может быть воссоздано в ответ на изменения, внесенные в VCL.свойства во время выполнения (некоторые изменения свойств могут быть применены только на уровне Windows API путем удаления и повторного создания окна).Хотя порядок сообщений (обычно) не меняется в разных версиях Windows, могут быть введены дополнительные сообщения, некоторые из которых могут изменить порядок, в котором код VCL, обернутый вокруг этих окон, может срабатывать или мешать поведению этого кода.

Возможно также, что в базовых окнах Windows API было введено поведение, которое VCL не обслуживает (опять же, скорее всего, это происходит при смешивании низкоуровневых вызовов API, как в этом случае).

Это особенно актуально при смешивании поведения VCL с низкоуровневыми прямыми вызовами API - как в этом случае.

Существуют и другие вещи, которые могут мешать определенным настройкам после применения, что требует от вассамостоятельно уничтожьте и заново создайте окно и повторно примените свои собственные настройки.

Я видел другие сообщения о проблемах в этой области с тем же кодом (не Delphi) в разных версиях XP - похоже, чтоизменение, внесенное в SP2, которое оказало некоторое влияние наего область.

В случае EM_SETMARGINS У меня была та же проблема, что и вы, и я исправил ее, посмотрев, как элемент управления TButtonEdit сумел применить требуемые поля.(который работал, по крайней мере, на моей установке Windows 7.)

Возможно, мне стало легче благодаря тому, что я реализовал собственный элемент управления вместо того, чтобы пытаться применить поля к некоторому существующему редактированиюконтроль.В приведенных ниже фрагментах кода TCustomPickEdit - это мой пользовательский класс управления, который включает в себя объект fButton , который содержит все настройки, относящиеся к кнопке выбора.Вам нужно будет внести соответствующие коррективы, чтобы применить этот код в вашей конкретной ситуации.

То, что я обнаружил, было следующим:

  1. Поля необходимо было применить как минимум в 3 местах.Во-первых, всякий раз, когда параметры, которые могут повлиять на поля, были изменены, во-вторых, всякий раз, когда создавался дескриптор окна элемента управления для редактирования, и, наконец, всякий раз, когда изменяется шрифт в элементе управления для редактирования:

  2. Даже с полямиПравильно установленный прямоугольник отсечения элемента управления необходимо отрегулировать для обеспечения правильного рисования.Это потребовало переопределить WndProc элемента управления редактированием и перехватить пару сообщений.Этот WndProc также необходим для ответа на уведомление об изменении шрифта для повторного применения полей в случае изменения шрифта элемента управления редактирования.

Код для работы с каждымиз них в моем случае показано ниже:

  procedure TCustomPickEdit.ConfigureButton;
  // 1. Apply margins when button settings are changed 
  begin
    fButton.Caption   := Button.Caption;
    fButton.Flat      := Button.Flat;
    fButton.Glyph     := Button.Glyph;
    fButton.NumGlyphs := Button.NumGlyphs;
    fButton.Visible   := Button.Visible;
    ApplyMargins;
  end;

  procedure TCustomPickEdit.CreateHandle;
  // 2. Apply margins when underlying window handle is created 
  begin
    inherited;
    ApplyMargins;
  end;

  procedure TCustomPickEdit.WndProc(var aMessage: TMessage);
  // 3. Adjust clipping rectangle for correct drawing
  // 4. Apply margins when font is changed
  var
    top: Integer;
  begin
    case aMessage.Msg of
      CN_CTLCOLORSTATIC,
      CN_CTLCOLOREDIT    : if Button.Visible then
                           begin
                             top := fButton.Top;
                             if ThemeServices.ThemesEnabled and Ctl3D then
                               Inc(top);

                             ExcludeClipRect(aMessage.WParam, fButton.Left,
                                                              top + 1,
                                                              fButton.Left + fButton.Width,
                                                              fButton.Height);
                           end;
    end;

    inherited;

    case aMessage.Msg of
      CM_FONTCHANGED : if NOT (csLoading in ComponentState) then
                         ApplyMargins;
    end;
  end;
1 голос
/ 18 ноября 2010

Я подозреваю, что вам, возможно, придется прочитать далее документацию по EM_SETMARGINS.В нем говорится:

HIWORD указывает новую ширину правого поля в пикселях.Это значение игнорируется, если wParam не включает EC_RIGHTMARGIN.

Редактировать элементы управления и Rich Edit 3.0 и более поздние версии: HIWORD может указать значение EC_USEFONTINFO, чтобы установить для правого поля узкую ширину, вычисленную с использованием текстовых метрик элементов управления.текущий шрифтЕсли для элемента управления не установлен шрифт, поле устанавливается на ноль.

Обратите внимание на второй абзац относительно EC_USEFONTINFO, чтобы установить узкую ширину.Это может означать, что это ЕДИНСТВЕННЫЙ способ установить узкую ширину.Я не знаю наверняка, так как не пробовал, но это может помочь.

Обратите внимание, что элементы управления Rich Edit и обычные поля редактирования имеют различное поведение, поэтому проверьте, какой из них вы используете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...