Skip to main content

A python binding of Miniblink

Project description

简介

关于PyWkeMiniblink

PyWkeMiniblink 是 Miniblink的Python绑定,参考了上游项目MBPython

PyWkeMiniblink: 项目地址 / 在线文档 / PYPI主页

关于Miniblink

Miniblink 是 chromium的精简版,删除了音视频功能,原接口参见官方接口文档,更完整的参见docs/source/wke.h 。

使用

安装

#安装依赖pywin32
pip3 install pywin32
#安装本地文件xx版本
pip3 install WkeMiniblink-xx-py3-none-any.whl
#从PYPI安装
pip3 install WkeMiniblink

示例

# -*- coding:utf-8 -*-
import os,sys,platform,time
import win32gui
from wkeMiniblink.wke import *
from wkeMiniblink.wkeEvent import *
from wkeMiniblink.wkeWin32 import *

if __name__=='__main__':
    webview = WebWindow()
    webview.create(0,0,0,800,600)
    def OnCloseEvent(context,*args,**kwargs):
        win32gui.PostQuitMessage(0)
        return True
    Wke.event.onWindowClosing(webview,OnCloseEvent,param='App Quit')
    webview.loadURL('https://www.w3school.com.cn/jsref/index.asp')
    webview.showWindow(True)
    Wke.runMessageLoop()

说明

全局接口Wke

DLL加载

目前版本采用PyWkeMiniblink包初始化时自动加载dll。

32位模式加载miniblink_4975_x32.dll,64位模式加载miniblink_4975_x64.dll。

搜索DLL所在位置的顺序:

  1. 脚本模式下python.exe所在在目录是否含有dll,PyInstaller打包模式下Package根目录否含有dll;
  2. PyWkeMiniblink包所在目录下的bin目录是否含有dll;
  3. 系统环境变量的目录下是否含有dll;

创建网页对象的方式

网页视图WebView

网页视图包括加载/渲染/设置/Js/Cookie等,但并不包括实际窗口功能。

网页窗口WebWindow

网页窗口继承自WebView,包括窗口功能。

  1. WebWindow WebWindow.create(0,x,y,h,w)由miniblink创建一个网页窗口,绘制与消息处理由miniblink内部处理;

    ​ 无需额外处理窗口消息与绘制过程。

  2. WebWindow WebWindow.build(父窗口hwnd,x,y,h,w)在父窗口内部,由miniblink创建一个网页窗口;

    ​ 需要关联处理父窗口与本窗口消息流程,主要为退出和调整大小的同步。

  3. WebView WebView.bind(父窗口hwnd,x,y,w,h)在一个已经创建的父窗口hwnd上绑定一个网页视图;

    ​ 需要处理父窗口的消息流程,以及自身的离屏绘制。

窗口消息分发

三种消息读取分发循环:Wke.runMessageLoop()、win32gui.PumpMessages()、wkePumpMessages(block)

自定义消息分发循环时可以参考wkePumpMessages的两种分发循环。

阻塞式

while True:
    res = windll.user32.GetMessageA(byref(msg), None, 0, 0)
    if  res != 0:
        windll.user32.TranslateMessage(byref(msg))
        windll.user32.DispatchMessageA(byref(msg))
    elif res == 0:
        windll.user32.TranslateMessage(byref(msg))
        windll.user32.DispatchMessageA(byref(msg))
        break
    else:
        raise RuntimeError(f"GetMessage {res}")

非阻塞式

while True:
    res = windll.user32.PeekMessageA(byref(msg), None,0, 0, 1)
    if  res != 0:
        windll.user32.TranslateMessage(byref(msg))
        windll.user32.DispatchMessageA(byref(msg))
        if msg.message in[WM_QUIT]: 
            break
        else:
            time.sleep(0.05)

窗口消息处理

当WebView/WebWindow绑定在父窗口下时,需要修改父窗口的消息处理函数,实现WebView/WebWindow子窗口的消息处理过程。

wkeWin32的HwndMsgAdapter使用自身的消息处理流程替换指定父窗口的消息处理,接受外部注册的python函数处理指定的消息。

替换后对于已经注册的消息,使用注册函数来响应,如果函数返回None,则继续调用父窗口的默认消息处理流程,若不为None则不调用;对于没注册的消息则使用父窗口的默认消息处理流程。

注册的消息响应函数可以有1~5个参数,如下:

Arg1 Arg2 Arg3 Arg4 Arg5
webview hwnd msg wParam lParam
self hwnd msg wParam lParam
hwnd msg wParam lParam
hwnd wParam lParam
wParam lParam
self
hwnd

HwndMsgAdapter的消息处理流程调用注册的消息响应函数时:

  • 参数hwnd/msg/wParam/lParam 使用父窗口的处理流程的句柄/消息/参数带入
  • 有5个参数时第一个参数名为self或webview,self则对应HwndProcAdapter类实例带入,webview对应HwndProcAdapter类实例的webview属性带入
  • 有1个参数时同上,参数名为其他时,以消息窗口句柄hwnd带入

Example:

	x,y,w,h = 0,0,640,480
    hwnd = wkeCreateWindow('Window',x,y,w,h)
    webview.build(hwnd,x,y,w,h)   

    a = HwndMsgAdapter()
    def wkeMsgProcQuit(webview,hwnd,msg,wParam,lParam):
        win32gui.PostQuitMessage(0)
        return 
    a.registerMsgProc(WM_SIZE,wkeMsgProcResize)
    a.registerMsgProc(WM_DESTROY,wkeMsgProcQuit)
    a.attach(hwnd,webview)
    webview.loadURL("http://192.168.1.1")
    ....

需要注意窗:替换消息处理函数与消息处理循环之间的穿插wke的某些窗体控制函数可能导致问题!

事件WkeEvent

Wke关于webview的事件管理是基于WebView,一个WebView对象的打开/关闭/加载/绘制等一系列事件都会触发执行其事件响应函数。

WkeEvent以【webview的id】【事件名称的id】 为二元结构,管理事件响应函数及其上下文。

注册事件处理函数onXXXX(webview,func,param)

  1. ​ 接受XXX事件处理的网页对象webview
  2. ​ XXX事件处理函数func
  3. ​ 注册前和调用后的贯穿参数param

事件处理函数func(context,*args,**kwargs)

  • ​ 经WkeEvent的翻译,传递给事件响应函数的上下文context是个字典,如下:

    ​ context = {"id":eventid,"param":param,"func":func,"webview":webview,"id":webview.cId,"event":event}

  • ​ param是注册回调函数时OnXXX(func,param)绑定的任意python object对象,func是绑定的python回调函数

  • ​ 不同的事件有特定的扩展参数,都写在kwargs中,例如Alert事件中通知消息就在kwargs["msg"]中

Example:

#//python 事件响应函数void OnAlertEvent(context:dict,kwargs={msg:str}) 
#/*typedef void(WKE_CALL_TYPE*wkeAlertBoxCallback)(wkeWebView webView, void* param, const wkeString msg);*/
# OnAlertCallback回调函数执行时包含: kwargs["msg"]
def main():
	
    Wke.setCookieAndStagePath(cookie=f'{father_folder }/build/cookie.dat',localStage=f'{father_folder }/build/LocalStage')
    webview = WebWindow()
    webview.create(0,0,0,800,600)

    def OnAlertEvent(context,*args,**kwargs):
        param = context["param"]
        print(f"{str(param)} \nargs:{pformat(args)}\nkwargs:{pformat(kwargs)}\n=======================\n")
        msg = kwargs["msg"]
        windowTitle = ""
        result  = win32gui.MessageBox(0, msg, windowTitle, win32con.MB_OK)
        return  result

    def OnCloseEvent(context,*args,**kwargs):
        win32gui.PostQuitMessage(0)
        return True

    webview.onAlertBox(OnAlertEvent,param='Alert')
    webview.onWindowClosing(OnCloseEvent,param='App Quit')
    #webview.loadURL('https://www.w3school.com.cn/tiy/t.asp?f=jsck_alert_2')
    webview.loadFile(f'{father_folder}/res/testdata/alert.html')
    
    webview.showWindow(True)
    Wke.runMessageLoop()

Webview绑定了一系列事件回调函数注册方法,和使用全局Wke.event管理器注册等价:

Wke.event.OnPaintEvent(webview,param,*args,**kwargs)
webview.OnPaintEvent(param,*args,**kwargs)

unittest/testWebViewOnEvent.py检查WkeEvent所有事件是否在WebView都有对应的绑定实现,并生成所需要的实现翻译代码。

Javascript 扩展

静态类函数:Wke.extend(func,name,param):

使用一个指定的python函数作为扩展的js函数

Example:

    webview = WebWindow()
    webview.create(0,0,0,800,600)
   
    def pyAction(**kwargs):
        es=kwargs['es']
        context =kwargs['param']
        webview = context
        arg_count=Wke.jsArgCount(es)
        val_ls=Wke.getJsArgs(es,arg_count)
        webview.runJsCode('alert("jsCallpy'+str(val_ls)+'")')
        return
    
    Wke.extend(pyAction,'jsCallpy', param=webview)

在html/js 中调用

<button onclick="jsCallpy('jsCallpy', 666)" style='margin-right: 20px;cursor: pointer;'>jsCallpy</button>

Javascript 集成

WebView/WebWindows的runJsCode/runJsFile/runJsFunc方法支持Python端在网页对象中运行js代码。

其它WkeWin32

WkeWin32包含了Win32相关下面的辅助方法:

wkeSetIcon/wkeCreateWindow/wkeCreateTransparentWindow/wkeSetWindowLongHook/wkeGetWindowLongHook 等方法;

定时类WkeTimer/截屏类WkeSnapShot

插件支持

Miniblink supports NPAPI plugins.

未验证

离屏渲染

WebView.bind(父窗口hwnd,x,y,w,h)在一个已经创建的父窗口hwnd上绑定一个网页视图,然后额外的处理父窗口的消息,以及父窗口到网页视图的绘制。

参见wkeWin32ProcMsg中WebViewWithProcHwnd和example/bindWebview.py

发布

pyinstaller

(Pyinstaller>=6.0.0 )

  • 在Pyinstaller打包 one dir(-D 目录模式)时,除可执行文件外,其余文件都将被转移到 _internal 文件夹

    即Package根目录

  • 在Pyinstaller打包 one file (-F 文件模式)时,除可执行文件外,其余文件都将被转移到一个临时文件夹

    即Package根目录

  • 在Python解释器模式下,以Lib\site-packages

    以此为Package的根目录

其他问题

Ctypes数据类型

参见prepare.py.translate()与wke.h.json

Alert/Prompt/Confirm

Minibilink支持Alert和Confirm,但是Prompt没实现。

可以使用wkeEvent的回调函数额外实现相应的GUI及其返回值控制,参见examples.

PromptBoxCallback的Py形参和返回值

正常情况下

typedef bool(WKE_CALL_TYPE*wkePromptBoxCallback)(wkeWebView webView, void* param, const wkeString msg, const wkeString defaultResult, wkeString result);
<<=>>
CFUNCTYPE(c_bool,_LRESULT,c_void_p,c_char_p,c_char_p,c_void_p)

​ 原回调函数返回值为c_bool,为保持形参形式一致,不做按引用传参数带出返回值,取消形参result,而是python的返回值。

​ 实际python回调函数返回值为Str(有字符串确定输入)/None(取消输入)

wkeGetString/wkeSetString/String/StingW

Miniblink文档中String对应utf8而StringW对应utf16

wkeEvent.py中32位下wkeGetStringW(str)运行正常,但是64位会c函数内部读异常

现在默认wkeString全部是utf8,改为wkeGetString(str),然后做binary->str的解码

wkeString的Ctypes参数类型

将只读wkeString 全翻译为c_char_p,方便ctypes自动转换字符串。

如果需要写入wkeString,就翻译为c_void_p (c_char_p自动翻译为None)

#wkeString:c_void_p,text:str
utf8 = text.encode(encoding)
l = len(utf8)
mb.wkeSetString(cast(wkeString,c_char_p),utf8,l)

wkePromptBoxCallback的最后一个参数为wkeString,需要作为传参返回,填入字符串。所以wkeString翻成c_void_p

TODO

Wke/WebView的job/request有些地方未修订验证

下载/插件/通信事件回调 暂都未验证

RunJs验证了参数功能正常,但是返回值总是None

Contact Us

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

wkeminiblink-0.1.17-py3-none-any.whl (38.4 MB view details)

Uploaded Python 3

WkeMiniblink-0.1.17-py3-none-any.whl (31.1 MB view details)

Uploaded Python 3

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page