News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Block Popup Messagebox on alt+spacebar

Started by raleep, July 25, 2012, 01:29:17 PM

Previous topic - Next topic

raleep

I found some C code that allegedly does it:

public override bool PreProcessMessage(ref Message msg)
        {
            // Always check for your window as the recipient!
            if (msg.HWnd == this.Handle)
            {
                // msg.Msg 0x104 is for SysKey
                // WParam 0x20 is for space key
                // LParam 0x20390001 is for space key modified by alt key
                if (msg.Msg == 0x104 && msg.WParam.ToInt32() == 0x20 && msg.LParam.ToInt32() == 0x20390001)
                {
                   // Prevent the message from being process, thus preventing the pop-up
                   // Use this time to alert anything that you want to know that alt+space was received
                    MessageBox.Show(msg.ToString());
                    msg = new Message();
                }
            }
            return base.PreProcessMessage(ref msg);
        }


I tried the following in an attempt to implement this:


WProc proc wp_hWnd,uMsg,wParam,lParam

pushad
mov eax, [uMsg]
mov edx, [wParam]
mov ecx, [lParam]
                           ;test for and process messages
cmp eax, WM_SYSKEYDOWN
  jnz @F
cmp ecx,20390001       ;alt spacebar
  jnz key

popad
mov eax,OFFSET NewMessage      ;a 0-terminated string
ret

@@:                        ;continue testing messages


Not surprisingly this doesn't work.

How does the C code work (assuming it does)?

Can anyone help?

Thanks, Robert

jj2007

Why so complicated? You could

- show the MsgBox until the user clicks cancel (which sets a "don't show again" flag, as in the deb macro)

- check for the state of CapsLock with GetKeyState (after all, you are only interested in your own app - otherwise use GetAsyncKeyState, but I doubt it will make a difference for CapsLock)

Or is there some other logic behind?

raleep

Quote from: jj2007 on July 25, 2012, 05:17:17 PM
Why so complicated? You could

- show the MsgBox until the user clicks cancel (which sets a "don't show again" flag, as in the deb macro)

The only options in the box are restore,minimize, and close (which exits the app),  Just pressing the alt key gets rid of the box, but I don't want it to show at all or require any action by the user.
Quote
- check for the state of CapsLock with GetKeyState (after all, you are only interested in your own app - otherwise use GetAsyncKeyState, but I doubt it will make a difference for CapsLock)

The CapsLock state has nothing to do with it.

Thanks,  Robert

Ryan

You could set a flag in the WM_SYSKEYDOWN message, and then reset it in the WM_SYSKEYUP message.  Check the flag before you show the MessageBox.

raleep

Quote from: Ryan on July 25, 2012, 11:43:50 PM
You could set a flag in the WM_SYSKEYDOWN message, and then reset it in the WM_SYSKEYUP message.  Check the flag before you show the MessageBox.

I don't "show the MessageBox".  It pops up automatically.  In almost any active window (not desktop, but explorer windows, browser windows, etc.).

I never noticed it before because I never had a reason to press alt+spacebar, but now I want to use alt+spacebar in ny app.

Thanks,  Robert

raleep

1.  The source of the C code is

Visual Studio Developer Center >Visual C# Forums > Visual C# Language > Disable Alt + Space
http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/3107c8df-8bb0-4152-ac1f-a86894972a6f
Post by IsshouFuuraibou Friday, November 03, 2006 6:47 AM

But I don't think there is any more information there.

2.  I also tried without success:

cmp eax, WM_SYSKEYDOWN
  jnz @F
cmp ecx,20390001       ;alt spacebar
  jnz key

popad
mov eax,OFFSET NewMessage      ;a 0-terminated string
mov uMsg,eax
xor     eax,eax
ret


The code is reached and executed, after which the popup appears (in the WinDbg debugger).

3.  The key routine executes popad
xor eax,eax
ret

whenever an alt key is detected (uMsg=12h).


Thanks,  Robert

Ryan

So it's not a MessageBox you're trying to block; it's the system menu.

Depending on how you create your window, you can omit WS_SYSMENU.  This will also get rid of the minimize, maximize and close (X) buttons.  WS_SYSMENU is included in WS_OVERLAPPEDWINDOW.

qWord

Removing TranslateMessage() from the message lopp maybe solve your problem.
MREAL macros - when you need floating point arithmetic while assembling!

Ryan

Would an Accelerator work?  If you let the Accelerator do the work, you could bypass TranslateMessage and DispatchMessage in your message loop entirely.

qWord

Filtering WM_SYSCOMMAND seems also to work:
.elseif uMsg == WM_SYSCOMMAND
    .if !(wParam == SC_KEYMENU && lParam == 20h)
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .endif
MREAL macros - when you need floating point arithmetic while assembling!

raleep

Quote from: Ryan on July 26, 2012, 12:28:10 AM
So it's not a MessageBox you're trying to block; it's the system menu.

Depending on how you create your window, you can omit WS_SYSMENU.  This will also get rid of the minimize, maximize and close (X) buttons.  WS_SYSMENU is included in WS_OVERLAPPEDWINDOW.

Yess!  That certainly appears to work.  I replaced WS_OVERLAPPEDWINDOW in my CreateWindowEx code by the other WS_'s included and, voila, no popup.  And I still have the minimize, maximize and close (X) buttons

I didn't know the popup was called the system menu.

Thank you!

Best wishes, Robert

raleep

Quote from: raleep on July 26, 2012, 04:51:51 AM

Yess!  That certainly appears to work.  I replaced WS_OVERLAPPEDWINDOW in my CreateWindowEx code by the other WS_'s included and, voila, no popup.  And I still have the minimize, maximize and close (X) buttons

Correction: I do not have the minimize, maximize and close (X) buttons.  And evidently WS_MINIMIZEBOX  & WS_MAXIMIZEBOX require WS_SYSMENU.

So I guess I'll go back to WS_OVERLAPPEDWINDOW, curse Microsoft, and use alt+w or some such instead of alt+spacebar.

Thanks,  Robert

Ryan

Look at qWord's post about filtering WM_SYSCOMMAND.

jj2007

At the end of the WM_CREATE handler:
push rv(GetSystemMenu, hWnd, 0)
.Repeat
invoke DeleteMenu, [esp+8], 0, MF_BYPOSITION
.Until !eax
pop eax
No more menu with Alt Space... but there are side effects :icon_mrgreen:

Now, honestly, try this:
CASE WM_SYSCOMMAND
.if wParam==SC_KEYMENU
return 1
.endif

:icon14:

npnw



http://msdn.microsoft.com/en-us/library/windows/desktop/ms646360(v=vs.85).aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633570(v=vs.85).aspx#designing_proc

Your application can call the DefWindowProc function as part of the processing of a message. In such a case, the application can modify the message parameters before passing the message to DefWindowProc, or it can continue with the default processing after performing its own operations.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms647591(v=vs.85).aspx

Accelerators
Accelerator keystrokes that select items from the window menu are translated into WM_SYSCOMMAND messages.
If an accelerator keystroke occurs that corresponds to a menu item when the window that owns the menu is minimized, no WM_COMMAND message is sent. However, if an accelerator keystroke occurs that does not match any of the items in the window's menu or in the window menu, a WM_COMMAND message is sent, even if the window is minimized.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646373(v=vs.85).aspx

Applies to: desktop apps only
Processes accelerator keys for menu commands. The function translates a WM_KEYDOWN or WM_SYSKEYDOWN message to a WM_COMMAND or WM_SYSCOMMAND message (if there is an entry for the key in the specified accelerator table) and then sends the WM_COMMAND or WM_SYSCOMMAND message directly to the specified window procedure. TranslateAccelerator does not return until the window procedure has processed the message.

Return value
Type: int
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.