⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 07.6 输入焦点的传递.txt

📁 网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
💻 TXT
📖 第 1 页 / 共 2 页
字号:

2. LRESULT CALLBACK NewEditProc ( 

3. HWND hwnd , 11 handle to window 

4. UINT uMsg , 11 message identifier 

5. WPARAM wParam, 11 first message parameter 

6. LPARAM lparam 11 second message parameter 

7. ) 

8. { 

9. if( uMsg WM_CHAR && wParam OxOd) 

10. { 


11. 11 : : SetFocus (GetNextW工ndow(hwnd, GW_HWNDNEXT)) ; 
12. SetFocus(: :GetWindow (hwnd, GW_HWNDNEXT) ); 

13. return 1; 

14. } 

15. else 

16. { , uMsg , wParam, lParam);

17. 18. return prevProc(hwnd. 



19. } 
Build并运行Mybole程序,打开测试对话框,先把输入焦点放到第一个编辑框中,然后按下回车键,将会发现输入焦点转移到了第二个编辑框。可见,上述例7-33代码同样实现了所需功能。
第三种获得窗口句柄的方法:利用 GetNextDlgTabltem函数来实现。该函数将返回指定控件前面或后面的一个具有WS TABSTOP风格的控件。关于WS TABSTOP风格,可以打开测试对话框中任一个编辑框控件的属性对话框,如图 7.43所示,可以看到有一个 Tab stop选项,如果选中该选工页,就设置了编辑框具有WS TABSTOP风格。读者可以再看看测试对话框中其他控件的属性,将会发现默认情况下,所有的编辑框控件和按钮控件都选中了此选工页,而静态文本控件并没有选中此选工页。如果设置了这个Tab stop属性,则在对话框中按下Tab键后,输入焦点可以转移到此控件上。 
Ed此l..il!l ".. Ir;:r!马,生F唱~ 
叫臣豆豆1 "y'" I e-.... Slylcs I '" 
回 IIDC_EOITl工j 
w、,....Ie r 6reup r恤"'0「剧.....ed 
~ T..…, 
图 7.43编辑框控件的属性对话框

260 I ~~ 

vc忡深λ详解 
GetNextDlgTabltem函数的原型声明如下所示: 
HWND GetNextDlgTabltem(HWND hDlg , HWND hCtl , BOOL bPrevious) ; 
该函数各个参数的意义如下所述: 
. hDlg 
指定将被搜索的对话框。 
. hCtl 
指定用来作为搜索开始点的控件。 
,
. bPrevious 
指定搜索的方向。如果此参数为TRUE,则该函数将寻找对话框中上一个控件:如果此参数为FALSE,则该函数将搜索对话框中下一个控件。
可见,如果想要利用 GetNextDlgTabItem函数来实现所需功能,首先需要获得对话框的句柄,而当前只有该对话框中子控件的句柄。可以通过调用子控件的 GetParent函数,得到它的父窗口,也就是对话框的句柄。另外,应该把GetNextDlgTabItem函数的第三个变量设置为FALSE,让它查找下一个控件。这样,在Mybole程序中,应把上面例7-33所示代码中第 12行代码,即调用GetWindow函数的语句替换为下面这行代码: 
SetFocus( ::GetNextDlgTab工tem( ::GetParent(hw口d) , hwnd, FALSE) ) ; 
再次Build井运行Mybole程序,先将输入焦点放在第一个编辑框,然后按下回车键,可以发现输入焦点被转移到第二个编辑框了。口J见,此方法同样实现了所需功能。如果想让焦点在对话框中各控件上依次传递,按照上述方法来实现的话,很显然是比' 
较麻烦的。这里再介绍另一种实现方法,就是利用对话框的默认按钮。在MFC中,默认情况下,当在对话框窗口中按下回车键时,会调用对话框的默认按钮的响应函数,我们可以在此默认按钮的响应函数中把焦点依次向下传递。
为了利用这种方法,首先将第一个编辑框的MultiLine选项取消。然后在CTestDlg类的OnOK函数中添加例7-34所示代码中加灰显示的那行语句。 
19IJ7-34 
void CTestDlg : :OnOK() 
// TODO : Add extra validation here 
GetDlg工tem(IDC_EDIT1) . >GetNextWindow()->SetFocus() ; 
//CDialog: :OnOK() ; 
这行新添加的代码先调用GetDlgltem函数获取第一个编辑框的窗口指针,然后利用此
. 指针调用 GetNextWindow函数得到它的下一个窗门,最后调用 SetFocus函数将输入焦点
设置到该窗口上。这里使用的都是CWnd类的成员函数,其中 GetNextWindow函数的原型声明如下所
刁之: 
. 


" I 261 
第 7章对话框( ) 
CWnd* GetNextWindow( U工 NT nFlag = GW_HWNDNEXT ) Consti 
该函数只有一个参数,用来指定返回的是下一个窗口的句柄 CGW_HWNDNEXT),还是上一个窗口的旬柄 (GW_HWNDPREV)。默认值就是 GW_HWNDNEXT,因此,这里不需要给它传递参数了。 
Build并运行 Mybole程序,打开测试对话框,先把焦点放置到第一个编辑框中,按下回车键,将会发现焦点转移到第二个编辑框了,但再次回车时,焦点并未转移到第三个编辑框中。我们分析一下 OnOK函数中添加的代码,这句代码首先获取到第一个编辑框的窗口指针,调用它的下一个窗口,并设置焦点。当再次回车时,仍由这个函数来响应,那么它获得的仍是第一个编辑框的指针,把焦点传递给它的下一个窗口,从而永远不会把焦点传递到第三个编辑框中。
为了使焦点能够依次向下传递,应该获取的是当前拥有焦点的窗口,然后利用此窗口去调用 GetNextWindow函数,得到当前拥有焦点的窗口的下一个窗口,再设置后者拥有焦点。因此,实现代码应该如下所示,即应该将上述例 7-34所示的 OnOK函数中己有的那行 GetDIgItem调用代码替换掉,换成例 7-35所示代码中加灰显示的那行代码: 
{9IJ 7-35 

void CTestDlg : :OnOK() // TODO : Add extra validation here 
//GetDlg工tem(工DC-EDITl)-〉GetNextWLrldow()-〉SetFocus() ; 
GetFocus()->GetNextWindow()->SetFocus() i 
CDialog : :OnOK()i 

Build并运行 Mybole程序,打开测试对话框,先把输入焦点放到第一个编辑框,然后按下回车键,将会发现焦点转移到第二个编辑框,再次按下回车键,可以看到焦点转移到了第三个编辅框。但是当我们继续再按三次回车键后,程序将弹出一个如图 7.44所示的对话框,提示程序出现了非法访问。这主要是因为在程序运行时,在调用 GetNextWindow函数获得下一个窗口的过程中,当对对话框中最后一个控件调用此函数时,它返回的这个窗口指针是一个空 (NULL)指针,此时再对该指针调用 SetFocus函数,就会出现非法访问,程序就会弹出如图 7.44所示的对话框。 

s 


、西‘革面....引用的、姐回回lD2II"冉lf.疆冉哥不幢2、Nd". 


.. I 
图 7.44非法访问提示对话框

如果我们把上述例 7-35所示的 OnOK函数中调用的 GetNextWindow函数换成 GetWindow函数,即用下面这行语句来代替该行代码,结果会如何呢? 
GetFocus()->GetWindow(GW_HWNDNEXT)->SetFocus()i 
262 I ~~~ 
vc忡深λ详解
读者会发现程序仍会出现上述的非法访问错误,这是因为 GetNextWindow和 GetWindow这两个函数的调用机理是一样的。为了解决这个问题,可以使用CWnd类的另一个成员函数: GetNextDlgTabltem来获取对话框中的下一个控件。该函数的原型声明如下所示: 
CWnd* GetNextDlgTab工tem( CWnd* pWndCtl , BOOL bPrevious = FALSE ) const i 
这个函数与上面介绍的 SDK同名函数的作用相同,其参数就是后者的后两个参数。因此,用下面这条语句代替上述例7-35所示的OnOK函数中调用GetNextWindow函数的那行代码: 
GetNextDlgTab工tem(GetFocus())->SetFocus() ; 
Build井运行Mybole程序,打开测试对话框,并把输入焦点放到第一个编辑框上,然后按下回车键,可以发现焦点转移到了第二个编辑框,继续按回车键,会发现焦点在对话框的各控件间来回传递。程序一切正常。
实际上, GetNextDlgTabltem函数和先前使用的GetNextWindow和GetWindow这两个函数搜索窗口的行为是不一样的。前者是查找具有Tab stop属性的控件,并按Tab顺序依次查找各控件。那么对话框的Tab顺序是什么样的顺序呢?在VC++开发环境窗口中,打开对话框资源编辑器,然后选择【Layout】菜单,会发现其中有一个【Taborder】菜单项,单击该菜单命令,然后在对话框资源编辑器中可以看到对话框各个子控件上都有一个序号 (如图7.45所示),这些序号就是各控件的Tab顺序。当用户在对话框中按 FTab键后,输入焦点将按照这个顺序依次传递。这个顺序是可以改变的,例如,如果想让本例中第一个编辑框的序号为1,可以在如图7.45所示状态下用鼠标单击这个控件,此时,会看到第一个编辑框的序号变为L OK按钮的序号为2,如图7.46所示。 

型回些lIfii军噩噩.
也酬,耻一:,.......啊?
1'"啊,咽了一一

吼叫WY『旦」吼恤.3啊?回刷 j i 
吼叫嘀「甲坦」吨编" l L哩雪:二J 
. 

>
图7.45对话框上各控件的初始Tab顺序图7.46将第一个编辑框的Tab顺序改为 l

再次运行Mybole程序,把输入焦点放置到第一个编辑框中,然后按下回车键,将会发现这时程序首先将焦点传递到 OK按钮上,然后是 Cancel按钮。也就是说, GetNextDlgTabltem函数按照各子控件的 Tab序号循环地去查找下一个窗口。 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -