Specifying a Window Procedure for child Windows
Asked Answered
W

2

7

I would like to know if its possible to specify a WndProc for a Child Window created by CreateWindowEx.

I have created a Window Class, the Main Window, the Window Procedure and a Message Loop already. The code works and I decided to keep it out for the clarity of my question.

This is my Window Proc, so far:

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        // Creation of the Win32 Window
        case WM_CREATE:
            // Add an Edit Field
            CreateWindowEx(
                WS_EX_CLIENTEDGE,
                "EDIT",
                "",
                WS_CHILD | WS_VISIBLE,
                5, 5, 200, 24,
                hwnd,
                (HMENU)100,
                g_Instance, // Comming from WinMain
                NULL
            );
            return DefWindowProc(hwnd, uMsg, lParam, wParam);
        case WM_KEYDOWN:
            // Track key presses on the edit field
            std::cout << "The key with the code " << wParam << " was pressed." << std::endl;
            return 0;
        case WM_PAINT:
            // Some painting code...
            return DefWindowProc(hwnd, uMsg, lParam, wParam);
        default:
            return DefWindowProc(hwnd, uMsg, lParam, wParam);
    }
}

I expected key presses on the child Edit Field that I created to throw a WM_KEYDOWN message, but they dont! The keys just get added to the Edit Field in my Window but do not cause a WM_KEYDOWN message.

It seems that the created Edit Window does not use my WndProc. How can I change that?

Workbench answered 5/6, 2015 at 13:40 Comment(0)
C
9

Your WndProc don't get WM_KEYDOWN messages because, if the user is typing inside the edit control, it means that it has the focus (not your window), so they are sent to the edit control window proc, not yours. However, the edit control window proc will send notifications to your WndProc (his parent window proc).

So, if you only want to react to the user changing the content of your child edit control, you don't need another window procedure. Your current WndProc will receive EN_CHANGE notification code through a WM_COMMAND message.

See https://msdn.microsoft.com/en-us/library/windows/desktop/bb761676(v=vs.85).aspx


If you really want to catch WM_KEYDOWN messages, you need to subclass the edit control, like this:

OldWndProc = (WNDPROC)SetWindowLongPtr (hButton, GWLP_WNDPROC, (LONG_PTR)NewWndProc);

You also need to define a new windows procedure (the NewWndProc), that should handle WM_KEYDOWN message (and any other message you want to handle). You also need to call OldWndProc as you would call DefWndProc in a standard WndProc, unless you want to prevent the edit control to do its normal processing.

For details on subclassing, see https://msdn.microsoft.com/en-us/library/windows/desktop/bb773183(v=vs.85).aspx

Edit

Responding to OP comment here.

If your window is a dialog box, you should be notified of enter key, in your WndProc:

 case WM_COMMAND:

      if(wParam == IDOFDEFBUTTON || wParam == IDOK) ...

See https://support2.microsoft.com/Default.aspx?scid=kb;en-us;Q102589

To be honest, I never took the time to understand what a dialog box really is. But if I recall correctly, you can get your window to get theses special notifications by calling IsDialogMessage in your message pump:

if(!IsDialogMessage(hWnd,&msg)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
 }

For interesting information about IsDialogMessage, see http://blogs.msdn.com/b/oldnewthing/archive/2012/04/16/10293933.aspx

If this doesn't give you enough control, you probably have to subclass the edit control.

Christophany answered 5/6, 2015 at 13:58 Comment(1)
Thanks a lot for the detailed answer. So I see EN_CHANGE gets fired when ever something happened in the child control. But is there a way to get WHAT happened with it? For example which key was pressed? Would be very handy if I could handle a key down of the Enter Key. Or will I need to subclass for that?Workbench
C
3

Your call to CreateWindowsEx creates a new window with "EDIT" wnd class having its own Window procedure. You need a new WndProc and set it to the newly created window (whose handle is returned by CreateWindowEx) via SetClassLong function

Chinaware answered 5/6, 2015 at 13:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.