首先我要申明一下,大家一定要看清楚我的意思,如果不敢肯定的话最好先试一下在回答。我最讨厌问题没看完就下结论者!写得多只是为了更清楚表达我的意思,没看完者请勿回贴!
  问题是这样引出的(以前我发过好几个这样的贴子):假设在按钮1的点击消息响应函数中使按钮1失效,那么在失效前一定要将焦点从按钮1(按钮1被点击,当然获得焦点)上移走,否则失效后的按钮样子很难看(和默认按钮的样子一样,但它不是默认按钮,最糟糕的是,如果再点击另一个按钮,这个被点击的按钮只能得到虚线框,边框没有加厚,说这么多还是建议你试试,VB在这方面就好多了,不用考虑这个问题),下面我说说我发现的这种奇怪现象,还请知情者解释一下:  新建一个对话框程序,“确定”和“取消”按钮不要动,默认(“确定”按钮)按钮也不要去改变,现在如下操作:新建4个按钮(button1 button2 button3 button4),然后重新确定按钮的TAB顺序,使他们的顺序为:button1 button2 button3 button4 IDOK IDCANCEL
给button1和button3添加点击响应函数,并在函数中写入如下程序:
void CLoginDemoDlg::OnButton1() 
{
GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
NextDlgCtrl();
}void CLoginDemoDlg::OnButton3() 
{
NextDlgCtrl();
GetDlgItem(IDC_BUTTON3)->EnableWindow(FALSE);
}  上面的程序效果就是在button1失效的时候将焦点设置在button2上(注意前面说过的TAB顺序),在button3失效的时候将焦点设置在button4上,这是我要的效果,而且工作正常!(大家不要认为我是无聊,我的一个程序就是这样做的:一个向上翻页按钮,一个向下翻页按钮,向上翻到第一页的时候,向上翻页变灰,焦点移到向下翻页上,这是从易用的角度考虑的)  不过大家注意到了吗?第一个函数内是先使窗口无效,再NextDlgCtrl(),而后一函数是先NextDlgCtrl()再使窗口无效,经过我无数次的测试,他们的次序必需是这样,有人能给我一个解释吗?button1和button3的唯一一个区别只是TAB顺序不同!!!
  注:如果使用GotoDlgCtrl函数,则先使按钮无效或先移动焦点效果是一样的,但该函数使用麻烦,需要得到将要获得焦点的窗口指针。  我相信有人要告诉我用SetFocus,用SetFocus设置焦点只是画个虚线框,它与用NextDlgCtrl、PrevDlgCtrl、GotoDlgCtrl设置的焦点有区别,如果以前没用过请自己实验一下。

解决方案 »

  1.   

    在你的两句话中分别加入下面两句话:
    CWnd *pWnd = GetFocus();
    pWnd->SetWindowText("Here");也就是void CLoginDemoDlg::OnButton1() 
    {
    GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE); CWnd *pWnd = GetFocus();
    pWnd->SetWindowText("Here"); NextDlgCtrl();
    }void CLoginDemoDlg::OnButton3() 
    {
    NextDlgCtrl(); CWnd *pWnd = GetFocus();
    pWnd->SetWindowText("Here"); GetDlgItem(IDC_BUTTON3)->EnableWindow(FALSE);
    }运行一下你就知道了(最好是debug模式)。对于先disable当前得到焦点的子窗口,这个时候是没有窗口得到焦点的(指针返回NULL),因此你NextDlgCtrl()会使得焦点设置给tab序为1的子窗口(在这里就是“确定”按钮)。如果你先NextDlgCtrl(),当然得到的是你预期的逻辑啦。
      

  2.   

    你们两人都没有看清楚我的问题!
    对于crystal521(水晶泪) ,两次顺序不一样才能达到目的,我就是问为什么顺序一亲反而达不到目的!!
    对于camelyi(C++打字员),你也一样:
    对于先disable当前得到焦点的子窗口,这个时候是没有窗口得到焦点的(指针返回NULL),因此你NextDlgCtrl()会使得焦点设置给tab序为1的子窗口(在这里就是“确定”按钮)。
    我说的很清楚,TAB第1是button1按钮,你还在糊说,不过你最大的错误是说:焦点设置给tab序为1的子窗口!事实刚好相反--焦点设置在了button2上!!!对于Button1来说:
    void CLoginDemoDlg::OnButton1() 
    {
    GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
    NextDlgCtrl();
    }
    是正确的,而你认为有问题,如果:
    void CLoginDemoDlg::OnButton1() 
    {
    NextDlgCtrl();
    GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
    }
    反而出错。注意你们的专业精神,我这么着重强调大家还是这样,不要把问问题的人当白吃!
    请先按照我说的做一个完全一样的工程,然后再去研究是怎么会事!
      

  3.   

    先申明,我只是个业余爱好者,不是高手。
    再申明,我照楼主说的上机编程试验过。结果:
    1.按钮Button1的tab序为1时,
    点击按钮Button1后,
    void CLoginDemoDlg::OnButton1() 
    {
    GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
    NextDlgCtrl();
    }
    按钮Button1失效,焦点在按钮Button2上,即按钮Button2上有虚线框。
    点击按钮Button3后,
    void CLoginDemoDlg::OnButton3() 
    {
    NextDlgCtrl();
    GetDlgItem(IDC_BUTTON3)->EnableWindow(FALSE);
    }
    按钮Button3失效,焦点在按钮Button4上,即按钮Button4上有虚线框。
    -----------------------
    2.再加上按钮Button0,设置按钮Button0的tab序为1时(注意此处)
    点击按钮Button1后,
    void CLoginDemoDlg::OnButton1() 
    {
    GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
    NextDlgCtrl();
    }
    按钮Button1失效,焦点在按钮Button0上,即按钮Button0上有虚线框。
    点击按钮Button3后,情况同上。个人认为像camelyi(C++打字员)所说,对于先disable当前得到焦点的子窗口,这个时候是没有窗口得到焦点的(指针返回NULL),因此NextDlgCtrl()会使得焦点设置给tab序为1的子窗口。
      

  4.   

    我上面说过:经过我无数次的测试,他们的次序好像必需是这样!
    对于treasurelife(菜虾) ,你比他们专业多了,不过你还是在乱说,下面是你的原话:
    对于先disable当前得到焦点的子窗口,这个时候是没有窗口得到焦点的(指针返回NULL),因此NextDlgCtrl()会使得焦点设置给tab序为1的子窗口。
    事实上点击button1就是先disable再NextDlgCtrl(),结束焦点被设置在了button2(TAB为2)上!!我再简单说说我得到结论,我看大家是没有耐心看懂我的意思了:
    一:如果使TAB为1的按钮失效并将焦点设置在下一个控件上,那么必需先先disable窗口再
    NextDlgCtrl();
    二:如果使TAB大于1的按钮失效并将焦点设置在下一个控件上,那么必需先再NextDlgCtrl();再
    disable窗口。这次我说的够清楚了吧?
    我的问题就是问为什么在这两种情况下,执行disable窗口和NextDlgCtrl();的顺序不一样?!再次强调如果将disable窗口和NextDlgCtrl();的调用顺序设为一样,那么总有一个设置焦点不会成功!我希望不要再来一个像crystal521(水晶泪) 的高手!!
      

  5.   

    楼主,你改过tab序么?我从你的文章里头没有看到这个事实啊。
    如果没有改过,则默认tab序从1到6分别为
    “确定”
    “取消”
    “button1”
    “button2”
    “button3”
    “button4”另外你的语气实在很讨厌!让我忍不住想要捏着鼻子了!
      

  6.   

    刚才我回复的时候楼上的回复还没有,这次我真的无语了。回复人: yang79tao() ( ) 信誉:100 
    我再简单说说我得到结论,我看大家是没有耐心看懂我的意思了:
    一:如果使TAB为1的按钮失效并将焦点设置在下一个控件上,那么必需先先disable窗口再
    NextDlgCtrl();
    二:如果使TAB大于1的按钮失效并将焦点设置在下一个控件上,那么必需先再NextDlgCtrl();再
    disable窗口。对于情况一,我建议你用Ctrl+D看看你的dialog的tab序,看看1到底在哪里,是在button1上还是在IDOK上。如果tab序1在button1上的话,先NextDlgCtrl()再disable和先disable再NextDlgCtrl()结果肯定相同。
    否则的话,先disable,这个时候没有窗口得到焦点,再NextDlgCtrl()就将焦点设置给了IDOK(缺省它的tab序就是1,IDCANCEL为2,其他的加上后依次递增)。忍不住要骂人了,楼主,你自己sb,不要赖别人。
      

  7.   

    新建一个对话框程序,“确定”和“取消”按钮不要动,默认(“确定”按钮)按钮也不要去改变,现在如下操作:新建4个按钮(button1 button2 button3 button4),然后重新确定按钮的TAB顺序,使他们的顺序为:button1 button2 button3 button4 IDOK IDCANCEL上面是我的原话,我一直认为没看清问题的人不要回答问题!!
      

  8.   

    sb楼主,我确保按照你的要求建立了工程。可惜!一:如果使TAB为1的按钮失效并将焦点设置在下一个控件上,那么必需先先disable窗口再
    NextDlgCtrl();对于这一点,我先next再disable结果相同啊!!!
      

  9.   

    唉,如果你再jjww说有问题,那就是你rpwt了!
      

  10.   

    这里我是对所有人说的:
    真是不好意思,今天我在我那个实验用的小工程上,将
    void CLoginDemoDlg::OnButton1() 
    {
    GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
    NextDlgCtrl();
    }
    改为:
    void CLoginDemoDlg::OnButton1() 
    {
    NextDlgCtrl();
    GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
    }
    也能达到要求,看来我以前在使用的时候有点小错误(我在一个很大的工程中发现这个问题的),我会回去找那个大工程中其它可能引起错误的地方,其实我也对为什么调用次序不一样而感到无法理解,故在这里问了一下,现在总是已知道答案:
    对于先使窗口无效,再NextDlgCtrl();因为没有任何子窗口获焦点,故NextDlgCtrl();产生的效果是:从TAB为1的控件开始查找,一直找到一个有效的控件,并将焦点设置给它,对于我的测试工程,就是button2了,这完全是一种巧合,因为将NextDlgCtrl();改成PrevDlgCtrl();后效果还是一样。
      问题的结论,在我那个大的工程中,是其它方面的问题而不是disable窗口和NextDlgCtrl();的调用顺序问题,所以这个问题到此为止,起是对不起大家,不过这50分会平分给你们的。
      

  11.   

    camelyi(C++打字员) 
    看来你比我专业多了,还请问一下你说的这几个名词是什么:
    sb
    jjww
    rpwt
    如果你是男人的话,你不会把“TA Ma DE”换成“TMD",你说呢?
    不过我是真的想知道他们的意思!还请指教。 
    上面的TA Ma DE,因为中文无法发,故用拼音代替!
      

  12.   

    傻*(a < * < c)
    唧唧歪歪
    人品问题楼主满意否?
      

  13.   

    呵呵!
    收到你的消息才来看的,Disable以后失去焦点在NextDlgCtrl当然逻辑乱了