├── 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 |
65 |
66 | |
70 |
71 |
72 | |
76 |