Как установить порядок перемещения между элементами управления Windows, созданными во время выполнения? - PullRequest
0 голосов
/ 12 декабря 2011

В нашем приложении есть ряд диалогов, для которых шаблон диалога определяет 4 кнопки в нижней части экрана.Однако (в зависимости от того, на какой версии нашего оборудования работает приложение) мы иногда создаем 2 дополнительные кнопки, а затем выстраиваем в ряд 6 кнопок (4 из шаблона, 2, созданные с помощью вызова CButton :: Create ()) вдоль нижней части.

У меня проблема в том, что обычно пользователь может перемещать фокус между этими кнопками с помощью клавиш со стрелками влево / вправо (нет мыши или сенсорного экрана, только ограниченная клавиатура).Это следует за TAB-порядком управления, как и следовало ожидать для 4 кнопок из шаблона. Однако 2 динамически создаваемых элемента управления, по-видимому, вставляются в начале TAB-порядка, и это означает (потому что они размещены в правой части экрана), что они находятся в «неправильном»msgstr "порядок, насколько идут клавиши курсора.Другими словами, когда фокус попадает на левую кнопку (порядок TAB 1), нажатие левой стрелки перемещает фокус на кнопку на правой стороне, что просто сбивает с толку ...

Кажется, что есть некоторая связь между Z-порядком (на который я могу повлиять SetWindowPos()) и TAB-порядком, но это не похоже на простое отношение 1 к 1: изменяя Z-порядок, я могу перемещать последовательностьвокруг так, чтобы кнопки были полностью в неправильном порядке, поэтому я могу изменить Z-порядок, но не могу понять, как получить их в правильном порядке.

Может ли кто-нибудь дать краткое объяснение того, как работает порядок TAB и как управлять последовательностью элементов управления во время выполнения?

Редактировать: Кол, предложенный ниже с использованием SetWindowPos()установить Z-порядок.Это я уже пробовал раньше, но это не позволяет клавишам курсора управлять фокусом, как ожидалось.

Однако, подтасовав это, я могу использовать TAB (в качестве теста - это не практично для конца-пользовательское решение) Я считаю, что решение Кола разрешает TAB-порядок.У меня проблема в том, что это не такой же, как порядок, используемый клавишами курсора!

Итак, пересмотрен вопрос: как я могу указать порядок, в котором левые / правые клавиши курсорапереместить фокус между элементами управления?

Решение: С помощью входов kol и MarkRansom я получил это сейчас.

Я использовал SetWindowPos(), как предложил kol дляпоставил мои новые кнопки после существующих кнопок в порядке TAB, а затем (как предложил Марк) сделал первую кнопку WS_GROUP | WS_TABSTOP, но очистил эти флаги от других кнопок.

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

Я посмотрел на свой шаблон диалога,и это было так:

IDD_QUERY DIALOG  0, 0, 156, 34
STYLE DS_SETFONT | WS_POPUP | WS_CAPTION
FONT 8, "MS Sans Serif"
BEGIN
    PUSHBUTTON      "+++Skey1+++",IDC_SKEY_1,1,21,36,12
    PUSHBUTTON      "+++Skey2+++",IDC_SKEY_2,40,21,37,12
    PUSHBUTTON      "+++Skey3+++",IDC_SKEY_3,79,21,36,12
    PUSHBUTTON      "+++Skey4+++",IDC_SKEY_4,118,21,36,12
    LTEXT           "Static",IDC_QUERY_MSG,2,1,153,15
END

Таким образом, статический IDC_QUERY_MSG, который используется для отображения информации для пользователя, шел после 4-й кнопки в шаблоне.Чтобы решить проблему, я переместил IDC_QUERY_MSG до первой кнопки (IDC_SKEY_1): это означает, что 6 кнопок не разделены статическим промежуточным звеном, и решил проблему.

Спасибо всем за помощь!

Ответы [ 5 ]

1 голос
/ 13 декабря 2011

Попробуйте:

  1. Создайте вектор идентификаторов dlg и заполните его в том порядке, в котором вы хотите, чтобы порядок табуляции был:

    typedef std::vector<int> TABLIST;
    
    TABLIST lst;
    lst.push_back( IDC_CONTROL1 );
    lst.push_back( IDC_CONTROL2 );
    lst.push_back( IDC_CONTROL3 );
    
  2. Затем вызовите метод setTabOrder со списком:

    void setTabOrder( TABLIST * plstTabs)
    {
        // Iterate through the list and put each item at the top of the tab order.
        // Remember to do this backwards so the last item is actually the first item
        // in the tab order
    
        HDWP hDefer = BeginDeferWindowPos( (int)plstTabs->size() );
    
        for ( TABLIST::reverse_iterator itTab = plstTabs->rbegin(); itTab != plstTabs->rend(); ++itTab )
        {
            DeferWindowPos( hDefer, GetDlgItem( *itTab )->m_hWnd, HWND_TOP, 0,0,0,0, 
                        SWP_NOSIZE | SWP_NOMOVE | SWP_NOREPOSITION );
        }
    
        EndDeferWindowPos( hDefer );
    
    }
    
1 голос
/ 12 декабря 2011

Используйте SetWindowPos член ваших кнопок. Вызов его на кнопку A и установка его первого параметра на кнопку B переводит кнопку A после кнопки B в порядок TAB. Если вы хотите установить порядок двух элементов управления, вы должны знать элементы управления до и после них в порядке TAB - этот пример показывает, как это сделать (это не MFC, а чистый WinAPI, но это легко понять).

== ОБНОВЛЕНИЕ ==

Я создал шаблон диалога с четырьмя кнопками внизу и окном редактирования сверху, с порядком табуляции button1 -> button2 -> button3 -> button4 -> editbox -> button1 -> ... В OnInitDialog я добавил две дополнительные кнопки во время выполнения и вставил их в существующий порядок табуляции между button4 и editbox с использованием SetWindowPos и GetNextWindow. Повторное нажатие клавиши TAB показывает, что порядок табуляции правильный: button1 -> button2 -> button3 -> button4 -> button5 -> button6 -> editbox -> button1 -> ...

class CTestDlg : public CDialogEx
{
public:
    CTestDlg() : CDialogEx(CTestDlg::IDD) {}
    enum { IDD = IDD_TESTDIALOG };

protected:
    CButton button5;
    CButton button6;
    virtual BOOL OnInitDialog();
};

BOOL CTestDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    CButton* button4 = (CButton*)GetDlgItem(IDBUTTON4);
    CWnd* next = button4->GetNextWindow(GW_HWNDNEXT);

    button5.Create("Button5", WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_PUSHBUTTON, CRect(340, 172, 415, 195), this, 1005);
    button5.SetWindowPos(button4, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 

    button6.Create("Button6", WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_PUSHBUTTON, CRect(422, 172, 497, 195), this, 1006);
    button6.SetWindowPos(&button5, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 

    if (next != NULL)
        next->SetWindowPos(&button6, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 

    return TRUE;
}

void CDynamicMfcButtonTestApp::OnTestRun()
{
    CTestDlg testDlg;
    testDlg.DoModal();  
}

== ОБНОВЛЕНИЕ2 ==

Порядок элементов управления можно установить с помощью SetWindowPos и GetNextWindow, как указано выше. «Порядок табуляции» и «порядок стрелок» можно установить, установив стили элементов управления WS_TABSTOP и WS_GROUP:

  • Стиль WS_TABSTOP определяет элементы управления, к которым пользователь может двигаться, нажимая клавишу TAB или клавиши SHIFT + TAB.

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

Более подробную информацию можно найти на MSDN, здесь .

0 голосов
/ 24 ноября 2017

Если вы говорите о порядке вкладок различных элементов управления в диалоговом окне:

Попробуйте это Откройте dlg в ресурсе и нажмите Ctrl + D Теперь вы можете установить порядок, выбирая элементы управления один за другим.

0 голосов
/ 05 сентября 2013

Модифицированная версия кода @ snowduded , позволяющая убедиться, что стиль WS_TABSTOP также используется.

// Build your order in a vector.
std::vector<WORD> vCtrlIds;
vCtrlIds.push_back(IDC_CONTROL1);
vCtrlIds.push_back(IDC_CONTROL2);
vCtrlIds.push_back(IDC_CONTROL3);
// ... keep doing it!

// Iterate through the list and put each item at the top of the tab order.
// Remember to do this backwards so the last item is actually the first item
// in the tab order.
HDWP vDefer = BeginDeferWindowPos(vCtrlIds.size());
for(auto vCtrlId(vCtrlIds.rbegin()); vCtrlId != vCtrlIds.rend(); ++vCtrlId){
    HWND vCtrl(GetDlgItem(*vCtrlId)); // Grab the handle.
    SetWindowLongPtr(vCtrl, GWL_STYLE, // Make sure we have WS_TABSTOP.
        GetWindowLongPtr(vCtrl, GWL_STYLE) | WS_TABSTOP);
    DeferWindowPos(vDefer, vCtrl, HWND_TOP, 0, 0, 0, 0, // Reorder.
        SWP_NOSIZE | SWP_NOMOVE | SWP_NOREPOSITION );
}
EndDeferWindowPos(vDefer);

Переход к @ snowdude дляотличное многоразовое решение.

0 голосов
/ 12 декабря 2011

Вы не можете изменить порядок вкладок во время выполнения. Что вы можете сделать, это поместить эти две кнопки в свой ресурс диалога (с правильным порядком вкладок) и сделать их невидимыми. Затем вы показываете / расставляете кнопки, как только они вам нужны.

...