Tweak subclass procedure so it can be used both in window and dialog box
Asked Answered
H

0

1

I am trying to catch ENTER and ESC key press in singleline edit control.

When user presses ENTER or ESC I want to take away keyboard focus from edit control and set it to listview control. Listview control is edit control's sibling.

My goal is to write single subclass procedure that can be used for subclassing edit controls in both main window and dialog box.

I have found this MSDN article that I found useful because of its second solution. Below is my adaptation of the code.

// subclass procedure for edit control
LRESULT CALLBACK InPlaceEditControl_SubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam,
    UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (message)
    {
    case WM_GETDLGCODE:
        return (DLGC_WANTALLKEYS | DefSubclassProc(hwnd, message, wParam, lParam));
    case WM_CHAR:
        //Process this message to avoid message beeps.
        switch (wParam)
        {
        case VK_RETURN:
            // change focus to listview
            SetFocus(hwndListView);
            return 0L;
        case VK_ESCAPE:
            // change focus to listview
            SetFocus(hwndListView);
            return 0L;
        default:
            return ::DefSubclassProc(hwnd, message, wParam, lParam);
        }
        break;
    case WM_KEYDOWN:
        switch (wParam)
        {
        case VK_RETURN:
            // change focus to listview
            SetFocus(hwndListView);
            return 0L;
        case VK_ESCAPE:
            // change focus to listview
            SetFocus(hwndListView);
            return 0L;
        default:
            return ::DefSubclassProc(hwnd, message, wParam, lParam);
        }
        break;
    case WM_NCDESTROY:
        ::RemoveWindowSubclass(hwnd, InPlaceEditControl_SubclassProc, uIdSubclass);
        return DefSubclassProc(hwnd, message, wParam, lParam);
    }
    return ::DefSubclassProc(hwnd, message, wParam, lParam);
}

QUESTION:

Is my adaptation correct or am I missing something (maybe instead of SetFocus I should use WM_NEXTDLGCTL like Raymond Chen pointed out)?

Heartbreaking answered 18/5, 2015 at 2:31 Comment(6)
As you found out already, calling SetFocus in a dialog will fail to update its internal state. This will lead to situations, where two button controls appear to be the default button at the same time. Since the documentation for WM_NEXTDLGCTL doesn't state that it can be sent to non-dialog windows, you'd have to write conditional code (that's what a standard edit control does).Collie
Since I don't know whether WM_NEXTDLGCTL is applicable to non-dialog windows, I asked a question. If the answer is, that you can use the message with any window, you'd simply have to replace your SetFocus-calls (and remove those in your WM_CHAR handler; this handler prevents message beeps due to the DLGC_WANTALLKEYS flag).Collie
Since I don't know whether WM_NEXTDLGCTL is applicable to non-dialog windows I have tested it with my subclass procedure, it does not seem to work. It is logical when you come to think of it, which means that I must have 2 separate subclass procedures. (and remove those in your WM_CHAR handler; I do not understand what you meant, can you edit the code in my post or be more detailed? I will start a bounty on this one, in hope someone like Raymond Chen can shed some authoritative light on this issue. It really sucks if one must duplicate code to handle both dialogbox and window...Heartbreaking
Since you asked for DLGC_WANTALLKEYS, you have to deal with keys that the standard edit control doesn't normally receive, namely VK_RETURN and VK_ESCAPE. You already updated input focus in your WM_KEYDOWN-handler, so you can simply ignore the keys in your WM_CHAR-handler, like the reference code does. No need to update the input focus again. Not trying to disappoint you, but there is no such thing as someone like Raymond Chen, much in the same way as there is no such thing as someone like Cuck Norris.Collie
@IInspectable: OK thank you. Not trying to disappoint you, but there is no such thing as someone like Raymond Chen, I did not mean to degrade/humiliate anyone, I just wanted to say that someone as experienced as him might know something we don't. It is my last hope, otherwise I really believe that I will be forced to duplicate the code as I firmly believe that WM_NEXTDLGCTL doesn't work in normal window. Again, I apologize if I offended you in any kind.Heartbreaking
I'm sorry, that didn't come across as intended. I wasn't offended in any way, just meant to point out, that it is rare to find someone who has either reverse engineered the dialog manager, or has access to the source code for the dialog manager, or has actually implemented the dialog manager.Collie

© 2022 - 2024 — McMap. All rights reserved.