How to customize the Enter key in the dialog box

Source: Internet
Author: User
In a dialog box-based program, the program exits every time you press the Enter key. Removing the bs_defpushbutton attribute of the button and rewriting the onok function is useless. How can we customize the carriage return key? This problem is easy, but it takes some time to understand it. This problem has been around for a long time in Windows development. For Beginners, this is an annoying problem. Fortunately, people have found a variety of solutions to this problem. This article will show you how to customize the Enter key behavior. If you want to disable the Enter key, the simplest way is to reload the onok function. This is not a bad idea, but if you reload onok, let it do nothing, what should I do when I press the Enter key with the mouse? You can change the ID of the Enter key, for example, id_my_ OK, and write a processor that calls enddialog. This method can also work, but it seems a little unprofessional. Another method is the "default" attribute of the disable return key. This is also the method proposed at the beginning of this article. The reason for the failure is that the bs_defpushbutton attribute of the uncheck return key is not enough, you can use Spy ++ to carefully observe the control and experiment, and then you can find that the Enter key still sends an Exit message. What is the problem? You must differentiate the OK key and the Enter key. You can write an onok processor to call the getcurrentmessage function to obtain the final message sent, which should be wm_command, and then check the low-order word (low-order word) of wparam) see where the command comes from. To solve the problem, you must understand what is happening behind the scenes. In spy ++, you can see that when you press the Enter key, windows sends a special wm_getdefid message to obtain the default command ID. Windows then sends it as wm_command. So what you need to do is to reload the wm_getdefid message. In the relevant Windows documents, wm_getdefid is described as the returned value: "If there is a default button, the returned value contains dc_hasdefid, the low-level word contains the identifier of the control. Otherwise, the return value is zero ." Based on the description in this section, if no default button exists, the return value should be zero. If you want to disable the default ID, you must return the dc_hasdefid in the high-level text.
Begin_message_map (cmydlg, cdialog)
On_message (dm_getdefid, ongetdefid)
...
End_message_map ()

Lresult cmydlg: ongetdefid (wparam WP, lparam LP)
{
Return makelong (0, dc_hasdefid );
}
Because MFC does not have a macro corresponding to dm_getdefid, you must use a general on_massage macro. In this way, you can press the Enter key at will, but nothing will happen. The above method solves the problem of exiting by pressing the Enter key program. But another problem arises: What should I do if I want to press the Enter key? Some people have asked you how to map the Enter key to the tab key, which is the same as pressing the Enter key-that is, moving the input focus to the next dialog box for control. This requires some work, but the simplest way is to use the acceleration key. Many programmers try to use onchar, and I will say to them: No, no, no! Onchar is a low-level interesting thing. You should try to avoid it. Worse, there are wm_keydown, wm_keyup, and so on. Who can handle these things? Onchar can be used to restrict characters that can be entered in the edit box, such as numbers and letters. To map a key to a command, the acceleration key is the best method. In this example, we create an acceleration key for vk_return, map it to the command id_my_enter, and write a command processor to do what you want.
Begin_message_map (cmydlg, cdialog)
On_command (id_my_enter, onmyenter)
......
End_message_map ()

Void cmydlg: onmyenter ()
{
Nextintaborder ();
}

Is the dialog box and code in this example. In the code, nextintaborder is a function that actually works. It uses getnextdlgtabitem to obtain the next control focus of the tab order.
If you are careful, you will find another problem that has not been solved, that is, the acceleration key is not automatically processed in the MFC dialog box, and you must write your own code to do this. To understand why, let's look back at the windows development process. In the age of C and the original Windows API, every Windows program had a central loop called message pump:
While (getmessage (...)){
Translatemessage (...);
Dispatchmessage (...);
} Here, the details are not important. What matters is that the message does not reach the program process. You must request the message. This is a man-made, non-preemptive multi-task method. This method uses the collaboration of each task to simulate a multi-task environment. As more and more functions are added, someone has come up with the idea of accelerating the key table, this table is used to map keys and command IDs. To achieve this, they invented a function called translateaccelerator. Now the message pump looks like this:
While (getmessage (...)){
If (translateaccelerator (haccel ...)){
// Handled, continue looping
} Else {
Translatemessage (...);
Dispatchmessage (...);
}
} Haccel is a key table handle. The details here are also not important. What is important is how to use the key table, that is, a special function is required to interpret the key message as a wm_command message. The translateaccelerator searches for the characters in the wm_keydown, wm_char, and wm_keyup sequences that match the table's key values. If it is found, it inserts a wm_command into the message queue. The command ID in the Message Queue can be any entry defined in the acceleration key table. In this way, you only need to set the acceleration key table (in the resource) and remember to call the corresponding function translateaccelerator, so you don't have to worry about anything. In a twinkling of an eye, it entered the 21st century. With the maturity of C ++ and MFC, almost all the message loops (but not all) are hidden in the MFC, in order to give any window a chance to get a message pump, MFC provides a dedicated virtual function pretranslatemessage. If you have enough courage to explore the Message Processing Mechanism in cwinthread, you will encounter code similar to the following:
// Simplified cwinthread
While (getmessage (...)){
If (pretranslatemessage (...)){
// Continue looping
} Else {
Translatemessage (...);
Dispatchmessage (...);
}
}
Cwinthread: pretranslatemessage is a virtual function. In an application, its default implementation calls another virtual function, cwnd: pretranslatemessage, with the same name. Therefore, if you need to do something in a message loop-for example, explain the acceleration key-you just need to reload pretranslatemessage. In fact, this is how cframewnd processes the acceleration key.
Bool cframewnd: pretranslatemessage (MSG * PMSG)
{
......
If (PMSG-> message> = wm_keyfirst &&
PMSG-> message <= wm_keylast)
{
: Translateaccelerator (m_hacceltable ,...);
}
} Where does cframewnd obtain the acceleration key table? When you load the framework, cframewnd: loadframe uses the same ID (such as idr_mainframe) as the document template to find the acceleration key table and load it to m_hacceltable. All the processing details are automated and concealed in MFC, so you don't have to worry about it-for the main framework only, if it is a dialog box, it is another situation. Because cdialog is not derived from cframewnd, it does not inherit any content related to the acceleration key. Don't worry, we can imitate the work of cframewnd, it is easy to add the acceleration key function for the dialog box. The first step is to load the acceleration key. The best place to load the acceleration key is in the oninitdialog function of the dialog box:
Bool cmydlg: oninitdialog ()
{
Cdialog: oninitdialog ();
......
// Load Accelerators
M_haccel =: loadaccelerators (afxgetresourcehandle (),
M_lpsztemplatename );
Assert (m_haccel );

Return true;
} In the acceleration key table, you can use any ID. Here I use the ID of the dialog box itself, (m_lpsztemplatename can be either a string name or an integer ID used by makeintresource ):
// The acceleration key (in dlgkeys. Rc) in this example)
Idd_mydialog accelerators discardable
Begin
Vk_return, id_my_enter, primary key, noinvert
End

Once you have loaded the acceleration key, the remaining thing is to reload the pretranslatemessage function:
Bool cmydlg: pretranslatemessage (MSG * PMSG)
{
If (wm_keyfirst <= PMSG-> message &&
PMSG-> message <= wm_keylast)
{
Haccel = m_haccel;
If (haccel &&
: Translateaccelerator (m_hwnd, haccel, PMSG ))
Return true;
}
Return cdialog: pretranslatemessage (PMSG );
} The reason for checking the key-type messages (from WM _ keyfirst to wm_keylast) is to increase the speed. If you know that it is not a key message, you don't have to waste time calling the translateaccelerator. Besides, translateaccelerator is a virtual function without adding a message ing entry. Just write this function. To sum up, in MFC, the acceleration key function is added to the dialog box by loading the acceleration key and reloading the pretranslatemessage function. That is to say, if you decide to use the acceleration key, you don't have to worry about ongetdefid, but map the ID without the command processor to vk_return. The example code in this article encapsulates a new dialog box class with the acceleration key: cdlgwinaccelerators, which is a common class. I hope everyone will like it. Finally, I wish everyone a pleasant programming experience. Reference from:

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.