User Tools

Site Tools


replacing_20the_20message_20pump

Replacing the message pump

by Richard Russell, January 2012

In Windows, every User Interface (UI) thread must have a message pump (or message loop), the function of which is to serialise and dispatch incoming messages to their destination windows.

In BBC BASIC for Windows the message pump is provided by the Run Time Engine, and generally the programmer doesn't need to be aware of it. For anybody who may be interested, this is its C code:

  while (GetMessage (&msg, NULL, 0, 0) != FALSE )
       {
         if (((hwndMDIC == NULL) ||
             !TranslateMDISysAccel (hwndMDIC, &msg))
          && ((haccel == NULL) ||
             !TranslateAccelerator (hwacc, haccel, &msg)))
           {
             TranslateMessage (&msg) ;
             DispatchMessage (&msg) ;
           }
       }

Very occasionally there may be a requirement to use a different message pump. For example, in order for keyboard navigation to work in a dialogue box, the message pump must include a call to the IsDialogMessage API.

Until very recently I believed that it was impossible to replace the existing BB4W message pump, and that therefore the only way to provide a different one was to start a new thread (each thread has its own message pump). This is the principal reason why the WINLIB2 library creates a new thread for every new dialogue box created.

However I have discovered that in fact there is a way of replacing the 'main' message pump, and the procedure listed below does exactly that:

        DEF PROCnewmessagepump
        LOCAL K%, L%, M%, N%, O%, P%, S%, U%, code%, pass%
        DIM code% 130, L% -1
        FOR pass% = 8 TO 10 STEP 2
          P% = code%
          [OPT pass%
          .K%
          add esp,28
          ret 16
 
          .N%
          sub esp,28
          push 0 : call "ReplyMessage"
          .U%
          push @hwnd% : call "IsWindow" : or eax,eax : jz K%
          mov eax,esp : push 0 : push 0 : push 0 : push eax
          call "GetMessage" : or eax,eax : jz K%
          push esp : push @haccel% : push @hwnd% : call "TranslateAccelerator"
          or eax,eax : jnz U%
          call "GetForegroundWindow"
          cmp eax,@hwnd% : jz S%
          push esp : push eax : call "IsDialogMessage"
          or eax,eax : jnz U%
          .S%
          push esp : call "TranslateMessage"
          push esp : call "DispatchMessage"
          jmps U%
 
          .M% cmp dword [esp+8],&502 : jz N%
          pop eax : push [^O%] : push eax : jmp "CallWindowProc"
          ]
        NEXT pass%
        SYS "GetWindowLong", @hwnd%, -4 TO O%
        SYS "SetWindowLong", @hwnd%, -4, M%
        SYS "SendMessage", @hwnd%, &502, 0, 0
        SYS "SetWindowLong", @hwnd%, -4, O%
        SYS "SendMessage", @hwnd%, 0, 0, 0
        ENDPROC
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
replacing_20the_20message_20pump.txt · Last modified: 2024/01/05 00:21 by 127.0.0.1