← 输入框|github.com|刷新
Skip to content

Overriden WndProc() method on Form control in WinForms is never getting called #2536

Closed as duplicate

Description

@proneon267

Environment

  • Pythonnet version: 3.0.5
  • Python version: 3.13.0
  • Operating System: Windows 11
  • .NET Runtime: .NET Framework 4.8.9282.0

Details

I am trying to override the WndProc() method on the Form control in WinForms. As described here in the docs: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.wndproc, WndProc() is meant to be overridden to custom handle window messages.

Here is a sample test script:

import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Form, Application
from System.Drawing import Size


class MyForm(Form):
    def __init__(self):
        super().__init__()
        self.Text = "WndProc Example"
        self.Size = Size(300, 200)

    def WndProc(self, m):
        print(f"WndProc called with message: {m}")
        super().WndProc(m)


Application.Run(MyForm())

However, on running the app, the WndProc() method is never getting called. I had also tried to override the WndProc() method of NativeWindow(https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.nativewindow.wndproc?view=windowsdesktop-9.0#system-windows-forms-nativewindow-wndproc(system-windows-forms-message@)), but the overriden WndProc() method is also never getting triggered.

Activity

  1. proneon267 commented on Jan 1, 2025

    @proneon267
    Author

    For anyone else who might need it, we can achieve the same using win32 APIs directly:

    import clr
    
    clr.AddReference("System.Windows.Forms")
    clr.AddReference("System.Drawing")
    
    from System.Windows.Forms import Form, Application
    from System.Drawing import Size
    import ctypes
    from ctypes import wintypes
    
    # Define necessary constants and functions
    GWL_WNDPROC = -4
    WM_CLOSE = 0x0010  # Example: close message
    
    # Define SetWindowLongPtrW
    windll = ctypes.WinDLL('user32', use_last_error=True)
    SetWindowLongPtr = windll.SetWindowLongPtrW
    SetWindowLongPtr.argtypes = [wintypes.HWND, wintypes.INT, ctypes.c_void_p]
    SetWindowLongPtr.restype = ctypes.c_void_p
    
    # Define GetWindowLongPtrW
    GetWindowLongPtr = windll.GetWindowLongPtrW
    GetWindowLongPtr.argtypes = [wintypes.HWND, wintypes.INT]
    GetWindowLongPtr.restype = ctypes.c_void_p
    
    # Define CallWindowProcW
    CallWindowProc = windll.CallWindowProcW
    CallWindowProc.argtypes = [
        ctypes.c_void_p,
        wintypes.HWND,
        wintypes.UINT,
        wintypes.WPARAM,
        wintypes.LPARAM,
    ]
    CallWindowProc.restype = ctypes.c_long
    
    
    class MyForm(Form):
        def __init__(self):
            super().__init__()
            self.Text = "WndProc Example"
            self.Size = Size(300, 200)
    
            # Get the window procedure (WndProc) for the window
            self.original_wndproc = GetWindowLongPtr(self.Handle.ToInt64(), GWL_WNDPROC)
            print(f"Original WndProc: {self.original_wndproc}")
    
            # Create a callback for the window procedure
            WNDPROC = ctypes.WINFUNCTYPE(
                ctypes.c_long,
                wintypes.HWND,
                wintypes.UINT,
                wintypes.WPARAM,
                wintypes.LPARAM,
            )
    
            # Register our WndProc to handle window messages
            self.wndproc_callback = WNDPROC(self.WndProc)
            SetWindowLongPtr(
                self.Handle.ToInt64(),
                GWL_WNDPROC,
                ctypes.cast(self.wndproc_callback, ctypes.c_void_p),
            )
    
            current_wndproc = GetWindowLongPtr(self.Handle.ToInt64(), GWL_WNDPROC)
            print(f"Current WndProc: {current_wndproc}")
    
        def WndProc(self, hwnd, msg, w_param, l_param):
            print(
                f"WndProc called: hwnd={hwnd}, msg={msg}, w_param={w_param}, l_param={l_param}"
            )
    
            # Handle specific message (for example, WM_CLOSE)
            if msg == WM_CLOSE:
                print("Window is closing.")
                return 0  # Prevent default close handling
    
            # Call the original window procedure for default handling
            return CallWindowProc(self.original_wndproc, hwnd, msg, w_param, l_param)
    
    
    # Run the application and create an instance of the form
    Application.Run(MyForm())
  2. proneon267 commented on Feb 5, 2025

    @proneon267
    Author

    Perhaps this is a duplicate of #2192, so close this issue as per your discretion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions