├── MBPython ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── __init__.cpython-38.pyc │ ├── bindwebview.cpython-36.pyc │ ├── bindwebview.cpython-38.pyc │ ├── callback.cpython-36.pyc │ ├── callback.cpython-38.pyc │ ├── config.cpython-36.pyc │ ├── cookie.cpython-36.pyc │ ├── cookie.cpython-38.pyc │ ├── defaultcallbackfunc.cpython-36.pyc │ ├── defaultcallbackfunc.cpython-38.pyc │ ├── initconfig.cpython-36.pyc │ ├── jsbindpy.cpython-36.pyc │ ├── jsrunpy.cpython-36.pyc │ ├── jsrunpy.cpython-38.pyc │ ├── message.cpython-36.pyc │ ├── message.cpython-38.pyc │ ├── method.cpython-36.pyc │ ├── method.cpython-38.pyc │ ├── miniblink.cpython-36.pyc │ ├── miniblink.cpython-38.pyc │ ├── myctypes.cpython-36.pyc │ ├── myctypes.cpython-38.pyc │ ├── network.cpython-36.pyc │ ├── network.cpython-38.pyc │ ├── proxy.cpython-36.pyc │ ├── proxy.cpython-38.pyc │ ├── pyrunjs.cpython-36.pyc │ ├── pyrunjs.cpython-38.pyc │ ├── screenshot.cpython-36.pyc │ ├── screenshot.cpython-38.pyc │ ├── seticon.cpython-36.pyc │ ├── seticon.cpython-38.pyc │ ├── timer.cpython-36.pyc │ ├── winConst.cpython-36.pyc │ ├── winConst.cpython-38.pyc │ ├── window.cpython-36.pyc │ ├── window.cpython-38.pyc │ ├── wkeStruct.cpython-36.pyc │ ├── wkeStruct.cpython-38.pyc │ ├── wndproc.cpython-36.pyc │ └── wndproc.cpython-38.pyc ├── bindwebview.py ├── callback.py ├── cookie.py ├── jsrunpy.py ├── message.py ├── method.py ├── miniblink.py ├── network.py ├── proxy.py ├── pyrunjs.py ├── screenshot.py ├── seticon.py ├── timer.py ├── winConst.py ├── window.py ├── wkeStruct.py └── wndproc.py ├── README.md ├── dist ├── MBPython-0.2.2-py3-none-any.whl └── MBPython-0.2.2.tar.gz ├── documents ├── Api-index.md └── README.md ├── front_end ├── README.md └── front_end.7z ├── plugins ├── README.md └── npswf32-11.5.dll ├── poetry.lock ├── pyproject.toml └── tests ├── __pycache__ ├── callbackfunc.cpython-36.pyc ├── callbackfunc.cpython-38.pyc ├── config.cpython-36.pyc ├── config.cpython-38.pyc ├── test_bindwebview.cpython-36.pyc ├── test_bindwindow.cpython-36.pyc ├── test_mbpython.cpython-36.pyc └── test_mbpython.cpython-38.pyc ├── callbackfunc.py ├── config.py ├── logo.ico ├── miniblink_x64.dll ├── node.dll ├── test_bindwebview.py ├── test_bindwindow.py ├── test_mbpython.py ├── testexe └── testexe.7z └── testjs ├── css └── iview.css ├── images ├── Thumbs.db ├── alipay.jpg ├── btn-control.png ├── girl.png ├── hader.png └── qq.jpg ├── javascript ├── iview.js ├── test.js ├── test_1.js └── vue.js └── testjs.html /MBPython/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import c_int 3 | from platform import architecture 4 | bit=architecture()[0] 5 | _LRESULT=c_int 6 | if bit == '64bit': 7 | from ctypes import c_longlong 8 | _LRESULT=c_longlong 9 | from .seticon import set_icon 10 | from .screenshot import screen_shot 11 | from .wndproc import WndProcHook 12 | from .timer import Timer 13 | from . import miniblink -------------------------------------------------------------------------------- /MBPython/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/bindwebview.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/bindwebview.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/bindwebview.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/bindwebview.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/callback.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/callback.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/callback.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/callback.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/config.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/config.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/cookie.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/cookie.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/cookie.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/cookie.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/defaultcallbackfunc.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/defaultcallbackfunc.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/defaultcallbackfunc.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/defaultcallbackfunc.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/initconfig.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/initconfig.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/jsbindpy.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/jsbindpy.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/jsrunpy.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/jsrunpy.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/jsrunpy.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/jsrunpy.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/message.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/message.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/message.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/message.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/method.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/method.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/method.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/method.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/miniblink.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/miniblink.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/miniblink.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/miniblink.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/myctypes.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/myctypes.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/myctypes.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/myctypes.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/network.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/network.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/network.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/network.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/proxy.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/proxy.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/proxy.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/proxy.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/pyrunjs.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/pyrunjs.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/pyrunjs.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/pyrunjs.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/screenshot.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/screenshot.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/screenshot.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/screenshot.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/seticon.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/seticon.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/seticon.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/seticon.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/timer.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/timer.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/winConst.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/winConst.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/winConst.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/winConst.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/window.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/window.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/window.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/window.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/wkeStruct.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/wkeStruct.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/wkeStruct.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/wkeStruct.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/wndproc.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/wndproc.cpython-36.pyc -------------------------------------------------------------------------------- /MBPython/__pycache__/wndproc.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/MBPython/__pycache__/wndproc.cpython-38.pyc -------------------------------------------------------------------------------- /MBPython/bindwebview.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import ( 3 | windll, 4 | byref 5 | ) 6 | from ctypes.wintypes import RGB 7 | from .winConst import WinConst 8 | from .wkeStruct import (Rect,mPos,mSize,COMPOSITIONFORM,bitMap,blendFunction,PAINTSTRUCT) 9 | from .method import method 10 | from .callback import CallBack 11 | from .wndproc import WndProcHook 12 | from . import _LRESULT 13 | 14 | gdi32=windll.gdi32 15 | user32 = windll.user32 16 | class BindWebview(): 17 | def __init__(self,miniblink,webview=0): 18 | global js 19 | self.mb=miniblink 20 | self.m_webview=webview 21 | self.cb=CallBack(miniblink) 22 | self.cb.wkePaintUpdatedCallback=self.__paint_func 23 | def bind_webview(self,hwnd=0,isTransparent=False,isZoom=True): 24 | 25 | if user32.IsWindow(hwnd)==0: 26 | return 0 27 | if self.m_webview==0: 28 | self.m_webview=self.mb.wkeCreateWebView() 29 | if self.m_webview==0: 30 | return 0 31 | self.isZoom=isZoom 32 | self.mb.wkeSetHandle(self.m_webview,hwnd) 33 | self.cb.wkeOnPaintUpdated(self.m_webview,hwnd) 34 | if isTransparent: 35 | self.mb.wkeSetTransparent(self.m_webview,1) 36 | exStyle=user32.GetWindowLongW(hwnd,WinConst.GWL_EXSTYLE) 37 | user32.SetWindowLongW(hwnd,WinConst.GWL_EXSTYLE,exStyle | WinConst.WS_EX_LAYERED) 38 | else: 39 | self.mb.wkeSetTransparent(self.m_webview,0) 40 | 41 | 42 | tmp_WndProc=WndProcHook(hwnd,self.m_webview) 43 | tmp_WndProc.onWndProcCallback=self.__myWndProcCallBack 44 | tmp_WndProc.hook_WndProc() 45 | 46 | 47 | rc=Rect() 48 | user32.GetClientRect(hwnd,byref(rc)) 49 | self.mb.wkeResize(self.m_webview,rc.Right - rc.Left, rc.Bottom - rc.Top) 50 | return self.m_webview 51 | def __paint_func(self,**kwargs): 52 | webview=kwargs['webview'] 53 | param=kwargs['param'] 54 | 55 | hdc=kwargs['hdc'] 56 | x=kwargs['x'] 57 | y=kwargs['y'] 58 | cx=kwargs['cx'] 59 | cy=kwargs['cy'] 60 | 61 | if param==None:return 62 | hwnd=param 63 | if (user32.GetWindowLongW(hwnd,WinConst.GWL_EXSTYLE) & WinConst.WS_EX_LAYERED)== WinConst.WS_EX_LAYERED: 64 | 65 | self.__transparentPaint(hwnd, hdc, x, y, cx, cy) 66 | else: 67 | rc=Rect(0,0,x+cx,y+cy) 68 | 69 | user32.InvalidateRect(hwnd, byref(rc), True) 70 | def __myWndProcCallBack(self,hwnd,msg,wParam,lParam): 71 | if msg==WinConst.WM_PAINT: 72 | 73 | if WinConst.WS_EX_LAYERED!=(WinConst.WS_EX_LAYERED & user32.GetWindowLongW(hwnd,WinConst.GWL_EXSTYLE)): 74 | ps=PAINTSTRUCT() 75 | hdc=user32.BeginPaint(hwnd,byref(ps)) 76 | rcClip = ps.rcPaint 77 | rcClient=Rect() 78 | user32.GetClientRect(hwnd,byref(rcClient)) 79 | 80 | rcInvalid=rcClient 81 | if (rcClient.Right != rcClip.Left) and (rcClip.Bottom != rcClip.Top): 82 | user32.IntersectRect(byref(rcInvalid),byref(rcClip),byref(rcClient)) 83 | srcX = rcInvalid.Left - rcClient.Left 84 | srcY = rcInvalid.Top - rcClient.Top 85 | destX = rcInvalid.Left 86 | destY = rcInvalid.Top 87 | width = rcInvalid.Right - rcInvalid.Left 88 | height = rcInvalid.Bottom - rcInvalid.Top 89 | if width!=0 and height!=0: 90 | 91 | tmp_dc=self.mb.wkeGetViewDC(self.m_webview) 92 | gdi32.BitBlt(hdc,destX, destY, width, height,tmp_dc,srcX, srcY,WinConst.SRCCOPY) 93 | self.mb.wkeUnlockViewDC(self.m_webview) 94 | user32.EndPaint(hwnd,byref(ps)) 95 | return 0 96 | elif msg==WinConst.WM_ERASEBKGND: 97 | return 1 98 | elif msg==WinConst.WM_SIZE: 99 | width= lParam & 65535 100 | height= lParam >> 16 101 | self.mb.wkeResize(self.m_webview,width,height) 102 | return 0 103 | elif msg==WinConst.WM_KEYDOWN: 104 | virtualKeyCode=wParam 105 | flags=0 106 | if ((lParam >> 16) & WinConst.KF_REPEAT)!=0: 107 | flags=flags | 0x4000 108 | if ((lParam >> 16) & WinConst.KF_EXTENDED)!=0: 109 | flags=flags | 0x0100 110 | if self.mb.wkeFireKeyDownEvent(self.m_webview,virtualKeyCode,flags)!=0: 111 | return 0 112 | elif msg==WinConst.WM_KEYUP: 113 | virtualKeyCode=wParam 114 | flags=0 115 | if virtualKeyCode==116: 116 | self.mb.wkeReload(self.m_webview) 117 | if ((lParam >> 16) & WinConst.KF_REPEAT)!=0: 118 | flags=flags | 0x4000 119 | if ((lParam >> 16) & WinConst.KF_EXTENDED)!=0: 120 | flags=flags | 0x0100 121 | if self.mb.wkeFireKeyUpEvent(self.m_webview,virtualKeyCode,flags)!=0: 122 | return 0 123 | elif msg==WinConst.WM_CHAR: 124 | virtualKeyCode=wParam 125 | flags=0 126 | if ((lParam >> 16) & WinConst.KF_REPEAT)!=0: 127 | flags=flags | 0x4000 128 | if self.mb.wkeFireKeyPressEvent(self.m_webview,virtualKeyCode,flags)!=0: 129 | return 0 130 | elif msg in [WinConst.WM_LBUTTONDOWN,WinConst.WM_MBUTTONDOWN,WinConst.WM_RBUTTONDOWN,WinConst.WM_LBUTTONDBLCLK,WinConst.WM_MBUTTONDBLCLK,WinConst.WM_RBUTTONDBLCLK,WinConst.WM_LBUTTONUP,WinConst.WM_MBUTTONUP,WinConst.WM_RBUTTONUP]: 131 | x=lParam & 65535 132 | y=lParam >> 16 133 | flags=0 134 | if msg in [WinConst.WM_LBUTTONDOWN,WinConst.WM_MBUTTONDOWN,WinConst.WM_RBUTTONDOWN]: 135 | if user32.GetFocus()!=hwnd: 136 | user32.SetFocus(hwnd) 137 | user32.SetCapture(hwnd) 138 | elif msg in [WinConst.WM_LBUTTONUP,WinConst.WM_MBUTTONUP,WinConst.WM_RBUTTONUP]: 139 | user32.ReleaseCapture() 140 | if (wParam & WinConst.MK_CONTROL)!=0: 141 | flags=flags | 8 142 | elif (wParam & WinConst.MK_SHIFT)!=0: 143 | flags=flags | 4 144 | elif (wParam & WinConst.MK_LBUTTON)!=0: 145 | flags=flags | 1 146 | elif (wParam & WinConst.MK_MBUTTON)!=0: 147 | flags=flags | 16 148 | elif (wParam & WinConst.MK_RBUTTON)!=0: 149 | flags=flags | 2 150 | self.mb.wkeFireMouseEvent(self.m_webview, msg, x, y, flags) 151 | return 0 152 | 153 | elif msg==WinConst.WM_MOUSEMOVE: 154 | x=lParam & 65535 155 | y=lParam >> 16 156 | flags=0 157 | if (wParam & WinConst.MK_LBUTTON)!=0: 158 | flags=flags | 1 159 | if self.mb.wkeFireMouseEvent(self.m_webview, msg, x, y, flags)!=0: 160 | return 0 161 | elif msg==WinConst.WM_CONTEXTMENU: 162 | pt=mPos() 163 | pt.x=lParam & 65535 164 | pt.y=lParam >> 16 165 | if pt.x!=-1 and pt.y!=-1: 166 | user32.ScreenToClient(hwnd,byref(pt)) 167 | flags=0 168 | if (wParam & WinConst.MK_CONTROL)!=0: 169 | flags=flags | 8 170 | if (wParam & WinConst.MK_SHIFT)!=0: 171 | flags=flags | 4 172 | if (wParam & WinConst.MK_LBUTTON)!=0: 173 | flags=flags | 1 174 | if (wParam & WinConst.MK_MBUTTON)!=0: 175 | flags=flags | 16 176 | if (wParam & WinConst.MK_RBUTTON)!=0: 177 | flags=flags | 2 178 | 179 | if self.mb.wkeFireContextMenuEvent(self.m_webview,pt.x,pt.y, flags)!=0: 180 | return 0 181 | elif msg==WinConst.WM_MOUSEWHEEL: 182 | pt=mPos() 183 | pt.x=lParam & 65535 184 | pt.y=lParam >> 16 185 | user32.ScreenToClient(hwnd,byref(pt)) 186 | delta= wParam >> 16 187 | flags=0 188 | 189 | if (wParam & WinConst.MK_CONTROL)!=0: 190 | flags=flags | 8 191 | if (wParam & WinConst.MK_SHIFT)!=0: 192 | flags=flags | 4 193 | if (wParam & WinConst.MK_LBUTTON)!=0: 194 | flags=flags | 1 195 | if (wParam & WinConst.MK_MBUTTON)!=0: 196 | flags=flags | 16 197 | if (wParam & WinConst.MK_RBUTTON)!=0: 198 | flags=flags | 2 199 | if self.mb.wkeFireMouseWheelEvent(self.m_webview,pt.x,pt.y,delta,flags)!=0: 200 | return 0 201 | elif msg==WinConst.WM_SETFOCUS: 202 | user32.SetFocus(hwnd) 203 | return 0 204 | elif msg==WinConst.WM_KILLFOCUS: 205 | self.mb.wkeKillFocus(self.m_webview) 206 | return 0 207 | elif msg==WinConst.WM_IME_STARTCOMPOSITION: 208 | caret=self.mb.wkeGetCaretRect(self.m_webview) 209 | mposForm=COMPOSITIONFORM() 210 | mposForm.dwStyle = 2 | 32 211 | mposForm.ptCurrentPos.x = caret.x 212 | mposForm.ptCurrentPos.y = caret.y 213 | hIMC=imm32.ImmGetContext(hwnd) 214 | imm32.ImmSetCompositionWindow(hIMC,byref(mposForm)) 215 | imm32.ImmReleaseContext(hwnd,hIMC) 216 | return 0 217 | elif msg==WinConst.WM_SETCURSOR: 218 | if self.mb.wkeFireWindowsMessage(self.m_webview,hwnd,WinConst.WM_SETCURSOR,wParam,lParam,0)!=0: 219 | return 0 220 | elif msg==WinConst.WM_NCHITTEST: 221 | if self.isZoom: 222 | return self.__on_nchittest(hwnd,lParam) 223 | elif msg==WinConst.WM_INPUTLANGCHANGE: 224 | return user32.DefWindowProcA(hwnd, msg, _LRESULT(wParam), _LRESULT(lParam)) 225 | 226 | def __transparentPaint(self,hwnd,hdc,x,y,cx,cy): 227 | rectDest=Rect() 228 | user32.GetClientRect(hwnd,byref(rectDest)) 229 | user32.OffsetRect(byref(rectDest),-rectDest.Left,-rectDest.Top) 230 | 231 | width = rectDest.Right - rectDest.Left 232 | height = rectDest.Bottom - rectDest.Top 233 | hBitmap = gdi32.GetCurrentObject(hdc, WinConst.OBJ_BITMAP) 234 | 235 | bmp=bitMap() 236 | bmp.bmType=0 237 | cbBuffer=gdi32.GetObjectA(hBitmap, 24,0) 238 | gdi32.GetObjectA(hBitmap, cbBuffer,byref(bmp)) 239 | sizeDest=mSize() 240 | sizeDest.cx =bmp.bmWidth 241 | sizeDest.cy =bmp.bmHeight 242 | 243 | hdcScreen = self.mb.wkeGetViewDC(self.m_webview)# user32.GetDC(_LRESULT(hwnd)) 244 | blendFunc32bpp=blendFunction() 245 | blendFunc32bpp.BlendOp = 0 246 | blendFunc32bpp.BlendFlags = 0 247 | blendFunc32bpp.SourceConstantAlpha = 255 248 | blendFunc32bpp.AlphaFormat = 1 249 | pointSource=mPos() 250 | callOk = user32.UpdateLayeredWindow(hwnd, hdcScreen, 0, byref(sizeDest), hdc, byref(pointSource), RGB(255,255,255), byref(blendFunc32bpp), WinConst.ULW_ALPHA) 251 | 252 | user32.ReleaseDC(hwnd, hdcScreen) 253 | def __on_nchittest(self,hwnd,lParam): 254 | if user32.IsZoomed(hwnd)!=0: 255 | return 1 256 | pt=mPos() 257 | pt.x=lParam & 65535 258 | pt.y=lParam >> 16 259 | user32.ScreenToClient(hwnd,byref(pt)) 260 | rc=Rect() 261 | user32.GetClientRect(hwnd,byref(rc)) 262 | iWidth = rc.Right - rc.Left 263 | iHeight = rc.Bottom - rc.Top 264 | if user32.PtInRect(byref(Rect(5, 0, iWidth - 5, 5)),pt): 265 | retn=12#HTTOP 266 | elif user32.PtInRect(byref(Rect(0, 5, 5, iHeight - 5)),pt): 267 | retn=10#HTLEFT 268 | elif user32.PtInRect(byref(Rect(iWidth - 5, 5, iWidth, iHeight - 10)),pt): 269 | retn=11#HTRIGHT 270 | elif user32.PtInRect(byref(Rect(5, iHeight - 5, iWidth - 10, iHeight)),pt): 271 | retn=15#HTBOTTOM 272 | elif user32.PtInRect(byref(Rect(0, 0, 5, 5)),pt): 273 | retn=13#HTTOPLEFT 274 | elif user32.PtInRect(byref(Rect(0, iHeight - 5, 5, iHeight)),pt): 275 | retn=16#HTBOTTOMLEFT 276 | elif user32.PtInRect(byref(Rect(iWidth - 5, 0, iWidth, 5)),pt): 277 | retn=14#HTTOPRIGHT 278 | elif user32.PtInRect(byref(Rect(iWidth - 10, iHeight - 10, iWidth, iHeight)),pt): 279 | retn=17#HTBOTTOMRIGHT 280 | else: 281 | retn=1 282 | return retn 283 | -------------------------------------------------------------------------------- /MBPython/callback.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import ( 3 | c_int, 4 | c_ulonglong, 5 | c_char_p, 6 | c_bool, 7 | c_void_p, 8 | POINTER, 9 | windll, 10 | CFUNCTYPE 11 | ) 12 | from .winConst import WinConst 13 | from .wkeStruct import (wkeRect,wkeWindowFeatures,wkeMemBuf,mPos) 14 | from .method import method 15 | from . import _LRESULT 16 | import json 17 | 18 | user32=windll.user32 19 | class CallBack(): 20 | def __init__(self,miniblink,width=360,height=480): 21 | self.mb=miniblink 22 | self.width=width 23 | self.height=height 24 | def wkeOnCreateView(self,webview,param=0): 25 | param=self.param_to_string(param) 26 | self.mb.wkeOnCreateView(webview,self._wkeCreateViewCallback,_LRESULT(param)) 27 | def wkeOnWindowClosing(self,webview,param=0): 28 | param=self.param_to_string(param) 29 | self.mb.wkeOnWindowClosing(webview,self._wkeWindowClosingCallback,_LRESULT(param)) 30 | def wkeOnWindowDestroy(self,webview,param=0): 31 | 32 | self.mb.wkeOnWindowDestroy(webview,self._wkeWindowDestroyCallback,_LRESULT(param)) 33 | def wkeOnPaintUpdated(self,webview,param=0): 34 | param=self.param_to_string(param) 35 | self.mb.wkeOnPaintUpdated(webview,self._wkePaintUpdatedCallback ,_LRESULT(param)) 36 | def wkeOnPaintBitUpdated(self,webview,param=0): 37 | param=self.param_to_string(param) 38 | self.mb.wkeOnPaintBitUpdated(webview, self._wkePaintBitUpdatedCallback,_LRESULT(param)) 39 | def wkeOnNavigation(self,webview,param=0): 40 | param=self.param_to_string(param) 41 | self.mb.wkeOnNavigation(webview,self._wkeNavigationCallback,_LRESULT(param)) 42 | def wkeOnTitleChanged(self,webview,param=0): 43 | param=self.param_to_string(param) 44 | self.mb.wkeOnTitleChanged(webview,self._wkeTitleChangedCallback,_LRESULT(param)) 45 | def wkeOnURLChanged2(self,webview,param=0): 46 | param=self.param_to_string(param) 47 | self.mb.wkeOnURLChanged2(webview,self._wkeURLChangedCallback2,_LRESULT(param)) 48 | def wkeOnMouseOverUrlChanged(self,webview,param=0): 49 | param=self.param_to_string(param) 50 | self.mb.wkeOnMouseOverUrlChanged(webview,self._wkeMouseOverUrlChangedCallback,_LRESULT(param)) 51 | def wkeOnAlertBox(self,webview,param=0): 52 | param=self.param_to_string(param) 53 | self.mb.wkeOnAlertBox(webview,self._wkeAlertBoxCallback,_LRESULT(param)) 54 | def wkeOnConfirmBox(self,webview,param=0): 55 | param=self.param_to_string(param) 56 | self.mb.wkeOnConfirmBox(webview,self._wkeConfirmBoxCallback,_LRESULT(param)) 57 | def wkeOnPromptBox(self,webview,param=0): 58 | param=self.param_to_string(param) 59 | self.mb.wkeOnPromptBox(webview,self._wkePromptBoxCallback,_LRESULT(param)) 60 | def wkeOnConsole(self,webview,param=0): 61 | self.mb.wkeOnConsole(webview,self._wkeConsoleCallback,_LRESULT(param)) 62 | def wkeOnDownload(self,webview,param=0): 63 | param=self.param_to_string(param) 64 | self.mb.wkeOnDownload(webview,self._wkeDownloadCallback,_LRESULT(param)) 65 | def wkeOnDocumentReady2(self,webview,param=0): 66 | param=self.param_to_string(param) 67 | self.mb.wkeOnDocumentReady2(webview,self._wkeDocumentReady2Callback,_LRESULT(param)) 68 | def wkeNetOnResponse(self,webview,param=0): 69 | param=self.param_to_string(param) 70 | self.mb.wkeNetOnResponse(webview,self._wkeNetResponseCallback,_LRESULT(param)) 71 | def wkeOnLoadUrlBegin(self,webview,param=0): 72 | param=self.param_to_string(param) 73 | self.mb.wkeOnLoadUrlBegin(webview,self._wkeLoadUrlBeginCallback,_LRESULT(param)) 74 | def wkeOnLoadUrlEnd(self,webview,param=0): 75 | param=self.param_to_string(param) 76 | self.mb.wkeOnLoadUrlEnd(webview,self._wkeLoadUrlEndCallback,_LRESULT(param)) 77 | def wkeOnLoadUrlFail(self,webview,param=0): 78 | param=self.param_to_string(param) 79 | self.mb.wkeOnLoadUrlFail(webview,self._wkeLoadUrlFailCallback,_LRESULT(param)) 80 | def wkeOnLoadingFinish(self,webview,param=0): 81 | param=self.param_to_string(param) 82 | self.mb.wkeOnLoadingFinish(webview,self._wkeLoadingFinishCallback,_LRESULT(param)) 83 | def wkeNetGetFavicon(self,webview,param=0): 84 | param=self.param_to_string(param) 85 | self.mb.wkeNetGetFavicon(webview,self._wkeOnNetGetFaviconCallback,_LRESULT(param)) 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | @method(CFUNCTYPE(c_bool, _LRESULT, c_void_p)) 94 | def _wkeWindowClosingCallback(self,webview, param): 95 | 96 | if hasattr(self,'wkeWindowClosingCallback'): 97 | param=self.get_param_value(param) 98 | return self.wkeWindowClosingCallback(webview=webview,param=param) 99 | return True 100 | @method(CFUNCTYPE(None, _LRESULT, c_void_p)) 101 | def _wkeWindowDestroyCallback(self,webview, param): 102 | if hasattr(self,'wkeWindowDestroyCallback'): 103 | param=self.get_param_value(param) 104 | self.wkeWindowDestroyCallback(webview=webview,param=param) 105 | user32.PostQuitMessage(0) 106 | @method(CFUNCTYPE(None,_LRESULT,c_void_p,_LRESULT,c_int,c_int,c_int,c_int)) 107 | def _wkePaintUpdatedCallback(self,webview,param,hdc,x,y,cx,cy): 108 | if hasattr(self,'wkePaintUpdatedCallback'): 109 | param=self.get_param_value(param) 110 | self.wkePaintUpdatedCallback(webview=webview,param=param,hdc=hdc,x=x,y=y,cx=cx,cy=cy) 111 | @method(CFUNCTYPE(None,_LRESULT,c_void_p,_LRESULT,POINTER(wkeRect),c_int,c_int)) 112 | def _wkePaintBitUpdatedCallback(self,webview,param,buf,rect,width,height): 113 | param=self.get_param_value(param) 114 | if hasattr(self,'wkePaintBitUpdatedCallback'): 115 | self.wkePaintBitUpdatedCallback(webview=webview,param=param,buf=buf,rect=rect,width=width,height=height) 116 | @method(CFUNCTYPE(None,_LRESULT,c_void_p,c_void_p)) 117 | def _wkeDocumentReady2Callback(self,webview,param,frameId): 118 | if hasattr(self,'wkeDocumentReady2Callback'): 119 | param=self.get_param_value(param) 120 | self.wkeDocumentReady2Callback(webview=webview,param=param,frameId=frameId) 121 | @method(CFUNCTYPE(_LRESULT, _LRESULT, c_void_p,c_int,c_void_p,POINTER(wkeWindowFeatures))) 122 | def _wkeCreateViewCallback(self,webview,param,navigationType,url,windowFeatures): 123 | 124 | if hasattr(self,'wkeCreateViewCallback'): 125 | url=self.mb.wkeGetStringW(url) 126 | param=self.get_param_value(param) 127 | return self.wkeCreateViewCallback(webview=webview,param=param,navigationType=navigationType,url=url,windowFeatures=windowFeatures) 128 | return 0 129 | @method(CFUNCTYPE(None, _LRESULT, c_void_p,c_int,c_void_p)) 130 | def _wkeNavigationCallback(self,webview,param,navigationType,url): 131 | 132 | if hasattr(self,'wkeNavigationCallback'): 133 | url=self.mb.wkeGetStringW(url) 134 | param=self.get_param_value(param) 135 | self.wkeNavigationCallback(webview=webview,param=param,navigationType=navigationType,url=url) 136 | @method(CFUNCTYPE(None, _LRESULT, c_void_p, c_void_p)) 137 | def _wkeTitleChangedCallback(self,webview, param, title): 138 | if hasattr(self,'wkeTitleChangedCallback'): 139 | title=self.mb.wkeGetStringW(title) 140 | param=self.get_param_value(param) 141 | self.wkeTitleChangedCallback(webview=webview, param=param, title=title) 142 | @method(CFUNCTYPE(None, _LRESULT, c_void_p, c_void_p)) 143 | def _wkeMouseOverUrlChangedCallback(self,webview, param, url): 144 | 145 | if hasattr(self,'wkeMouseOverUrlChangedCallback'): 146 | url=self.mb.wkeGetStringW(url) 147 | param=self.get_param_value(param) 148 | self.wkeMouseOverUrlChangedCallback(webview=webview, param=param, url=url) 149 | @method(CFUNCTYPE(None, _LRESULT, c_void_p,c_int,c_void_p)) 150 | def _wkeURLChangedCallback2(self,webview,param,frameId,url): 151 | 152 | if hasattr(self,'wkeURLChangedCallback2'): 153 | url=self.mb.wkeGetStringW(url) 154 | param=self.get_param_value(param) 155 | self.wkeURLChangedCallback2(webview=webview, param=param,frameId=frameId,url=url) 156 | @method(CFUNCTYPE(None, _LRESULT, c_void_p,c_void_p)) 157 | def _wkeAlertBoxCallback(self,webview,param,msg): 158 | 159 | if hasattr(self,'wkeAlertBoxCallback'): 160 | msg=self.mb.wkeGetStringW(msg) 161 | param=self.get_param_value(param) 162 | self.wkeAlertBoxCallback(webview=webview, param=param,msg=msg) 163 | 164 | @method(CFUNCTYPE(c_bool, _LRESULT, c_void_p,c_void_p)) 165 | def _wkeConfirmBoxCallback(self,webview,param,msg): 166 | 167 | if hasattr(self,'wkeConfirmBoxCallback'): 168 | msg=self.mb.wkeGetStringW(msg) 169 | param=self.get_param_value(param) 170 | return self.wkeConfirmBoxCallback(webview=webview, param=param,msg=msg) 171 | return False 172 | @method(CFUNCTYPE(c_bool, _LRESULT, c_void_p,c_void_p,c_void_p,c_void_p)) 173 | def _wkePromptBoxCallback(self,webview,param,msg,defaultResult,result): 174 | 175 | if hasattr(self,'wkePromptBoxCallback'): 176 | msg=self.mb.wkeGetStringW(msg) 177 | defaultResult=self.mb.wkeGetStringW(defaultResult) 178 | param=self.get_param_value(param) 179 | return self.wkePromptBoxCallback(webview=webview, param=param,msg=msg,defaultResult=defaultResult,result=result) 180 | return False 181 | @method(CFUNCTYPE(None, _LRESULT,c_void_p, c_int,c_void_p,c_void_p,c_ulonglong,c_void_p)) 182 | def _wkeConsoleCallback(self,webview,param,level,msg,sourceName,sourceLine,stackTrace): 183 | 184 | if hasattr(self,'wkeConsoleCallback'): 185 | msg=self.mb.wkeGetStringW(msg) 186 | sourceName=self.mb.wkeGetStringW(sourceName) 187 | stackTrace=self.mb.wkeGetStringW(stackTrace) 188 | param=self.get_param_value(param) 189 | self.wkeConsoleCallback(webview=webview, param=param,level=level,msg=msg,sourceName=sourceName,sourceLine=sourceLine,stackTrace=stackTrace) 190 | @method(CFUNCTYPE(c_bool,_LRESULT,c_void_p,c_char_p)) 191 | def _wkeDownloadCallback(self,webview,param,url): 192 | 193 | if hasattr(self,'wkeDownloadCallback'): 194 | url=url.decode() 195 | param=self.get_param_value(param) 196 | self.wkeDownloadCallback(webview=webview, param=param,url=url) 197 | return True 198 | @method(CFUNCTYPE(c_bool,_LRESULT,c_void_p,c_char_p,c_void_p)) 199 | def _wkeNetResponseCallback(self,webview,param,url,job): 200 | 201 | if hasattr(self,'wkeNetResponseCallback'): 202 | url=url.decode() 203 | param=self.get_param_value(param) 204 | return self.wkeNetResponseCallback(webview=webview, param=param,url=url,job=job) 205 | return False 206 | @method(CFUNCTYPE(c_bool,_LRESULT,c_void_p,c_char_p,c_void_p)) 207 | def _wkeLoadUrlBeginCallback(self,webview,param,url,job): 208 | 209 | if hasattr(self,'wkeLoadUrlBeginCallback'): 210 | url=url.decode() 211 | param=self.get_param_value(param) 212 | return self.wkeLoadUrlBeginCallback(webview=webview, param=param,url=url,job=job) 213 | return False 214 | @method(CFUNCTYPE(None,_LRESULT,c_void_p,c_char_p,c_void_p,c_void_p,c_int)) 215 | def _wkeLoadUrlEndCallback(self,webview,param,url,job,buf,lens): 216 | if hasattr(self,'wkeLoadUrlEndCallback'): 217 | url=url.decode() 218 | param=self.get_param_value(param) 219 | self.wkeLoadUrlEndCallback(webview=webview, param=param,url=url,job=job,buf=buf,lens=lens) 220 | @method(CFUNCTYPE(None,_LRESULT,c_void_p,c_char_p,c_void_p)) 221 | def _wkeLoadUrlFailCallback(self,webview,param,url,job): 222 | if hasattr(self,'wkeLoadUrlFailCallback'): 223 | url=url.decode() 224 | param=self.get_param_value(param) 225 | self.wkeLoadUrlFailCallback(webview=webview, param=param,url=url,job=job) 226 | @method(CFUNCTYPE(None,_LRESULT,c_void_p,c_void_p,c_int,c_void_p)) 227 | def _wkeLoadingFinishCallback(self,webview,param,url,result,failedReason): 228 | if hasattr(self,'wkeLoadingFinishCallback'): 229 | url=self.mb.wkeGetStringW(url) 230 | if result==1: 231 | failedReason=self.mb.wkeGetStringW(failedReason) 232 | param=self.get_param_value(param) 233 | self.wkeLoadingFinishCallback(webview=webview, param=param,url=url,result=result,failedReason=failedReason) 234 | @method(CFUNCTYPE(None, _LRESULT, c_void_p,c_char_p,POINTER(wkeMemBuf))) 235 | def _wkeOnNetGetFaviconCallback(self,webview,param,url,buf): 236 | if hasattr(self,'wkeOnNetGetFaviconCallback'): 237 | url=url.decode() 238 | param=self.get_param_value(param) 239 | self.wkeOnNetGetFaviconCallback(webview=webview, param=param,url=url,buf=buf) 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | def param_to_string(self,param): 248 | if param!=0: 249 | _type=0 250 | if isinstance(param,str): 251 | _type='1' 252 | elif isinstance(param,int): 253 | _type='2' 254 | elif isinstance(param,float): 255 | _type='3' 256 | elif isinstance(param,list): 257 | _type='4' 258 | elif isinstance(param,tuple): 259 | _type='5' 260 | param=list(param) 261 | elif isinstance(param,dict): 262 | _type='6' 263 | else: 264 | param=0 265 | if _type in ['4','5','6']: 266 | param=json.dumps(param) 267 | if _type!=0: 268 | param=f'{_type}-|-lochen-119182686-|-{param}' 269 | param=self.mb.wkeCreateStringW(param,len(param)) 270 | return param 271 | def get_param_value(self,param): 272 | if param!=None: 273 | param_str=self.mb.wkeGetStringW(param) 274 | ls=param_str.split('-|-lochen-119182686-|-') 275 | _type=ls[0] 276 | _param=ls[1] 277 | if _type=='1': 278 | ... 279 | elif _type=='2': 280 | _param=int(_param) 281 | elif _type=='3': 282 | _param=float(_param) 283 | elif _type in ['4','5','6']: 284 | _param=json.loads(_param) 285 | if _type=='5': 286 | _param=tuple(_param) 287 | return _param 288 | -------------------------------------------------------------------------------- /MBPython/cookie.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from .pyrunjs import PyRunJS 4 | class Cookie(): 5 | def __init__(self,miniblink): 6 | self.mb=miniblink 7 | self.js=PyRunJS(miniblink) 8 | def wkeGetCookieW(self,webview): 9 | 10 | return self.mb.wkeGetCookieW(webview) 11 | 12 | def wkeSetCookie(self,webview,url,cookie): 13 | 14 | cookie=cookie.split(';') 15 | for x in cookie: 16 | self.mb.wkeSetCookie(webview,url.encode('utf8'),x.encode('utf8')) 17 | 18 | self.mb.wkePerformCookieCommand(webview,2) 19 | 20 | def set_cookie_by_js(self,webview,url,cookie): 21 | 22 | js_code=f"var cookie='{cookie}';"+''' 23 | cookie.split(';').forEach(function(e){ 24 | document.cookie=e 25 | })''' 26 | self.js.run_js(webview,js_code) 27 | 28 | self.mb.wkeLoadURLW(webview, url) 29 | 30 | def wkeSetCookieJarPath(self,webview,path): 31 | 32 | self.mb.wkeSetCookieJarPath(webview,path) 33 | 34 | def wkeSetCookieJarFullPath(self,webview,path): 35 | 36 | self.mb.wkeSetCookieJarFullPath(webview,path) 37 | 38 | def wkeClearCookie(self,webview): 39 | 40 | self.mb.wkeClearCookie(webview) -------------------------------------------------------------------------------- /MBPython/jsrunpy.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from ctypes import ( 4 | CFUNCTYPE, 5 | c_longlong, 6 | c_float, 7 | c_void_p, 8 | c_wchar_p 9 | ) 10 | from .method import method 11 | from . import _LRESULT 12 | 13 | class JsRunPy(): 14 | def __init__(self,miniblink): 15 | 16 | self.mb=miniblink 17 | 18 | def get_js_args_val(self,es,arg_count): 19 | val_ls=[None]*arg_count 20 | for i in range(arg_count): 21 | 22 | arg_type=self.mb.jsArgType(es,i) 23 | 24 | if arg_type==0: 25 | val=self.mb.jsArg(es,i) 26 | val=self.mb.jsToInt(es, c_longlong(val)) 27 | elif arg_type==1: 28 | val=self.mb.jsArg(es,i) 29 | val=self.mb.jsToTempStringW(es, c_longlong(val)) 30 | elif arg_type==2: 31 | val=self.mb.jsArg(es,i) 32 | val=self.mb.jsToTempStringW(es, c_longlong(val)) 33 | if val=='false': 34 | val=False 35 | else: 36 | val=True 37 | 38 | elif arg_type==5 or arg_type==7: 39 | val=None 40 | elif arg_type==6: 41 | 42 | val=self.mb.jsArg(es,i) 43 | lens=self.mb.jsGetLength(es,c_longlong(val)) 44 | tmp_arr=[None]*lens 45 | for j in range(lens): 46 | tmp_val=self.mb.jsGetAt(es,c_longlong(val),j) 47 | if self.mb.jsIsNumber(tmp_val)==1: 48 | tmp_val=self.mb.jsToInt(es, c_longlong(tmp_val)) 49 | elif self.mb.jsIsString(tmp_val)==1: 50 | tmp_val=self.mb.jsToTempStringW(es, c_longlong(tmp_val)) 51 | tmp_val=c_wchar_p(tmp_val).value 52 | elif self.mb.jsIsBoolean(tmp_val)==1: 53 | tmp_val=self.mb.jsToTempStringW(es, c_longlong(tmp_val)) 54 | if tmp_val=='false': 55 | tmp_val=False 56 | else: 57 | tmp_val=True 58 | tmp_arr[j]=tmp_val 59 | val=tmp_arr 60 | else: 61 | val=self.mb.jsArg(es,i) 62 | val=self.mb.jsToTempStringW(es, c_longlong(val)) 63 | val_ls[i]=val 64 | 65 | return val_ls 66 | 67 | def to_js_args_val(self,es,val): 68 | 69 | if isinstance(val,str): 70 | val=self.mb.jsStringW(es,val) 71 | elif isinstance(val,int): 72 | val=self.mb.jsInt(val) 73 | elif isinstance(val,float): 74 | val=self.mb.jsFloat(val) 75 | elif isinstance(val,bool): 76 | val=self.mb.jsBoolean(val) 77 | 78 | elif isinstance(val,list): 79 | lens=len(val) 80 | tmp_arr=self.mb.jsEmptyArray(es) 81 | for i in range(lens): 82 | if isinstance(val[i],int): 83 | tmp_val=self.mb.jsInt(val[i]) 84 | elif isinstance(val[i],str): 85 | tmp_val=self.mb.jsStringW(es,val[i]) 86 | elif isinstance(val[i],float): 87 | tmp_val=self.mb.jsFloat(c_float(val[i])) 88 | self.mb.jsSetAt(es, c_longlong(tmp_arr), i, c_longlong(tmp_val)) 89 | val=tmp_arr 90 | elif isinstance(val,dict): 91 | tmp_obj=self.mb.jsEmptyObject(es) 92 | for k,v in val.items(): 93 | if isinstance(v,int): 94 | v=self.mb.jsInt(v) 95 | elif isinstance(v,str): 96 | v=self.mb.jsStringW(es,v) 97 | elif isinstance(v,float): 98 | v=self.mb.jsFloat(c_float(v)) 99 | self.mb.jsSet(es,c_longlong(tmp_obj),k.encode(),c_longlong(v)) 100 | val=tmp_obj 101 | return val 102 | 103 | def bind_func(self,func_name,arg_count=0,param=0): 104 | js_bind_func=getattr(self,func_name) 105 | func_name=func_name.encode() 106 | self.mb.wkeJsBindFunction(func_name,js_bind_func,param,arg_count) 107 | 108 | @method(CFUNCTYPE(c_longlong, _LRESULT, c_void_p)) 109 | def call_py_func(self,es,param): 110 | 111 | if hasattr(self,'python_func'): 112 | return self.python_func(es=es,param=param) 113 | return 0 -------------------------------------------------------------------------------- /MBPython/message.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import ( 3 | windll, 4 | c_long, 5 | c_ulong, 6 | c_ushort 7 | ) 8 | from .wkeStruct import mPos 9 | 10 | user32 = windll.user32 11 | class Message(): 12 | def __init__(self,miniblink): 13 | 14 | self.mb=miniblink 15 | def wkeFireMouseEvent(self,webview,msg,x,y,flags=0): 16 | 17 | return self.mb.wkeFireMouseEvent(webview,msg,x,y,flags) 18 | def wkeFireKeyDownEvent(self,webview,virtualKeyCode,flags=0): 19 | 20 | return self.mb.wkeFireKeyDownEvent(webview,virtualKeyCode,flags,False) 21 | def wkeFireKeyUpEvent(self,webview,virtualKeyCode,flags=0): 22 | 23 | return self.mb.wkeFireKeyUpEvent(webview,virtualKeyCode,flags,False) 24 | def wkeFireKeyPressEvent(self,webview,virtualKeyCode,flags): 25 | return self.mb.wkeFireKeyPressEvent(webview,virtualKeyCode,flags,False) 26 | def wkeFireWindowsMessage(self,webview,hwnd,msg,wParam,lParam,result): 27 | 28 | return self.mb.wkeFireWindowsMessage(webview,hwnd,msg,wParam,lParam,result) 29 | 30 | @staticmethod 31 | def fire_mouse_msg(hwnd,msg,x,y): 32 | pos=c_long(c_ushort(x).value | c_ulong(c_ushort(y).value).value << 16).value 33 | return user32.PostMessageW(hwnd,msg,0,pos) 34 | 35 | @staticmethod 36 | def fire_keyboard_msg(hwnd,virtualKeyCode,msg): 37 | return user32.SendMessageW(hwnd,msg,virtualKeyCode,0) 38 | 39 | @staticmethod 40 | def get_mouse_pos(): 41 | p=mPos() 42 | user32.GetCursorPos(byref(p)) 43 | 44 | return p 45 | -------------------------------------------------------------------------------- /MBPython/method.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | def method(prototype): 3 | class MethodDescriptor(object): 4 | __slots__ = ['func', 'bound_funcs'] 5 | def __init__(self, func): 6 | self.func = func 7 | self.bound_funcs = {} 8 | def __get__(self, obj, type=None): 9 | if obj!=None: 10 | try: 11 | return self.bound_funcs[obj,type] 12 | except: 13 | ret = self.bound_funcs[obj,type] = prototype( 14 | self.func.__get__(obj, type)) 15 | return ret 16 | return MethodDescriptor -------------------------------------------------------------------------------- /MBPython/miniblink.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import ( 3 | c_int, 4 | c_longlong, 5 | c_float, 6 | c_char_p, 7 | c_wchar_p, 8 | c_bool, 9 | c_void_p, 10 | POINTER, 11 | cdll 12 | ) 13 | from .wkeStruct import (wkeProxy,wkePostBodyElements,wkeRect) 14 | 15 | from .bindwebview import BindWebview 16 | from .callback import CallBack 17 | from .cookie import Cookie 18 | from .jsrunpy import JsRunPy 19 | from .message import Message 20 | from .network import NetWork 21 | from .proxy import Proxy 22 | from .pyrunjs import PyRunJS 23 | from .window import Window 24 | from . import _LRESULT 25 | import platform 26 | 27 | 28 | 29 | class Miniblink(): 30 | def __init__(self,mb): 31 | self.bindwebview=BindWebview(mb) 32 | self.callback=CallBack(mb) 33 | self.cookie=Cookie(mb) 34 | self.jsrunpy=JsRunPy(mb) 35 | self.message=Message(mb) 36 | self.network=NetWork(mb) 37 | self.proxy=Proxy(mb) 38 | self.pyrunjs=PyRunJS(mb) 39 | self.window=Window(mb) 40 | @staticmethod 41 | def init(node_path): 42 | 43 | architecture=platform.architecture()[0] 44 | if architecture=='64bit' and (not node_path.endswith('x64.dll')): 45 | print('请使用与node.dll位数对应的Python版本') 46 | return 0 47 | elif architecture=='32bit' and node_path.endswith('x64.dll'): 48 | print('请使用与node.dll位数对应的Python版本') 49 | return 0 50 | 51 | mb=cdll.LoadLibrary(node_path) 52 | mb.wkeInit() 53 | 54 | mb.wkeCreateWebWindow.restype=_LRESULT 55 | mb.wkeCreateWebView.restype=_LRESULT 56 | mb.wkeSetWindowTitleW.argtypes=[_LRESULT] 57 | mb.wkeSetTransparent.argtypes=[_LRESULT] 58 | mb.wkeSetHandleOffset.argtypes=[_LRESULT] 59 | mb.wkeSetHandle.argtypes=[_LRESULT] 60 | mb.wkeKillFocus.argtypes=[_LRESULT] 61 | mb.wkeRepaintIfNeeded.argtypes=[_LRESULT] 62 | mb.wkeWake.argtypes=[_LRESULT] 63 | mb.wkeGetCaretRect.argtypes=[_LRESULT] 64 | mb.wkeGetCaretRect.restype=wkeRect 65 | mb.wkeResize.argtypes=[_LRESULT] 66 | mb.wkeShowWindow.argtypes=[_LRESULT] 67 | mb.wkeMoveToCenter.argtypes=[_LRESULT] 68 | mb.wkeGoForward.argtypes=[_LRESULT] 69 | mb.wkeGoBack.argtypes=[_LRESULT] 70 | mb.wkeLoadURLW.argtypes=[_LRESULT] 71 | mb.wkeLoadHTMLW.argtypes=[_LRESULT] 72 | mb.wkeLoadFile.argtypes=[_LRESULT] 73 | mb.wkeReload.argtypes=[_LRESULT] 74 | mb.wkeStopLoading.argtypes=[_LRESULT] 75 | mb.wkeWidth.argtypes=[_LRESULT] 76 | mb.wkeWidth.restype=_LRESULT 77 | mb.wkeHeight.argtypes=[_LRESULT] 78 | mb.wkeHeight.restype=_LRESULT 79 | mb.wkeContentsWidth.argtypes=[_LRESULT] 80 | mb.wkeContentsWidth.restype=_LRESULT 81 | mb.wkeContentsHeight.argtypes=[_LRESULT] 82 | mb.wkeContentsHeight.restype=_LRESULT 83 | mb.wkeGetWindowHandle.argtypes=[_LRESULT] 84 | mb.wkeGetWindowHandle.restype=_LRESULT 85 | mb.wkeGetURL.argtypes=[_LRESULT] 86 | mb.wkeGetURL.restype=c_char_p 87 | mb.wkeGetFrameUrl.argtypes=[_LRESULT] 88 | mb.wkeGetFrameUrl.restype=c_char_p 89 | mb.wkeGetSource.argtypes=[_LRESULT] 90 | mb.wkeGetSource.restype=c_char_p 91 | mb.wkeUtilSerializeToMHTML.argtypes=[_LRESULT] 92 | mb.wkeUtilSerializeToMHTML.restype=c_char_p 93 | mb.wkeGetViewDC.argtypes=[_LRESULT] 94 | mb.wkeGetViewDC.restype=_LRESULT 95 | mb.wkeFireMouseEvent.argtypes=[_LRESULT] 96 | mb.wkeFireKeyDownEvent.argtypes=[_LRESULT] 97 | mb.wkeFireKeyUpEvent.argtypes=[_LRESULT] 98 | mb.wkeFireKeyPressEvent.argtypes=[_LRESULT] 99 | mb.wkeFireWindowsMessage.argtypes=[_LRESULT] 100 | mb.wkeFireMouseWheelEvent.argtypes=[_LRESULT,c_int,c_int,_LRESULT,c_int] 101 | mb.wkeFireContextMenuEvent.argtypes=[_LRESULT] 102 | 103 | mb.wkeOnCreateView.argtypes=[_LRESULT] 104 | mb.wkeOnPaintUpdated.argtypes=[_LRESULT] 105 | mb.wkeOnPaintBitUpdated.argtypes=[_LRESULT] 106 | mb.wkeOnNavigation.argtypes=[_LRESULT] 107 | mb.wkeOnTitleChanged.argtypes=[_LRESULT] 108 | mb.wkeOnURLChanged2.argtypes=[_LRESULT] 109 | mb.wkeOnMouseOverUrlChanged.argtypes=[_LRESULT] 110 | mb.wkeOnAlertBox.argtypes=[_LRESULT] 111 | mb.wkeOnConfirmBox.argtypes=[_LRESULT] 112 | mb.wkeOnPromptBox.argtypes=[_LRESULT] 113 | mb.wkeOnConsole.argtypes=[_LRESULT] 114 | mb.wkeOnDownload.argtypes=[_LRESULT] 115 | mb.wkeOnDocumentReady2.argtypes=[_LRESULT] 116 | mb.wkeNetOnResponse.argtypes=[_LRESULT] 117 | mb.wkeOnLoadUrlBegin.argtypes=[_LRESULT] 118 | mb.wkeOnLoadUrlEnd.argtypes=[_LRESULT] 119 | mb.wkeOnLoadUrlEnd.argtypes=[_LRESULT] 120 | mb.wkeOnLoadingFinish.argtypes=[_LRESULT] 121 | mb.wkeOnLoadUrlFail.argtypes=[_LRESULT] 122 | mb.wkeNetGetFavicon.argtypes=[_LRESULT] 123 | mb.wkeOnWindowClosing.argtypes=[_LRESULT] 124 | mb.wkeOnWindowDestroy.argtypes=[_LRESULT] 125 | 126 | mb.wkeIsDocumentReady.argtypes=[_LRESULT] 127 | mb.wkeNetHookRequest.argtypes=[_LRESULT] 128 | mb.wkeNetGetRequestMethod.argtypes=[_LRESULT] 129 | mb.wkeNetGetRequestMethod.restype=_LRESULT 130 | mb.jsArgCount.argtypes=[_LRESULT] 131 | mb.jsArgCount.restype=_LRESULT 132 | mb.wkeGlobalExec.argtypes=[_LRESULT] 133 | mb.wkeGlobalExec.restype=_LRESULT 134 | mb.jsGetGlobal.argtypes=[_LRESULT,c_char_p] 135 | mb.jsGetGlobal.restype=_LRESULT 136 | mb.jsGet.argtypes=[_LRESULT] 137 | mb.jsGet.restype=_LRESULT 138 | mb.wkeRunJSW.argtypes=[_LRESULT,c_wchar_p] 139 | mb.wkeRunJSW.restype=c_longlong 140 | mb.jsToStringW.argtypes=[_LRESULT,c_longlong] 141 | mb.jsToStringW.restype=c_wchar_p 142 | mb.wkeRunJsByFrame.argtypes=[_LRESULT] 143 | mb.wkeRunJsByFrame.restype=_LRESULT 144 | mb.wkeGetGlobalExecByFrame.argtypes=[_LRESULT] 145 | mb.wkeGetGlobalExecByFrame.restype=_LRESULT 146 | mb.wkeJsBindFunction.argtypes=[c_char_p] 147 | mb.jsToTempStringW.argtypes=[_LRESULT] 148 | mb.jsToTempStringW.restype=c_wchar_p 149 | mb.jsArgType.argtypes=[_LRESULT] 150 | mb.jsArgType.restype=_LRESULT 151 | mb.jsArg.argtypes=[_LRESULT] 152 | mb.jsArg.restype=_LRESULT 153 | mb.jsGetLength.argtypes=[_LRESULT] 154 | mb.jsGetLength.restype=_LRESULT 155 | mb.jsGetAt.argtypes=[_LRESULT] 156 | mb.jsGetAt.restype=_LRESULT 157 | mb.jsSetAt.argtypes=[_LRESULT] 158 | mb.jsGetKeys.argtypes=[_LRESULT] 159 | 160 | mb.jsCall.argtypes=[_LRESULT] 161 | mb.jsCall.restype=_LRESULT 162 | mb.jsIsNumber.argtypes=[c_longlong] 163 | mb.jsIsNumber.restype=_LRESULT 164 | mb.jsToInt.argtypes=[_LRESULT] 165 | mb.jsToInt.restype=_LRESULT 166 | mb.jsIsString.argtypes=[c_longlong] 167 | mb.jsIsString.restype=_LRESULT 168 | mb.jsIsBoolean.argtypes=[c_longlong] 169 | mb.jsIsBoolean.restype=_LRESULT 170 | mb.jsStringW.argtypes=[_LRESULT,c_wchar_p] 171 | mb.jsEmptyArray.argtypes=[_LRESULT] 172 | mb.jsEmptyArray.restype=_LRESULT 173 | mb.jsStringW.restype=_LRESULT 174 | mb.jsBoolean.argtypes=[c_bool] 175 | mb.jsBoolean.restype=_LRESULT 176 | mb.jsFloat.argtypes=[c_float] 177 | mb.jsInt.argtypes=[_LRESULT] 178 | mb.jsInt.restype=_LRESULT 179 | mb.jsEmptyObject.argtypes=[_LRESULT] 180 | mb.jsEmptyObject.restype=_LRESULT 181 | mb.jsSet.argtypes=[_LRESULT] 182 | mb.wkeSetLocalStorageFullPath.argtypes=[_LRESULT,c_wchar_p] 183 | mb.wkeSetCookieEnabled.argtypes=[_LRESULT] 184 | mb.wkeSetCookie.argtypes=[_LRESULT] 185 | mb.wkePerformCookieCommand.argtypes=[_LRESULT] 186 | mb.wkeSetCookieJarPath.argtypes=[_LRESULT,c_wchar_p] 187 | mb.wkeSetCookieJarFullPath.argtypes=[_LRESULT,c_wchar_p] 188 | mb.wkeClearCookie.argtypes=[_LRESULT] 189 | mb.wkeSetProxy.argtypes=[POINTER(wkeProxy)] 190 | mb.wkeSetViewProxy.argtypes=[_LRESULT,POINTER(wkeProxy)] 191 | mb.wkeNetGetPostBody.argtypes=[_LRESULT] 192 | mb.wkeNetGetPostBody.restype=POINTER(wkePostBodyElements) 193 | mb.wkeNetCancelRequest.argtypes=[_LRESULT] 194 | mb.wkeNetSetData.argtypes=[_LRESULT,c_char_p] 195 | mb.wkeNetSetMIMEType.argtypes=[_LRESULT,c_char_p] 196 | mb.wkePostURLW.argtypes=[_LRESULT,c_wchar_p,c_char_p] 197 | mb.wkeSetTouchEnabled.argtypes=[_LRESULT] 198 | mb.wkeSetDeviceParameter.argtypes=[_LRESULT] 199 | mb.wkeSetWebViewName.argtypes=[_LRESULT] 200 | mb.wkeSetZoomFactor.argtypes=[_LRESULT] 201 | mb.wkeSetNavigationToNewWindowEnable.argtypes=[_LRESULT] 202 | mb.wkeSetContextMenuEnabled.argtypes=[_LRESULT] 203 | mb.wkeSetHeadlessEnabled.argtypes=[_LRESULT] 204 | mb.wkeSetDragEnable.argtypes=[_LRESULT] 205 | mb.wkeAddPluginDirectory.argtypes=[_LRESULT,c_wchar_p] 206 | mb.wkeSetNpapiPluginsEnabled.argtypes=[_LRESULT] 207 | mb.wkeSetCspCheckEnable.argtypes=[_LRESULT] 208 | mb.wkeSetDebugConfig.argtypes=[_LRESULT] 209 | mb.wkeSetString.argtypes=[_LRESULT] 210 | mb.wkeSetUserAgentW.argtypes=[_LRESULT] 211 | mb.wkeGetUserAgent.argtypes=[_LRESULT] 212 | mb.wkeGetUserAgent.restype=c_char_p 213 | 214 | mb.wkeGetCookieW.argtypes=[_LRESULT] 215 | mb.wkeGetCookieW.restype=c_wchar_p 216 | mb.wkeCreateStringW.restype=_LRESULT 217 | mb.wkeGetStringW.argtypes=[_LRESULT] 218 | mb.wkeGetStringW.restype=c_wchar_p 219 | 220 | 221 | return mb 222 | def create(mb): 223 | return NewMiniblink(mb) 224 | 225 | -------------------------------------------------------------------------------- /MBPython/network.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import c_char 3 | import binascii 4 | class NetWork(): 5 | def __init__(self,miniblink): 6 | self.types=['.jpg','.png','.mp4','.ts','.mp3','.avi','.gif'] 7 | self.bufs=[] 8 | self.mb=miniblink 9 | def wkeLoadURLW(self,webview,url): 10 | self.mb.wkeLoadURLW(webview,url) 11 | def wkeLoadHTMLW(self,webview,html): 12 | self.mb.wkeLoadHTMLW(webview,html) 13 | def wkeLoadFile(self,webview,file_path): 14 | file_path=file_path.encode() 15 | self.mb.wkeLoadFile(webview,file_path) 16 | def wkePostURLW(self,webview,url,data): 17 | data=data.encode() 18 | lens=len(data) 19 | self.mb.wkeLoadURLW(webview,data,lens) 20 | def wkeReload(self,webview): 21 | self.mb.wkeReload(webview) 22 | def wkeStopLoading(self,webview): 23 | self.mb.wkeStopLoading(webview) 24 | def wkeGetURL(self,webview): 25 | url=self.mb.wkeGetURL(webview) 26 | return url.decode() 27 | def wkeGetFrameUrl(self,webview,frameId): 28 | url=self.mb.wkeGetFrameUrl(webview,frameId) 29 | return url.decode('utf8') 30 | def wkeGetSource(self,webview): 31 | source=self.mb.wkeGetSource(webview) 32 | return source.decode() 33 | def wkeUtilSerializeToMHTML(self,webview): 34 | mhtml_content=self.mb.wkeUtilSerializeToMHTML(webview) 35 | 36 | return mhtml_content 37 | def get_type(self,url): 38 | for x in self.types: 39 | if x in url: 40 | return x 41 | return 42 | 43 | def save_buf_data(self,url,buf,lens): 44 | 45 | if lens==0:return 46 | contents=(c_char * lens).from_address(buf) 47 | _type=self.get_type(url) 48 | if _type==None:return 49 | name=binascii.crc32(url.encode()) 50 | file_name=f'{name}{_type}' 51 | try: 52 | with open(file_name,'wb') as f: 53 | f.write(contents) 54 | self.bufs.append({url:file_name}) 55 | except: 56 | ... 57 | finally: 58 | ... 59 | 60 | def cancel_request(self,job,url,ident_ls=['.jpg']): 61 | 62 | for x in ident_ls: 63 | if x in url: 64 | self.mb.wkeNetCancelRequest(job) 65 | return True 66 | return False 67 | def set_response_data(self,job,data='',file_name=None): 68 | 69 | lens=len(data) 70 | if lens!=0: 71 | self.mb.wkeNetSetData(job,data,lens) 72 | return True 73 | elif file_name!=None: 74 | with open(file_name) as f: 75 | data=f.read() 76 | data=data.encode() 77 | lens=len(data) 78 | if lens!=0: 79 | if '.js' in file_name: 80 | self.mb.wkeNetSetMIMEType(job,b'text/javascript') 81 | elif '.html' in file_name: 82 | self.mb.wkeNetSetMIMEType(job,b'text/html') 83 | self.mb.wkeNetSetData(job,data,lens) 84 | return True 85 | return False 86 | 87 | def get_post_data(self,job,url,ident=''): 88 | 89 | if ident not in url:return '',0,None 90 | elements=self.mb.wkeNetGetPostBody(job) 91 | try: 92 | data=elements.contents.element.contents.contents.data.contents.data 93 | lens=elements.contents.element.contents.contents.data.contents.length 94 | except: 95 | return '',0,None 96 | data=data[:lens].decode('utf8','ignore') 97 | print('post_data',data,lens) 98 | return data,lens,elements -------------------------------------------------------------------------------- /MBPython/proxy.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import ( 3 | c_int, 4 | c_ushort 5 | ) 6 | from .wkeStruct import wkeProxy 7 | 8 | class Proxy(): 9 | def __init__(self,miniblink): 10 | 11 | self.mb=miniblink 12 | 13 | def wkeSetProxy(self,ip,port,proxy_type=1,user=None,password=None): 14 | 15 | if not all([ip,port]):return 16 | if user==None: 17 | user=b'' 18 | else: 19 | user=user.encode('utf8') 20 | if password==None: 21 | password=b'' 22 | else: 23 | password=password.encode('utf8') 24 | ip=ip.encode('utf8') 25 | port=int(port) 26 | proxy= wkeProxy(type=c_int(proxy_type), hostname=ip, port=c_ushort(port),username=user,password=password) 27 | self.mb.wkeSetProxy(proxy) 28 | 29 | def wkeSetViewProxy(self,webview,ip,port,proxy_type=1,user=None,password=None): 30 | 31 | if not all([ip,port]):return 32 | if user==None: 33 | user=b'' 34 | else: 35 | user=user.encode('utf8') 36 | if password==None: 37 | password=b'' 38 | else: 39 | password=password.encode('utf8') 40 | ip=ip.encode('utf8') 41 | port=int(port) 42 | proxy= wkeProxy(type=c_int(proxy_type), hostname=ip, port=c_ushort(port),username=user,password=password) 43 | self.mb.wkeSetViewProxy(webview,proxy) -------------------------------------------------------------------------------- /MBPython/pyrunjs.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import (c_longlong,byref) 3 | from .method import method 4 | 5 | 6 | class PyRunJS(): 7 | def __init__(self,miniblink): 8 | 9 | self.mb=miniblink 10 | 11 | def run_js(self,webview,js_code): 12 | 13 | es=self.mb.wkeGlobalExec(webview) 14 | val=self.mb.wkeRunJSW(webview,js_code) 15 | val=self.mb.jsToStringW(es,val) 16 | if val=='undefined': 17 | val=None 18 | return val 19 | 20 | def run_js_file(self,webview,file_name): 21 | with open(file_name) as f: 22 | js_code=f.read() 23 | return self.run_js(webview,js_code) 24 | def run_js_byframe(self,webview,frameId,js_code,isInClosure=True): 25 | 26 | js_code=js_code.encode() 27 | val=self.mb.wkeRunJsByFrame(webview,frameId,js_code,isInClosure) 28 | es = self.mb.wkeGetGlobalExecByFrame(webview, frameId) 29 | val=self.mb.jsToTempStringW(es, c_longlong(val)) 30 | return val 31 | 32 | def run_js_global(self,webview,func_name,param_ls=[],this_func=0): 33 | 34 | es=self.mb.wkeGlobalExec(webview) 35 | if this_func==0: 36 | func_name=func_name.encode() 37 | func=self.mb.jsGetGlobal(es,func_name) 38 | else: 39 | ... 40 | argCount=len(param_ls) 41 | args_ls=(c_longlong *argCount)() 42 | 43 | for i,param in enumerate(param_ls): 44 | if isinstance(param,str): 45 | param=self.mb.jsStringW(es,param) 46 | elif isinstance(param,int): 47 | param=self.mb.jsInt(c_longlong(param)) 48 | elif isinstance(param,float): 49 | param=self.mb.jsFloat(param) 50 | elif isinstance(param,bool): 51 | param=self.mb.jsBoolean(param) 52 | args_ls[i]=param 53 | 54 | callRet=self.mb.jsCall(es,c_longlong(func),c_longlong(this_func),byref(args_ls),c_longlong(argCount)) 55 | val=self.mb.jsToStringW(es,c_longlong(callRet)) 56 | return val -------------------------------------------------------------------------------- /MBPython/screenshot.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import windll 3 | from .winConst import WinConst 4 | import win32gui, win32ui 5 | from struct import pack 6 | import collections 7 | import zlib 8 | 9 | 10 | user32=windll.user32 11 | def to_png(data, size, level=6, file_name=None): 12 | width, height = size 13 | line = width * 3 14 | png_filter = pack(">B", 0) 15 | scanlines = b"".join( 16 | [png_filter + data[y * line : y * line + line] for y in range(height)] 17 | ) 18 | 19 | magic = pack(">8B", 137, 80, 78, 71, 13, 10, 26, 10) 20 | 21 | 22 | ihdr = [b"", b"IHDR", b"", b""] 23 | ihdr[2] = pack(">2I5B", width, height, 8, 2, 0, 0, 0) 24 | ihdr[3] = pack(">I", zlib.crc32(b"".join(ihdr[1:3])) & 0xFFFFFFFF) 25 | ihdr[0] = pack(">I", len(ihdr[2])) 26 | 27 | 28 | idat = [b"", b"IDAT", zlib.compress(scanlines, level), b""] 29 | idat[3] = pack(">I", zlib.crc32(b"".join(idat[1:3])) & 0xFFFFFFFF) 30 | idat[0] = pack(">I", len(idat[2])) 31 | 32 | 33 | iend = [b"", b"IEND", b"", b""] 34 | iend[3] = pack(">I", zlib.crc32(iend[1]) & 0xFFFFFFFF) 35 | iend[0] = pack(">I", len(iend[2])) 36 | 37 | if not file_name: 38 | return magic + b"".join(ihdr + idat + iend) 39 | with open(file_name, "wb") as f: 40 | f.write(magic+ b"".join(ihdr + idat + iend)) 41 | return None 42 | class pixelsParse: 43 | __slots__ = {"__rgb", "pos", "raw", "size"} 44 | def __init__(self, data, left=0,top=0,width=0,height=0, size=None): 45 | 46 | _Pos = collections.namedtuple("Pos", "left, top") 47 | _Size = collections.namedtuple("Size", "width, height") 48 | self.__rgb = None 49 | self.raw = data 50 | self.pos = _Pos(left, top) 51 | if size is not None: 52 | self.size = size 53 | else: 54 | self.size = _Size(width, height) 55 | @property 56 | def height(self): 57 | return self.size.height 58 | @property 59 | def left(self): 60 | return self.pos.left 61 | @property 62 | def rgb(self): 63 | 64 | if not self.__rgb: 65 | rgb = bytearray(self.height * self.width * 3) 66 | raw = self.raw 67 | rgb[0::3] = raw[2::4] 68 | rgb[1::3] = raw[1::4] 69 | rgb[2::3] = raw[0::4] 70 | self.__rgb = bytes(rgb) 71 | return self.__rgb 72 | @property 73 | def top(self): 74 | return self.pos.top 75 | @property 76 | def width(self): 77 | return self.size.width 78 | def generate_bitBmp(hwnd=0,screenDC=0,left=0,top=0,width=0,height=0,cx=0,cy=0): 79 | 80 | if screenDC==0: 81 | 82 | screenDC = user32.GetWindowDC(hwnd) 83 | 84 | mfcDC = win32ui.CreateDCFromHandle(screenDC) 85 | 86 | saveDC = mfcDC.CreateCompatibleDC() 87 | 88 | saveBitMap = win32ui.CreateBitmap() 89 | 90 | saveBitMap.CreateCompatibleBitmap(mfcDC,width,height) 91 | 92 | saveDC.SelectObject(saveBitMap) 93 | 94 | saveDC.BitBlt((0,0), (width,height), mfcDC, (0, 0), WinConst.SRCCOPY) 95 | 96 | pixels = saveBitMap.GetBitmapBits(True) 97 | img=pixelsParse(data=bytearray(pixels), left=left 98 | ,top=top,width=width,height=height) 99 | pixels=None 100 | return img 101 | 102 | def screen_shot(file_name,hwnd=0,screenDC=0,left=0,top=0,width=0,height=0): 103 | if not all([width,height]):return False 104 | img=generate_bitBmp(hwnd=hwnd, screenDC=screenDC,left=left,top=top,width=width,height=height,cx=0,cy=0) 105 | to_png(img.rgb, img.size, level=6, file_name=file_name) 106 | img=None 107 | return True 108 | def whole_screenshot(mb,webview,file_name): 109 | 110 | left=0 111 | top=0 112 | width=mb.wkeGetContentWidth(webview) 113 | height=mb.wkeGetContentHeight(webview) 114 | pixels=create_string_buffer(width*height*4) 115 | mb.wkeResize(webview,width,height) 116 | mb.wkeUpdate() 117 | mb.wkePaint(webview,byref(pixels),0) 118 | img=pixelsParse(data=bytearray(pixels), left=left 119 | ,top=top,width=width,height=height) 120 | to_png(img.rgb, img.size, level=6, file_name=file_name) 121 | pixels=None 122 | img=None 123 | return True 124 | 125 | -------------------------------------------------------------------------------- /MBPython/seticon.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import windll 3 | from .winConst import WinConst 4 | from os import path 5 | 6 | user32 = windll.user32 7 | kernel32= windll.kernel32 8 | RelPath = lambda file : path.join(path.dirname(path.abspath(__file__)), file) 9 | 10 | def set_icon(hwnd, filename): 11 | if not filename.endswith('.ico'): 12 | return False 13 | hModel = kernel32.GetModuleHandleW(None) 14 | hIcon = user32.LoadImageW(hModel,RelPath(filename),WinConst.IMAGE_ICON,48, 48,WinConst.LR_LOADFROMFILE | WinConst.LR_CREATEDIBSECTION) 15 | user32.SendMessageW(hwnd, WinConst.WM_SETICON, WinConst.ICON_BIG, hIcon) 16 | return True 17 | def set_icon_2(hwnd,filename): 18 | if not filename.endswith('.ico'): 19 | return False 20 | import win32api 21 | import win32gui 22 | icon_big = win32gui.LoadImage( 23 | None, RelPath(filename), WinConst.IMAGE_ICON, 24 | 48, 48, WinConst.LR_LOADFROMFILE) 25 | win32api.SendMessage(hwnd, WinConst.WM_SETICON,WinConst.ICON_BIG, icon_big) 26 | return True 27 | -------------------------------------------------------------------------------- /MBPython/timer.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import ( 3 | c_void_p, 4 | windll, 5 | WINFUNCTYPE 6 | ) 7 | from ctypes.wintypes import ( 8 | DWORD, 9 | HWND, 10 | UINT 11 | ) 12 | from .method import method 13 | user32=windll.user32 14 | 15 | 16 | class Timer: 17 | def __init__(self): 18 | self.timer_func_dict={} 19 | def setTimer(self,hwnd,nid,dwTime,is_timer_one=True): 20 | self.is_timer_one=is_timer_one 21 | return user32.SetTimer (hwnd,nid, dwTime, self._timerCallBack) 22 | @method(WINFUNCTYPE(c_void_p,HWND,c_void_p,UINT,DWORD)) 23 | def _timerCallBack(self,hwnd,msg,nid,dwTime): 24 | if hasattr(self,'timerCallBack'): 25 | if self.is_timer_one: 26 | self.timerCallBack(hwnd=hwnd,msg=msg,nid=nid,dwTime=dwTime) 27 | user32.KillTimer(hwnd,nid) 28 | return 0 29 | return self.timerCallBack(hwnd=hwnd,msg=msg,nid=nid,dwTime=dwTime) 30 | -------------------------------------------------------------------------------- /MBPython/winConst.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class WinConst(): 3 | GWL_EXSTYLE = -20 4 | GWL_WNDPROC = -4 5 | WS_EX_LAYERED = 524288 6 | WM_PAINT = 15 7 | WM_ERASEBKGND = 20 8 | WM_SIZE = 5 9 | WM_KEYDOWN = 256 10 | WM_KEYUP = 257 11 | WM_CHAR = 258 12 | WM_LBUTTONDOWN = 513 13 | WM_LBUTTONUP = 514 14 | WM_MBUTTONDOWN = 519 15 | WM_RBUTTONDOWN = 516 16 | WM_LBUTTONDBLCLK = 515 17 | WM_MBUTTONDBLCLK = 521 18 | WM_RBUTTONDBLCLK = 518 19 | WM_MBUTTONUP = 520 20 | WM_RBUTTONUP = 517 21 | WM_MOUSEMOVE = 512 22 | WM_CONTEXTMENU = 123 23 | WM_MOUSEWHEEL = 522 24 | WM_SETFOCUS = 7 25 | WM_KILLFOCUS = 8 26 | WM_IME_STARTCOMPOSITION = 269 27 | WM_NCHITTEST = 132 28 | WM_GETMINMAXINFO = 36 29 | WM_DESTROY = 2 30 | WM_SETCURSOR = 32 31 | MK_CONTROL = 8 32 | MK_SHIFT = 4 33 | MK_LBUTTON = 1 34 | MK_MBUTTON = 16 35 | MK_RBUTTON = 2 36 | KF_REPEAT = 16384 37 | KF_EXTENDED = 256 38 | SRCCOPY = 13369376 39 | CAPTUREBLT = 1073741824 40 | CFS_POINT = 2 41 | CFS_FORCE_POSITION = 32 42 | OBJ_BITMAP = 7 43 | AC_SRC_OVER = 0 44 | AC_SRC_ALPHA = 1 45 | ULW_ALPHA = 2 46 | WM_INPUTLANGCHANGE = 81 47 | WM_NCDESTROY = 130 48 | IMAGE_ICON=1 49 | LR_LOADFROMFILE=16 50 | WM_SETICON=128 51 | ICON_SMALL=0 52 | ICON_BIG=1 53 | IMAGE_ICON = 1 54 | LR_CREATEDIBSECTION = 0x00002000 55 | SRCCOPY = 13369376 56 | IDC_SIZENS=32645 57 | IDC_SIZEWE=32644 58 | IDC_SIZENWSE=32642 59 | IDC_SIZENESW=32643 -------------------------------------------------------------------------------- /MBPython/window.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import ( 3 | c_float, 4 | byref, 5 | windll 6 | ) 7 | from ctypes.wintypes import MSG 8 | from .wkeStruct import Rect 9 | 10 | user32=windll.user32 11 | class Window(): 12 | def __init__(self,miniblink): 13 | self.width=360 14 | self.height=480 15 | self.mb=miniblink 16 | def wkeCreateWebWindow(self,_type=0,hwnd=0,x=0,y=0,width=360,height=480): 17 | 18 | webview =self.mb.wkeCreateWebWindow( 19 | _type,hwnd, x, y, 20 | width, height 21 | ) 22 | return webview 23 | def wkeShowWindow(self,webview,_bool=True): 24 | self.mb.wkeShowWindow(webview,_bool) 25 | def wkeCreateWebView(self): 26 | 27 | return self.mb.wkeCreateWebView() 28 | def wkeDestroyWebView(self,webview): 29 | self.mb.wkeDestroyWebView(webview) 30 | def wkeMoveToCenter(self,webview): 31 | self.mb.wkeMoveToCenter(webview) 32 | def wkeRunMessageLoop(self): 33 | self.mb.wkeRunMessageLoop(0) 34 | def wkeSetUserAgentW(self,webview,ua): 35 | self.mb.wkeSetUserAgentW(webview,ua) 36 | def wkeGetUserAgent(self,webview): 37 | ua=self.mb.wkeGetUserAgent(webview) 38 | return ua.decode() 39 | def wkeSetDragEnable(self,webview,_bool): 40 | 41 | self.mb.wkeSetDragEnable(webview,_bool) 42 | def wkeAddPluginDirectory(self,webview,_path): 43 | 44 | self.mb.wkeAddPluginDirectory(webview,_path) 45 | def wkeSetNpapiPluginsEnabled(self,webview,_bool,_path=None): 46 | 47 | if _path!=None: 48 | self.wkeAddPluginDirectory(webview,_path) 49 | self.mb.wkeSetNpapiPluginsEnabled(webview,_bool) 50 | def wkeSetCspCheckEnable(self,webview,_bool=False): 51 | 52 | self.mb.wkeSetCspCheckEnable(webview,_bool) 53 | def wkeSetDebugConfig(self,webview,debug,param): 54 | 55 | debug=debug.encode() 56 | if isinstance(param,str): 57 | param=param.encode() 58 | self.mb.wkeSetDebugConfig(webview,debug,param) 59 | def wkeSetHeadlessEnabled(self,webview,_bool): 60 | 61 | self.mb.wkeSetHeadlessEnabled(webview,_bool) 62 | def wkeSetNavigationToNewWindowEnable(self,webview,_bool): 63 | 64 | self.mb.wkeSetNavigationToNewWindowEnable(webview,_bool) 65 | def wkeSetWebViewName(self,webview,name): 66 | self.mb.wkeSetWebViewName(webview,name.encode()) 67 | def wkeSetZoomFactor(self,webview,factor): 68 | 69 | self.mb.wkeSetZoomFactor(webview,factor) 70 | def wkeSetContextMenuEnabled(self,webview,_bool): 71 | 72 | self.mb.wkeSetContextMenuEnabled(webview,_bool) 73 | def wkeSetWindowTitleW(self,webview,title): 74 | self.mb.wkeSetWindowTitleW(webview, title) 75 | def wkeSetTransparent(self,webview,_bool): 76 | 77 | self.mb.wkeSetTransparent(webview,_bool) 78 | def wkeSetHandleOffset(self,webview,x,y): 79 | 80 | self.mb.wkeSetHandleOffset(webview,x,y) 81 | def wkeSetHandle(self,webview,hwnd): 82 | 83 | self.mb.wkeSetHandle(webview,hwnd) 84 | def wkeResize(self,webview,width=0,height=0): 85 | 86 | if width==0 or height==0:return False 87 | self.mb.wkeResize(webview,width,height) 88 | return True 89 | def wkeWidth(self,webview): 90 | 91 | return self.mb.wkeWidth(webview) 92 | def wkeHeight(self,webview): 93 | 94 | return self.mb.wkeHeight(webview) 95 | def wkeContentsWidth(self,webview): 96 | 97 | return self.mb.wkeContentsWidth(webview) 98 | def wkeContentsHeight(self,webview): 99 | 100 | return self.mb.wkeContentsHeight(webview) 101 | def wkeGoForward(self,webview): 102 | self.mb.wkeGoForward(webview) 103 | def wkeGoBack(self,webview): 104 | self.mb.wkeGoBack(webview) 105 | def wkeGetWindowHandle(self,webview): 106 | 107 | return self.mb.wkeGetWindowHandle(webview) 108 | 109 | def wkeGetViewDC(self,webview): 110 | 111 | hdc=self.mb.wkeGetViewDC(webview) 112 | return hdc 113 | def wkeSetTouchEnabled(self,webview,_bool): 114 | 115 | b=not _bool 116 | self.mb.wkeSetTouchEnabled(webview,_bool) 117 | 118 | self.mb.wkeSetMouseEnabled(webview,b) 119 | def simulate_device(self,webview,key,value,_int,_float): 120 | 121 | key=key.encode() 122 | if value=='': 123 | value=b'' 124 | else: 125 | value=value.encode() 126 | self.mb.wkeSetDeviceParameter(webview, key,value,_int,c_float(_float)) 127 | def bind_window(self,hwnd=0,show=True): 128 | 129 | if hwnd==0: 130 | user32.PostQuitMessage(0) 131 | return 0 132 | webview=self.wkeCreateWebWindow(_type=2,hwnd=hwnd) 133 | rc=Window.get_client_rect(hwnd) 134 | width = rc.Right - rc.Left 135 | height = rc.Bottom - rc.Top 136 | 137 | self.wkeResize(webview,width,height) 138 | self.wkeShowWindow(webview,show) 139 | return webview 140 | def message_loop(self,webview=None): 141 | 142 | msg = MSG() 143 | while user32.GetMessageW(byref(msg), None, 0, 0) > 0: 144 | user32.TranslateMessage(byref(msg)) 145 | user32.DispatchMessageW(byref(msg)) 146 | 147 | 148 | @staticmethod 149 | def get_window_rect(hwnd): 150 | rect=Rect() 151 | user32.GetWindowRect(hwnd,byref(rect)) 152 | return rect 153 | 154 | @staticmethod 155 | def get_client_rect(hwnd): 156 | rect=Rect() 157 | user32.GetClientRect(hwnd,byref(rect)) 158 | return rect 159 | -------------------------------------------------------------------------------- /MBPython/wkeStruct.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from ctypes import ( 3 | c_int, 4 | c_ushort, 5 | c_long, 6 | c_longlong, 7 | c_char, 8 | c_char_p, 9 | c_wchar_p, 10 | c_bool, 11 | c_void_p, 12 | c_size_t, 13 | Structure, 14 | POINTER 15 | ) 16 | 17 | from ctypes.wintypes import ( 18 | LPARAM, 19 | DWORD, 20 | LONG, 21 | WORD, 22 | BYTE 23 | ) 24 | 25 | class wkeProxy(Structure): 26 | 27 | _fields_ = [('type', c_int),('hostname', c_char *100),('port', c_ushort ),('username', c_char *50),('password',c_char *50)] 28 | class wkeRect(Structure): 29 | 30 | _fields_=[('x',c_int),('y',c_int),('w',c_int),('h',c_int)] 31 | class wkeMemBuf(Structure): 32 | 33 | _fields_=[('size',c_int),('data',c_char_p),('length',c_size_t)] 34 | class wkeString(Structure): 35 | ... 36 | class wkePostBodyElement(Structure): 37 | 38 | _fields_=[('size',c_int),('type',c_int),('data',POINTER(wkeMemBuf)),('filePath',wkeString),('fileStart',c_longlong),('fileLength',c_longlong)] 39 | ... 40 | class wkePostBodyElements(Structure): 41 | 42 | _fields_ =[('size',c_int),('element',POINTER(POINTER(wkePostBodyElement))),('elementSize',c_size_t),('isDirty',c_bool)] 43 | class wkeScreenshotSettings(Structure): 44 | 45 | _fields_=[('structSize',c_int),('width',c_int),('height',c_int)] 46 | class wkeWindowFeatures(Structure): 47 | 48 | _fields_=[('x',c_int),('y',c_int),('width',c_int),('height',c_int),('menuBarVisible',c_bool),('statusBarVisible',c_bool),('toolBarVisible',c_bool),('locationBarVisible',c_bool),('scrollbarsVisible',c_bool),('resizable',c_bool),('fullscreen',c_bool)] 49 | 50 | class wkePrintSettings(Structure): 51 | 52 | _fields_=[('structSize',c_int),('dpi',c_int),('width',c_int),('height',c_int),('marginTop',c_int),('marginBottom',c_int),('marginLeft',c_int),('marginRight',c_int),('isPrintPageHeadAndFooter',c_bool),('isPrintBackgroud',c_bool),('isLandscape',c_bool)] 53 | class wkePdfDatas(Structure): 54 | 55 | _fields_=[('count',c_int),('sizes',c_size_t),('datas',c_void_p)] 56 | 57 | class Rect(Structure): 58 | 59 | _fields_=[('Left',c_int),('Top',c_int),('Right',c_int),('Bottom',c_int)] 60 | 61 | class mPos(Structure): 62 | 63 | _fields_=[('x',c_int),('y',c_int)] 64 | 65 | class mSize(Structure): 66 | ... 67 | mSize._fields_=[('cx',c_int),('cy',c_int)] 68 | 69 | class bitMap(Structure): 70 | 71 | _fields_=[('bmType',c_int),('bmWidth',c_int),('bmHeight',c_int),('bmWidthBytes',c_int),('bmPlanes',c_int),('bmBitsPixel',c_int),('bmBits',c_int)] 72 | 73 | class blendFunction(Structure): 74 | 75 | _fields_=[('BlendOp',BYTE),('BlendFlags',BYTE),('SourceConstantAlpha',BYTE),('AlphaFormat',BYTE)] 76 | 77 | 78 | class COMPOSITIONFORM(Structure): 79 | 80 | _fields_=[('dwStyle',c_int),('ptCurrentPos',mPos),('rcArea',Rect)] 81 | 82 | 83 | class BITMAPINFOHEADER(Structure): 84 | """ 关于DIB的尺寸和颜色格式的信息 """ 85 | _fields_ = [ 86 | ("biSize", DWORD), 87 | ("biWidth", LONG), 88 | ("biHeight", LONG), 89 | ("biPlanes", WORD),#永远为1 90 | ("biBitCount", WORD),#1(双色),4(16色),8(256色),24(真彩色),32(真彩色) 91 | ("biCompression", DWORD),#0不压缩 92 | ("biSizeImage", DWORD),#表示位图数据的大小以字节为单位 93 | ("biXPelsPerMeter", LONG), 94 | ("biYPelsPerMeter", LONG), 95 | ("biClrUsed", DWORD),#位图实际使用的颜色表中的颜色数 96 | ("biClrImportant", DWORD)#位图显示过程中重要的颜色数 97 | ] 98 | class BITMAPFILEHEADER(Structure): 99 | __file__=[ 100 | ('bfType',c_int),#BMP类型:19778,也就是BM 101 | ('bfSize',c_int),#文件字节数:14 + BITMAPINFOHEADER.biSize + BITMAPINFOHEADER.biSizeImage 102 | ('bfReserved1',c_int), 103 | ('bfReserved2',c_int), 104 | ('bfOffBits',c_int)#位图的数据信息离文件头的偏移量:14 + BITMAPINFOHEADER.biSize 105 | ] 106 | class BITMAPINFO(Structure): 107 | 108 | _fields_ = [("bmiHeader", BITMAPINFOHEADER), ("bmiColors", DWORD * 3)] 109 | 110 | class COPYDATASTRUCT(Structure): 111 | _fields_ = [('dwData', LPARAM),('cbData', DWORD),('lpData', c_char_p)] 112 | 113 | 114 | from . import _LRESULT 115 | class PAINTSTRUCT(Structure): 116 | _fields_=[('hdc',_LRESULT),('fErase',c_int),('rcPaint',Rect),('fRestore',c_int),('fIncUpdate',c_int),('rgbReserved',c_char *32)] 117 | -------------------------------------------------------------------------------- /MBPython/wndproc.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from .winConst import WinConst 3 | from .wkeStruct import COPYDATASTRUCT 4 | from ctypes import (cast,c_char_p,py_object,sizeof,byref,string_at,create_string_buffer,POINTER) 5 | import win32gui 6 | import win32api 7 | import json 8 | 9 | PCOPYDATASTRUCT = POINTER(COPYDATASTRUCT) 10 | class WndProcHook: 11 | def __init__(self,hwnd,webview=None): 12 | self.webview=webview 13 | self.hwnd=hwnd 14 | self.msg_func_dict = {} 15 | def hook_WndProc(self): 16 | self.oldWndProc = win32gui.SetWindowLong(self.hwnd, WinConst.GWL_WNDPROC, self._onWndProcCallback) 17 | def unhook_WndProc(self): 18 | win32api.SetWindowLong(self.hwnd, WinConst.GWL_WNDPROC, self.oldWndProc) 19 | def add_msg_func(self,webview,hwnd,msg,msg_func): 20 | self.msg_func_dict[msg] = msg_func 21 | def _onWndProcCallback(self, hwnd, msg, wParam, lParam): 22 | 23 | if msg in self.msg_func_dict: 24 | argcount=self.msg_func_dict[msg].__code__.co_argcount 25 | ret=None 26 | if argcount==5: 27 | arg_vals=self.msg_func_dict[msg].__code__.co_varnames 28 | if arg_vals[0]=='self': 29 | ret=self.msg_func_dict[msg](self.webview,hwnd,wParam, lParam) 30 | elif argcount==4: 31 | ret=self.msg_func_dict[msg](self.webview,hwnd,wParam, lParam) 32 | elif argcount==3: 33 | ret=self.msg_func_dict[msg](hwnd,wParam, lParam) 34 | elif argcount==2: 35 | ret=self.msg_func_dict[msg](wParam, lParam) 36 | if ret!=None: 37 | return ret 38 | if hasattr(self,'onWndProcCallback'): 39 | ret=self.onWndProcCallback(hwnd=hwnd, msg=msg, wParam=wParam, lParam=lParam) 40 | if ret!=None: 41 | return ret 42 | if msg == WinConst.WM_DESTROY: 43 | self.unhook_WndProc() 44 | return win32gui.CallWindowProc(self.oldWndProc, hwnd, msg, wParam, lParam) 45 | 46 | @staticmethod 47 | def value_to_msg(value,copydate=False): 48 | if copydate: 49 | cds=COPYDATASTRUCT() 50 | cds.dwData=0 51 | value=json.dumps(value).encode() 52 | cds.cbData = sizeof(create_string_buffer(value)) 53 | cds.lpData = c_char_p(value) 54 | return byref(cds) 55 | else: 56 | value=json.dumps(value).encode() 57 | return c_char_p(value) 58 | @staticmethod 59 | def msg_to_value(wParam,lParam,copydate=False): 60 | if lParam!=0: 61 | try: 62 | if copydate: 63 | pCDS=cast(lParam, PCOPYDATASTRUCT) 64 | value=string_at(pCDS.contents.lpData).decode() 65 | else: 66 | value=cast(lParam, c_char_p).value.decode() 67 | except: 68 | return 69 | value=json.loads(value) 70 | return value -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MBPython 2 | 3 | Miniblink is a lighter browser widget base on chromium, 4 | just one file, faster browser kernel of blink to integrate HTML UI in your app. 5 | 6 | MBPython is an open source project founded by lochen to provide python bindings for the Miniblink. Examples of embedding Miniblink browser are available for many popular GUI toolkits including: wxPython, PyQt, PySide, Kivy, Panda3D, PyGTK, PyGObject, PyGame/PyOpenGL and PyWin32. 7 | 8 | By using C interface, you can create a browser just some line code. 9 | There are many use cases for MBPython. You can embed a web browser control based on MBPython with great HTML 5 support. You can use it to create a HTML 5 based GUI in an application, this can act as a replacement for standard GUI toolkits like wxWidgets, Qt or GTK. You can render web content off-screen in application that use custom drawing frameworks. You can use it for automated testing of existing applications. You can use it for web scraping or as a web crawler, or other kind of internet bots. 10 | 11 | ### Latest release 12 | 13 | OS | Py3 | 32bit | 64bit | Requirements 14 | --- | --- | --- | --- | --- 15 | Windows | 3.6+ | Yes | Yes | Windows 7+ 16 | 17 | ### Installation 18 | 19 | ```bash 20 | pip install --user MBPython 21 | ``` 22 | 23 | ### How to use 24 | Download the node.dll add to your project. 25 | 26 |

27 | The free version can only be called on the UI thread. 28 |

29 | 30 | Create a simple Window 31 | ```bash 32 | from MBPython import miniblink 33 | mbpython=miniblink.Miniblink 34 | mb=mbpython.init('node.dll') 35 | wke=mbpython(mb) 36 | window=wke.window 37 | webview=window.wkeCreateWebWindow(0,0,0,0,860,760) 38 | window.wkeShowWindow(webview) 39 | window.wkeRunMessageLoop() 40 | ``` 41 | 42 | ### PyInstaller 43 | 44 | ```bash 45 | pyinstall xxx.py --noconsole 46 | ``` 47 | 48 | ### Examples 49 | 50 | See the [tests](https://github.com/lochen88/MBPython/tree/master/tests) folder 51 | 52 | ### Tutorial 53 | 54 | See the [documents](https://github.com/lochen88/MBPython/tree/master/documents) folder 55 | 56 | ### What about CEF? 57 | 58 | In short: I do not like CEF, it is too big, comes with too many dependency resolution library, and I think we can make a better and more intuitive one. Here are a few things that I don't like. 59 | 60 | ### Resources 61 | 62 | 63 | 64 | 70 | 76 | 77 |
65 |

66 | 67 |

68 | if you have any questions,you can contact me,and i will try my best to help you 69 |
71 |

72 | 73 |

74 | If you would like to support general MBPython development efforts by making a donation then please scan to pay by the alipay 75 |
78 | 79 | * [Project Website](https://github.com/lochen88/MBPython) 80 | * [Issue Tracker](https://github.com/lochen88/MBPython/issues) 81 | * [Official Website](https://weolar.github.io/miniblink/) 82 | * [QQ Group-198671899](https://qm.qq.com/cgi-bin/qm/qr?k=JipVq9gRdpPf4dqjPK9bkL99u-_BLwZz&jump_from=webapi) 83 | 84 | 85 | -------------------------------------------------------------------------------- /dist/MBPython-0.2.2-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/dist/MBPython-0.2.2-py3-none-any.whl -------------------------------------------------------------------------------- /dist/MBPython-0.2.2.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/dist/MBPython-0.2.2.tar.gz -------------------------------------------------------------------------------- /documents/Api-index.md: -------------------------------------------------------------------------------- 1 | # Api index 2 | 3 | * [window(object)-Methods](#methods) 4 | * [wkeCreateWebWindow](#wkeCreateWebWindow) 5 | * [wkeShowWindow](#wkeShowWindow) 6 | * [wkeCreateWebView](#wkeCreateWebView) 7 | * [wkeDestroyWebView](#wkeDestroyWebView) 8 | * [wkeMoveToCenter](#wkeMoveToCenter) 9 | * [wkeRunMessageLoop](#wkeRunMessageLoop) 10 | * [wkeSetUserAgentW](#wkeSetUserAgentW) 11 | * [wkeSetDragEnable](#wkeSetDragEnable) 12 | * [wkeAddPluginDirectory](#wkeAddPluginDirectory) 13 | * [wkeSetNpapiPluginsEnabled](#wkeSetNpapiPluginsEnabled) 14 | * [wkeSetCspCheckEnable](#wkeSetCspCheckEnable) 15 | * [wkeSetDebugConfig](#wkeSetDebugConfig) 16 | * [wkeSetNavigationToNewWindowEnable](#wkeSetNavigationToNewWindowEnable) 17 | * [wkeSetWebViewName](#wkeSetWebViewName) 18 | * [wkeSetZoomFactor](#wkeSetZoomFactor) 19 | * [wkeSetContextMenuEnabled](#wkeSetContextMenuEnabled) 20 | * [wkeSetWindowTitleW](#wkeSetWindowTitleW) 21 | * [wkeSetTransparent](#wkeSetTransparent) 22 | * [wkeSetHandle](#wkeSetHandle) 23 | * [wkeResize](#wkeResize) 24 | * [wkeWidth](#wkeWidth) 25 | * [wkeHeight](#wkeHeight) 26 | * [wkeContentsWidth](#wkeContentsWidth) 27 | * [wkeContentsHeight](#wkeContentsHeight) 28 | * [wkeGoForward](#wkeGoForward) 29 | * [wkeGoBack](#wkeGoBack) 30 | * [wkeGetWindowHandle](#wkeGetWindowHandle) 31 | * [wkeGetViewDC](#wkeGetViewDC) 32 | * [wkeSetTouchEnabled](#wkeSetTouchEnabled) 33 | * [simulate_device](#simulate_device) 34 | * [bind_window](#bind_window) 35 | 36 | * [network(object)-Methods](#methods) 37 | * [wkeLoadURLW](#wkeLoadURLW) 38 | * [wkeLoadHTMLW](#wkeLoadHTMLW) 39 | * [wkeLoadFile](#wkeLoadFile) 40 | * [wkePostURLW](#wkePostURLW) 41 | * [wkeReload](#wkeReload) 42 | * [wkeStopLoading](#wkeStopLoading) 43 | * [wkeGetURL](#wkeGetURL) 44 | * [wkeGetFrameUrl](#wkeGetFrameUrl) 45 | * [wkeGetSource](#wkeGetSource) 46 | * [wkeUtilSerializeToMHTML](#wkeUtilSerializeToMHTML) 47 | * [save_buf_data](#save_buf_data) 48 | * [cancel_request](#cancel_request) 49 | 50 | * [pyrunjs(object)-Methods](#methods) 51 | * [run_js](#run_js) 52 | * [run_js_file](#run_js_file) 53 | * [run_js_byframe](#run_js_byframe) 54 | * [run_js_global](#run_js_global) 55 | 56 | * [jsrunpy(object)-Methods](#methods) 57 | * [get_js_args_val](#get_js_args_val) 58 | * [to_js_args_val](#to_js_args_val) 59 | * [bind_func](#bind_func) 60 | 61 | * [proxy(object)-Methods](#methods) 62 | * [wkeSetProxy](#wkeSetProxy) 63 | * [wkeSetViewProxy](#wkeSetViewProxy) 64 | 65 | * [cookie(object)-Methods](#methods) 66 | * [wkeGetCookieW](#wkeGetCookieW) 67 | * [wkeSetCookie](#wkeSetCookie) 68 | * [wkeSetCookieJarPath](#wkeSetCookieJarPath) 69 | * [wkeSetCookieJarFullPath](#wkeSetCookieJarFullPath) 70 | * [wkeClearCookie](#wkeClearCookie) 71 | 72 | * [message(object)-Methods](#methods) 73 | * [wkeFireMouseEvent](#wkeFireMouseEvent) 74 | * [wkeFireKeyDownEvent](#wkeFireKeyDownEvent) 75 | * [wkeFireKeyUpEvent](#wkeFireKeyUpEvent) 76 | * [wkeFireKeyPressEvent](#wkeFireKeyPressEvent) 77 | * [wkeFireWindowsMessage](#wkeFireWindowsMessage) 78 | 79 | * [bindwebview(object)-Methods](#methods) 80 | * [bind_webview](#bind_webview) 81 | 82 | * [callback(object)-Methods](#methods) 83 | * [wkeOnCreateView](#wkeOnCreateView) 84 | * [wkeOnWindowClosing](#wkeOnWindowClosing) 85 | * [wkeOnWindowDestroy](#wkeOnWindowDestroy) 86 | * [wkeOnPaintUpdated](#wkeOnPaintUpdated) 87 | * [wkeOnPaintBitUpdated](#wkeOnPaintBitUpdated) 88 | * [wkeOnTitleChanged](#wkeOnTitleChanged) 89 | * [wkeOnURLChanged2](#wkeOnURLChanged2) 90 | * [wkeOnMouseOverUrlChanged](#wkeOnMouseOverUrlChanged) 91 | * [wkeOnAlertBox](#wkeOnAlertBox) 92 | * [wkeOnConfirmBox](#wkeOnConfirmBox) 93 | * [wkeOnPromptBox](#wkeOnPromptBox) 94 | * [wkeOnConsole](#wkeOnConsole) 95 | * [wkeOnDownload](#wkeOnDownload) 96 | * [wkeOnDocumentReady2](#wkeOnDocumentReady2) 97 | * [wkeNetOnResponse](#wkeNetOnResponse) 98 | * [wkeOnLoadUrlBegin](#wkeOnLoadUrlBegin) 99 | * [wkeOnLoadUrlEnd](#wkeOnLoadUrlEnd) 100 | * [wkeOnLoadUrlFail](#wkeOnLoadUrlFail) 101 | * [wkeOnLoadingFinish](#wkeOnLoadingFinish) 102 | * [wkeNetGetFavicon](#wkeNetGetFavicon) 103 | 104 | 105 | ## Methods 106 | 107 | ### wkeCreateWebWindow 108 | 109 | | Parameter | Type | description 110 | | --- | --- | --- | 111 | | _type | int |0:normal window,1:transparent window,3:embedded window | 112 | | hwnd | int |embedded other window's handle | 113 | | x | int | x axis | 114 | | y | int | y axis | 115 | | width | int | window's width | 116 | | height | int | window's height | 117 | | __Return__ | int | webview | 118 | 119 | ### wkeShowWindow 120 | 121 | | Parameter | Type | description 122 | | --- | --- | --- | 123 | | webview | int | -- | 124 | | _bool | bool | -- | 125 | | __Return__ | None | -- | 126 | 127 | ### wkeCreateWebView 128 | 129 | | Parameter | Type | description 130 | | --- | --- | --- | 131 | | __Return__ | int | webview | 132 | 133 | ### wkeDestroyWebView 134 | 135 | | Parameter | Type | description 136 | | --- | --- | --- | 137 | | webview | int | -- | 138 | | __Return__ | None | -- | 139 | 140 | ### wkeMoveToCenter 141 | 142 | | Parameter | Type | description 143 | | --- | --- | --- | 144 | | webview | int | -- | 145 | | __Return__ | None | -- | 146 | 147 | ### wkeRunMessageLoop 148 | 149 | | Parameter | Type | description 150 | | --- | --- | --- | 151 | | __Return__ | None | -- | 152 | 153 | ### wkeSetUserAgentW 154 | 155 | | Parameter | Type | description 156 | | --- | --- | --- | 157 | | webview | int | -- | 158 | | ua | string | -- | 159 | | __Return__ | None | -- | 160 | 161 | ### wkeGetUserAgent 162 | 163 | | Parameter | Type | description 164 | | --- | --- | --- | 165 | | webview | int | -- | 166 | | __Return__ | None | -- | 167 | 168 | ### wkeSetDragEnable 169 | 170 | | Parameter | Type | description 171 | | --- | --- | --- | 172 | | webview | int | -- | 173 | | _bool | bool | -- | 174 | | __Return__ | None | -- | 175 | 176 | ### wkeAddPluginDirectory 177 | 178 | | Parameter | Type | description 179 | | --- | --- | --- | 180 | | webview | int | -- | 181 | | _path | string | -- | 182 | | __Return__ | None | -- | 183 | 184 | ### wkeSetNpapiPluginsEnabled 185 | 186 | | Parameter | Type | description 187 | | --- | --- | --- | 188 | | webview | int | -- | 189 | | _bool | bool | -- | 190 | | _path | string | -- | 191 | | __Return__ | None | -- | 192 | 193 | If you want to use flash must ues this method 194 | 195 | ### wkeSetCspCheckEnable 196 | 197 | | Parameter | Type | description 198 | | --- | --- | --- | 199 | | webview | int | -- | 200 | | _bool | bool | -- | 201 | | __Return__ | None | -- | 202 | 203 | ### wkeSetDebugConfig 204 | 205 | | Parameter | Type | description 206 | | --- | --- | --- | 207 | | webview | int | -- | 208 | | debug | string | -- | 209 | | param | string | -- | 210 | | __Return__ | None | -- | 211 | 212 | ### wkeSetCspCheckEnable 213 | 214 | | Parameter | Type | description 215 | | --- | --- | --- | 216 | | webview | int | -- | 217 | | _bool | bool | -- | 218 | | __Return__ | None | -- | 219 | 220 | ### wkeSetHeadlessEnabled 221 | 222 | | Parameter | Type | description 223 | | --- | --- | --- | 224 | | webview | int | -- | 225 | | _bool | bool | -- | 226 | | __Return__ | None | -- | 227 | 228 | ### wkeSetNavigationToNewWindowEnable 229 | 230 | | Parameter | Type | description 231 | | --- | --- | --- | 232 | | webview | int | -- | 233 | | _bool | bool | -- | 234 | | __Return__ | None | -- | 235 | 236 | ### wkeSetWebViewName 237 | 238 | | Parameter | Type | description 239 | | --- | --- | --- | 240 | | webview | int | -- | 241 | | name | string | -- | 242 | | __Return__ | None | -- | 243 | 244 | ### wkeSetZoomFactor 245 | 246 | | Parameter | Type | description 247 | | --- | --- | --- | 248 | | webview | int | -- | 249 | | factor | int | -- | 250 | | __Return__ | None | -- | 251 | 252 | ### wkeSetContextMenuEnabled 253 | 254 | | Parameter | Type | description 255 | | --- | --- | --- | 256 | | webview | int | -- | 257 | | _bool | bool | -- | 258 | | __Return__ | None | -- | 259 | 260 | ### wkeSetWindowTitleW 261 | 262 | | Parameter | Type | description 263 | | --- | --- | --- | 264 | | webview | int | -- | 265 | | title | string | -- | 266 | | __Return__ | None | -- | 267 | 268 | ### wkeSetHandleOffset 269 | 270 | | Parameter | Type | description 271 | | --- | --- | --- | 272 | | webview | int | -- | 273 | | x | int | -- | 274 | | y | int | -- | 275 | | __Return__ | None | -- | 276 | 277 | ### wkeSetHandle 278 | 279 | | Parameter | Type | description 280 | | --- | --- | --- | 281 | | webview | int | -- | 282 | | hwnd | int | -- | 283 | | __Return__ | None | -- | 284 | 285 | ### wkeResize 286 | 287 | | Parameter | Type | description 288 | | --- | --- | --- | 289 | | webview | int | -- | 290 | | width | int | -- | 291 | | height | int | -- | 292 | | __Return__ | None | -- | 293 | 294 | ### wkeWidth 295 | 296 | | Parameter | Type | description 297 | | --- | --- | --- | 298 | | webview | int | -- | 299 | | __Return__ | int | width | 300 | 301 | ### wkeHeight 302 | 303 | | Parameter | Type | description 304 | | --- | --- | --- | 305 | | webview | int | -- | 306 | | __Return__ | int | height | 307 | 308 | ### wkeContentsWidth 309 | 310 | | Parameter | Type | description 311 | | --- | --- | --- | 312 | | webview | int | -- | 313 | | __Return__ | int | contentswidth | 314 | 315 | ### wkeContentsHeight 316 | 317 | | Parameter | Type | description 318 | | --- | --- | --- | 319 | | webview | int | -- | 320 | | __Return__ | int | contentsheight | 321 | 322 | ### wkeGoForward 323 | 324 | | Parameter | Type | description 325 | | --- | --- | --- | 326 | | webview | int | -- | 327 | | __Return__ | None | -- | 328 | 329 | ### wkeGoForward 330 | 331 | | Parameter | Type | description 332 | | --- | --- | --- | 333 | | webview | int | -- | 334 | | __Return__ | None | -- | 335 | 336 | ### wkeGetWindowHandle 337 | 338 | | Parameter | Type | description 339 | | --- | --- | --- | 340 | | webview | int | -- | 341 | | __Return__ | int |hwnd | 342 | 343 | ### wkeGetViewDC 344 | 345 | | Parameter | Type | description 346 | | --- | --- | --- | 347 | | webview | int | -- | 348 | | __Return__ | int | DC | 349 | 350 | ### wkeSetTouchEnabled 351 | 352 | | Parameter | Type | description 353 | | --- | --- | --- | 354 | | webview | int | -- | 355 | | _bool | bool | -- | 356 | | __Return__ | None | -- | 357 | 358 | ### simulate_device 359 | 360 | | Parameter | Type | description 361 | | --- | --- | --- | 362 | | webview | int | -- | 363 | | key | string | -- | 364 | | value | string | -- | 365 | | _int | int | -- | 366 | | _float | float | -- | 367 | | __Return__ | None | -- | 368 | 369 | ### bind_window 370 | 371 | | Parameter | Type | description 372 | | --- | --- | --- | 373 | | hwnd | int | -- | 374 | | _bool | bool | -- | 375 | | __Return__ | int | webview | 376 | 377 | ### run_js 378 | 379 | | Parameter | Type | description 380 | | --- | --- | --- | 381 | | webview | int | -- | 382 | | js_code | string | -- | 383 | | __Return__ | string | -- | 384 | 385 | ### run_js_file 386 | 387 | | Parameter | Type | description 388 | | --- | --- | --- | 389 | | webview | int | -- | 390 | | file_name | string | -- | 391 | | __Return__ | string | -- | 392 | 393 | ### run_js_byframe 394 | 395 | | Parameter | Type | description 396 | | --- | --- | --- | 397 | | webview | int | -- | 398 | | frameId | int | -- | 399 | | js_code | string | -- | 400 | | isInClosure | bool | -- | 401 | | __Return__ | string | -- | 402 | 403 | ### run_js_global 404 | 405 | | Parameter | Type | description 406 | | --- | --- | --- | 407 | | webview | int | -- | 408 | | func_name | string | -- | 409 | | param_ls | list | -- | 410 | | this_func | string | -- | 411 | | __Return__ | string | -- | 412 | 413 | ### wkeSetProxy 414 | 415 | | Parameter | Type | description 416 | | --- | --- | --- | 417 | | ip | string | -- | 418 | | port | string | -- | 419 | | proxy_type | int | 0:WKE_PROXY_NONE,1:WKE_PROXY_HTTP,2:WKE_PROXY_SOCKS4,3:WKE_PROXY_SOCKS4A,4:WKE_PROXY_SOCKS5,5:WKE_PROXY_SOCKS5HOSTNAME | 420 | | user | string | -- | 421 | | password | string | -- | 422 | | __Return__ | None | -- | 423 | 424 | ### wkeSetViewProxy 425 | 426 | | Parameter | Type | description 427 | | --- | --- | --- | 428 | | webview | int | -- | 429 | | ip | string | -- | 430 | | port | string | -- | 431 | | proxy_type | int | -- | 432 | | user | string | -- | 433 | | password | string | -- | 434 | | __Return__ | None | -- | 435 | 436 | ### wkeLoadURLW 437 | 438 | | Parameter | Type | description 439 | | --- | --- | --- | 440 | | webview | int | -- | 441 | | url | string | -- | 442 | | __Return__ | None | -- | 443 | 444 | ### wkeLoadHTMLW 445 | 446 | | Parameter | Type | description 447 | | --- | --- | --- | 448 | | webview | int | -- | 449 | | html | string | -- | 450 | | __Return__ | None | -- | 451 | 452 | ### wkeLoadFile 453 | 454 | | Parameter | Type | description 455 | | --- | --- | --- | 456 | | webview | int | -- | 457 | | file_path | string | -- | 458 | | __Return__ | None | -- | 459 | 460 | ### wkeReload 461 | 462 | | Parameter | Type | description 463 | | --- | --- | --- | 464 | | webview | int | -- | 465 | | __Return__ | None | -- | 466 | 467 | ### wkeStopLoading 468 | 469 | | Parameter | Type | description 470 | | --- | --- | --- | 471 | | webview | int | -- | 472 | | __Return__ | None | -- | 473 | 474 | ### wkeGetURL 475 | 476 | | Parameter | Type | description 477 | | --- | --- | --- | 478 | | webview | int | -- | 479 | | __Return__ | string | url | 480 | 481 | ### wkeGetFrameUrl 482 | 483 | | Parameter | Type | description 484 | | --- | --- | --- | 485 | | webview | int | -- | 486 | | frameId | int | -- | 487 | | __Return__ | string | url | 488 | 489 | ### wkeGetSource 490 | 491 | | Parameter | Type | description 492 | | --- | --- | --- | 493 | | webview | int | -- | 494 | | __Return__ | string | html | 495 | 496 | ### wkeUtilSerializeToMHTML 497 | 498 | | Parameter | Type | description 499 | | --- | --- | --- | 500 | | webview | int | -- | 501 | | __Return__ | string | mhtml | 502 | 503 | ### save_buf_data 504 | 505 | | Parameter | Type | description 506 | | --- | --- | --- | 507 | | url | string | -- | 508 | | buf | int | -- | 509 | | lens | int | -- | 510 | | __Return__ | None | -- | 511 | 512 | Use it in the wkeLoadUrlEndCallback method 513 | 514 | ### cancel_request 515 | 516 | | Parameter | Type | description 517 | | --- | --- | --- | 518 | | job | int | -- | 519 | | url | string | -- | 520 | | ident_ls | list | -- | 521 | | __Return__ | bool | -- | 522 | 523 | ### get_js_args_val 524 | 525 | | Parameter | Type | description 526 | | --- | --- | --- | 527 | | es | int | -- | 528 | | arg_count | int | -- | 529 | | __Return__ | list | args | 530 | 531 | ### to_js_args_val 532 | 533 | | Parameter | Type | description 534 | | --- | --- | --- | 535 | | es | int | -- | 536 | | val | -- | string/int/float/bool/list | 537 | | __Return__ | int | jsvalue | 538 | 539 | ### bind_func 540 | 541 | | Parameter | Type | description 542 | | --- | --- | --- | 543 | | func_name | string | callback funtion name | 544 | | arg_count | int | -- | 545 | | param | int | ptr | 546 | | __Return__ | None | -- | 547 | self-defined callback function: python_func 548 | 549 | ### wkeGetCookieW 550 | 551 | | Parameter | Type | description 552 | | --- | --- | --- | 553 | | webview | int | -- | 554 | | __Return__ | string | cookie | 555 | 556 | ### wkeSetCookie 557 | 558 | | Parameter | Type | description 559 | | --- | --- | --- | 560 | | webview | int | -- | 561 | | url | string | -- | 562 | | cookie | string | -- | 563 | | __Return__ | None | -- | 564 | 565 | ### wkeSetCookieJarPath 566 | 567 | | Parameter | Type | description 568 | | --- | --- | --- | 569 | | webview | int | -- | 570 | | path | string | F:\MBPython | 571 | | __Return__ | None | -- | 572 | 573 | ### wkeSetCookieJarFullPath 574 | 575 | | Parameter | Type | description 576 | | --- | --- | --- | 577 | | webview | int | -- | 578 | | path | string | F:\MBPython\mycookie.dat | 579 | | __Return__ | None | -- | 580 | 581 | ### wkeClearCookie 582 | 583 | | Parameter | Type | description 584 | | --- | --- | --- | 585 | | webview | int | -- | 586 | | __Return__ | None | -- | 587 | 588 | ### wkeFireMouseEvent 589 | 590 | | Parameter | Type | description 591 | | --- | --- | --- | 592 | | webview | int | -- | 593 | | msg | int | -- | 594 | | x | int | -- | 595 | | y | int | -- | 596 | | flags | int | -- | 597 | | __Return__ | bool | -- | 598 | 599 | ### wkeFireKeyDownEvent 600 | 601 | | Parameter | Type | description 602 | | --- | --- | --- | 603 | | webview | int | -- | 604 | | virtualKeyCode | int | -- | 605 | | flags | int | -- | 606 | | __Return__ | bool | -- | 607 | 608 | ### wkeFireKeyUpEvent 609 | 610 | | Parameter | Type | description 611 | | --- | --- | --- | 612 | | webview | int | -- | 613 | | virtualKeyCode | int | -- | 614 | | flags | int | -- | 615 | | __Return__ | bool | -- | 616 | 617 | ### wkeFireKeyPressEvent 618 | 619 | | Parameter | Type | description 620 | | --- | --- | --- | 621 | | webview | int | -- | 622 | | virtualKeyCode | int | -- | 623 | | flags | int | -- | 624 | | __Return__ | bool | -- | 625 | 626 | ### wkeFireWindowsMessage 627 | 628 | | Parameter | Type | description 629 | | --- | --- | --- | 630 | | webview | int | -- | 631 | | hwnd | int | -- | 632 | | msg | int | -- | 633 | | wParam | int | -- | 634 | | lParam | int | -- | 635 | | result | int | -- | 636 | | __Return__ | bool | -- | 637 | 638 | ### bind_webview 639 | 640 | | Parameter | Type | description 641 | | --- | --- | --- | 642 | | hwnd | int | -- | 643 | | isTransparent | bool | -- | 644 | | isZoom | bool | -- | 645 | | __Return__ | int | webview | 646 | 647 | ### wkeOnCreateView 648 | 649 | | Parameter | Type | description 650 | | --- | --- | --- | 651 | | webview | int | -- | 652 | | param | int | ptr | 653 | | __Return__ | None | -- | 654 | self-defined callback function:wkeCreateViewCallback 655 | 656 | ### wkeOnWindowClosing 657 | 658 | | Parameter | Type | description 659 | | --- | --- | --- | 660 | | webview | int | -- | 661 | | param | int | ptr | 662 | | __Return__ | None | -- | 663 | self-defined callback function:wkeWindowClosingCallback 664 | 665 | ### wkeOnWindowDestroy 666 | 667 | | Parameter | Type | description 668 | | --- | --- | --- | 669 | | webview | int | -- | 670 | | param | int | ptr | 671 | | __Return__ | None | -- | 672 | self-defined callback function:wkeWindowDestroyCallback 673 | 674 | ### wkeOnPaintUpdated 675 | 676 | | Parameter | Type | description 677 | | --- | --- | --- | 678 | | webview | int | -- | 679 | | param | int | ptr | 680 | | __Return__ | None | -- | 681 | self-defined callback function:wkePaintUpdatedCallback 682 | 683 | ### wkeOnPaintBitUpdated 684 | 685 | | Parameter | Type | description 686 | | --- | --- | --- | 687 | | webview | int | -- | 688 | | param | int | ptr | 689 | | __Return__ | None | -- | 690 | self-defined callback function:wkePaintBitUpdatedCallback 691 | 692 | ### wkeOnNavigation 693 | 694 | | Parameter | Type | description 695 | | --- | --- | --- | 696 | | webview | int | -- | 697 | | param | int | ptr | 698 | | __Return__ | None | -- | 699 | self-defined callback function:wkeNavigationCallback 700 | 701 | ### wkeOnTitleChanged 702 | 703 | | Parameter | Type | description 704 | | --- | --- | --- | 705 | | webview | int | -- | 706 | | param | int | ptr | 707 | | __Return__ | None | -- | 708 | self-defined callback function:wkeTitleChangedCallback 709 | 710 | ### wkeOnURLChanged2 711 | 712 | | Parameter | Type | description 713 | | --- | --- | --- | 714 | | webview | int | -- | 715 | | param | int | ptr | 716 | | __Return__ | None | -- | 717 | self-defined callback function:wkeURLChangedCallback2 718 | 719 | ### wkeOnMouseOverUrlChanged 720 | 721 | | Parameter | Type | description 722 | | --- | --- | --- | 723 | | webview | int | -- | 724 | | param | int | ptr | 725 | | __Return__ | None | -- | 726 | self-defined callback function:wkeMouseOverUrlChangedCallback 727 | 728 | ### wkeOnAlertBox 729 | 730 | | Parameter | Type | description 731 | | --- | --- | --- | 732 | | webview | int | -- | 733 | | param | int | ptr | 734 | | __Return__ | None | -- | 735 | self-defined callback function:wkeAlertBoxCallback 736 | 737 | ### wkeOnConfirmBox 738 | 739 | | Parameter | Type | description 740 | | --- | --- | --- | 741 | | webview | int | -- | 742 | | param | int | ptr | 743 | | __Return__ | None | -- | 744 | self-defined callback function:wkeConfirmBoxCallback 745 | 746 | ### wkeOnPromptBox 747 | 748 | | Parameter | Type | description 749 | | --- | --- | --- | 750 | | webview | int | -- | 751 | | param | int | ptr | 752 | | __Return__ | None | -- | 753 | self-defined callback function:wkePromptBoxCallback 754 | 755 | ### wkeOnConsole 756 | 757 | | Parameter | Type | description 758 | | --- | --- | --- | 759 | | webview | int | -- | 760 | | param | int | ptr | 761 | | __Return__ | None | -- | 762 | self-defined callback function:wkeConsoleCallback 763 | 764 | ### wkeOnDownload 765 | 766 | | Parameter | Type | description 767 | | --- | --- | --- | 768 | | webview | int | -- | 769 | | param | int | ptr | 770 | | __Return__ | None | -- | 771 | self-defined callback function:wkeDownloadCallback 772 | 773 | ### wkeOnDocumentReady2 774 | 775 | | Parameter | Type | description 776 | | --- | --- | --- | 777 | | webview | int | -- | 778 | | param | int | ptr | 779 | | __Return__ | None | -- | 780 | self-defined callback function:wkeDocumentReady2Callback 781 | 782 | ### wkeNetOnResponse 783 | 784 | | Parameter | Type | description 785 | | --- | --- | --- | 786 | | webview | int | -- | 787 | | param | int | ptr | 788 | | __Return__ | None | -- | 789 | self-defined callback function:wkeNetResponseCallback 790 | 791 | ### wkeOnLoadUrlBegin 792 | 793 | | Parameter | Type | description 794 | | --- | --- | --- | 795 | | webview | int | -- | 796 | | param | int | ptr | 797 | | __Return__ | None | -- | 798 | self-defined callback function:wkeLoadUrlBeginCallback 799 | 800 | ### wkeOnLoadUrlEnd 801 | 802 | | Parameter | Type | description 803 | | --- | --- | --- | 804 | | webview | int | -- | 805 | | param | int | ptr | 806 | | __Return__ | None | -- | 807 | self-defined callback function:wkeLoadUrlEndCallback 808 | 809 | ### wkeOnLoadUrlFail 810 | 811 | | Parameter | Type | description 812 | | --- | --- | --- | 813 | | webview | int | -- | 814 | | param | int | ptr | 815 | | __Return__ | None | -- | 816 | self-defined callback function:wkeLoadUrlFailCallback 817 | 818 | ### wkeOnLoadingFinish 819 | 820 | | Parameter | Type | description 821 | | --- | --- | --- | 822 | | webview | int | -- | 823 | | param | int | ptr | 824 | | __Return__ | None | -- | 825 | self-defined callback function:wkeLoadingFinishCallback 826 | 827 | ### wkeNetGetFavicon 828 | 829 | | Parameter | Type | description 830 | | --- | --- | --- | 831 | | webview | int | -- | 832 | | param | int | ptr | 833 | | __Return__ | None | -- | 834 | self-defined callback function:wkeOnNetGetFaviconCallback 835 | 836 | 837 | 838 | -------------------------------------------------------------------------------- /documents/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial 2 | With MBPython you can embed a web browser control based 3 | on Chromium in a Python application. You can also use it to 4 | create a HTML 5 based GUI in an application that can act as 5 | a replacement for standard GUI toolkits such as wxWidgets, 6 | Qt or GTK. With this tutorial you will learn MBPython 7 | basics. This tutorial will discuss the three featured examples: 8 | 9 | [test_mbpython.py](../tests/test_mbpython.py), 10 | [test_bindwindow.py](../tests/test_bindwindow.py) 11 | and [test_bindwebview.py](../tests/test_bindwebview.py). 12 | 13 | ## Install and run example 14 | 15 | You can install with pip. Alternatively you can download packages for offline installation from QQ-Group. 16 | 17 | Run the commands below to install the MBPython package, clone 18 | the repository and run the test_mbpython example: 19 | 20 | ```bash 21 | pip install --user MBPython 22 | git clone https://github.com/lochen88/MBPython.git 23 | cd MBPython/tests/ 24 | python test_mbpython.py 25 | ``` 26 | 27 | The [test_mbpython.py](../tests/test_mbpython.py) example is the 28 | most basic example. It doesn't depend on any third party GUI framework. 29 | It creates a browser widget without providing any window information 30 | (parent window is not specified), thus Miniblink automatically takes care of 31 | creating a top-level window, and in that window a Chromium widget 32 | is being embedded. When creating the browser, the "url" parameter is 33 | specified, which causes the browser to initially navigate to Baidu website. Let's analyze the code from that example: 34 | 35 | 1. `from MBPython import miniblink` - Import the miniblink module 36 | 2. `wke.init('node.dll')` - Initialize Miniblink. This function must be called 37 | somewhere in the beginning of your code. It must be called before 38 | any application window is created. It must be called only once 39 | during app's lifetime. 40 | 3. `window.wkeCreateWebWindow(0,0,0,0,860,760)` - Create 41 | a browser, this function returns a Browser object. 42 | 4. `window.wkeRunMessageLoop()` - Run Miniblink message loop. Message loop is a programming construct that waits for and 43 | dispatches events or messages in a program. All desktop GUI 44 | programs must run some kind of message loop. The test_mbpython.py 45 | example doesn't depend on any third party GUI framework and thus 46 | can run Miniblink message loop directly by calling window.wkeRunMessageLoop(). 47 | However in other examples that embed Miniblink browser with GUI frameworks 48 | such as Qt/wxPython/Tkinter you can't call window.wkeRunMessageLoop(), because 49 | these frameworks run a message loop of its own. 50 | 51 | ## Javascript integration 52 | In the free version of Miniblink, Python and Javascript just can communicate sync. 53 | 54 | In [test_bindwindow.py](../tests/test_bindwindow.py) and [test_bindwebview.py](../tests/test_bindwindow.py) example you will find 55 | 56 | example usage of javascript bindings, javascript callbacks 57 | and python callbacks. Here is part of its source code: 58 | 59 | ```python 60 | def test_js_run_py(**kwargs): 61 | es=kwargs['es'] 62 | param=kwargs['param'] 63 | arg_count=jsrunpy.mb.jsArgCount(es) 64 | val_ls=jsrunpy.get_js_args_val(es,arg_count) 65 | print(val_ls,'test_js_run_py') 66 | 67 | hwnd=param 68 | if val_ls[0]=='move': 69 | user32.ReleaseCapture() 70 | user32.SendMessageW(hwnd,161, 2, 0) 71 | elif val_ls[0]=='close': 72 | win32gui.PostQuitMessage(0) 73 | elif val_ls[0]=='max': 74 | ismax=user32.IsZoomed(hwnd) 75 | if ismax==0: 76 | user32.ShowWindow(hwnd,3) 77 | elif ismax==1: 78 | user32.ShowWindow(hwnd,1) 79 | elif val_ls[0]=='min': 80 | user32.ShowWindow(hwnd,2) 81 | elif val_ls[0]=='menu': 82 | return jsrunpy.to_js_args_val(es,'点击菜单') 83 | elif val_ls[0]=='loadurl': 84 | pyrunjs.run_js(webview,'alert("create new window")') 85 | j_webview=window.wkeCreateWebWindow(0,0,0,360,480) 86 | network.wkeLoadURLW(j_webview,'https://www.baidu.com/') 87 | window.wkeShowWindow(j_webview) 88 | return 0 89 | ``` 90 | 91 | ## Plugins and Flash support 92 | 93 | Miniblink supports NPAPI plugins. 94 | 95 | ## Off-screen rendering 96 | 97 | Off-screen rendering, in short OSR, also known as windowless 98 | rendering, is a method of rendering pages into a memory buffer 99 | without creating an actual visible window. This method of 100 | rendering has its uses, some pluses and some minuses. Its main 101 | use is so that web page rendering can be integrated into apps 102 | that have its own rendering systems and they can draw web browser 103 | contents only if they are provided a pixel buffer to draw. MBPython 104 | provides [test_bindwebview.py](../tests/test_bindwindow.py) example of integrating Miniblink off-screen rendering 105 | with frameworks. 106 | 107 | * [Api-index](https://github.com/lochen88/MBPython/blob/master/documents/api.md#methods) -------------------------------------------------------------------------------- /front_end/README.md: -------------------------------------------------------------------------------- 1 | 要使用开发者工具请解压front_end.7z 2 | -------------------------------------------------------------------------------- /front_end/front_end.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/front_end/front_end.7z -------------------------------------------------------------------------------- /plugins/README.md: -------------------------------------------------------------------------------- 1 | 2 | 这是插件目录 3 | 比如要支持Flash插件, 就请放入 NPSWF32.dll 或者 NPSWF64.dll -------------------------------------------------------------------------------- /plugins/npswf32-11.5.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/plugins/npswf32-11.5.dll -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "altgraph" 3 | version = "0.17" 4 | description = "Python graph (network) package" 5 | category = "main" 6 | optional = false 7 | python-versions = "*" 8 | 9 | [package.source] 10 | type = "legacy" 11 | url = "https://pypi.doubanio.com/simple" 12 | reference = "douban" 13 | 14 | [[package]] 15 | name = "future" 16 | version = "0.18.2" 17 | description = "Clean single-source support for Python 3 and 2" 18 | category = "main" 19 | optional = false 20 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 21 | 22 | [package.source] 23 | type = "legacy" 24 | url = "https://pypi.doubanio.com/simple" 25 | reference = "douban" 26 | 27 | [[package]] 28 | name = "macholib" 29 | version = "1.14" 30 | description = "Mach-O header analysis and editing" 31 | category = "main" 32 | optional = false 33 | python-versions = "*" 34 | 35 | [package.dependencies] 36 | altgraph = ">=0.15" 37 | 38 | [package.source] 39 | type = "legacy" 40 | url = "https://pypi.doubanio.com/simple" 41 | reference = "douban" 42 | 43 | [[package]] 44 | name = "pefile" 45 | version = "2019.4.18" 46 | description = "Python PE parsing module" 47 | category = "main" 48 | optional = false 49 | python-versions = "*" 50 | 51 | [package.dependencies] 52 | future = "*" 53 | 54 | [package.source] 55 | type = "legacy" 56 | url = "https://pypi.doubanio.com/simple" 57 | reference = "douban" 58 | 59 | [[package]] 60 | name = "pyinstaller" 61 | version = "4.0" 62 | description = "PyInstaller bundles a Python application and all its dependencies into a single package." 63 | category = "main" 64 | optional = false 65 | python-versions = "*" 66 | 67 | [package.dependencies] 68 | altgraph = "*" 69 | macholib = {version = ">=1.8", markers = "sys_platform == \"darwin\""} 70 | pefile = {version = ">=2017.8.1", markers = "sys_platform == \"win32\""} 71 | pyinstaller-hooks-contrib = ">=2020.6" 72 | pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""} 73 | 74 | [package.extras] 75 | encryption = ["tinyaes (>=1.0.0)"] 76 | hook_testing = ["pytest (>=2.7.3)", "execnet (>=1.5.0)", "psutil"] 77 | 78 | [package.source] 79 | type = "legacy" 80 | url = "https://pypi.doubanio.com/simple" 81 | reference = "douban" 82 | 83 | [[package]] 84 | name = "pyinstaller-hooks-contrib" 85 | version = "2020.9" 86 | description = "Community maintained hooks for PyInstaller" 87 | category = "main" 88 | optional = false 89 | python-versions = "*" 90 | 91 | [package.source] 92 | type = "legacy" 93 | url = "https://pypi.doubanio.com/simple" 94 | reference = "douban" 95 | 96 | [[package]] 97 | name = "pywin32" 98 | version = "228" 99 | description = "Python for Window Extensions" 100 | category = "main" 101 | optional = false 102 | python-versions = "*" 103 | 104 | [package.source] 105 | type = "legacy" 106 | url = "https://pypi.doubanio.com/simple" 107 | reference = "douban" 108 | 109 | [[package]] 110 | name = "pywin32-ctypes" 111 | version = "0.2.0" 112 | description = "" 113 | category = "main" 114 | optional = false 115 | python-versions = "*" 116 | 117 | [package.source] 118 | type = "legacy" 119 | url = "https://pypi.doubanio.com/simple" 120 | reference = "douban" 121 | 122 | [metadata] 123 | lock-version = "1.1" 124 | python-versions = "^3.6" 125 | content-hash = "96758e801a45b0b146576482f4824ce4fab2e2c9418b6da3396e4491e63cd38f" 126 | 127 | [metadata.files] 128 | altgraph = [ 129 | {file = "altgraph-0.17-py2.py3-none-any.whl", hash = "sha256:c623e5f3408ca61d4016f23a681b9adb100802ca3e3da5e718915a9e4052cebe"}, 130 | {file = "altgraph-0.17.tar.gz", hash = "sha256:1f05a47122542f97028caf78775a095fbe6a2699b5089de8477eb583167d69aa"}, 131 | ] 132 | future = [ 133 | {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, 134 | ] 135 | macholib = [ 136 | {file = "macholib-1.14-py2.py3-none-any.whl", hash = "sha256:c500f02867515e6c60a27875b408920d18332ddf96b4035ef03beddd782d4281"}, 137 | {file = "macholib-1.14.tar.gz", hash = "sha256:0c436bc847e7b1d9bda0560351bf76d7caf930fb585a828d13608839ef42c432"}, 138 | ] 139 | pefile = [ 140 | {file = "pefile-2019.4.18.tar.gz", hash = "sha256:a5d6e8305c6b210849b47a6174ddf9c452b2888340b8177874b862ba6c207645"}, 141 | ] 142 | pyinstaller = [ 143 | {file = "pyinstaller-4.0.tar.gz", hash = "sha256:970beb07115761d5e4ec317c1351b712fd90ae7f23994db914c633281f99bab0"}, 144 | ] 145 | pyinstaller-hooks-contrib = [ 146 | {file = "pyinstaller-hooks-contrib-2020.9.tar.gz", hash = "sha256:a5fd45a920012802e3f2089e1d3501ef2f49265dfea8fc46c3310f18e3326c91"}, 147 | {file = "pyinstaller_hooks_contrib-2020.9-py2.py3-none-any.whl", hash = "sha256:c382f3ac1a42b45cfecd581475c36db77da90e479b2f5bcb6d840d21fa545114"}, 148 | ] 149 | pywin32 = [ 150 | {file = "pywin32-228-cp27-cp27m-win32.whl", hash = "sha256:37dc9935f6a383cc744315ae0c2882ba1768d9b06700a70f35dc1ce73cd4ba9c"}, 151 | {file = "pywin32-228-cp27-cp27m-win_amd64.whl", hash = "sha256:11cb6610efc2f078c9e6d8f5d0f957620c333f4b23466931a247fb945ed35e89"}, 152 | {file = "pywin32-228-cp35-cp35m-win32.whl", hash = "sha256:1f45db18af5d36195447b2cffacd182fe2d296849ba0aecdab24d3852fbf3f80"}, 153 | {file = "pywin32-228-cp35-cp35m-win_amd64.whl", hash = "sha256:6e38c44097a834a4707c1b63efa9c2435f5a42afabff634a17f563bc478dfcc8"}, 154 | {file = "pywin32-228-cp36-cp36m-win32.whl", hash = "sha256:ec16d44b49b5f34e99eb97cf270806fdc560dff6f84d281eb2fcb89a014a56a9"}, 155 | {file = "pywin32-228-cp36-cp36m-win_amd64.whl", hash = "sha256:a60d795c6590a5b6baeacd16c583d91cce8038f959bd80c53bd9a68f40130f2d"}, 156 | {file = "pywin32-228-cp37-cp37m-win32.whl", hash = "sha256:af40887b6fc200eafe4d7742c48417529a8702dcc1a60bf89eee152d1d11209f"}, 157 | {file = "pywin32-228-cp37-cp37m-win_amd64.whl", hash = "sha256:00eaf43dbd05ba6a9b0080c77e161e0b7a601f9a3f660727a952e40140537de7"}, 158 | {file = "pywin32-228-cp38-cp38-win32.whl", hash = "sha256:fa6ba028909cfc64ce9e24bcf22f588b14871980d9787f1e2002c99af8f1850c"}, 159 | {file = "pywin32-228-cp38-cp38-win_amd64.whl", hash = "sha256:9b3466083f8271e1a5eb0329f4e0d61925d46b40b195a33413e0905dccb285e8"}, 160 | {file = "pywin32-228-cp39-cp39-win32.whl", hash = "sha256:ed74b72d8059a6606f64842e7917aeee99159ebd6b8d6261c518d002837be298"}, 161 | {file = "pywin32-228-cp39-cp39-win_amd64.whl", hash = "sha256:8319bafdcd90b7202c50d6014efdfe4fde9311b3ff15fd6f893a45c0868de203"}, 162 | ] 163 | pywin32-ctypes = [ 164 | {file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"}, 165 | {file = "pywin32_ctypes-0.2.0-py2.py3-none-any.whl", hash = "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"}, 166 | ] 167 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "MBPython" 3 | version = "0.2.2" 4 | description = "Miniblink binding for python" 5 | authors = ["lochen <1191826896@qq.com>"] 6 | license = "MIT" 7 | readme = "README.md" 8 | homepage = "https://github.com/lochen88/MBPython" 9 | repository = "https://github.com/lochen88/MBPython" 10 | 11 | [tool.poetry.dependencies] 12 | python = "^3.6" 13 | pywin32 = "^228" 14 | 15 | 16 | [tool.poetry.dev-dependencies] 17 | 18 | [build-system] 19 | requires = ["poetry-core>=1.0.0"] 20 | build-backend = "poetry.core.masonry.api" 21 | 22 | [[tool.poetry.source]] 23 | name = "douban" 24 | default = true 25 | url = "https://pypi.doubanio.com/simple/" -------------------------------------------------------------------------------- /tests/__pycache__/callbackfunc.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/__pycache__/callbackfunc.cpython-36.pyc -------------------------------------------------------------------------------- /tests/__pycache__/callbackfunc.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/__pycache__/callbackfunc.cpython-38.pyc -------------------------------------------------------------------------------- /tests/__pycache__/config.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/__pycache__/config.cpython-36.pyc -------------------------------------------------------------------------------- /tests/__pycache__/config.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/__pycache__/config.cpython-38.pyc -------------------------------------------------------------------------------- /tests/__pycache__/test_bindwebview.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/__pycache__/test_bindwebview.cpython-36.pyc -------------------------------------------------------------------------------- /tests/__pycache__/test_bindwindow.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/__pycache__/test_bindwindow.cpython-36.pyc -------------------------------------------------------------------------------- /tests/__pycache__/test_mbpython.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/__pycache__/test_mbpython.cpython-36.pyc -------------------------------------------------------------------------------- /tests/__pycache__/test_mbpython.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/__pycache__/test_mbpython.cpython-38.pyc -------------------------------------------------------------------------------- /tests/callbackfunc.py: -------------------------------------------------------------------------------- 1 | 2 | from ctypes import c_char_p 3 | class callBackTest(): 4 | def __init__(self,miniblink,runjs,callback,network): 5 | self.mb=miniblink 6 | self.js=runjs 7 | self.cb=callback 8 | self.network=network 9 | def document_ready_func(self,**kwargs): 10 | webview=kwargs['webview'] 11 | param=kwargs['param'] 12 | frameId=kwargs['frameId'] 13 | url=self.mb.wkeGetFrameUrl(webview,frameId).decode() 14 | if 'about:blank' in url:return 15 | if self.mb.wkeIsDocumentReady(webview)!=0: 16 | print('wkeDocumentReady2Callback',frameId,param,url) 17 | self.test_js(webview=webview,frameId=frameId) 18 | def test_js(self,webview,frameId=1): 19 | # self.js.run_js(webview,js_code='return 1+1') 20 | # self.js.run_js(webview, js_code='return document.body.innerHTML') 21 | # self.js.run_js(webview, js_code='return window.parent.frames["contentFrame"].document.getElementsByClassName("m-cvrlst f-cb")[0].innerHTML') 22 | # self.js.run_js(webview, js_code='return document.getElementById("testiframe").contentWindow.document.body.innerHTML') 23 | # self.js.run_js(webview, js_code='document.write(666)') 24 | # self.js.run_js(webview, js_code='return 1+1.1') 25 | # self.js.run_js(webview, js_code='return PyRunJS("hi"," baby")') 26 | # self.js.run_js_byframe(webview, frameId, 'return document.body.innerHTML', isInClosure=True) 27 | # self.js.run_js_global(webview,'globaljs',['good']) 28 | ... 29 | 30 | 31 | -------------------------------------------------------------------------------- /tests/config.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from os import getcwd 3 | 4 | 5 | init_path=getcwd() 6 | icon_path=f'{init_path}/logo.ico' 7 | node_path=f'{init_path}/node.dll' 8 | # node_path=f'{init_path}/miniblink_x64.dll' 9 | -------------------------------------------------------------------------------- /tests/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/logo.ico -------------------------------------------------------------------------------- /tests/miniblink_x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/miniblink_x64.dll -------------------------------------------------------------------------------- /tests/node.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/node.dll -------------------------------------------------------------------------------- /tests/test_bindwebview.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import os 3 | import sys 4 | from pathlib import Path 5 | current_folder = Path(__file__).absolute().parent 6 | father_folder = str(current_folder.parent) 7 | os.chdir(str(current_folder)) 8 | sys.path.append(father_folder) 9 | 10 | from callbackfunc import callBackTest 11 | from MBPython import miniblink 12 | from config import node_path 13 | 14 | import win32gui 15 | from win32con import * 16 | from ctypes import windll 17 | user32=windll.user32 18 | def WndProc(hwnd,msg,wParam,lParam): 19 | if msg == WM_DESTROY: 20 | win32gui.PostQuitMessage(0) 21 | sys.exit(0) 22 | return 0 23 | return win32gui.DefWindowProc(hwnd,msg,wParam,lParam) 24 | def get_hwnd(): 25 | wc = win32gui.WNDCLASS() 26 | wc.hbrBackground = COLOR_BTNFACE + 1 27 | wc.hCursor = win32gui.LoadCursor(0,IDI_APPLICATION) 28 | wc.lpszClassName = "MBPython" 29 | wc.style = CS_GLOBALCLASS|CS_VREDRAW | CS_HREDRAW 30 | wc.lpfnWndProc = WndProc 31 | reg = win32gui.RegisterClass(wc) 32 | hwnd = win32gui.CreateWindow(reg,'MBPython-webview绑定测试-1191826896',WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_POPUP|WS_MINIMIZEBOX,300,100,860,760,0,0,0,None) 33 | return hwnd 34 | def test_js_run_py(**kwargs): 35 | es=kwargs['es'] 36 | param=kwargs['param'] 37 | arg_count=jsrunpy.mb.jsArgCount(es) 38 | val_ls=jsrunpy.get_js_args_val(es,arg_count) 39 | print(val_ls,'test_js_run_py') 40 | 41 | hwnd=param 42 | if val_ls[0]=='move': 43 | user32.ReleaseCapture() 44 | user32.SendMessageW(hwnd,161, 2, 0) 45 | elif val_ls[0]=='close': 46 | win32gui.PostQuitMessage(0) 47 | elif val_ls[0]=='max': 48 | ismax=user32.IsZoomed(hwnd) 49 | if ismax==0: 50 | user32.ShowWindow(hwnd,3) 51 | elif ismax==1: 52 | user32.ShowWindow(hwnd,1) 53 | elif val_ls[0]=='min': 54 | user32.ShowWindow(hwnd,2) 55 | elif val_ls[0]=='menu': 56 | return jsrunpy.to_js_args_val(es,'click-menu') 57 | elif val_ls[0]=='loadurl': 58 | j_webview=window.wkeCreateWebWindow(0,0,0,0,360,480) 59 | network.wkeLoadURLW(j_webview,'https://www.baidu.com/') 60 | window.wkeShowWindow(j_webview) 61 | return 0 62 | def test(): 63 | mbpython=miniblink.Miniblink 64 | mb=mbpython.init(node_path) 65 | wke=mbpython(mb) 66 | if mb==0:return 67 | global jsrunpy,window,network 68 | window=wke.window 69 | callback=wke.callback 70 | network=wke.network 71 | pyrunjs=wke.pyrunjs 72 | jsrunpy=wke.jsrunpy 73 | bindwebview=wke.bindwebview 74 | cbtest=callBackTest(mb,pyrunjs,callback,network) 75 | 76 | callback.wkeDocumentReady2Callback=cbtest.document_ready_func 77 | jsrunpy.python_func=test_js_run_py 78 | 79 | hwnd=get_hwnd() 80 | jsrunpy.bind_func('call_py_func', arg_count=2, param=hwnd) 81 | webview=bindwebview.bind_webview(hwnd=hwnd,isTransparent=True,isZoom=True) 82 | param='测试绑定webview' 83 | 84 | callback.wkeOnDocumentReady2(webview,param) 85 | 86 | # network.wkeLoadURLW(webview,'https://www.baidu.com/') 87 | 88 | 89 | # win32gui.ShowWindow(hwnd,SW_SHOWNORMAL) 90 | win32gui.ShowWindow(hwnd,SW_SHOWNORMAL) 91 | 92 | network.wkeLoadFile(webview,'/testjs/testjs.html') 93 | 94 | win32gui.PumpMessages() 95 | if __name__=='__main__': 96 | test() -------------------------------------------------------------------------------- /tests/test_bindwindow.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import os 3 | import sys 4 | from pathlib import Path 5 | current_folder = Path(__file__).absolute().parent 6 | father_folder = str(current_folder.parent) 7 | os.chdir(str(current_folder)) 8 | sys.path.append(father_folder) 9 | 10 | from config import icon_path,node_path 11 | from callbackfunc import callBackTest 12 | from MBPython import miniblink 13 | from MBPython import set_icon 14 | from MBPython.wkeStruct import Rect 15 | 16 | mbpython=miniblink.Miniblink 17 | mb=mbpython.init(node_path) 18 | wke=mbpython(mb) 19 | 20 | import win32gui 21 | from win32con import * 22 | from ctypes import windll,byref 23 | user32=windll.user32 24 | def WndProc(hwnd,msg,wParam,lParam): 25 | if msg == WM_PAINT: 26 | rect=Rect() 27 | user32.GetClientRect(hwnd,byref(rect)) 28 | window.wkeResize(webview,rect.Right - rect.Left,rect.Bottom - rect.Top) 29 | if msg == WM_DESTROY: 30 | win32gui.PostQuitMessage(0) 31 | return 0 32 | return win32gui.DefWindowProc(hwnd,msg,wParam,lParam) 33 | def get_hwnd(): 34 | wc = win32gui.WNDCLASS() 35 | wc.hbrBackground = COLOR_BTNFACE + 1 36 | wc.hCursor = win32gui.LoadCursor(0,IDI_APPLICATION) 37 | wc.lpszClassName = "MBPython" 38 | wc.style = CS_GLOBALCLASS|CS_VREDRAW | CS_HREDRAW 39 | wc.lpfnWndProc = WndProc 40 | reg = win32gui.RegisterClass(wc) 41 | hwnd = win32gui.CreateWindowEx(0, reg,'MBPython-窗口绑定测试-1191826896',WS_OVERLAPPEDWINDOW,300,100,860,760, 0, 0, 0, None) 42 | return hwnd 43 | def test_js_run_py(**kwargs): 44 | es=kwargs['es'] 45 | param=kwargs['param'] 46 | arg_count=jsrunpy.mb.jsArgCount(es) 47 | val_ls=jsrunpy.get_js_args_val(es,arg_count) 48 | print(val_ls,'test_js_run_py') 49 | 50 | hwnd=param 51 | if val_ls[0]=='move': 52 | user32.ReleaseCapture() 53 | user32.SendMessageW(hwnd,161, 2, 0) 54 | elif val_ls[0]=='close': 55 | win32gui.PostQuitMessage(0) 56 | elif val_ls[0]=='max': 57 | ismax=user32.IsZoomed(hwnd) 58 | if ismax==0: 59 | user32.ShowWindow(hwnd,3) 60 | elif ismax==1: 61 | user32.ShowWindow(hwnd,1) 62 | elif val_ls[0]=='min': 63 | user32.ShowWindow(hwnd,2) 64 | elif val_ls[0]=='menu': 65 | return jsrunpy.to_js_args_val(es,'click-menu') 66 | elif val_ls[0]=='loadurl': 67 | 68 | pyrunjs.run_js(webview,'alert("create new window")') 69 | wke2=mbpython(mb) 70 | j_webview=wke2.window.wkeCreateWebWindow(0,0,0,0,360,480) 71 | wke2.network.wkeLoadURLW(j_webview,'https://www.baidu.com/') 72 | wke2.window.wkeShowWindow(j_webview) 73 | 74 | return 0 75 | def test(): 76 | if mb==0:return 77 | global webview,window,jsrunpy,network,pyrunjs 78 | window=wke.window 79 | callback=wke.callback 80 | network=wke.network 81 | pyrunjs=wke.pyrunjs 82 | jsrunpy=wke.jsrunpy 83 | cbtest=callBackTest(mb,pyrunjs,callback,network) 84 | 85 | jsrunpy.python_func=test_js_run_py 86 | callback.wkeDocumentReady2Callback=cbtest.document_ready_func 87 | 88 | hwnd=get_hwnd() 89 | jsrunpy.bind_func('call_py_func', arg_count=2, param=hwnd) 90 | set_icon(hwnd,icon_path) 91 | webview=window.bind_window(hwnd=hwnd) 92 | 93 | param='测试传参' 94 | callback.wkeOnDocumentReady2(webview,param) 95 | callback.wkeOnWindowDestroy(webview) 96 | 97 | # network.wkeLoadURLW(webview,'https://www.baidu.com/') 98 | 99 | 100 | win32gui.ShowWindow(hwnd,SW_SHOWNORMAL) 101 | win32gui.ShowWindow(hwnd,SW_SHOWNORMAL) 102 | 103 | network.wkeLoadFile(webview,'/testjs/testjs.html') 104 | 105 | win32gui.PumpMessages() 106 | if __name__=='__main__': 107 | test() -------------------------------------------------------------------------------- /tests/test_mbpython.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import os 3 | import sys 4 | from pathlib import Path 5 | current_folder = Path(__file__).absolute().parent 6 | father_folder = str(current_folder.parent) 7 | os.chdir(str(current_folder)) 8 | sys.path.append(father_folder) 9 | 10 | 11 | from MBPython import miniblink 12 | from config import node_path 13 | def test(): 14 | mbpython=miniblink.Miniblink 15 | mb=mbpython.init(node_path) 16 | wke=mbpython(mb) 17 | if mb==0:return 18 | window=wke.window 19 | callback=wke.callback 20 | network=wke.network 21 | 22 | webview=window.wkeCreateWebWindow(0,0,0,0,860,760) 23 | callback.wkeOnWindowDestroy(webview) 24 | 25 | network.wkeLoadURLW(webview,'https://www.baidu.com/') 26 | 27 | window.wkeShowWindow(webview) 28 | window.wkeShowWindow(webview) 29 | window.wkeRunMessageLoop() 30 | 31 | if __name__=='__main__': 32 | test() 33 | ... 34 | -------------------------------------------------------------------------------- /tests/testexe/testexe.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/testexe/testexe.7z -------------------------------------------------------------------------------- /tests/testjs/images/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/testjs/images/Thumbs.db -------------------------------------------------------------------------------- /tests/testjs/images/alipay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/testjs/images/alipay.jpg -------------------------------------------------------------------------------- /tests/testjs/images/btn-control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/testjs/images/btn-control.png -------------------------------------------------------------------------------- /tests/testjs/images/girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/testjs/images/girl.png -------------------------------------------------------------------------------- /tests/testjs/images/hader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/testjs/images/hader.png -------------------------------------------------------------------------------- /tests/testjs/images/qq.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lochen88/MBPython/69c92475d24aedc4509fdb69d445f4128a2cccda/tests/testjs/images/qq.jpg -------------------------------------------------------------------------------- /tests/testjs/javascript/test.js: -------------------------------------------------------------------------------- 1 | // document.write('') 2 | var el=document.querySelector('head') 3 | 4 | var importjs=function(jspath){ 5 | var newElement = document.createElement('script'); 6 | newElement.setAttribute('type','text/javascript'); 7 | newElement.setAttribute('src',jspath); 8 | el.appendChild(newElement) 9 | console.log('成功引入js') 10 | } 11 | 12 | var generateParentNode=function(el,classname){ 13 | elem = document.createElement('div') 14 | elem.className=classname 15 | el.parentNode.replaceChild(elem,el) 16 | elem.appendChild(el) 17 | } 18 | 19 | 20 | importjs('javascript/test_1.js') 21 | var testImportJs=function(){ 22 | var a=test_1(); 23 | return 'testImportJs-'+a+1 24 | } 25 | 26 | 27 | 28 | var creatVueApp=function(){ 29 | const app3 = new Vue({ 30 | el: '#app3', 31 | data() { 32 | return{ 33 | msg:'引入js手动新建app3' 34 | } 35 | }, 36 | methods:{ 37 | testApp3Click(){ 38 | this.msg='app3-测试vue点击' 39 | } 40 | } 41 | }).$mount('#app3') 42 | } 43 | 44 | document.addEventListener("DOMContentLoaded", function(event) { 45 | const app4 = new Vue({ 46 | el: '#app4', 47 | data() { 48 | return{ 49 | msg:'引入js自动创建app4' 50 | } 51 | }, 52 | methods:{ 53 | testApp4Click(){ 54 | this.msg='app4-测试vue点击' 55 | } 56 | } 57 | }).$mount('#app4') 58 | }) 59 | -------------------------------------------------------------------------------- /tests/testjs/javascript/test_1.js: -------------------------------------------------------------------------------- 1 | var test_1=function(){ 2 | console.log('我是test_1') 3 | return 1 4 | } 5 | -------------------------------------------------------------------------------- /tests/testjs/javascript/vue.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vue.js v1.0.28 3 | * (c) 2016 Evan You 4 | * Released under the MIT License. 5 | */ 6 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.Vue=e()}(this,function(){"use strict";function t(e,n,r){if(i(e,n))return void(e[n]=r);if(e._isVue)return void t(e._data,n,r);var s=e.__ob__;if(!s)return void(e[n]=r);if(s.convert(n,r),s.dep.notify(),s.vms)for(var o=s.vms.length;o--;){var a=s.vms[o];a._proxy(n),a._digest()}return r}function e(t,e){if(i(t,e)){delete t[e];var n=t.__ob__;if(!n)return void(t._isVue&&(delete t._data[e],t._digest()));if(n.dep.notify(),n.vms)for(var r=n.vms.length;r--;){var s=n.vms[r];s._unproxy(e),s._digest()}}}function i(t,e){return Mi.call(t,e)}function n(t){return Wi.test(t)}function r(t){var e=(t+"").charCodeAt(0);return 36===e||95===e}function s(t){return null==t?"":t.toString()}function o(t){if("string"!=typeof t)return t;var e=Number(t);return isNaN(e)?t:e}function a(t){return"true"===t||"false"!==t&&t}function h(t){var e=t.charCodeAt(0),i=t.charCodeAt(t.length-1);return e!==i||34!==e&&39!==e?t:t.slice(1,-1)}function l(t){return t.replace(Vi,c)}function c(t,e){return e?e.toUpperCase():""}function u(t){return t.replace(Bi,"$1-$2").replace(Bi,"$1-$2").toLowerCase()}function f(t){return t.replace(zi,c)}function p(t,e){return function(i){var n=arguments.length;return n?n>1?t.apply(e,arguments):t.call(e,i):t.call(e)}}function d(t,e){e=e||0;for(var i=t.length-e,n=new Array(i);i--;)n[i]=t[i+e];return n}function v(t,e){for(var i=Object.keys(e),n=i.length;n--;)t[i[n]]=e[i[n]];return t}function m(t){return null!==t&&"object"==typeof t}function g(t){return Ui.call(t)===Ji}function _(t,e,i,n){Object.defineProperty(t,e,{value:i,enumerable:!!n,writable:!0,configurable:!0})}function y(t,e){var i,n,r,s,o,a=function a(){var h=Date.now()-s;h=0?i=setTimeout(a,e-h):(i=null,o=t.apply(r,n),i||(r=n=null))};return function(){return r=this,n=arguments,s=Date.now(),i||(i=setTimeout(a,e)),o}}function b(t,e){for(var i=t.length;i--;)if(t[i]===e)return i;return-1}function w(t){var e=function e(){if(!e.cancelled)return t.apply(this,arguments)};return e.cancel=function(){e.cancelled=!0},e}function C(t,e){return t==e||!(!m(t)||!m(e))&&JSON.stringify(t)===JSON.stringify(e)}function $(t){return/native code/.test(t.toString())}function k(t){this.size=0,this.limit=t,this.head=this.tail=void 0,this._keymap=Object.create(null)}function x(){return fn.charCodeAt(vn+1)}function A(){return fn.charCodeAt(++vn)}function O(){return vn>=dn}function T(){for(;x()===Tn;)A()}function N(t){return t===kn||t===xn}function j(t){return Nn[t]}function E(t,e){return jn[t]===e}function S(){for(var t,e=A();!O();)if(t=A(),t===On)A();else if(t===e)break}function F(t){for(var e=0,i=t;!O();)if(t=x(),N(t))S();else if(i===t&&e++,E(i,t)&&e--,A(),0===e)break}function D(){for(var t=vn;!O();)if(mn=x(),N(mn))S();else if(j(mn))F(mn);else if(mn===An){if(A(),mn=x(),mn!==An){gn!==bn&&gn!==$n||(gn=wn);break}A()}else{if(mn===Tn&&(gn===Cn||gn===$n)){T();break}gn===wn&&(gn=Cn),A()}return fn.slice(t+1,vn)||null}function P(){for(var t=[];!O();)t.push(R());return t}function R(){var t,e={};return gn=wn,e.name=D().trim(),gn=$n,t=L(),t.length&&(e.args=t),e}function L(){for(var t=[];!O()&&gn!==wn;){var e=D();if(!e)break;t.push(H(e))}return t}function H(t){if(yn.test(t))return{value:o(t),dynamic:!1};var e=h(t),i=e===t;return{value:i?t:e,dynamic:i}}function I(t){var e=_n.get(t);if(e)return e;fn=t,pn={},dn=fn.length,vn=-1,mn="",gn=bn;var i;return fn.indexOf("|")<0?pn.expression=fn.trim():(pn.expression=D().trim(),i=P(),i.length&&(pn.filters=i)),_n.put(t,pn),pn}function M(t){return t.replace(Sn,"\\$&")}function W(){var t=M(Mn.delimiters[0]),e=M(Mn.delimiters[1]),i=M(Mn.unsafeDelimiters[0]),n=M(Mn.unsafeDelimiters[1]);Dn=new RegExp(i+"((?:.|\\n)+?)"+n+"|"+t+"((?:.|\\n)+?)"+e,"g"),Pn=new RegExp("^"+i+"((?:.|\\n)+?)"+n+"$"),Fn=new k(1e3)}function V(t){Fn||W();var e=Fn.get(t);if(e)return e;if(!Dn.test(t))return null;for(var i,n,r,s,o,a,h=[],l=Dn.lastIndex=0;i=Dn.exec(t);)n=i.index,n>l&&h.push({value:t.slice(l,n)}),r=Pn.test(i[0]),s=r?i[1]:i[2],o=s.charCodeAt(0),a=42===o,s=a?s.slice(1):s,h.push({tag:!0,value:s.trim(),html:r,oneTime:a}),l=n+i[0].length;return l1?t.map(function(t){return z(t,e)}).join("+"):z(t[0],e,!0)}function z(t,e,i){return t.tag?t.oneTime&&e?'"'+e.$eval(t.value)+'"':U(t.value,i):'"'+t.value+'"'}function U(t,e){if(Rn.test(t)){var i=I(t);return i.filters?"this._applyFilters("+i.expression+",null,"+JSON.stringify(i.filters)+",false)":"("+t+")"}return e?t:"("+t+")"}function J(t,e,i,n){G(t,1,function(){e.appendChild(t)},i,n)}function q(t,e,i,n){G(t,1,function(){et(t,e)},i,n)}function Q(t,e,i){G(t,-1,function(){nt(t)},e,i)}function G(t,e,i,n,r){var s=t.__v_trans;if(!s||!s.hooks&&!rn||!n._isCompiled||n.$parent&&!n.$parent._isCompiled)return i(),void(r&&r());var o=e>0?"enter":"leave";s[o](i,r)}function Z(t){if("string"==typeof t){t=document.querySelector(t)}return t}function X(t){if(!t)return!1;var e=t.ownerDocument.documentElement,i=t.parentNode;return e===t||e===i||!(!i||1!==i.nodeType||!e.contains(i))}function Y(t,e){var i=t.getAttribute(e);return null!==i&&t.removeAttribute(e),i}function K(t,e){var i=Y(t,":"+e);return null===i&&(i=Y(t,"v-bind:"+e)),i}function tt(t,e){return t.hasAttribute(e)||t.hasAttribute(":"+e)||t.hasAttribute("v-bind:"+e)}function et(t,e){e.parentNode.insertBefore(t,e)}function it(t,e){e.nextSibling?et(t,e.nextSibling):e.parentNode.appendChild(t)}function nt(t){t.parentNode.removeChild(t)}function rt(t,e){e.firstChild?et(t,e.firstChild):e.appendChild(t)}function st(t,e){var i=t.parentNode;i&&i.replaceChild(e,t)}function ot(t,e,i,n){t.addEventListener(e,i,n)}function at(t,e,i){t.removeEventListener(e,i)}function ht(t){var e=t.className;return"object"==typeof e&&(e=e.baseVal||""),e}function lt(t,e){Ki&&!/svg$/.test(t.namespaceURI)?t.className=e:t.setAttribute("class",e)}function ct(t,e){if(t.classList)t.classList.add(e);else{var i=" "+ht(t)+" ";i.indexOf(" "+e+" ")<0&<(t,(i+e).trim())}}function ut(t,e){if(t.classList)t.classList.remove(e);else{for(var i=" "+ht(t)+" ",n=" "+e+" ";i.indexOf(n)>=0;)i=i.replace(n," ");lt(t,i.trim())}t.className||t.removeAttribute("class")}function ft(t,e){var i,n;if(vt(t)&&bt(t.content)&&(t=t.content),t.hasChildNodes())for(pt(t),n=e?document.createDocumentFragment():document.createElement("div");i=t.firstChild;)n.appendChild(i);return n}function pt(t){for(var e;e=t.firstChild,dt(e);)t.removeChild(e);for(;e=t.lastChild,dt(e);)t.removeChild(e)}function dt(t){return t&&(3===t.nodeType&&!t.data.trim()||8===t.nodeType)}function vt(t){return t.tagName&&"template"===t.tagName.toLowerCase()}function mt(t,e){var i=Mn.debug?document.createComment(t):document.createTextNode(e?" ":"");return i.__v_anchor=!0,i}function gt(t){if(t.hasAttributes())for(var e=t.attributes,i=0,n=e.length;i=h.length){for(var t=0;t=97&&e<=122||e>=65&&e<=90?"ident":e>=49&&e<=57?"number":"else"}function Mt(t){var e=t.trim();return("0"!==t.charAt(0)||!isNaN(t))&&(n(e)?h(e):"*"+e)}function Wt(t){function e(){var e=t[c+1];if(u===ur&&"'"===e||u===fr&&'"'===e)return c++,n="\\"+e,p[ir](),!0}var i,n,r,s,o,a,h,l=[],c=-1,u=or,f=0,p=[];for(p[nr]=function(){void 0!==r&&(l.push(r),r=void 0)},p[ir]=function(){void 0===r?r=n:r+=n},p[rr]=function(){p[ir](),f++},p[sr]=function(){if(f>0)f--,u=cr,p[ir]();else{if(f=0,r=Mt(r),r===!1)return!1;p[nr]()}};null!=u;)if(c++,i=t[c],"\\"!==i||!e()){if(s=It(i),h=vr[u],o=h[s]||h.else||dr,o===dr)return;if(u=o[0],a=p[o[1]],a&&(n=o[2],n=void 0===n?i:n,a()===!1))return;if(u===pr)return l.raw=t,l}}function Vt(t){var e=er.get(t);return e||(e=Wt(t),e&&er.put(t,e)),e}function Bt(t,e){return Yt(e).get(t)}function zt(e,i,n){var r=e;if("string"==typeof i&&(i=Wt(i)),!i||!m(e))return!1;for(var s,o,a=0,h=i.length;a-1?i.replace(xr,Qt):i,e+"scope."+i)}function Qt(t,e){return Nr[e]}function Gt(t){wr.test(t),Nr.length=0;var e=t.replace(kr,Jt).replace(Cr,"");return e=(" "+e).replace(Or,qt).replace(xr,Qt),Zt(e)}function Zt(t){try{return new Function("scope","return "+t+";")}catch(t){return Ut}}function Xt(t){var e=Vt(t);if(e)return function(t,i){zt(t,e,i)}}function Yt(t,e){t=t.trim();var i=gr.get(t);if(i)return e&&!i.set&&(i.set=Xt(i.exp)),i;var n={exp:t};return n.get=Kt(t)&&t.indexOf("[")<0?Zt("scope."+t):Gt(t),e&&(n.set=Xt(t)),gr.put(t,n),n}function Kt(t){return Ar.test(t)&&!Tr.test(t)&&"Math."!==t.slice(0,5)}function te(){Er.length=0,Sr.length=0,Fr={},Dr={},Pr=!1}function ee(){for(var t=!0;t;)t=!1,ie(Er),ie(Sr),Er.length?t=!0:(Zi&&Mn.devtools&&Zi.emit("flush"),te())}function ie(t){for(var e=0;e0){var o=s+(n?e:wt(e));r=Gr.get(o),r||(r=qe(i,t.$options,!0),Gr.put(o,r))}else r=qe(i,t.$options,!0);this.linker=r}function ye(t,e,i){var n=t.node.previousSibling;if(n){for(t=n.__v_frag;!(t&&t.forId===i&&t.inserted||n===e);){if(n=n.previousSibling,!n)return;t=n.__v_frag}return t}}function be(t){for(var e=-1,i=new Array(Math.floor(t));++e47&&e<58?parseInt(t,10):1===t.length&&(e=t.toUpperCase().charCodeAt(0),e>64&&e<91)?e:ms[t]});return i=[].concat.apply([],i),function(e){if(i.indexOf(e.keyCode)>-1)return t.call(this,e)}}function Ae(t){return function(e){return e.stopPropagation(),t.call(this,e)}}function Oe(t){return function(e){return e.preventDefault(),t.call(this,e)}}function Te(t){return function(e){if(e.target===e.currentTarget)return t.call(this,e)}}function Ne(t){if(ws[t])return ws[t];var e=je(t);return ws[t]=ws[e]=e,e}function je(t){t=u(t);var e=l(t),i=e.charAt(0).toUpperCase()+e.slice(1);Cs||(Cs=document.createElement("div"));var n,r=_s.length;if("filter"!==e&&e in Cs.style)return{kebab:t,camel:e};for(;r--;)if(n=ys[r]+i,n in Cs.style)return{kebab:_s[r]+t,camel:n}}function Ee(t){var e=[];if(qi(t))for(var i=0,n=t.length;i=r?i():t[s].call(e,n)}var r=t.length,s=0;t[0].call(e,n)}function De(t,e,i){for(var r,s,o,a,h,c,f,p=[],d=i.$options.propsData,v=Object.keys(e),m=v.length;m--;)s=v[m],r=e[s]||Hs,h=l(s),Is.test(h)&&(f={name:s,path:h,options:r,mode:Ls.ONE_WAY,raw:null},o=u(s),null===(a=K(t,o))&&(null!==(a=K(t,o+".sync"))?f.mode=Ls.TWO_WAY:null!==(a=K(t,o+".once"))&&(f.mode=Ls.ONE_TIME)),null!==a?(f.raw=a,c=I(a),a=c.expression,f.filters=c.filters,n(a)&&!c.filters?f.optimizedLiteral=!0:f.dynamic=!0,f.parentPath=a):null!==(a=Y(t,o))?f.raw=a:d&&null!==(a=d[s]||d[h])&&(f.raw=a),p.push(f));return Pe(p)}function Pe(t){return function(e,n){e._props={};for(var r,s,l,c,f,p=e.$options.propsData,d=t.length;d--;)if(r=t[d],f=r.raw,s=r.path,l=r.options,e._props[s]=r,p&&i(p,s)&&Le(e,r,p[s]),null===f)Le(e,r,void 0);else if(r.dynamic)r.mode===Ls.ONE_TIME?(c=(n||e._context||e).$get(r.parentPath),Le(e,r,c)):e._context?e._bindDir({name:"prop",def:Ws,prop:r},null,null,n):Le(e,r,e.$get(r.parentPath));else if(r.optimizedLiteral){var v=h(f);c=v===f?a(o(f)):v,Le(e,r,c)}else c=l.type===Boolean&&(""===f||f===u(r.name))||f,Le(e,r,c)}}function Re(t,e,i,n){var r=e.dynamic&&Kt(e.parentPath),s=i;void 0===s&&(s=Ie(t,e)),s=We(e,s,t);var o=s!==i;Me(e,s,t)||(s=void 0),r&&!o?St(function(){n(s)}):n(s)}function Le(t,e,i){Re(t,e,i,function(i){Lt(t,e.path,i)})}function He(t,e,i){Re(t,e,i,function(i){t[e.path]=i})}function Ie(t,e){var n=e.options;if(!i(n,"default"))return n.type!==Boolean&&void 0;var r=n.default;return m(r),"function"==typeof r&&n.type!==Function?r.call(t):r}function Me(t,e,i){if(!t.options.required&&(null===t.raw||null==e))return!0;var n=t.options,r=n.type,s=!r,o=[];if(r){qi(r)||(r=[r]);for(var a=0;ae?-1:t===e?0:1}),e=0,i=a.length;ep.priority)&&(p=f,c=r.name,a=di(r.name),o=r.value,l=h[1],u=h[2]));return p?fi(t,l,o,i,p,c,u,a):void 0}function ui(){}function fi(t,e,i,n,r,s,o,a){var h=I(i),l={name:e,arg:o,expression:h.expression,filters:h.filters,raw:i,attr:s,modifiers:a,def:r};"for"!==e&&"router-view"!==e||(l.ref=gt(t));var c=function(t,e,i,n,r){l.ref&&Lt((n||t).$refs,l.ref,null),t._bindDir(l,e,i,n,r)};return c.terminal=!0,c}function pi(t,e){function i(t,e,i){var n=i&&mi(i),r=!n&&I(s);v.push({name:t,attr:o,raw:a,def:e,arg:l,modifiers:c,expression:r&&r.expression,filters:r&&r.filters,interp:i,hasOneTime:n})}for(var n,r,s,o,a,h,l,c,u,f,p,d=t.length,v=[];d--;)if(n=t[d],r=o=n.name,s=a=n.value,f=V(s),l=null,c=di(r),r=r.replace(io,""),f)s=B(f),l=r,i("bind",Ds.bind,f);else if(no.test(r))c.literal=!Ks.test(r),i("transition",Ys.transition);else if(to.test(r))l=r.replace(to,""),i("on",Ds.on);else if(Ks.test(r))h=r.replace(Ks,""),"style"===h||"class"===h?i(h,Ys[h]):(l=h,i("bind",Ds.bind));else if(p=r.match(eo)){if(h=p[1],l=p[2],"else"===h)continue;u=jt(e,"directives",h,!0),u&&i(h,u)}if(v.length)return vi(v)}function di(t){var e=Object.create(null),i=t.match(io);if(i)for(var n=i.length;n--;)e[i[n].slice(1)]=!0;return e}function vi(t){return function(e,i,n,r,s){for(var o=t.length;o--;)e._bindDir(t[o],i,n,r,s)}}function mi(t){for(var e=t.length;e--;)if(t[e].oneTime)return!0}function gi(t){return"SCRIPT"===t.tagName&&(!t.hasAttribute("type")||"text/javascript"===t.getAttribute("type"))}function _i(t,e){return e&&(e._containerAttrs=bi(t)),vt(t)&&(t=ce(t)),e&&(e._asComponent&&!e.template&&(e.template=""),e.template&&(e._content=ft(t),t=yi(t,e))),bt(t)&&(rt(mt("v-start",!0),t),t.appendChild(mt("v-end",!0))),t}function yi(t,e){var i=e.template,n=ce(i,!0);if(n){var r=n.firstChild;if(!r)return n;var s=r.tagName&&r.tagName.toLowerCase();return e.replace?(t===document.body,n.childNodes.length>1||1!==r.nodeType||"component"===s||jt(e,"components",s)||tt(r,"is")||jt(e,"elementDirectives",s)||r.hasAttribute("v-for")||r.hasAttribute("v-if")?n:(e._replacerAttrs=bi(r),wi(t,r),r)):(t.appendChild(n),t)}}function bi(t){if(1===t.nodeType&&t.hasAttributes())return d(t.attributes)}function wi(t,e){for(var i,n,r=t.attributes,s=r.length;s--;)i=r[s].name,n=r[s].value,e.hasAttribute(i)||oo.test(i)?"class"===i&&!V(n)&&(n=n.trim())&&n.split(/\s+/).forEach(function(t){ct(e,t)}):e.setAttribute(i,n)}function Ci(t,e){if(e){for(var i,n,r=t._slotContents=Object.create(null),s=0,o=e.children.length;s1?d(i):i;var r=e&&i.some(function(t){return t._fromParent});r&&(n=!1);for(var s=d(arguments,1),o=0,a=i.length;oe?s:-s}var i=null,n=void 0;t=po(t);var r=d(arguments,1),s=r[r.length-1];"number"==typeof s?(s=s<0?-1:1,r=r.length>1?r.slice(0,-1):r):s=1;var o=r[0];return o?("function"==typeof o?i=function(t,e){return o(t,e)*s}:(n=Array.prototype.concat.apply([],r),i=function(t,r,s){return s=s||0,s>=n.length-1?e(t,r,s):e(t,r,s)||i(t,r,s+1)}),t.slice().sort(i)):t}function Hi(t,e){var i;if(g(t)){var n=Object.keys(t);for(i=n.length;i--;)if(Hi(t[n[i]],e))return!0}else if(qi(t)){for(i=t.length;i--;)if(Hi(t[i],e))return!0}else if(null!=t)return t.toString().toLowerCase().indexOf(e)>-1}function Ii(i){function n(t){return new Function("return function "+f(t)+" (options) { this._init(options) }")()}i.options={directives:Ds,elementDirectives:fo,filters:mo,transitions:{},components:{},partials:{},replace:!0},i.util=Kn,i.config=Mn,i.set=t,i.delete=e,i.nextTick=ln,i.compiler=ao,i.FragmentFactory=_e,i.internalDirectives=Ys,i.parsers={path:mr,text:Ln,template:qr,directive:En,expression:jr},i.cid=0;var r=1;i.extend=function(t){t=t||{};var e=this,i=0===e.cid;if(i&&t._Ctor)return t._Ctor;var s=t.name||e.options.name,o=n(s||"VueComponent");return o.prototype=Object.create(e.prototype),o.prototype.constructor=o,o.cid=r++,o.options=Nt(e.options,t),o.super=e,o.extend=e.extend,Mn._assetTypes.forEach(function(t){o[t]=e[t]}),s&&(o.options.components[s]=o),i&&(t._Ctor=o),o},i.use=function(t){if(!t.installed){var e=d(arguments,1);return e.unshift(this),"function"==typeof t.install?t.install.apply(t,e):t.apply(null,e),t.installed=!0,this}},i.mixin=function(t){i.options=Nt(i.options,t)},Mn._assetTypes.forEach(function(t){i[t]=function(e,n){return n?("component"===t&&g(n)&&(n.name||(n.name=e),n=i.extend(n)),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}}),v(i.transition,Vn)}var Mi=Object.prototype.hasOwnProperty,Wi=/^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/,Vi=/-(\w)/g,Bi=/([^-])([A-Z])/g,zi=/(?:^|[-_\/])(\w)/g,Ui=Object.prototype.toString,Ji="[object Object]",qi=Array.isArray,Qi="__proto__"in{},Gi="undefined"!=typeof window&&"[object Object]"!==Object.prototype.toString.call(window),Zi=Gi&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,Xi=Gi&&window.navigator.userAgent.toLowerCase(),Yi=Xi&&Xi.indexOf("trident")>0,Ki=Xi&&Xi.indexOf("msie 9.0")>0,tn=Xi&&Xi.indexOf("android")>0,en=Xi&&/iphone|ipad|ipod|ios/.test(Xi),nn=void 0,rn=void 0,sn=void 0,on=void 0;if(Gi&&!Ki){var an=void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend,hn=void 0===window.onanimationend&&void 0!==window.onwebkitanimationend;nn=an?"WebkitTransition":"transition",rn=an?"webkitTransitionEnd":"transitionend",sn=hn?"WebkitAnimation":"animation",on=hn?"webkitAnimationEnd":"animationend"}var ln=function(){function t(){i=!1;var t=e.slice(0);e.length=0;for(var n=0;n=this.length&&(this.length=Number(t)+1),this.splice(t,1,e)[0]}),_(Gn,"$remove",function(t){if(this.length){var e=b(this,t);return e>-1?this.splice(e,1):void 0}});var Xn=Object.getOwnPropertyNames(Zn),Yn=!0;Ft.prototype.walk=function(t){for(var e=Object.keys(t),i=0,n=e.length;i",""],tr:[2,"","
"],col:[2,"","
"]};Wr.td=Wr.th=[3,"","
"],Wr.option=Wr.optgroup=[1,'"],Wr.thead=Wr.tbody=Wr.colgroup=Wr.caption=Wr.tfoot=[1,"","
"],Wr.g=Wr.defs=Wr.symbol=Wr.use=Wr.image=Wr.text=Wr.circle=Wr.ellipse=Wr.line=Wr.path=Wr.polygon=Wr.polyline=Wr.rect=[1,'',""];var Vr=/<([\w:-]+)/,Br=/&#?\w+?;/,zr=/