Может ли Windows управлять несколькими точками фокусировки на одном элементе управления? - PullRequest
0 голосов
/ 03 января 2012

Я создаю пользовательский элемент управления, который должен иметь несколько точек фокусировки.Например, в 1 элементе управления, скажем, есть 3 области (могут быть определены как прямоугольник на холсте), которые должны иметь фокус.В зависимости от того, какой из них имеет фокус, я не хочу, чтобы вокруг него была пунктирная линия Windows по умолчанию, а какая-то особая обработка.Я ничего не знаю о том, как даже дать одному пользовательскому элементу управления свой собственный фокус.

Первоначальный проект представлял собой один TPanel с несколькими элементами управления VCL, каждый из которых, конечно, имел свое собственное окно, таким образом, имея свой собственный фокус.Но теперь я помещаю его в собственный класс, который больше не будет существовать в этих трех элементах управления (они были там только в версии 1 в качестве прототипа), и теперь мне нужно каким-то образом имитировать фокус в этих различных регионах.

Я полагаю, что нечто похожее на что-то простое, например, TListBox, где определенные элементы в этом элементе управления получают фокус вместо целого элемента управления.

Вот изображение, помогающее продемонстрировать, что я делаю...

enter image description here

На верхнем изображен оригинал с кнопками.Но тот, что внизу, - это новый, который я строю и который все нарисован на заказ.

Чтобы уточнить, я хотел бы узнать, есть ли в Windows специальная обработка для этого типа сценария, прежде чем я начнузаново изобрести колесо.

Я не ищу "Самый простой" способ сделать это.И я также не хочу, чтобы рекомендации вернулись к тому, что у меня было раньше, потому что есть много причин, по которым я не хочу 1 элемент управления с несколькими другими элементами управления внутри.Мне просто нужно «да» или «нет» с объяснением.

Подробнее

Я только что понял, что основная проблема заключается в использовании клавиши tab.Элемент управления должен сначала получить фокус, запустить фокус на любом подпункте, который он должен, затем ответить на tab по моей команде, пока он не достигнет конца, затем передать табуляцию следующему элементу управления.Тогда это также нуждается в Shift + Tab, а также.Как, черт возьми, я бы реализовал эту вкладку?Вот где я застрял, но меня просто поразило, что это главная причина, по которой я спрашиваю.

Ответы [ 3 ]

4 голосов
/ 04 января 2012

Об обработке клавиши TAB - должно быть что-то вроде этого: вы обрабатываете сообщение WM_GETDLGCODE , чтобы указать, что вы хотите обработать TAB ключом, то есть

TMyControl = ...
  protected
     procedure WMGetDlgCode(var Msg: TMessage); message WM_GETDLGCODE;
     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
...
procedure TMyControl.WMGetDlgCode(var Msg: TMessage);
begin
  inherited;
  Msg.Result:= Msg.Result or DLGC_WANTTAB;
end;

и в переопределенном методе KeyDown вы решаете, что делать в ответ на него, что-то вроде

procedure TMyControl.KeyDown(var Key: Word; Shift: TShiftState);
begin
  if(Key = VK_TAB)then begin
     if(ssShift in Shift)then begin
        if(first subcontrol is focused) set focus to previous control on parent
        else set focus to previous child area
     end else begin
        if(last subcontrol is focused) set focus to next control on parent
        else set focus to next child area
     end;
  end else inherited;
end;
3 голосов
/ 03 января 2012

Нет, вы не можете заставить окна распознавать несколько точек фокусировки клавиатуры внутри одного дескриптора окна, поскольку каждый элемент управления с дескриптором окна либо имеет, либо не имеет фокус клавиатуры. «Внутренний фокус» между несколькими элементами управления зависит от вас.

Как вы уже знали, самый простой способ сделать это - иметь несколько субэлементов управления со своими собственными оконными дескрипторами, как вы и сказали:

TMyThreeEditControls = class(TControl) //  parent has no window handle!!!!
    protected
        FEdit1:TEdit;
        FEdit2:TEdit;
        FEdit3:TEdit;
    ...
end

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

Короче говоря, «составной» подход, когда вы включаете в свой основной элемент управления субобъекты (другие элементы управления), от которого вы пытаетесь отойти, фактически является единственным способом, позволяющим Windows выполнять большую часть работы.

С другой стороны, то, что вы, возможно, ищете, это не способ рисования самого элемента управления, а некоторый код, позволяющий создать видимость, что он сфокусирован, в ваших собственных пользовательских процедурах рисования, если это то, чем вы являетесь ищите, вы должны заглянуть в исходный код VCL или эту ссылку на about.com для примеров того, как сказать Windows нарисовать прямоугольник фокуса и т. д. Ссылка about.com является имитацией и не использовать реальный код Windows для рисования фокуса с учетом темы Windows.

Обновление: возможно, что вы также ищете способ определить, находятся ли координаты мыши в указанном прямоугольнике (прямоугольник представляет собой кнопку в вашем случае) и, если это так, нарисовать "горячее состояние" «для кнопки. Есть больше подзадач, которые необходимо выполнить, если вы хотите создать элемент управления самостоятельно, я рекомендую вам изучить существующие элементы управления, такие как TStringGrid и TCategoryButtons, в исходном коде VCL, чтобы увидеть код обработки MouseMove, MouseDown и MouseUp, который вам понадобится. делать то, что вы пытаетесь сделать. В частности, исходный код StringGrid - это способ увидеть, как «клавиша табуляции» может использоваться в одном элементе управления с одним дескриптором окна, поскольку в этом элементе управления клавиша табуляции может использоваться (если включены правильные параметры) для перемещаться по всем ячейкам в сетке строк, как если бы каждая была отдельным элементом управления, даже если это все один элемент управления.

1 голос
/ 04 января 2012

Еще один способ добиться этого - использовать одно поле редактирования, которое вы повторно используете для каждого региона, на который вы хотите «сфокусироваться». По сути, именно так работают решетки Delphi.

Когда пользователь щелкает в этой области (или нажимает клавишу Tab в вашем элементе управления), вы устанавливаете текст элементов управления для редактирования в данные в этой области, устанавливаете границы элементов управления для редактирования в этой области и делаете их видимыми. Когда пользователь выходит из элемента управления (нажав на него или вкладку), вы скрываете элемент управления редактирования. Если вы заставите свой элемент управления принять клавишу табуляции, вы можете заставить ее «редактировать» следующую область, когда они нажимают на табуляцию, и выходить из нее, когда они находятся в последней области.

Тогда вам нужно просто сохранить введенные данные в нужном месте в вашем компоненте.

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