0

Appreciate guidance and help here please;

I have searched and tried many solutions and it seems non are working with .Net 6 when I tried to center the MessageBox.Show() at the center of the parent Form!

So I have followed this: Winforms-How can I make MessageBox appear centered on MainForm?

AND How to Make MessageBoxes Center on their Parent Forms

When I tried to debug the code above and step through, the hook is not being called. Win32 is a wrapper calss of User32.dll

public static DialogResult Show(string msg, string title, MessageBoxButtons btns, MessageBoxIcon icon)
            {
                // Create a callback delegate
                _hookProcDelegate = new Win32.WindowsHookProc(HookCallback);
    
                // Remember the title & message that we'll look for.
                // The hook sees *all* windows, so we need to make sure we operate on the right one.
                _msg = msg;
                _title = title;
    
                // Set the hook.
                // Suppress "GetCurrentThreadId() is deprecated" warning. 
                // It's documented that Thread.ManagedThreadId doesn't work with SetWindowsHookEx()
    #pragma warning disable 0618
                _hHook = Win32.SetWindowsHookEx(Win32.WH_CBT, _hookProcDelegate, IntPtr.Zero, AppDomain.GetCurrentThreadId());
    #pragma warning restore 0618
    
                // Pop a standard MessageBox. The hook will center it.
                DialogResult rslt = MessageBox.Show(msg, title, btns, icon);
    
                // Release hook, clean up (may have already occurred)
                Unhook();
    
                return rslt;
            }


    private static int HookCallback(int code, IntPtr wParam, IntPtr lParam)
            {
                int hHook = _hHook; // Local copy for CallNextHookEx() JIC we release _hHook
    
                // Look for HCBT_ACTIVATE, *not* HCBT_CREATEWND:
                //   child controls haven't yet been created upon HCBT_CREATEWND.
                if (code == Win32.HCBT_ACTIVATE)
                {
                    string cls = Win32.GetClassName(wParam);
                    if (cls == "#32770")    // MessageBoxes are Dialog boxes
                    {
                        string title = Win32.GetWindowText(wParam);
                        string msg = Win32.GetDlgItemText(wParam, 0xFFFF);  // -1 aka IDC_STATIC
                        if ((title == _title) && (msg == _msg))
                        {
                            CenterWindowOnParent(wParam);
                            Unhook();   // Release hook - we've done what we needed
                        }
                    }
                }
                return Win32.CallNextHookEx(hHook, code, wParam, lParam);
            }

_hook returns 0 / Last Error Code 87 (ERROR_INVALID_PARAMETER)

_hHook = Win32.SetWindowsHookEx(Win32.WH_CBT, _hookProcDelegate, IntPtr.Zero, AppDomain.GetCurrentThreadId());
int lastErrorCode = Marshal.GetLastWin32Error();

The SetWindowsHookEx:

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
            public static extern int SetWindowsHookEx(int idHook, WindowsHookProc lpfn, IntPtr hInstance, int threadId)

;

I ran the same code with .Net Framework 4.8 and it works fine! is there anything I have to update to make it works with .Net 6

Unis
  • 365
  • 1
  • 4
  • 13
  • CBT hook, yuck. Nobugz code still has no bugs, works fine in net6.0 – Hans Passant Jul 29 '22 at 17:20
  • I know, tell me about :(. I did not know of CBT hook until I came across this issue. I ran the demo side by side on `.net 6` and `net framework`. worked fine on `.net framework` but not on `.net 6` – Unis Jul 29 '22 at 17:37
  • Just in case, you can easily do that with UI Automation. Add a Handler to `WindowPattern.WindowOpenedEvent`, with target `AutomationElement.RootElement`. When a MessageBox is shown, the event is raised: check that `[Element].Current.ClassName == "#32770" && [Element].Current.ProcessId == Process.GetCurrentProcess().Id`. If the condition is met, use `[Element].Current.NativeWindowHandle` to call `GetWindow()` with `uCmd` set to `GW_OWNER`, then `var ownerForm = Control.FromHandle([Owner]);`. Call `MoveWindow()` (the MessageBox has no `TransformPattern`) to center `[Element]` on `ownerForm`. – Jimi Jul 29 '22 at 19:35
  • 1
    @Jimi Thank you. Would you mind adding an answer with the actual code, please? It's just hard to follow on comments and I am just scratching the surface with C# and Windows Application. It looks sooooo much better than dealing with CBT hook :(. – Unis Jul 29 '22 at 20:01
  • @Jimi: Please don't answer in comment, create a real answer. – Poul Bak Jul 29 '22 at 22:40
  • @PoulBak I cannot post answers here for now, I can only give some suggestions (mostly when it looks like not so many are willing to provide an actual answer). – Jimi Jul 29 '22 at 23:30

0 Answers0