wxPython处理Windows消息的一种实现方法

wxPython处理Windows消息的一种实现方法

wxWidgets可以很方便的处理Windows消息,只要重载wxWindow类中的MSWWindowProc函数就可以了。而wxPython是没提供这个方法的,需要用pywin32模块调用几个Win32 API才能实现处理Windows消息。虽然麻烦了点,但总比没有解决办法要好。

Sometimes you may need to catch a Windows message that is not already handled by wxWidgets, so there is no wxEvent for it. With a bit of help from the PyWin32 modules it is possible to hook into the WndProc chain for a wxWindow and watch for the message you are interested in.

The magic is in the win32gui.SetWindowLong function. When used with the win32con.GWL_WNDPROC flag it causes a new WndProc to be set for the window, and returns the old one. This lets you write a function in Python that can get first crack at all the Windows messages being sent to the window, and if you are not interested in them then pass them on to the original wxWidgets WndProc.

 

方法一:

import wx   
import win32api   
import win32gui   
import win32con   

class TestFrame(wx.Frame):   
    def __init__(self):   
        wx.Frame.__init__(self, None, title="WndProc Test", size=(200,150))   
        p = wx.Panel(self)   

        # Set the WndProc to our function   
        self.oldWndProc = win32gui.SetWindowLong(self.GetHandle(),   
                                                 win32con.GWL_WNDPROC,   
                                                 self.MyWndProc)   

        # Make a dictionary of message names to be used for printing below   
        self.msgdict = {}   
        for name in dir(win32con):   
            if name.startswith("WM_"):   
                value = getattr(win32con, name)   
                self.msgdict[value] = name   


    def MyWndProc(self, hWnd, msg, wParam, lParam):   
        # Display what we've got.   
        print (self.msgdict.get(msg), msg, wParam, lParam)   

        # Restore the old WndProc. Notice the use of wxin32api   
        # instead of win32gui here. This is to avoid an error due to   
        # not passing a callable object.   
        if msg == win32con.WM_DESTROY:   
            win32api.SetWindowLong(self.GetHandle(),   
                                   win32con.GWL_WNDPROC,   
                                   self.oldWndProc)   

        # Pass all messages (in this case, yours may be different) on   
        # to the original WndProc   
        return win32gui.CallWindowProc(self.oldWndProc,   
                                       hWnd, msg, wParam, lParam)   

app = wx.PySimpleApp()   
f = TestFrame()   
f.Show()   
app.MainLoop() 
import wx
import win32api
import win32gui
import win32con

class TestFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="WndProc Test", size=(200,150))
        p = wx.Panel(self)

        # Set the WndProc to our function
        self.oldWndProc = win32gui.SetWindowLong(self.GetHandle(),
                                                 win32con.GWL_WNDPROC,
                                                 self.MyWndProc)

        # Make a dictionary of message names to be used for printing below
        self.msgdict = {}
        for name in dir(win32con):
            if name.startswith("WM_"):
                value = getattr(win32con, name)
                self.msgdict[value] = name


    def MyWndProc(self, hWnd, msg, wParam, lParam):
        # Display what we've got.
        print (self.msgdict.get(msg), msg, wParam, lParam)

        # Restore the old WndProc. Notice the use of wxin32api
        # instead of win32gui here. This is to avoid an error due to
        # not passing a callable object.
        if msg == win32con.WM_DESTROY:
            win32api.SetWindowLong(self.GetHandle(),
                                   win32con.GWL_WNDPROC,
                                   self.oldWndProc)

        # Pass all messages (in this case, yours may be different) on
        # to the original WndProc
        return win32gui.CallWindowProc(self.oldWndProc,
                                       hWnd, msg, wParam, lParam)

app = wx.PySimpleApp()
f = TestFrame()
f.Show()
app.MainLoop()

 

方法二:

import ctypes   
import wx   

from ctypes import c_long, c_int   

# grab the functions we need - unicode/not doesn't really matter   
# for this demo   
SetWindowLong = ctypes.windll.user32.SetWindowLongW   
CallWindowProc = ctypes.windll.user32.CallWindowProcW   


# a function type for the wndprc so ctypes can wrap it   
WndProcType = ctypes.WINFUNCTYPE(c_int, c_long, c_int, c_int, c_int)   

# constants   
GWL_WNDPROC = -4 

class TestFrame(wx.Frame):   
    def __init__(self, parent):   
        wx.Frame.__init__(self, parent)   
        # need to hold a reference to WINFUNCTYPE wrappers,   
        # so they don't get GCed   
        self.newWndProc = WndProcType(self.MyWndProc)   
        self.oldWndProc = SetWindowLong(   
            self.GetHandle(),   
            GWL_WNDPROC,   
            self.newWndProc   
        )   


    def MyWndProc(self, hWnd, msg, wParam, lParam):   
        print msg,wParam,lParam   
        return CallWindowProc(   
            self.oldWndProc,   
            hWnd,   
            msg,   
            wParam,   
            lParam   
        )   

app =wx.App(False)   
f = TestFrame(None)   
f.Show()   
app.MainLoop()

你可能感兴趣的:(wxPython)