chrome PPAPI 开发(一)

Pywinauto+某应用程序(学习至第9讲)--受阻 受阻点使用pywinauto,chrome legacy window下控件无法定位。因其下为非标准控件,故转战pyautogui。1、选择应用程序窗口中,针对窗口类型/窗口标题操作,容易报错。 目前可选项只有: 使用正确的窗口标题也无法做到2、窗口最小化时,无法进行恢复正常大小操作;无法进行指定应用程序打开操作;1、在线安装 2、离线安装 2、自动化的切入点–后端技术、程序个数 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qdJntpUS-1656467044603)(C 阅读详情

    最近遇到一个需要在chrome49版本的浏览器上支持老版本 ActiveX 插件的问题。
    在网上翻来覆去找资料,最终的矛头都指向chrome的 PPAPI 开发,于是下载了一个ppapi的资源包。大家可从“我的资源”去下载。
    下面说一下如何开发一个可调试的ppapi 例子的过程。

    1. 环境准备
    安装Visual Studio。我的是VS2013。
    2. 解压ppapi 资源包到某个目录,例如 D://APIs/BHO-master/
    3. 在VS2013中新建一个最简单的 Win32 的DLL(C++ 工程),去掉StdAfx.h 和StdAfx.cpp 文件。
    4. 在工程主文件中输入代码。

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <tchar.h>

#include "Win32Project1.h"

#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_module.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppb.h"
#include "ppapi/c/ppb_core.h"
#include "ppapi/c/ppb_graphics_2d.h"
#include "ppapi/c/ppb_image_data.h"
#include "ppapi/c/ppb_instance.h"
#include "ppapi/c/ppb_view.h"
#include "ppapi/c/ppp.h"
#include "ppapi/c/ppp_instance.h"
#include "ppapi/c/ppb_input_event.h"
#include "ppapi/c/ppp_input_event.h"

#include "ppapi/c/ppb_var.h"
#include "ppapi/c/ppb_var_dictionary.h"
#include "ppapi/c/ppb_var_array.h"
#include "ppapi/c/ppb_messaging.h"
#include "ppapi/c/ppp_messaging.h"
#include <stdlib.h>

PPB_GetInterface g_get_browser_interface = NULL;

const PPB_Core* g_core_interface;
const PPB_Graphics2D* g_graphics_2d_interface;
const PPB_ImageData* g_image_data_interface;
const PPB_Instance* g_instance_interface;
const PPB_View* g_view_interface;
const PPB_InputEvent *g_input_interface;
const PPB_MouseInputEvent *g_mouse_interface;

const PPB_Var* g_var_interface;
const PPB_VarDictionary *g_dictionary_interface;
const PPB_VarArray *g_array_interface;
const PPB_Messaging *g_message_interface;

/******foruok: create native window begin******/

static HWND g_child_window = NULL;
struct CreateChildWinParam {
    struct PP_Rect r;
    HWND hWndParent;
};
HANDLE g_hThread = NULL;
DWORD g_dwThreadId = 0;
BOOL g_bInProcess = 0;

static LRESULT CALLBACK VideoWindowProc(HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
    )
{
    PAINTSTRUCT ps;
    HDC hdc;
    RECT r;
    TCHAR textIn[] = _T("Child Window(in-process)");
    TCHAR text[] = _T("Child Window(out-process)");
    switch (uMsg)
    {
    case WM_PAINT:
        GetClientRect(hwnd, &r);
        hdc = BeginPaint(hwnd, &ps);
        SetTextColor(hdc, RGB(0, 200, 0));
        FillRect(hdc, &r, (HBRUSH)GetStockObject(GRAY_BRUSH));
        if (g_bInProcess)
        {
            TextOut(hdc, 10, 50, textIn, ARRAYSIZE(textIn) - 1);
        }
        else
        {
            TextOut(hdc, 10, 50, text, ARRAYSIZE(text) - 1);
        }
        EndPaint(hwnd, &ps);
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}


static void RegisterVideoWindowClass()
{
    WNDCLASSEX wcex = {
        /* cbSize = */ sizeof(WNDCLASSEX),
        /* style = */ CS_HREDRAW | CS_VREDRAW,
        /* lpfnWndProc = */ VideoWindowProc,
        /* cbClsExtra = */ 0,
        /* cbWndExtra = */ 0,
        /* hInstance = */ GetModuleHandle(NULL),
        /* hIcon = */ NULL,
        /* hCursor = */ LoadCursor(NULL, IDC_ARROW),
        /* hbrBackground = */ 0,
        /* lpszMenuName = */ NULL,
        /* lpszClassName = */ _T("_ChildWindowClass"),
        /* hIconSm = */ NULL,
    };
    RegisterClassEx(&wcex);
}

DWORD WINAPI ThreadProc(LPVOID lpParam)
{
    MSG msg;

    struct CreateChildWinParam *para = (struct CreateChildWinParam *)lpParam;

    TCHAR szLog[256] = { 0 };
    g_child_window = CreateWindowEx(0, _T("_ChildWindowClass"), _T("ChildWindow"),
        para->hWndParent == NULL ? (WS_OVERLAPPEDWINDOW | WS_VISIBLE) : (WS_CHILD | WS_VISIBLE | WS_DISABLED),
        para->r.point.x, para->r.point.y, para->r.size.width, para->r.size.height,
        para->hWndParent, NULL, GetModuleHandle(NULL), NULL);
    _stprintf_s(szLog, 256, _T("create child window(standalone msg loop) at (%d, %d) child = 0x%08x\r\n"),
        para->r.point.x, para->r.point.y,
        g_child_window);
    OutputDebugString(szLog);

    BOOL fGotMessage;
    while ((fGotMessage = GetMessage(&msg, (HWND)NULL, 0, 0)) != 0 && fGotMessage != -1)
    {
        TranslateMessage(&msg);
        if (msg.message == WM_USER && msg.hwnd == NULL)
        {
            OutputDebugString(_T("child window message loop quit\r\n"));
            g_dwThreadId = 0;
            g_hThread = NULL;
            g_child_window = NULL;
            return 0;
        }
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

void CreateChildWindowOnMainThread(void *param, int32_t result)
{
    struct CreateChildWinParam *p = (struct CreateChildWinParam *)param;
    g_child_window = CreateWindowEx(0, _T("_ChildWindowClass"), _T("ChildWindow"),
        WS_CHILD | WS_VISIBLE,
        p->r.point.x, p->r.point.y, p->r.size.width, p->r.size.height,
        p->hWndParent, NULL, GetModuleHandle(NULL), NULL);
    TCHAR szLog[256] = { 0 };
    _stprintf_s(szLog, 256, _T("create child window(in-process) at (%d, %d) child = 0x%08x\r\n"),
        p->r.point.x, p->r.point.y,
        g_child_window);
    OutputDebugString(szLog);
    ShowWindow(g_child_window, SW_SHOW);
    UpdateWindow(g_child_window);
}

void CreateChildWindow(struct PP_Rect *r)
{
    HWND hwnd = FindWindowEx(NULL, NULL, _T("CefBrowserWindow"), NULL);
    HWND hwndWeb = FindWindowEx(hwnd, NULL, _T("Chrome_WidgetWin_0"), NULL);;
    /*if (hwndWeb)
    {
    hwndWeb = FindWindowEx(hwndWeb, NULL, _T("Chrome_RenderWidgetHostHWND"), NULL); //web contents
    }*/
    if (hwndWeb != NULL)OutputDebugString(_T("Got Chrome_RenderWidgetHostHWND\r\n"));
    DWORD pluginPid = GetCurrentProcessId();
    DWORD browserPid = 0;
    GetWindowThreadProcessId(hwnd, &browserPid);
    TCHAR szLog[256] = { 0 };
    _stprintf_s(szLog, 256, _T("Browser pid - %d, plugin pid - %d, brower hwnd - 0x%08x, webpage hwnd - 0x%08x\r\n"),
        browserPid, pluginPid, hwnd, hwndWeb);
    OutputDebugString(szLog);
    struct CreateChildWinParam *para = (CreateChildWinParam *)(struct PP_Rect *)malloc(sizeof(struct CreateChildWinParam));
    para->r = *r;
    para->hWndParent = hwndWeb;

    if (browserPid == pluginPid)
    {
        g_bInProcess = TRUE;
        g_core_interface->CallOnMainThread(0, PP_MakeCompletionCallback(CreateChildWindowOnMainThread, para), 0);
    }
    else
    {
        g_bInProcess = FALSE;
        g_hThread = CreateThread(NULL, 0, ThreadProc, para, 0, &g_dwThreadId);
        if (g_hThread != NULL)
        {
            OutputDebugString(_T("Launch child window thread.\r\n"));
        }
        else
        {
            OutputDebugString(_T("Launch child window thread FAILED!\r\n"));
        }
    }
}

/* PPP_Instance implementation -----------------------------------------------*/

struct InstanceInfo {
    PP_Instance pp_instance;
    struct PP_Size last_size;
    PP_Resource graphics;

    struct InstanceInfo* next;
};

/** Linked list of all live instances. */
struct InstanceInfo* all_instances = NULL;

/** Returns a refed resource corresponding to the created graphics 2d. */
PP_Resource MakeAndBindGraphics2D(PP_Instance instance,
    const struct PP_Size* size) {
    PP_Resource graphics;

    graphics = g_graphics_2d_interface->Create(instance, size, PP_FALSE);
    if (!graphics)
        return 0;

    if (!g_instance_interface->BindGraphics(instance, graphics)) {
        g_core_interface->ReleaseResource(graphics);
        return 0;
    }
    return graphics;
}

void FlushCompletionCallback(void* user_data, int32_t result) {
    /* Don't need to do anything here. */
}

unsigned int g_colors[4] = { 0xFF888888, 0xFFFF00FF, 0xFF00FFFF, 0xFFEA00FF };
unsigned int g_color_index = 0;

void Repaint(struct InstanceInfo* instance, const struct PP_Size* size) {
    PP_Resource image;
    struct PP_ImageDataDesc image_desc;
    uint32_t* image_data;
    int num_words, i;

    /* Ensure the graphics 2d is ready. */
    if (!instance->graphics) {
        instance->graphics = MakeAndBindGraphics2D(instance->pp_instance, size);
        if (!instance->graphics)
            return;
    }

    /* Create image data to paint into. */
    image = g_image_data_interface->Create(
        instance->pp_instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, PP_TRUE);
    if (!image)
        return;
    g_image_data_interface->Describe(image, &image_desc);

    /* Fill the image with blue. */
    image_data = (uint32_t*)g_image_data_interface->Map(image);
    if (!image_data) {
        g_core_interface->ReleaseResource(image);
        return;
    }
    num_words = image_desc.stride * size->height / 4;

    g_color_index++;
    if (g_color_index >= sizeof(g_colors) / sizeof(g_colors[0])) g_color_index = 0;

    for (i = 0; i < num_words; i++)
        image_data[i] = g_colors[g_color_index];

    /* Paint image to graphics 2d. */
    g_graphics_2d_interface->ReplaceContents(instance->graphics, image);
    g_graphics_2d_interface->Flush(instance->graphics,
        PP_MakeCompletionCallback(&FlushCompletionCallback, NULL));

    g_core_interface->ReleaseResource(image);
}

/** Returns the info for the given instance, or NULL if it's not found. */
struct InstanceInfo* FindInstance(PP_Instance instance) {
    struct InstanceInfo* cur = all_instances;
    while (cur) {
        if (cur->pp_instance == instance)
            return cur;
        cur = cur->next;
    }
    return NULL;
}

PP_Bool Instance_DidCreate(PP_Instance instance,
    uint32_t argc,
    const char* argn[],
    const char* argv[]) {
    struct InstanceInfo* info =
        (struct InstanceInfo*)malloc(sizeof(struct InstanceInfo));
    info->pp_instance = instance;
    info->last_size.width = 0;
    info->last_size.height = 0;
    info->graphics = 0;

    /* Insert into linked list of live instances. */
    info->next = all_instances;
    all_instances = info;

    g_input_interface->RequestInputEvents(instance, PP_INPUTEVENT_CLASS_MOUSE);
    g_input_interface->RequestFilteringInputEvents(instance, PP_INPUTEVENT_CLASS_MOUSE);

    OutputDebugString(_T("Instance_DidCreate\r\n"));

    return PP_TRUE;
}

void Instance_DidDestroy(PP_Instance instance) {
    /* Find the matching item in the linked list, delete it, and patch the
    * links.
    */
    struct InstanceInfo** prev_ptr = &all_instances;
    struct InstanceInfo* cur = all_instances;
    while (cur) {
        if (instance == cur->pp_instance) {
            *prev_ptr = cur->next;
            g_core_interface->ReleaseResource(cur->graphics);
            free(cur);
            return;
        }
        prev_ptr = &cur->next;
        cur = cur->next;
    }

    /**foruok: close native window**/
    if (g_child_window != NULL)SendMessage(g_child_window, WM_CLOSE, 0, 0);
    if (g_dwThreadId != 0)
    {
        OutputDebugString(_T("Plugin was destroyed, tell child window close and thread exit\r\n"));
        PostThreadMessage(g_dwThreadId, WM_USER, 0, 0);
    }
}

void Instance_DidChangeView(PP_Instance pp_instance,
    PP_Resource view) {
    struct PP_Rect position;
    struct InstanceInfo* info = FindInstance(pp_instance);
    if (!info)
        return;

    if (g_view_interface->GetRect(view, &position) == PP_FALSE)
        return;

    if (info->last_size.width != position.size.width ||
        info->last_size.height != position.size.height) {
        /* Got a resize, repaint the plugin. */
        Repaint(info, &position.size);
        info->last_size.width = position.size.width;
        info->last_size.height = position.size.height;

        /**foruok: call create window**/
        if (g_child_window == NULL)
        {
            CreateChildWindow(&position);
        }
    }

    OutputDebugString(_T("Instance_DidChangeView\r\n"));
}

void Instance_DidChangeFocus(PP_Instance pp_instance, PP_Bool has_focus) {
}

PP_Bool Instance_HandleDocumentLoad(PP_Instance pp_instance,
    PP_Resource pp_url_loader) {
    return PP_FALSE;
}

static PPP_Instance instance_interface = {
    &Instance_DidCreate,
    &Instance_DidDestroy,
    &Instance_DidChangeView,
    &Instance_DidChangeFocus,
    &Instance_HandleDocumentLoad
};

PP_Bool InputEvent_HandleInputEvent(PP_Instance instance, PP_Resource input_event)
{
    struct PP_Point pt;
    TCHAR szLog[512] = { 0 };
    switch (g_input_interface->GetType(input_event))
    {
    case PP_INPUTEVENT_TYPE_MOUSEDOWN:
        pt = g_mouse_interface->GetPosition(input_event);
        _stprintf_s(szLog, 512, _T("InputEvent_HandleInputEvent, mouse down at [%d, %d]\r\n"), pt.x, pt.y);
        OutputDebugString(szLog);
        break;
        /*
        case PP_INPUTEVENT_TYPE_MOUSEUP:
        OutputDebugString(_T("InputEvent_HandleInputEvent, mouse up\r\n"));
        break;

        case PP_INPUTEVENT_TYPE_MOUSEMOVE:
        OutputDebugString(_T("InputEvent_HandleInputEvent, mouse move\r\n"));
        break;
        case PP_INPUTEVENT_TYPE_MOUSEENTER:
        OutputDebugString(_T("InputEvent_HandleInputEvent, mouse enter\r\n"));
        break;
        case PP_INPUTEVENT_TYPE_MOUSELEAVE:
        OutputDebugString(_T("InputEvent_HandleInputEvent, mouse leave\r\n"));
        break;
        */
    default:
        return PP_FALSE;
    }
    struct InstanceInfo* info = FindInstance(instance);
    if (info && info->last_size.width > 0)
    {
        Repaint(info, &info->last_size);
    }
    return PP_TRUE;
}

static PPP_InputEvent input_interface = {
    &InputEvent_HandleInputEvent
};

/* Global entrypoints --------------------------------------------------------*/

PP_EXPORT int32_t PPP_InitializeModule(PP_Module module,
    PPB_GetInterface get_browser_interface) {

    /**foruok: register window class**/
    RegisterVideoWindowClass();

    g_get_browser_interface = get_browser_interface;

    g_core_interface = (const PPB_Core*)
        get_browser_interface(PPB_CORE_INTERFACE);
    g_instance_interface = (const PPB_Instance*)
        get_browser_interface(PPB_INSTANCE_INTERFACE);
    g_image_data_interface = (const PPB_ImageData*)
        get_browser_interface(PPB_IMAGEDATA_INTERFACE);
    g_graphics_2d_interface = (const PPB_Graphics2D*)
        get_browser_interface(PPB_GRAPHICS_2D_INTERFACE);
    g_view_interface = (const PPB_View*)
        get_browser_interface(PPB_VIEW_INTERFACE);
    g_input_interface = (const PPB_InputEvent*)get_browser_interface(PPB_INPUT_EVENT_INTERFACE);
    g_mouse_interface = (const PPB_MouseInputEvent*)get_browser_interface(PPB_MOUSE_INPUT_EVENT_INTERFACE);

    if (!g_core_interface || !g_instance_interface || !g_image_data_interface ||
        !g_graphics_2d_interface || !g_view_interface ||
        !g_input_interface || !g_mouse_interface)
        return -1;

    g_var_interface = (const PPB_Var*)get_browser_interface(PPB_VAR_INTERFACE);
    g_dictionary_interface = (const PPB_VarDictionary*)get_browser_interface(PPB_VAR_DICTIONARY_INTERFACE);
    g_array_interface = (const PPB_VarArray*)get_browser_interface(PPB_VAR_ARRAY_INTERFACE);
    g_message_interface = (const PPB_Messaging*)get_browser_interface(PPB_MESSAGING_INTERFACE);

    OutputDebugString(_T("PPP_InitializeModule\r\n"));
    return PP_OK;
}

PP_EXPORT void PPP_ShutdownModule() {
}

void Plugin_HandleMessage(PP_Instance instance, struct PP_Var message)
{
    char szLog[256] = { 0 };
    //sprintf_s(szLog, 256, "Plugin_HandleMessage, type = %d\r\n", message.type);
    OutputDebugStringA(szLog);

    if (message.type == PP_VARTYPE_DICTIONARY)
    {
        char command[] = "command";
        struct PP_Var commandKey = g_var_interface->VarFromUtf8(command, sizeof(command)-1);
        struct PP_Var commandVar = g_dictionary_interface->Get(message, commandKey);
        int len = 0;
        const char *strCommand = g_var_interface->VarToUtf8(commandVar, (uint32_t*)&len);
        g_var_interface->Release(commandKey);

        //sprintf_s(szLog, 256, "Plugin_HandleMessage, dict, command = %s, len = %d\r\n", strCommand, len);
        OutputDebugStringA(szLog);

        if (len == 0)
        {
            OutputDebugString(_T("Tang_plugin, recv invalid command\r\n"));
            g_var_interface->Release(commandVar);
            return;
        }
        if (strncmp(strCommand, "joinConf", len) == 0)
        {
            char confIdKey[] = "confId";
            char userNameKey[] = "userName";
            char *szConfId = 0;
            char*szUserName = 0;
            struct PP_Var idKey = g_var_interface->VarFromUtf8(confIdKey, sizeof(confIdKey)-1);
            struct PP_Var userKey = g_var_interface->VarFromUtf8(userNameKey, sizeof(userNameKey)-1);
            struct PP_Var var = g_dictionary_interface->Get(message, idKey);
            const char *value = g_var_interface->VarToUtf8(var, (uint32_t*)&len);
            if (len > 0)
            {
                szConfId = (char*)malloc(len + 1);
                strncpy_s(szConfId, len + 1, value, len);
                szConfId[len] = 0;
            }
            g_var_interface->Release(var);

            var = g_dictionary_interface->Get(message, userKey);
            value = g_var_interface->VarToUtf8(var, (uint32_t*)&len);
            if (len > 0)
            {
                szUserName = (char*)malloc(len + 1);
                strncpy_s(szUserName, len + 1, value, len);
                szUserName[len] = 0;
            }
            g_var_interface->Release(var);

            //sprintf_s(szLog, 256, "Plugin_HandleMessage, dict, command = joinConf, user = %s, confId = %s\r\n", szUserName, szConfId);
            OutputDebugStringA(szLog);

            if (szConfId && szUserName)
            {
                //sprintf_s(szLog, 256, "plugin got confId - %s, user - %s\r\n", szConfId, szUserName);
                OutputDebugStringA(szLog);
                //joinConf(szConfId, szUserName);
            }
            else
            {
                OutputDebugString(_T("Invalid conference id or userName\r\n"));
            }
            if (szConfId) free(szConfId);
            if (szUserName) free(szUserName);
            g_var_interface->Release(idKey);
            g_var_interface->Release(userKey);

            /* fake attendees*/
            char szMsgTypeValue[] = "userlist";
            char szTypeKey[] = "type";
            struct PP_Var typeKey = g_var_interface->VarFromUtf8(szTypeKey, sizeof(szTypeKey)-1);
            struct PP_Var typeValue = g_var_interface->VarFromUtf8(szMsgTypeValue, sizeof(szMsgTypeValue)-1);
            struct PP_Var attendee = g_dictionary_interface->Create();
            g_dictionary_interface->Set(attendee, typeKey, typeValue);

            struct PP_Var userArray = g_array_interface->Create();
            char szUser1[] = "ZhangSan";
            char szUser2[] = "LiSi";
            struct PP_Var user1 = g_var_interface->VarFromUtf8(szUser1, sizeof(szUser1)-1);
            struct PP_Var user2 = g_var_interface->VarFromUtf8(szUser2, sizeof(szUser2)-1);
            g_array_interface->Set(userArray, 0, user1);
            g_array_interface->Set(userArray, 1, user2);

            char szValueKey[] = "value";
            struct PP_Var valueKey = g_var_interface->VarFromUtf8(szValueKey, sizeof(szValueKey)-1);
            g_dictionary_interface->Set(attendee, valueKey, userArray);

            g_message_interface->PostMessage(instance, attendee);
            OutputDebugString(_T("Post attendee to browser"));

            g_var_interface->Release(typeKey);
            g_var_interface->Release(typeValue);
            g_var_interface->Release(user1);
            g_var_interface->Release(user2);
            g_var_interface->Release(valueKey);
            g_var_interface->Release(userArray);
            g_var_interface->Release(attendee);
        }
        else if (strncmp(strCommand, "viewVideo", len) == 0)
        {
            char userIdKey[] = "userId";
            char *szUserId = 0;
            struct PP_Var idKey = g_var_interface->VarFromUtf8(userIdKey, sizeof(userIdKey)-1);
            struct PP_Var var = g_dictionary_interface->Get(message, idKey);
            const char *value = g_var_interface->VarToUtf8(var, (uint32_t*)&len);
            if (len > 0)
            {
                szUserId = (char*)malloc(len + 1);
                strncpy_s(szUserId, len + 1, value, len);
                szUserId[len] = 0;
            }
            if (szUserId)
            {
                //sprintf_s(szLog, 256, "plugin got userId - %s\r\n", szUserId);
                OutputDebugStringA(szLog);
                //viewVideo(szUserId, g_child_window);
            }
            else
            {
                OutputDebugString(_T("Invalid viewVideo command without userId\r\n"));
            }
            if (szUserId) free(szUserId);
            g_var_interface->Release(var);
            g_var_interface->Release(idKey);
        }
        g_var_interface->Release(commandVar);
    }
    else if (message.type == PP_VARTYPE_STRING)
    {
        char hello_world[] = "Hello world!";
        struct PP_Var var = g_var_interface->VarFromUtf8(hello_world, sizeof(hello_world)-1);
        g_message_interface->PostMessage(instance, var); // var will be copyed
        g_var_interface->Release(var);
    }
}

static PPP_Messaging message_interface = {
    &Plugin_HandleMessage
};


PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
    if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0)
    {
        OutputDebugString(_T("PPP_GetInterface, instance_interface\r\n"));
        return &instance_interface;
    }
    else if (strcmp(interface_name, PPP_INPUT_EVENT_INTERFACE) == 0)
    {
        OutputDebugString(_T("PPP_GetInterface, input_interface\r\n"));
        return &input_interface;
    }
    else if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0)
    {
        OutputDebugString(_T("PPP_GetInterface, message_interface\r\n"));
        return &message_interface;
    }

    return NULL;
}

 


    5. 右键选择工程属性,在工程的包含目录中加入  D://APIs/BHO-master/
    6. 编译工程得到一个 dll,例如 ppapiexample.dll。
    7. 编写一个cef.html 文件,

<!DOCTYPE html>
<html>
  <!--
  Copyright (c) 2016 foruok@微信订阅号“程序视界”(programmer_sight). 
  All rights reserved.
  Use of this source code is governed by a BSD-style license that can be
  found in the LICENSE file.
  -->
<head>
    <style type="text/css">
    #contacts
    {
        margin: 10px;
        width: 300px;
        height: 200px;
        background-color: gray;
    }
    </style>
    <script type="text/javascript">
      function handleMessage(message) {
        alert(message.data.type);
        if(message.data.type.localeCompare("userlist") == 0){
          var i = 0;
          ul = document.getElementById("attendee");
          for(; i < message.data.value.length; i++){
            var li = document.createElement("li");
            li.appendChild(document.createTextNode(message.data.value[i]));
            ul.appendChild(li);
          }
        }
      }

      function joinConference(){
        plugin = document.getElementById('tangplugin');
        plugin.postMessage({
            command:"joinConf", 
            confId: document.getElementById("confId").value, 
            userName: document.getElementById("userName").value
          });
      }
      function viewSharedVideo(){
        plugin = document.getElementById('tangplugin');
        plugin.postMessage({
            command:"viewVideo", 
            userId: document.getElementById("userId").value
          });
      }

      function initialize() {
        plugin = document.getElementById('tangplugin');
        plugin.addEventListener('message', handleMessage, false);
      }

      document.addEventListener('DOMContentLoaded', initialize, false);
    </script>
  <title>Tang in Plugin</title>
</head>

<body>
<form>
ConferenceID: <input type="text" id="confId" />&nbsp;&nbsp;User: 
<input type="text" id="userName" />&nbsp;&nbsp;<input  type="button" value="Join" onclick="joinConference()"/>
</form>
<hr>
<div id="contacts">
<p>contacts:</p>
<ul id="attendee">
  <!--
  here will show attendee list, added by JS callback
  -->
</ul>
UserId:<input type="text" id="userId" />&nbsp;&nbsp;<button type="button" onclick="viewSharedVideo()">View Video</button>
</div>

<p>share video:</p>
<embed id="tangplugin" type="application/x-ppapi-tang-video" width="300px" height="200px" top="40px" left="20px">

</body>
</html>

    8. 制作一个 .bat 文件,文件内容类似如下:
chrome --register-pepper-
plugins="C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\49.0.2623.110\\tplugin\\ppapiexample.dll;application/x-ppapi-tang-video"  D:\\APIs\\BHO-master\\cef.html
    9.  运行该 .bat 文件,查看效果。

NPAPI和PPAPI插件开发 NPAPI和PPAPI开发 Author: kagula Revison: 1 Last modify date:2015-10-20 环境:  [1]Visual Studio 2010 SP1     Visaul Stuio  2013 Update4  [2]Python2.7  [3]Firefox 41.0.1  [4]IE 11  [5]Google ch 阅读详情

相关推荐

Qt调用Chrome浏览器

最近有个小项目需要跳转网页,之前有了解过,但是没有在项目中使用过Qt网页嵌入;结合自己之前的博客,有如下两种技术可以实现我的需求:1、2、然后就想到了调用Chrome浏览器的方案!

贝勒里恩的博客 6733

chrome窗口

这个窗口是gpu进程创建的,作为一个子窗口嵌入到父窗口 Chrome_WidgetWin_1 中,chrome在使用gpu渲染时,网页的渲染最后会在GPU中渲染,即 Intermediate D3D Window 窗口。所以,我们需要一个假的 HWND,其窗口类为Chrome_RenderWidgetHostHWND 作为可访问性树的根每个选项卡。默认容器窗口是包含网页的整个窗口WebContents 等。// 用于匹配 Chrome 窗口的窗口类的前缀。浏览器将其重新设置为其窗口的子窗口。

LIJIWEI0611的博客 5563

使用SPY++查看窗口信息去分析C++客户端UI软件问题

使用SPY++查看窗口信息去分析C++客户端UI软件问题

dvlinker的技术专栏 1万+

谷歌浏览器的源码分析(34)

通过上一次的分析,我们看到所有网页数据经过HTML分析器之后,都会变成一个一个RenderObject对象,那么这些RenderObject对象又是怎么样显示到界面上面的呢?现在就带着这个疑问来分析下面的代码,这样肯定会找到解决方法的。怎么样找到入口呢?其实可以先从界面显示的类开始,可以看到显示界面的窗口类名称叫做Chrome_RenderWidgetHostHWND,有了这个类名称,就...

anjichan4261的博客 613

PPAPI插件开发实战示例

PPAPI(Pepper Plugin API)是由Chromium项目开发的一个跨平台插件接口,旨在提供更安全、更高效的插件开发环境。通过PPAPI,开发者可以编写出可在Chrome、Firefox等现代浏览器上运行的插件。PPAPI的主要优势在于它提供了一套简化且统一的API,使得插件能够在不同的浏览器中具有一致的行为。DEPS文件是Google Chrome项目中使用的一个脚本文件,它的作用是声明项目依赖关系和管理外部代码。这个文件通常位于项目的根目录,由gni工具解释执行。

weixin_34064233的博客 899

音频降采样系数

如果需要把8K, 16K, 32K, 48K采样率的音频数据降为4K的音频数据, 最简单的方法根据降频倍数来取点, 但是线性度不好. 另一种线性度好一点的方法是: 取适当个数的点数, 各点乘以各自点的系数, 然后相加取平均值. 降频倍数与系数的关系如下: 2倍:     {0.3, 0.4, 0.3} 4倍:    {0.15, 0.2, 0.3, 0.2, 0.15} 8倍:   {0

joans123的专栏 4646

Chrome 插件PPAPI 开发(一)环境搭建

前言:本文参考了其他已有的文章,在其基础上简化了一些没有必要的操作。 同时也记录一下chrome 插件ppapi环境的基础搭建。并且感谢已有文章作者的大无畏的分享精神! 在这附上参考文章链接:https://blog.youkuaiyun.com/y601500359/article/details/72821974 当前系统版本为 Windows 10 x64, Chrome版本 71.0.357...

weixin_30887919的博客 1480

手把手教你用STM32F103的普通IO口读取SSI编码器(附完整代码与示波器调试心得)

本文详细介绍了如何利用STM32F103的普通IO口读取SSI绝对式编码器数据,提供完整的硬件连接方案、精确时序控制的软件实现及示波器调试技巧。通过低成本方案实现高精度位置反馈,适用于工业自动化和机器人控制领域。

weixin_29172963的博客 452

Chrome PPAPI 开发环境

https://www.cnblogs.com/snowyying/p/5458765.html https://blog.youkuaiyun.com/y601500359/article/details/72821974 https://www.pressc.cn/1049.html(比较详细) Pepper Plugin API (PPAPI) plugins 是 Google 在原有网景 NPA...

ZouZou的专栏 2652

激光雷达测距方式全解析:ToF、三角测距和FMCW到底怎么选?

本文深度解析激光雷达三种主流测距方式(ToF、三角测距和FMCW)的技术原理、环境适应性和成本模型,提供场景化选型决策指南。通过对比各技术在精度、抗干扰能力和维护成本等方面的表现,帮助工程师在自动驾驶、工业检测和消费电子等领域做出最优选择。

qqq44的博客 719

交换机背板带宽、交换容量与包转发率到底是啥?

在网络工程中,交换机是核心设备之一,而关于它的性能指标,背板带宽、交换容量、以及包转发率往往成为人们衡量其性能的重要参数。这些术语的定义、关系、以及在实际场景中的应用,都对交换机的选型与部署有着重要意义。本文将为您全面解读这些概念,帮助您深入了解交换机的核心性能指标。

网络技术联盟站 1549

NPAPI和PPAPI开发

介绍NPAPI和PPAPI的具体开发过程!

lee353086的专栏 3万+

五、MT8168 音频驱动之SPEAKER

本章主要讲解MT8168平台的内部SPEAKER驱动配置。分为HP接法和LINE OUT接法。2.1.3 audio_custom_exp.h设置。2.1.4 mixer_paths.xml设置。2.2.3 mixer_paths.xml设置。2.1.2 ProjectConfig 设置。2.2.2 ProjectConfig 设置。2.2.1 deconfig设置。2.1.1 DTS设置。......

Joon2020的博客 1664

PPAPI插件开发指南

转载请注明出处:http://www.cnblogs.com/fangkm/p/4401075.html 前言 插件一直是浏览器的重要组成部分,丰富浏览器的运行能力,实现一些HTML+JS实现不了本地应用(比如音视频、文件操作等)。早期广为熟知的是IE下的插件ActiveX,这是一项熟悉可能暴露年龄的技术,它基于COM规范,在IE占浏览器市场主流份额的时代,ActiveX可谓出尽了风头,但它并...

weixin_30741653的博客 1311

VTK GPU 加速渲染技术

/ 创建颜色工具// 创建立方体数据// 创建OpenGL映射器(注意使用vtkOpenGLPolyDataMapper而不是常规的vtkPolyDataMapper)// 启用VBO(顶点缓冲对象)// 声明几何体是静态的以获得最佳性能// 创建actor// 创建渲染器、渲染窗口和交互器renderWindow->SetWindowName("VTK自定义着色器示例");// 添加actor到渲染器。

深之JohnChen的专栏 1242

【S32K3 MCAL配置】-1.1-GPIO配置及其应用-DIO之高低电平输出-点亮LED灯(基于MCAL)

【S32K3 MCAL配置】-1.1-GPIO配置及其应用-点亮LED灯(基于MCAL)

「汽车电子助手」的博客 1937

Chrome配置和使用PPAPI-环境配置

最近听说Chrome开始不支持PPAPI插件了,但是项目上必须要用Chrome调用本地dll做一些事情,抱着试一试的心态,找了一下资料,下面总结一下PPAPI配置过程。 第一步,准备python2.7 网上大神说必须使用2.7版本,至于为什么都说是其他不支持,下载地址为:https://www.python.org/ftp/python/2.7/python-2.7.msi 这个是32位版本的,安...

youyicc 5751

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

PPAPI开发FAQ

PPAPI,用于开发支持Chrome的浏览器插件。 基础: (1)https://developer.chrome.com/native-client/devguide/tutorial/tutorial-part1        下载并安装nacal环境 (2)https://developer.chrome.com/native-client/devguide/devcycle/vs-a

zzstack的专栏 1112

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

npapi和ppapi区别

与NPAPI不同,PPAPI将插件运行在沙盒模式下,可以隔离插件与浏览器之间的交互,防止插件对浏览器造成损害。安全性:PPAPI更安全,它将插件运行在沙盒中,这意味着插件只能访问允许的资源,而不能访问系统上的其他资源。架构:NPAPI是基于浏览器进程的插件API,而PPAPI是基于Chrome浏览器的进程的插件API。总的来说,PPAPI是NPAPI的现代替代品,更安全、更可靠,并支持更多现代Web技术。平台支持:NPAPI是跨浏览器平台的,而PPAPI是Chrome浏览器专用的API。

学无止尽,谨言慎行! 4189

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Chrome插件架构演进:从NPAPI到PPAPI的技术革命与启示

Chrome插件架构经历了从NPAPI到PPAPI的重大技术革新。NPAPI作为跨浏览器插件标准存在安全隐患和性能问题,促使谷歌开发更安全的PPAPI架构。PPAPI通过沙盒隔离机制大幅提升安全性,采用进程隔离和硬件加速优化性能,同时精简API设计增强稳定性。这一演进体现了浏览器技术向安全优先、性能优化的发展趋势,为现代Web生态建设提供了重要启示。技术变革周期缩短背景下,平衡兼容性与创新性成为关键挑战。

John_ToStr的博客 294

PPAPI开发之路(三)通过本地服务发布例子:media_stream_video的PPAPI

前言:在进行下文之前,先介绍下发布PPAPI的几种格式 :Chrome PPAPI插件只能使用PPAPI接口的NativeClient(NaCl)方式编写,Native Client分别有三种embed类型: 1、“application/x-ppapi”:平台相关,唯一能直接使用win32 api的platfrom(有功能上的限制)。dll格式,不允许通过...

269
下一篇: C++编程——LIBCURL
gccflagger
博客等级 码龄15年 5粉丝 2原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值