我们的应用程序中有一系列对话框,这些对话框的对话框模板在屏幕底部定义了4个按钮。 但是(取决于应用程序在哪个硬件版本上运行),有时我们会另外创建2个按钮,然后在底部排列6个按钮(模板中的4个按钮,通过调用CButton :: Create()创建的2个按钮)。

我的问题是通常用户可以使用向左/向右箭头键在这些按钮之间移动焦点(没有鼠标或触摸屏,只有受限的键盘)。 正如您期望模板中的4个按钮一样,这遵循控制TAB顺序。 但是,这2个动态创建的控件似乎是在TAB顺序的开头插入的,这意味着(因为它们位于屏幕的右侧),直到它们位于“错误”顺序为止。光标键消失了。 换句话说,当焦点移至左侧按钮(TAB顺序1)时,按左箭头会将焦点跳转至右侧的按钮,这简直是令人困惑。

Z顺序(我可以用SetWindowPos()影响)和TAB顺序之间似乎存在某些联系,但这似乎不是简单的一对一:通过更改Z顺序,我可以移动序列以便按钮完全按错误的顺序排列,因此我可以更改Z顺序,但无法弄清楚如何按正确的顺序排列它们。

任何人都可以对TAB顺序的工作原理以及运行时如何控制控件顺序进行简要说明吗?

编辑:下面建议使用SetWindowPos()设置Z顺序的kol。 我之前曾尝试过此操作,但它不能让光标键按预期控制焦点。

但是,通过进行组装,我可以使用TAB(作为测试-这对于最终用户解决方案不切实际),我发现kol的解决方案确实可以解决TAB顺序。 我的问题是,这是一样的光标键使用的顺序!

因此,修改后的问题是:如何指定控件之间向左/向右光标键移动焦点的顺序?

解决方案:在kol和MarkRansom的帮助下,我现在开始工作了。

我按照kol的建议使用SetWindowPos()将新按钮按TAB顺序放在现有按钮之后,然后(如Mark所建议的)制成第一个按钮WS_GROUP | WS_TABSTOP 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模板中的第四个按钮之后 要解决这个问题,让我感动IDC_QUERY_MSG第一个按钮( IDC_SKEY_1 ):这意味着6个按键不是由静态其间分手了,并且已经解决了这个问题。

感谢大家的帮助!

===============>>#1 票数:1 已采纳

使用按钮的SetWindowPos成员。 在按钮A上调用它并将其第一个参数设置为按钮B,按TAB顺序将按钮A放在按钮B之后。 如果要设置两个控件的顺序,则必须按TAB顺序了解它们之前和之后的控件- 此示例说明了如何执行此操作(它不是MFC,而是纯WinAPI,但很容易理解)。

==更新==

我创建了一个对话框模板,在其底部有四个按钮,在顶部有一个编辑框,其中的TAB顺序为button1 -> button2 -> button3 -> button4 -> editbox -> button1 -> ...在OnInitDialog中,我添加了两个附加按钮在运行时,并插入到它们之间的现有TAB顺序button4editbox使用SetWindowPosGetNextWindow 反复按TAB键表示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 ==

可以使用SetWindowPosGetNextWindow设置控件的顺序,如上所述。 可以通过设置控件的WS_TABSTOP和WS_GROUP样式来设置“选项卡顺序”和“箭头顺序”:

  • WS_TABSTOP样式指定用户可以通过按TAB键或SHIFT + TAB键将其移动到的控件。

  • WS_GROUP样式标记了一组控件的开始。 如果用户开始按方向键时组中的控件具有输入焦点,则焦点将保留在组中。 通常,组中的第一个控件必须具有WS_GROUP样式,并且组中的所有其他控件都不能具有此样式。 该组中的所有控件都必须是连续的,也就是说,它们必须是连续创建的,没有中间控件。

更多细节可以在MSDN上找到, 在这里

===============>>#2 票数:1

尝试这个:

  1. 创建一个dlg id的向量,并按照您希望按Tab键顺序的顺序填充它:

     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 ); } 

===============>>#3 票数:0

@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以获取出色的可重用解决方案。

===============>>#4 票数:0

如果要讨论对话框中不同控件的选项卡顺序:

尝试此操作在资源中打开dlg,然后按Ctrl + D。现在可以通过依次选择控件来设置顺序。

===============>>#5 票数:-1

您无法在运行时更改选项卡顺序。 可以做的是将这两个按钮放在对话框资源中(按正确的选项卡顺序),并使它们不可见。 然后,您会在需要时立即显示/排列按钮。

  ask by AAT translate from so

未解决问题?本站智能推荐:

2回复

在没有Tab键的情况下在Windows Mobile中的对话框控件之间移动

我有一个用C ++ MFC编写的Windows Mobile 5.0应用程序,其中包含许多对话框。 我当前定位的其中一个设备没有Tab键,因此我想使用另一个键在控件之间移动。 这适用于按钮,但不适用于编辑控件或组合框。 我看过类似的问题,但答案并不适合。 我尝试覆盖CDialog ::
2回复

Windows CE-禁用CComboBox高亮

我正在使用Visual Studio 2008使用C ++和MFC为Windows CE 6编写应用程序。 选择元素后,我想删除CComboBox派生类的蓝色突出显示。 根据此MSDN文章 ,我无法将组合框的样式设置为LBS_OWNERDRAWFIXED或CBS_OWNERDRAWFIX
2回复

滚动后MFC控件消失

我正在WinCE中基于对话框的MFC应用程序上工作。 我在对话框中创建了几个控件并向下滚动。 当我再次向上滚动时,第一个屏幕中的控件消失了。 控制在OnInitDialog()中创建坐标,如下所示,在坐标(50,10)处 我在OnVScroll()中执行的滚动处理如下
1回复

在Windows CE 6.0上无法使用ATL调用Dialog.DoModal

我们有一个适用于Windows CE和Windows Mobile的应用程序。 如果按下工具栏中的按钮,则在此应用程序内部应显示一个对话框。 Windows CE 7和Windows Mobile 6.5.3可以很好地工作,但是由于某些原因,它在Windows CE 6.0上无法工作。 我
2回复

寻找创建C ++ DLL的代码示例然后在C#中进行P / Invoke(适用于Windows CE 5/6)

我有C#的经验,但没有C ++的经验。 最近我的Windows CE 5 C#程序遇到了性能问题,我正在考虑将计算转移到C ++ DLL然后P /从C#调用它,因为C ++支持硬件浮点协处理器而.NET CF则不支持。 我整个上午都在搜索网络,试图找到一个完整的示例,演示如何创建C ++
1回复

如何在Windows CE中优化绘图例程以实现最大刷新率?

在我的应用程序中,我正在绘制一组线(如垂直图),刷新率将在一秒钟内达到30倍左右。 我已经计算出性能,绘制完整线条需要400毫秒,但这还不够快,因为我们必须每34毫秒刷新一次屏幕。 我正在CDC上画画。 我们将在具有400 MHz处理器的Windows CE设备上进行绘图。 绘图
1回复

在运行时从MFC中的派生类添加控件

我有两节课。 class DialogBase继承自CDialog类DialogDerived继承自DialogBase。 我想在通过派生类调用Dialog(CDialogBase)时动态添加一个复选框。 可能吗? 如果有,怎么样?
1回复

Windows CE中的C ++编辑框对齐

我正在使用C ++(MFC)开发Windows CE 6应用程序。 如果在对话框上放置一个编辑框,则可以在设计时在“对话”编辑器中对文本进行对齐,而不会出现问题。 但是,当我将应用程序部署到目标设备时,文本始终会左对齐。 如果我使用m_EditVariable.ModifyStyl
1回复

Windows CE MessageBox不显示Unicode文本和图标透明度

我正在修改Windows CE应用程序以通过Unicode显示各种语言。 通过更改资源文件上的字体,我设法将其显示在按钮中,但无法使其在MessageBox中正确显示“παρίσταταί”。 结果看起来像这样: 我找到了一个开放源代码XMessageBox替代品,并进行
1回复

C ++ / MFC如何将多个文件从PC复制到WinCE(移动设备)?

我试图将整个目录(包括其中的所有文件和子目录)从PC复制到WinCE(移动设备)。 我知道RAPI.DLL可以控制WinCE中的文件,但在PC和WinCE之间似乎不起作用。 都不是Win32文件控制界面。 如果有人帮助我解决这个难题,将不胜感激。 任何可供参考的开源包装器类也