WkeMiniblink


NameWkeMiniblink JSON
Version 0.1.17 PyPI version JSON
download
home_pageNone
SummaryA python binding of Miniblink
upload_time2025-07-09 09:27:05
maintainerNone
docs_urlNone
authorStoneFlaw
requires_pythonNone
licenseNone
keywords miniblink wke webbrowser
VCS
bugtrack_url
requirements Pywin32
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 简介



**关于PyWkeMiniblink**

PyWkeMiniblink 是 [Miniblink](https://weolar.github.io/miniblink/)的Python绑定,参考了上游项目[MBPython](https://github.com/lochen88/MBPython)。

PyWkeMiniblink: [项目地址](https://github.com/StoneFlaw/PyWkeMiniblink)  /  [在线文档](https://pywkeminiblink.readthedocs.io/zh-cn/latest/)  / [PYPI主页](https://pypi.org/project/WkeMiniblink/)

**关于Miniblink**

Miniblink 是 chromium的精简版,删除了音视频功能,原接口参见[官方接口文档](https://miniblink.net/views/doc/index.html),更完整的参见docs/source/wke.h 。



# 使用

## 安装

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



## 示例

```python
# -*- 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的两种分发循环。

阻塞式

```python
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}")
```

非阻塞式

```python
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:

```python
	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
#//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管理器注册等价:

```python
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:

```python
    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 中调用

```html
<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](mailto://wyh917@163.com)


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "WkeMiniblink",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "Miniblink Wke webbrowser",
    "author": "StoneFlaw",
    "author_email": "wyh917@163.com",
    "download_url": null,
    "platform": null,
    "description": "# \u7b80\u4ecb\r\n\r\n\r\n\r\n**\u5173\u4e8ePyWkeMiniblink**\r\n\r\nPyWkeMiniblink \u662f [Miniblink](https://weolar.github.io/miniblink/)\u7684Python\u7ed1\u5b9a\uff0c\u53c2\u8003\u4e86\u4e0a\u6e38\u9879\u76ee[MBPython](https://github.com/lochen88/MBPython)\u3002\r\n\r\nPyWkeMiniblink\uff1a [\u9879\u76ee\u5730\u5740](https://github.com/StoneFlaw/PyWkeMiniblink)  /  [\u5728\u7ebf\u6587\u6863](https://pywkeminiblink.readthedocs.io/zh-cn/latest/)  / [PYPI\u4e3b\u9875](https://pypi.org/project/WkeMiniblink/)\r\n\r\n**\u5173\u4e8eMiniblink**\r\n\r\nMiniblink \u662f chromium\u7684\u7cbe\u7b80\u7248\uff0c\u5220\u9664\u4e86\u97f3\u89c6\u9891\u529f\u80fd,\u539f\u63a5\u53e3\u53c2\u89c1[\u5b98\u65b9\u63a5\u53e3\u6587\u6863](https://miniblink.net/views/doc/index.html),\u66f4\u5b8c\u6574\u7684\u53c2\u89c1docs/source/wke.h \u3002\r\n\r\n\r\n\r\n# \u4f7f\u7528\r\n\r\n## \u5b89\u88c5\r\n\r\n```shell\r\n#\u5b89\u88c5\u4f9d\u8d56pywin32\r\npip3 install pywin32\r\n#\u5b89\u88c5\u672c\u5730\u6587\u4ef6xx\u7248\u672c\r\npip3 install WkeMiniblink-xx-py3-none-any.whl\r\n#\u4ecePYPI\u5b89\u88c5\r\npip3 install WkeMiniblink\r\n```\r\n\r\n\r\n\r\n## \u793a\u4f8b\r\n\r\n```python\r\n# -*- coding:utf-8 -*-\r\nimport os,sys,platform,time\r\nimport win32gui\r\nfrom wkeMiniblink.wke import *\r\nfrom wkeMiniblink.wkeEvent import *\r\nfrom wkeMiniblink.wkeWin32 import *\r\n\r\nif __name__=='__main__':\r\n    webview = WebWindow()\r\n    webview.create(0,0,0,800,600)\r\n    def OnCloseEvent(context,*args,**kwargs):\r\n        win32gui.PostQuitMessage(0)\r\n        return True\r\n    Wke.event.onWindowClosing(webview,OnCloseEvent,param='App Quit')\r\n    webview.loadURL('https://www.w3school.com.cn/jsref/index.asp')\r\n    webview.showWindow(True)\r\n    Wke.runMessageLoop()\r\n```\r\n\r\n# \u8bf4\u660e\r\n\r\n## \u5168\u5c40\u63a5\u53e3Wke\r\n\r\n### DLL\u52a0\u8f7d\r\n\r\n\u76ee\u524d\u7248\u672c\u91c7\u7528PyWkeMiniblink\u5305\u521d\u59cb\u5316\u65f6\u81ea\u52a8\u52a0\u8f7ddll\u3002\r\n\r\n32\u4f4d\u6a21\u5f0f\u52a0\u8f7dminiblink_4975_x32.dll,64\u4f4d\u6a21\u5f0f\u52a0\u8f7dminiblink_4975_x64.dll\u3002\r\n\r\n\u641c\u7d22DLL\u6240\u5728\u4f4d\u7f6e\u7684\u987a\u5e8f:\r\n\r\n1. \u811a\u672c\u6a21\u5f0f\u4e0bpython.exe\u6240\u5728\u5728\u76ee\u5f55\u662f\u5426\u542b\u6709dll\uff0cPyInstaller\u6253\u5305\u6a21\u5f0f\u4e0bPackage\u6839\u76ee\u5f55\u5426\u542b\u6709dll;\r\n2. PyWkeMiniblink\u5305\u6240\u5728\u76ee\u5f55\u4e0b\u7684bin\u76ee\u5f55\u662f\u5426\u542b\u6709dll;\r\n3. \u7cfb\u7edf\u73af\u5883\u53d8\u91cf\u7684\u76ee\u5f55\u4e0b\u662f\u5426\u542b\u6709dll;\r\n\r\n\r\n\r\n## \u521b\u5efa\u7f51\u9875\u5bf9\u8c61\u7684\u65b9\u5f0f\r\n\r\n### \u7f51\u9875\u89c6\u56feWebView\r\n\r\n\u7f51\u9875\u89c6\u56fe\u5305\u62ec\u52a0\u8f7d/\u6e32\u67d3/\u8bbe\u7f6e/Js/Cookie\u7b49,\u4f46\u5e76\u4e0d\u5305\u62ec\u5b9e\u9645\u7a97\u53e3\u529f\u80fd\u3002\r\n\r\n### \u7f51\u9875\u7a97\u53e3WebWindow\r\n\r\n\u7f51\u9875\u7a97\u53e3\u7ee7\u627f\u81eaWebView\uff0c\u5305\u62ec\u7a97\u53e3\u529f\u80fd\u3002\r\n\r\n1. WebWindow\r\n    \tWebWindow.create(0,x,y,h,w)\u7531miniblink\u521b\u5efa\u4e00\u4e2a\u7f51\u9875\u7a97\u53e3\uff0c\u7ed8\u5236\u4e0e\u6d88\u606f\u5904\u7406\u7531miniblink\u5185\u90e8\u5904\u7406\uff1b\r\n\r\n    \u200b\t\u65e0\u9700\u989d\u5916\u5904\u7406\u7a97\u53e3\u6d88\u606f\u4e0e\u7ed8\u5236\u8fc7\u7a0b\u3002\r\n\r\n2. WebWindow\r\n    \tWebWindow.build(\u7236\u7a97\u53e3hwnd,x,y,h,w)\u5728\u7236\u7a97\u53e3\u5185\u90e8,\u7531miniblink\u521b\u5efa\u4e00\u4e2a\u7f51\u9875\u7a97\u53e3\uff1b\r\n\r\n    \u200b\t\u9700\u8981\u5173\u8054\u5904\u7406\u7236\u7a97\u53e3\u4e0e\u672c\u7a97\u53e3\u6d88\u606f\u6d41\u7a0b\uff0c\u4e3b\u8981\u4e3a\u9000\u51fa\u548c\u8c03\u6574\u5927\u5c0f\u7684\u540c\u6b65\u3002\r\n\r\n3. WebView\r\n    \tWebView.bind(\u7236\u7a97\u53e3hwnd,x,y,w,h)\u5728\u4e00\u4e2a\u5df2\u7ecf\u521b\u5efa\u7684\u7236\u7a97\u53e3hwnd\u4e0a\u7ed1\u5b9a\u4e00\u4e2a\u7f51\u9875\u89c6\u56fe\uff1b\r\n\r\n    \u200b\t\u9700\u8981\u5904\u7406\u7236\u7a97\u53e3\u7684\u6d88\u606f\u6d41\u7a0b\uff0c\u4ee5\u53ca\u81ea\u8eab\u7684\u79bb\u5c4f\u7ed8\u5236\u3002\r\n\r\n    \r\n\r\n## \u7a97\u53e3\u6d88\u606f\u5206\u53d1\r\n\r\n\u4e09\u79cd\u6d88\u606f\u8bfb\u53d6\u5206\u53d1\u5faa\u73af\uff1aWke.runMessageLoop()\u3001win32gui.PumpMessages()\u3001wkePumpMessages(block)\t\r\n\r\n\u81ea\u5b9a\u4e49\u6d88\u606f\u5206\u53d1\u5faa\u73af\u65f6\u53ef\u4ee5\u53c2\u8003wkePumpMessages\u7684\u4e24\u79cd\u5206\u53d1\u5faa\u73af\u3002\r\n\r\n\u963b\u585e\u5f0f\r\n\r\n```python\r\nwhile True:\r\n    res = windll.user32.GetMessageA(byref(msg), None, 0, 0)\r\n    if  res != 0:\r\n        windll.user32.TranslateMessage(byref(msg))\r\n        windll.user32.DispatchMessageA(byref(msg))\r\n    elif res == 0:\r\n        windll.user32.TranslateMessage(byref(msg))\r\n        windll.user32.DispatchMessageA(byref(msg))\r\n        break\r\n    else:\r\n        raise RuntimeError(f\"GetMessage {res}\")\r\n```\r\n\r\n\u975e\u963b\u585e\u5f0f\r\n\r\n```python\r\nwhile True:\r\n    res = windll.user32.PeekMessageA(byref(msg), None,0, 0, 1)\r\n    if  res != 0:\r\n        windll.user32.TranslateMessage(byref(msg))\r\n        windll.user32.DispatchMessageA(byref(msg))\r\n        if msg.message in[WM_QUIT]: \r\n            break\r\n        else:\r\n            time.sleep(0.05)\r\n```\r\n\r\n\r\n\r\n## \u7a97\u53e3\u6d88\u606f\u5904\u7406\r\n\r\n*\u5f53WebView/WebWindow\u7ed1\u5b9a\u5728\u7236\u7a97\u53e3\u4e0b\u65f6,\u9700\u8981\u4fee\u6539\u7236\u7a97\u53e3\u7684\u6d88\u606f\u5904\u7406\u51fd\u6570,\u5b9e\u73b0WebView/WebWindow\u5b50\u7a97\u53e3\u7684\u6d88\u606f\u5904\u7406\u8fc7\u7a0b\u3002*\r\n\r\nwkeWin32\u7684**HwndMsgAdapter**\u4f7f\u7528\u81ea\u8eab\u7684\u6d88\u606f\u5904\u7406\u6d41\u7a0b\u66ff\u6362\u6307\u5b9a\u7236\u7a97\u53e3\u7684\u6d88\u606f\u5904\u7406\uff0c\u63a5\u53d7\u5916\u90e8\u6ce8\u518c\u7684python\u51fd\u6570\u5904\u7406\u6307\u5b9a\u7684\u6d88\u606f\u3002\r\n\r\n\u66ff\u6362\u540e\u5bf9\u4e8e\u5df2\u7ecf\u6ce8\u518c\u7684\u6d88\u606f,\u4f7f\u7528\u6ce8\u518c\u51fd\u6570\u6765\u54cd\u5e94,\u5982\u679c\u51fd\u6570\u8fd4\u56deNone,\u5219\u7ee7\u7eed\u8c03\u7528\u7236\u7a97\u53e3\u7684\u9ed8\u8ba4\u6d88\u606f\u5904\u7406\u6d41\u7a0b,\u82e5\u4e0d\u4e3aNone\u5219\u4e0d\u8c03\u7528;\u5bf9\u4e8e\u6ca1\u6ce8\u518c\u7684\u6d88\u606f\u5219\u4f7f\u7528\u7236\u7a97\u53e3\u7684\u9ed8\u8ba4\u6d88\u606f\u5904\u7406\u6d41\u7a0b\u3002\r\n\r\n\u6ce8\u518c\u7684\u6d88\u606f\u54cd\u5e94\u51fd\u6570\u53ef\u4ee5\u67091~5\u4e2a\u53c2\u6570,\u5982\u4e0b:\r\n\r\n|  Arg1   |  Arg2  |  Arg3  |  Arg4  |  Arg5  |\r\n| :-----: | :----: | :----: | :----: | :----: |\r\n| webview |  hwnd  |  msg   | wParam | lParam |\r\n|  self   |  hwnd  |  msg   | wParam | lParam |\r\n|  hwnd   |  msg   | wParam | lParam |        |\r\n|  hwnd   | wParam | lParam |        |        |\r\n| wParam  | lParam |        |        |        |\r\n|  self   |        |        |        |        |\r\n|  hwnd   |        |        |        |        |\r\n\r\nHwndMsgAdapter\u7684\u6d88\u606f\u5904\u7406\u6d41\u7a0b\u8c03\u7528\u6ce8\u518c\u7684\u6d88\u606f\u54cd\u5e94\u51fd\u6570\u65f6:\r\n\r\n- \u53c2\u6570hwnd/msg/wParam/lParam \u4f7f\u7528\u7236\u7a97\u53e3\u7684\u5904\u7406\u6d41\u7a0b\u7684\u53e5\u67c4/\u6d88\u606f/\u53c2\u6570\u5e26\u5165\r\n- \u67095\u4e2a\u53c2\u6570\u65f6\u7b2c\u4e00\u4e2a\u53c2\u6570\u540d\u4e3aself\u6216webview,self\u5219\u5bf9\u5e94HwndProcAdapter\u7c7b\u5b9e\u4f8b\u5e26\u5165,webview\u5bf9\u5e94HwndProcAdapter\u7c7b\u5b9e\u4f8b\u7684webview\u5c5e\u6027\u5e26\u5165\r\n- \u67091\u4e2a\u53c2\u6570\u65f6\u540c\u4e0a,\u53c2\u6570\u540d\u4e3a\u5176\u4ed6\u65f6,\u4ee5\u6d88\u606f\u7a97\u53e3\u53e5\u67c4hwnd\u5e26\u5165\r\n\r\nExample:\r\n\r\n```python\r\n\tx,y,w,h = 0,0,640,480\r\n    hwnd = wkeCreateWindow('Window',x,y,w,h)\r\n    webview.build(hwnd,x,y,w,h)   \r\n\r\n    a = HwndMsgAdapter()\r\n    def wkeMsgProcQuit(webview,hwnd,msg,wParam,lParam):\r\n        win32gui.PostQuitMessage(0)\r\n        return \r\n    a.registerMsgProc(WM_SIZE,wkeMsgProcResize)\r\n    a.registerMsgProc(WM_DESTROY,wkeMsgProcQuit)\r\n    a.attach(hwnd,webview)\r\n    webview.loadURL(\"http://192.168.1.1\")\r\n    ....\r\n```\r\n\r\n***\u9700\u8981\u6ce8\u610f\u7a97\uff1a\u66ff\u6362\u6d88\u606f\u5904\u7406\u51fd\u6570\u4e0e\u6d88\u606f\u5904\u7406\u5faa\u73af\u4e4b\u95f4\u7684\u7a7f\u63d2wke\u7684\u67d0\u4e9b\u7a97\u4f53\u63a7\u5236\u51fd\u6570\u53ef\u80fd\u5bfc\u81f4\u95ee\u9898\uff01***\r\n\r\n## \u4e8b\u4ef6WkeEvent\r\n\r\n*Wke\u5173\u4e8ewebview\u7684\u4e8b\u4ef6\u7ba1\u7406\u662f\u57fa\u4e8eWebView\uff0c\u4e00\u4e2aWebView\u5bf9\u8c61\u7684\u6253\u5f00/\u5173\u95ed/\u52a0\u8f7d/\u7ed8\u5236\u7b49\u4e00\u7cfb\u5217\u4e8b\u4ef6\u90fd\u4f1a\u89e6\u53d1\u6267\u884c\u5176\u4e8b\u4ef6\u54cd\u5e94\u51fd\u6570\u3002*\r\n\r\n**WkeEvent\u4ee5\u3010webview\u7684id\u3011\u3010\u4e8b\u4ef6\u540d\u79f0\u7684id\u3011 \u4e3a\u4e8c\u5143\u7ed3\u6784\uff0c\u7ba1\u7406\u4e8b\u4ef6\u54cd\u5e94\u51fd\u6570\u53ca\u5176\u4e0a\u4e0b\u6587\u3002**\r\n\r\n### \u6ce8\u518c\u4e8b\u4ef6\u5904\u7406\u51fd\u6570onXXXX(webview,func,param) \r\n\r\n1. \u200b\t\t\u63a5\u53d7XXX\u4e8b\u4ef6\u5904\u7406\u7684\u7f51\u9875\u5bf9\u8c61webview\r\n2. \u200b\t\tXXX\u4e8b\u4ef6\u5904\u7406\u51fd\u6570func\r\n3. \u200b\t\t\u6ce8\u518c\u524d\u548c\u8c03\u7528\u540e\u7684\u8d2f\u7a7f\u53c2\u6570param\t\t\r\n\r\n###  \u4e8b\u4ef6\u5904\u7406\u51fd\u6570func(context,*args,**kwargs)\r\n\r\n- \u200b\t\t\u7ecfWkeEvent\u7684\u7ffb\u8bd1\uff0c\u4f20\u9012\u7ed9\u4e8b\u4ef6\u54cd\u5e94\u51fd\u6570\u7684\u4e0a\u4e0b\u6587context\u662f\u4e2a\u5b57\u5178\uff0c\u5982\u4e0b\uff1a\r\n\r\n    \u200b\t\tcontext = {\"id\":eventid,\"param\":param,\"func\":func,\"webview\":webview,\"id\":webview.cId,\"event\":event}\r\n\r\n- \u200b\t\tparam\u662f\u6ce8\u518c\u56de\u8c03\u51fd\u6570\u65f6OnXXX(func,param)\u7ed1\u5b9a\u7684\u4efb\u610fpython object\u5bf9\u8c61\uff0cfunc\u662f\u7ed1\u5b9a\u7684python\u56de\u8c03\u51fd\u6570\r\n\r\n- \u200b\t\t\u4e0d\u540c\u7684\u4e8b\u4ef6\u6709\u7279\u5b9a\u7684\u6269\u5c55\u53c2\u6570\uff0c\u90fd\u5199\u5728kwargs\u4e2d\uff0c\u4f8b\u5982Alert\u4e8b\u4ef6\u4e2d\u901a\u77e5\u6d88\u606f\u5c31\u5728kwargs[\"msg\"]\u4e2d\r\n\r\n\r\nExample:\r\n\r\n```python\r\n#//python \u4e8b\u4ef6\u54cd\u5e94\u51fd\u6570void OnAlertEvent(context:dict,kwargs={msg:str}) \r\n#/*typedef void(WKE_CALL_TYPE*wkeAlertBoxCallback)(wkeWebView webView, void* param, const wkeString msg);*/\r\n# OnAlertCallback\u56de\u8c03\u51fd\u6570\u6267\u884c\u65f6\u5305\u542b: kwargs[\"msg\"]\r\ndef main():\r\n\t\r\n    Wke.setCookieAndStagePath(cookie=f'{father_folder }/build/cookie.dat',localStage=f'{father_folder }/build/LocalStage')\r\n    webview = WebWindow()\r\n    webview.create(0,0,0,800,600)\r\n\r\n    def OnAlertEvent(context,*args,**kwargs):\r\n        param = context[\"param\"]\r\n        print(f\"{str(param)} \\nargs:{pformat(args)}\\nkwargs:{pformat(kwargs)}\\n=======================\\n\")\r\n        msg = kwargs[\"msg\"]\r\n        windowTitle = \"\"\r\n        result  = win32gui.MessageBox(0, msg, windowTitle, win32con.MB_OK)\r\n        return  result\r\n\r\n    def OnCloseEvent(context,*args,**kwargs):\r\n        win32gui.PostQuitMessage(0)\r\n        return True\r\n\r\n    webview.onAlertBox(OnAlertEvent,param='Alert')\r\n    webview.onWindowClosing(OnCloseEvent,param='App Quit')\r\n    #webview.loadURL('https://www.w3school.com.cn/tiy/t.asp?f=jsck_alert_2')\r\n    webview.loadFile(f'{father_folder}/res/testdata/alert.html')\r\n    \r\n    webview.showWindow(True)\r\n    Wke.runMessageLoop()\r\n```\r\n\r\nWebview\u7ed1\u5b9a\u4e86\u4e00\u7cfb\u5217\u4e8b\u4ef6\u56de\u8c03\u51fd\u6570\u6ce8\u518c\u65b9\u6cd5\uff0c\u548c\u4f7f\u7528\u5168\u5c40Wke.event\u7ba1\u7406\u5668\u6ce8\u518c\u7b49\u4ef7:\r\n\r\n```python\r\nWke.event.OnPaintEvent(webview,param,*args,**kwargs)\r\nwebview.OnPaintEvent(param,*args,**kwargs)\r\n```\r\n\r\nunittest/testWebViewOnEvent.py\u68c0\u67e5WkeEvent\u6240\u6709\u4e8b\u4ef6\u662f\u5426\u5728WebView\u90fd\u6709\u5bf9\u5e94\u7684\u7ed1\u5b9a\u5b9e\u73b0\uff0c\u5e76\u751f\u6210\u6240\u9700\u8981\u7684\u5b9e\u73b0\u7ffb\u8bd1\u4ee3\u7801\u3002\r\n\r\n### Javascript \u6269\u5c55\r\n\r\n\u9759\u6001\u7c7b\u51fd\u6570:Wke.extend(func,name,param):\r\n\r\n\u4f7f\u7528\u4e00\u4e2a\u6307\u5b9a\u7684python\u51fd\u6570\u4f5c\u4e3a\u6269\u5c55\u7684js\u51fd\u6570\r\n\r\nExample:\r\n\r\n```python\r\n    webview = WebWindow()\r\n    webview.create(0,0,0,800,600)\r\n   \r\n    def pyAction(**kwargs):\r\n        es=kwargs['es']\r\n        context =kwargs['param']\r\n        webview = context\r\n        arg_count=Wke.jsArgCount(es)\r\n        val_ls=Wke.getJsArgs(es,arg_count)\r\n        webview.runJsCode('alert(\"jsCallpy'+str(val_ls)+'\")')\r\n        return\r\n    \r\n    Wke.extend(pyAction,'jsCallpy', param=webview)\r\n```\r\n\r\n \u5728html/js \u4e2d\u8c03\u7528\r\n\r\n```html\r\n<button onclick=\"jsCallpy('jsCallpy', 666)\" style='margin-right: 20px;cursor: pointer;'>jsCallpy</button>\r\n```\r\n\r\n## Javascript \u96c6\u6210\r\n\r\nWebView/WebWindows\u7684runJsCode/runJsFile/runJsFunc\u65b9\u6cd5\u652f\u6301Python\u7aef\u5728\u7f51\u9875\u5bf9\u8c61\u4e2d\u8fd0\u884cjs\u4ee3\u7801\u3002\r\n\r\n## \u5176\u5b83WkeWin32\r\n\r\nWkeWin32\u5305\u542b\u4e86Win32\u76f8\u5173\u4e0b\u9762\u7684\u8f85\u52a9\u65b9\u6cd5\uff1a\r\n\r\nwkeSetIcon/wkeCreateWindow/wkeCreateTransparentWindow/wkeSetWindowLongHook/wkeGetWindowLongHook \u7b49\u65b9\u6cd5;\r\n\r\n\u5b9a\u65f6\u7c7bWkeTimer/\u622a\u5c4f\u7c7bWkeSnapShot\r\n\r\n# \u63d2\u4ef6\u652f\u6301\r\n\r\nMiniblink supports NPAPI plugins.\r\n\r\n\u672a\u9a8c\u8bc1\r\n\r\n# \u79bb\u5c4f\u6e32\u67d3\r\n\r\nWebView.bind(\u7236\u7a97\u53e3hwnd,x,y,w,h)\u5728\u4e00\u4e2a\u5df2\u7ecf\u521b\u5efa\u7684\u7236\u7a97\u53e3hwnd\u4e0a\u7ed1\u5b9a\u4e00\u4e2a\u7f51\u9875\u89c6\u56fe\uff0c\u7136\u540e\u989d\u5916\u7684\u5904\u7406\u7236\u7a97\u53e3\u7684\u6d88\u606f\uff0c\u4ee5\u53ca\u7236\u7a97\u53e3\u5230\u7f51\u9875\u89c6\u56fe\u7684\u7ed8\u5236\u3002\r\n\r\n\u53c2\u89c1wkeWin32ProcMsg\u4e2dWebViewWithProcHwnd\u548cexample/bindWebview.py\r\n\r\n\r\n\r\n# \u53d1\u5e03\r\n\r\n## pyinstaller\r\n\r\n(Pyinstaller>=6.0.0 )\r\n\r\n- \u5728Pyinstaller\u6253\u5305 one dir\uff08-D \u76ee\u5f55\u6a21\u5f0f\uff09\u65f6\uff0c\u9664\u53ef\u6267\u884c\u6587\u4ef6\u5916\uff0c\u5176\u4f59\u6587\u4ef6\u90fd\u5c06\u88ab\u8f6c\u79fb\u5230 _internal \u6587\u4ef6\u5939\r\n\r\n    \u5373Package\u6839\u76ee\u5f55\r\n\r\n- \u5728Pyinstaller\u6253\u5305 one file \uff08-F \u6587\u4ef6\u6a21\u5f0f\uff09\u65f6\uff0c\u9664\u53ef\u6267\u884c\u6587\u4ef6\u5916\uff0c\u5176\u4f59\u6587\u4ef6\u90fd\u5c06\u88ab\u8f6c\u79fb\u5230\u4e00\u4e2a\u4e34\u65f6\u6587\u4ef6\u5939\r\n\r\n    \u5373Package\u6839\u76ee\u5f55\r\n\r\n- \u5728Python\u89e3\u91ca\u5668\u6a21\u5f0f\u4e0b,\u4ee5Lib\\site-packages\r\n\r\n    \u4ee5\u6b64\u4e3aPackage\u7684\u6839\u76ee\u5f55\r\n\r\n\r\n\r\n# \u5176\u4ed6\u95ee\u9898\r\n\r\n## Ctypes\u6570\u636e\u7c7b\u578b\r\n\r\n\u53c2\u89c1prepare.py.translate()\u4e0ewke.h.json\r\n\r\n## Alert/Prompt/Confirm\r\n\r\nMinibilink\u652f\u6301Alert\u548cConfirm,\u4f46\u662fPrompt\u6ca1\u5b9e\u73b0\u3002\r\n\r\n\u53ef\u4ee5\u4f7f\u7528wkeEvent\u7684\u56de\u8c03\u51fd\u6570\u989d\u5916\u5b9e\u73b0\u76f8\u5e94\u7684GUI\u53ca\u5176\u8fd4\u56de\u503c\u63a7\u5236\uff0c\u53c2\u89c1examples.\r\n\r\n## PromptBoxCallback\u7684Py\u5f62\u53c2\u548c\u8fd4\u56de\u503c\r\n\r\n\u6b63\u5e38\u60c5\u51b5\u4e0b\r\n\r\n```\r\ntypedef bool(WKE_CALL_TYPE*wkePromptBoxCallback)(wkeWebView webView, void* param, const wkeString msg, const wkeString defaultResult, wkeString result);\r\n<<=>>\r\nCFUNCTYPE(c_bool,_LRESULT,c_void_p,c_char_p,c_char_p,c_void_p)\r\n```\r\n\r\n\u200b      \u539f\u56de\u8c03\u51fd\u6570\u8fd4\u56de\u503c\u4e3ac_bool,\u4e3a\u4fdd\u6301\u5f62\u53c2\u5f62\u5f0f\u4e00\u81f4,\u4e0d\u505a\u6309\u5f15\u7528\u4f20\u53c2\u6570\u5e26\u51fa\u8fd4\u56de\u503c,\u53d6\u6d88\u5f62\u53c2result,\u800c\u662fpython\u7684\u8fd4\u56de\u503c\u3002\r\n\r\n\u200b      \u5b9e\u9645python\u56de\u8c03\u51fd\u6570\u8fd4\u56de\u503c\u4e3aStr(\u6709\u5b57\u7b26\u4e32\u786e\u5b9a\u8f93\u5165)/None(\u53d6\u6d88\u8f93\u5165)\r\n\r\n## wkeGetString/wkeSetString/String/StingW\r\n\r\nMiniblink\u6587\u6863\u4e2dString\u5bf9\u5e94utf8*\u800cStringW\u5bf9\u5e94utf16*\r\n\r\nwkeEvent.py\u4e2d32\u4f4d\u4e0bwkeGetStringW(str)\u8fd0\u884c\u6b63\u5e38,\u4f46\u662f64\u4f4d\u4f1ac\u51fd\u6570\u5185\u90e8\u8bfb\u5f02\u5e38\r\n\r\n\u73b0\u5728\u9ed8\u8ba4wkeString\u5168\u90e8\u662futf8\uff0c\u6539\u4e3awkeGetString(str),\u7136\u540e\u505abinary->str\u7684\u89e3\u7801\r\n\r\n## wkeString\u7684Ctypes\u53c2\u6570\u7c7b\u578b\r\n\r\n\u5c06\u53ea\u8bfbwkeString \u5168\u7ffb\u8bd1\u4e3ac_char_p,\u65b9\u4fbfctypes\u81ea\u52a8\u8f6c\u6362\u5b57\u7b26\u4e32\u3002\r\n\r\n\u5982\u679c\u9700\u8981\u5199\u5165wkeString,\u5c31\u7ffb\u8bd1\u4e3ac_void_p (c_char_p\u81ea\u52a8\u7ffb\u8bd1\u4e3aNone)\r\n\r\n```\r\n#wkeString:c_void_p,text:str\r\nutf8 = text.encode(encoding)\r\nl = len(utf8)\r\nmb.wkeSetString(cast(wkeString,c_char_p),utf8,l)\r\n```\r\n\r\nwkePromptBoxCallback\u7684\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u4e3awkeString,\u9700\u8981\u4f5c\u4e3a\u4f20\u53c2\u8fd4\u56de,\u586b\u5165\u5b57\u7b26\u4e32\u3002\u6240\u4ee5wkeString\u7ffb\u6210c_void_p\r\n\r\n\r\n\r\n# TODO\r\n\r\nWke/WebView\u7684job/request\u6709\u4e9b\u5730\u65b9\u672a\u4fee\u8ba2\u9a8c\u8bc1\r\n\r\n\u4e0b\u8f7d/\u63d2\u4ef6/\u901a\u4fe1\u4e8b\u4ef6\u56de\u8c03 \u6682\u90fd\u672a\u9a8c\u8bc1\r\n\r\nRunJs\u9a8c\u8bc1\u4e86\u53c2\u6570\u529f\u80fd\u6b63\u5e38,\u4f46\u662f\u8fd4\u56de\u503c\u603b\u662fNone\r\n\r\n\r\n\r\n\r\n# [Contact Us](mailto://wyh917@163.com)\r\n\r\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "A python binding of Miniblink",
    "version": "0.1.17",
    "project_urls": {
        "Bug Tracker": "https://github.com/StoneFlaw/PyWkeMiniblink/issues",
        "Documentation": "https://pywkeminiblink.readthedocs.io/zh-cn/latest/",
        "Homepage": "https://pypi.org/project/WkeMiniblink/",
        "Source Code": "https://github.com/StoneFlaw/PyWkeMiniblink"
    },
    "split_keywords": [
        "miniblink",
        "wke",
        "webbrowser"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "ae316eeb81a346511dd14d28f1dc51211cf7a585ed01c5a9ae2c16d095e603e0",
                "md5": "4eeb26c4e7e565efbc8d9a251c44bcd9",
                "sha256": "6c9b8c1488fe850b142f6d8871473a729fa8dde5e979577445e121324fa998f8"
            },
            "downloads": -1,
            "filename": "WkeMiniblink-0.1.17-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4eeb26c4e7e565efbc8d9a251c44bcd9",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 31144650,
            "upload_time": "2025-07-09T09:27:05",
            "upload_time_iso_8601": "2025-07-09T09:27:05.564133Z",
            "url": "https://files.pythonhosted.org/packages/ae/31/6eeb81a346511dd14d28f1dc51211cf7a585ed01c5a9ae2c16d095e603e0/WkeMiniblink-0.1.17-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-09 09:27:05",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "StoneFlaw",
    "github_project": "PyWkeMiniblink",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "Pywin32",
            "specs": []
        }
    ],
    "lcname": "wkeminiblink"
}
        
Elapsed time: 0.42192s