Click here to Skip to main content
15,887,175 members
Articles / Programming Languages / C
Tip/Trick

For Simplicity's Sake in Windows

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
26 Jan 2024CPOL4 min read 4K   1   1
Capture Enter key in edit control with no dialog box and no subclass.
This is another approach to intercepting a key from inside an edit control in Windows. This redirects a message using a field inside the MSG structure in the WinMain message loop instead of subclassing. It is a simple solution for a simple use case.

Introduction

When a dialog box is not used, the purpose of the code is not complex and Microsoft's recommendations are not appropriate, this solution offers an alternative to customising Windows control messages.

Background

I have a Windows single line edit control that the user could enter a filename into. The default processing of this edit control did not include the return/Enter key input because I do not use dialogs. My main window is a straightforward window. The default edit control processes the Enter key by returning to the expected dialog parent. This is no use to me and thus I must code for the use of the Enter key to submit or accept input at the edit control.

Initially, while testing that the input filename was correctly retrieved and processed in my program, my workaround was to focus on the start window (the parent of the edit control) after input and press the Enter key. Just as if there was a Submit or Accept button. My code to retrieve and process the input was then initiated from the start window procedure. Once everything was working well with the input, I needed to find a way to allow the user to enter and return input with the Enter key while inside the edit control. A much more natural method of input.

My research found a lot of solutions to the question of how an application can customise the processing of keys entered into an edit control. But these solutions used subclassing. In subclassing, processing of a control is diverted to an application customised subprocedure. Then the default edit control procedure is called to continue with the rest. This is the recommendation in the Microsoft Learn documentation.

But there is no need to subclass an edit control. In my particular case, I need to process only the Enter key - all other editing can be left to the default edit procedure. So subclassing seems to be overkill in this case. All the text retrieval and processing is already set up from my main/start window procedure. I just need to intercept the edit control Enter key message.

Note that the default edit control process sends EN_CHANGE and EN_UPDATE notifications in the WPARAM parameter through the WM_COMMAND message to the start window procedure every time a character is input. It is an interesting exercise to print the wParam at this point as a hex value. The (HIWORD)wParam part shows whether it is change or update (4 or 3) and the (LOWORD)wParam gives the hex value of the edit control ID specified in the create window function. Change notifies keyboard input and update notifies write of the input to display. The notification values are found in the winuser.h header file.

But I cannot see a way to determine what key is actually pressed at that point. So the message must be rerouted from the edit control to the main window in the message loop of the WinMain entry function. All messages go through this loop.

Using the Code

C++
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    if (GetWindowLongPtr(msg.hwnd,GWLP_ID) == ID_inpfn && msg.wParam == 0x0d)
        SendMessage(hsw,WM_KEYDOWN,(WPARAM)VK_RETURN,0);
}

Whether this condition is true or false, the dispatch of this message here will have no result because the edit control has no dialog box to send to. This is the original problem that is solved when the loop gets the newly sent message from the queue.

msg.hwnd is the window handle that the message was got from - the input edit control in this case.

hsw is the handle of the start window (main window) so that the nessage is processed in the main window WNDPROC function. To make sure that this message is from the edit control and that it is not a return key from the main window for some other purpose, this condition is placed before retrieval and processing of the input:

C++
// in WNDPROC WndProc() switch(uMsg) statement

  case WM_KEYDOWN:
    switch(wParam) {
      case VK_RETURN: {
        HWND hfcs = GetFocus();
        if (GetWindowLongPtr(hfcs,GWLP_ID) == ID_inpfn)  {
            // input workings
        }
        break;
      }

Since the return comes from inside the edit control, the focus must still be with the control.

ID_inpfn is the designated HMENU field in the create window function for the edit control. It is defined in the preprocessor as:

C++
#define ID_inpfn 100
C++
HWND hi = CreateWindowEx(0,
      "EDIT", 0,
      WS_CHILD|WS_VISIBLE|ES_LEFT,
      20,20,100,20,
      hsw, (HMENU)ID_inpfn,
      (HINSTANCE)GetWindowLongPtr(hsw, GWLP_HINSTANCE), 0);

msg.wParam == 0x0d is the hex representation of VK_RETURN, which could be put in there instead for readability. Personally, I like to be reminded that Windows predominately uses hex values.

Points of Interest

It is a useful exercise to take a look at the MSG structure from winuser.h:

C++
typedef struct tagMSG {
  HWND hwnd;
  UINT message;
  WPARAM wParam;
  LPARAM lParam;
  DWORD time;
  POINT pt;
} MSG,*PMSG,*NPMSG,*LPMSG;

From this, we can see different ways to access a message using this available information. This is a simple solution for a simple problem.

History

  • 26th January, 2024: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
New Zealand New Zealand
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Ștefan-Mihai MOGA30-Jan-24 11:10
professionalȘtefan-Mihai MOGA30-Jan-24 11:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.