[wxPython] Re: Operating on hWnd / calldll callback

Thanks Robin for the hint of using win32gui - did not even think of it. Worked using the win32gui.MoveWindow. I've enclosed my small test code. Run from DOS prompt, supply an AVI / MPEG file as an argument. Only the Play and Exit buttons works.

At the bottom I've enclosed the documentation of using the 'notify' flag - taken from MSDN. So in order to get this to work, I have to supply the handle to my frame object as the last parameter in the call to mciSendString. Then my frame should be set up to process the MM_MCINOTIFY event. How would I do that (using EVT_CUSTOM ?).

Thanks for help.
Nikolai Kirsebom

---- MY EXAMPLE CODE ----

···

#
#
#
from wxPython.wx import *
import sys, array
import win32gui

from dynwin import windll, gencb
winmm = windll.module('winmm')
    
def Send(s, cb=None):
    mciSendString=windll.calldll.get_proc_address(winmm.handle, "mciSendStringA")
    bufIn=array.array('c', s + '\0')
    bufOut=array.array('c', '\0' * 128)
    ret=windll.calldll.call_foreign_function(mciSendString, 'wwLL', 'l',
                                             (bufIn, bufOut, 128L, 0L))
    s = bufOut.tostring()
    if s.index('\0') > 0:
        s = s[0:s.index('\0')]
    else:
        s = ""
    return (ret, s)

def SendGetHandle():
    return Send("status mov window handle")[1]
    
def SendGetSize():
    return Send("where mov source")[1]
    
class VideoPlayer(wxFrame):
    def __init__(self, w, h):
        wxFrame.__init__(self, None, -1, "", wxDefaultPosition, (w, h)) #,
                         #style=wxSIMPLE_BORDER|wxSTAY_ON_TOP|wxCAPTION)
        self.play = wxButton(self, 100, "Play")
        self.stop = wxButton(self, 101, "Stop")
        self.exit = wxButton(self, 102, "Exit")
        self.theWindow = wxPanel(self, -1)
        self.theHandle = self.theWindow.GetHandle()

        lc = wxLayoutConstraints()
        lc.top.SameAs(self, wxTop, 0)
        lc.left.SameAs(self, wxLeft, 0)
        lc.width.AsIs()
        lc.height.AsIs()
        self.play.SetConstraints(lc)
        EVT_BUTTON(self, 100, self.OnPlay)
        
        lc = wxLayoutConstraints()
        lc.top.SameAs(self, wxTop, 0)
        lc.left.RightOf(self.play, 0)
        lc.width.AsIs()
        lc.height.AsIs()
        self.stop.SetConstraints(lc)
        EVT_BUTTON(self, 101, self.OnStop)
        
        lc = wxLayoutConstraints()
        lc.top.SameAs(self, wxTop, 0)
        lc.right.SameAs(self, wxRight, 0)
        lc.width.AsIs()
        lc.height.AsIs()
        self.exit.SetConstraints(lc)
        EVT_BUTTON(self, 102, self.OnExit)

        lc = wxLayoutConstraints()
        lc.top.Below(self.play, 0)
        lc.left.SameAs(self, wxLeft, 0)
        lc.right.SameAs(self, wxRight, 0)
        lc.bottom.SameAs(self, wxBottom, 0)
        self.theWindow.SetConstraints(lc)

        self.FileName = None

        self.SetAutoLayout(true)

    def SetFile(self, fn):
        self.FileName = fn
        Send("open avivideo")
        Send("open %s alias mov style child parent %d" % (self.FileName, self.theHandle))
        Send("window mov state show")
        self.MovieHWND = int(SendGetHandle())
        v = SendGetSize()
        movieWidth = int(v.split()[2])
        movieHeight = int(v.split()[3])
        width, height = self.theWindow.GetSize()

        l = (width-movieWidth)/2
        t = (height-movieHeight)/2
        r = l + movieWidth
        b = t + movieHeight

        win32gui.MoveWindow(self.MovieHWND, l/2, t/2, r, b, 1)
        self.SetTitle(fn)
        
    def OnPlay(self, event):
        if self.FileName:
            Send("seek mov to start")
            Send("play mov notify")

    def OnStop(self, event):
        pass

    def OnExit(self, event):
        Send("close avivideo")
        self.Destroy()
        
if __name__ == '__main__':
    class DemoApp(wxApp):
        def OnInit(self):
            self.videoPlayer = VideoPlayer(450, 500)
            self.videoPlayer.Show(true)
            self.SetTopWindow(self.videoPlayer)
            return true

    app = DemoApp(0)
    app.videoPlayer.SetFile(sys.argv[1])
    app.MainLoop()

---- FROM MSDN ---

The "notify" (MCI_NOTIFY) flag directs the device to post an MM_MCINOTIFY message when the device completes an action. Your application must have a window procedure to process the MM_MCINOTIFY message for notification to have any effect. An MM_MCINOTIFY message indicates that the processing of a command has completed, but it does not indicate whether the command was completed successfully, failed, or was superseded or aborted.
The application specifies the handle to the destination window for the message when it issues a command. In the command-string interface, this handle is the last parameter of the mciSendString function. In the command-message interface, the handle is specified in the low-order word of the dwCallBack member of the structure sent with the command message. (Every structure associated with a command message contains this member.)

Nikolai Kirsebom wrote:

Thanks Robin for the hint of using win32gui - did not even think of it. Worked using the win32gui.MoveWindow. I've enclosed my small test code. Run from DOS prompt, supply an AVI / MPEG file as an argument. Only the Play and Exit buttons works.

At the bottom I've enclosed the documentation of using the 'notify' flag - taken from MSDN. So in order to get this to work, I have to supply the handle to my frame object as the last parameter in the call to mciSendString. Then my frame should be set up to process the MM_MCINOTIFY event. How would I do that (using EVT_CUSTOM ?).

Maybe some code from Dynwin package can help you?

HTH
Niki Spahiev