c00000fd
c00000fd

Reputation: 22255

How to use accelerator table in a subclassed control?

I am subclassing a control and at this point I want to add some keyboard shortcuts to it. There's about a dozen of them defined in an accelerator table in the resource.

I know that I can utilize these accelerators from the main app, by calling TranslateAccelerator and then TranslateMessage and DispatchMessage from its main loop.

But can I check if accelerator key sequence is pressed from a subclassed control from within WndProc itself?

EDIT: In other words, would it be bad to do something like this?

LRESULT CSubclassedWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    // TODO: Add your specialized code here and/or call the base class

    if(message == WM_KEYDOWN ||
        message == WM_CHAR ||
        message == WM_SYSKEYDOWN ||
        message == WM_SYSCHAR)
    {
        if(hAccel)
        {
            CRect rcThis;
            this->GetWindowRect(&rcThis);
            this->ScreenToClient(&rcThis);
            POINT pnt = {(rcThis.right + rcThis.left) / 2, (rcThis.bottom + rcThis.top) / 2};

            MSG msg = {this->GetSafeHwnd(), message, wParam, lParam, ::GetTickCount(), pnt};
            if(::TranslateAccelerator(this->GetSafeHwnd(), hAccel, &msg))
            {
                //Accelerator was recognized and sent as WM_COMMAND message to the same window
                return 0;
            }
        }
    }

    switch(message)
    {
    case WM_COMMAND:
        {
            //Special accelerator commands
            if(HIWORD(wParam) == 1 &&
                lParam == 0)
            {
                //See which command was it
                switch(LOWORD(wParam))
                {
                case ID_MY_ACCELERATOR_ID1:
                    {
                        //Do work...
                    }
                    return 0;

                case ID_MY_ACCELERATOR_ID2:
                    {
                        //Do work...
                    }
                    return 0;
                }
            }
        }
        break;

    case WM_ERASEBKGND:
        //process it
        return TRUE;
    case WM_PAINT:
        //process it
        return TRUE;
    case WM_KEYDOWN:
        //process it
        break;

    //etc.
    }

    return CWnd::WindowProc(message, wParam, lParam);
}

Upvotes: 0

Views: 248

Answers (1)

Anders
Anders

Reputation: 101569

I believe the standard Windows controls just use WM_KEYDOWN/CHAR and GetKeyState but I don't see why you can't use TranslateAccelerator.

TranslateAccelerator is in some ways better because it knows how to handle Alt.Gr but it will also ignore the key if the mouse is captured (IIRC) so it depends on your needs.

Calling TranslateAccelerator on the top-level window after GetMessage is of course the best option because it will check the window menu to see if the command is disabled...

Upvotes: 2

Related Questions