PreTranslateMessage equivalent in a non-MFC Win32 app

Recently this question came up in the Microsoft MFC Newsgroup, where someone was porting an MFC app to pure-API, and wanted to know what the PreTranslateMessage equivalent was for the pure-API application. Essentially all you need to do is to put your code just before the TranslateMessage call, as shown in the code snippet below :-

// Main message loop
while (GetMessage(&msg, NULL, 0, 0))
{
    if (!TranslateAccelerator(
        msg.hwnd, hAccelTable, &msg))
    {
        //Put your PreTranslateMessage stuff here
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

Or if you don’t want to do that, you could do this as well, though it seems less elegant :-

LRESULT CALLBACK WndProc(HWND hWnd,
    UINT message, WPARAM wParam, LPARAM lParam)
{
    //Put your PreTranslateMessage stuff here

    switch (message)
    {
    case WM_COMMAND:
        //...
    case WM_PAINT:
        //... etc.

    default:
        return DefWindowProc(hWnd,
            message, wParam, lParam);
    }
    return 0;
}

The basic thing to remember is that, there is no message called PreTranslateMessage in Win32. PreTranslateMessage is something the MFC developers added so that we have an option to do something before a call is made to TranslateMessage/DispatchMessage; and incidentally, some Win32 Gurus like Joe Newcomer for instance, are quite vocal about their opinion that using PreTranslateMessage is bad style.

Advertisements

11 thoughts on “PreTranslateMessage equivalent in a non-MFC Win32 app

  1. Nish..
    I am creating an ATL Composite control.There in the control class i couldn’t find any PreTranslateMessage.Can i use the same code there?I have a webbrowser control in that, and i am handling its events in Invoke method.

  2. Hi Dreamz

    Uhm, if you want to handle the keyboard, override PreTranslateAccelerator.

    For the ATL control, you don’t really have direct access to the message handling loop. So you cannot use the technique I’ve mentioned in the blog entry [as far as I know, but I am not much of an ATL guy, so better double check this elsewhere].

  3. Hi again Dreamz

    In my previous reply, I assumed that your ATL control was in a DLL. If it is in an EXE, then you can override PreMessageLoop.

    BTW I assume that you are using VC++ 7.1 🙂

  4. Hi Nish,

    I agree with first implementation of PreTranslateMessage pure WIN32 programming. I have a doubt on second implementation of PreTranslateMessage in WndProc. As of my knowledge WndProc procedure is called by DispatchMessage API. Before this usally TranslateMessage is called. Greatly appriciated if you clarify this.

    Thanks
    Choudam

  5. Hi Choudam

    Your interpretation is very correct. The second alternative is not really a pre-translate-handler, but basically for all purposes it serves a similar purpose, in the sense that we still have the option of preventing any specific-message handler from being called, prevent the default window procedure from being called and we can modify WPARAM and LPARAM if we chose to etc. I hope I’ve made myself clear?

  6. Hi nish…

    I’m using a MFC control in managed wrapper ( usercontrol ), the MFC control has keyboard accelrator handled in PreTranslateMessage(over written function ) .. but in .net this function is not at all called … what might be the problem ???
    can u pls tell me ??

    bye
    Chetan.M

  7. hi nish i use a ActiveX control of flash macromedia in a MFC Dialge i try hard to recive
    WM_RBUTTONDOWN message from this control but i fail , what i want is to prevent only
    the right click menu and replace it with any thing menu, messagebox,any thing
    1- i use subclass ,but how to subclass a non MFC control ?
    2- i try to use SetWindowLong with callback dosn’t work

    please can you help but in details or example

  8. In WTL world the Pretranslate is a virtual function in a Class called CMessageFilter

    ///////////////////////////////////////////////////////////////////////////////
    // CMessageFilter – Interface for message filter support

    class CMessageFilter
    {
    public:
    virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;
    };

    Which is then fired in the CMessageLoop class that creates the message pump of ATL/WTL apps like so.
    // message loop
    int Run()
    {
    BOOL bDoIdle = TRUE;
    int nIdleCount = 0;
    BOOL bRet;

    for(;;)
    {
    while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
    {
    if(!OnIdle(nIdleCount++))
    bDoIdle = FALSE;
    }

    bRet = ::GetMessage(&m_msg, NULL, 0, 0);

    if(bRet == -1)
    {
    ATLTRACE2(atlTraceUI, 0, _T(“::GetMessage returned -1 (error)\n”));
    continue; // error, don’t process
    }
    else if(!bRet)
    {
    ATLTRACE2(atlTraceUI, 0, _T(“CMessageLoop::Run – exiting\n”));
    break; // WM_QUIT, exit message loop
    }

    if(!PreTranslateMessage(&m_msg))
    {
    ::TranslateMessage(&m_msg);
    ::DispatchMessage(&m_msg);
    }

    if(IsIdleMessage(&m_msg))
    {
    bDoIdle = TRUE;
    nIdleCount = 0;
    }
    }

    return (int)m_msg.wParam;
    }

  9. Modifying the main message loop does not help to monitor messages in a modal dialog box. The main message loop is never called. Somehow in MFC apps the PreTranslateMessage gives you access to modal dialog box messages, but I see no equivalent way to do it in API apps? Does anyone know how to get to the message loop for modal dialog boxes in an API app? You can see how to do it for MFC apps here:

    http://support.microsoft.com/kb/100770

    but how to do it for API apps, as the main message loop is never called.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s