• Duilib嵌入CEF禁止浏览器响应拖拽事件


    转载:http://blog.csdn.net/liuyan20092009/article/details/53819473

    转载:https://blog.csdn.net/u012778714(封装成Duilib控件)

    转载:https://blog.csdn.net/CYY_JLSAINI/article/details/80090091?utm_source=blogxgwz5

    在开发中有一个需求,拖拽外部文件到客户端,然后客户端响应WM_DROPFILES消息,在拖拽消息里处理一下业务,最后把处理结果显示到客户区html中,但实际中发现当拖拽文件到客户区,浏览器首先处理了拖拽事件,外层的Win32窗口无法捕捉到拖拽消息,因此要想实现此操作,刚开始我想了一个本办法,在客户区最外层罩了一个透明的Win32原生窗口,这样拖拽文件时,在最外层透明窗口的WM_DROPFILES消息中处理具体业务,最后用C++调用js函数,在页面显示处理结果。

    方法一:

    透明窗口

    LayeredWindow.h

     1 #ifndef _LAYEREDWINDOW_H_
     2 #define _LAYEREDWINDOW_H_
     3 
     4 class CLayeredWindow :public WindowImplBase
     5 {
     6 public:
     7     CLayeredWindow();
     8     ~CLayeredWindow();
     9 
    10 public:
    11     LPCTSTR GetWindowClassName() const;    
    12 
    13     virtual void OnFinalMessage(HWND hWnd);
    14 
    15     virtual LRESULT ResponseDefaultKeyEvent(WPARAM wParam);
    16 
    17     virtual UILIB_RESOURCETYPE GetResourceType() const;
    18 
    19     virtual CDuiString GetSkinFile();
    20 
    21     virtual CDuiString GetSkinFolder();
    22 
    23     virtual CControlUI* CreateControl(LPCTSTR pstrClass);
    24 
    25     virtual void InitWindow();
    26 
    27     virtual void Notify(TNotifyUI& msg);
    28 
    29     virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
    30 
    31     virtual void OnClick(TNotifyUI& msg);
    32 
    33     void OnPrepare();
    34 };
    35 #endif//_LAYEREDWINDOW_H_

    LayeredWindow.cpp

      1 #include "stdafx.h"
      2 #include "LayeredWindow.h" 
      3 
      4 CLayeredWindow::CLayeredWindow()
      5 {
      6 
      7 }
      8 
      9 CLayeredWindow::~CLayeredWindow()
     10 {
     11 
     12 }
     13 
     14 LPCTSTR CLayeredWindow::GetWindowClassName() const
     15 {
     16     return _T("LayeredWindow");
     17 }
     18 
     19 void CLayeredWindow::OnFinalMessage(HWND hWnd)
     20 {
     21     CWindowWnd::OnFinalMessage(hWnd);
     22 }
     23 
     24 LRESULT CLayeredWindow::ResponseDefaultKeyEvent(WPARAM wParam)
     25 {
     26     if (wParam == VK_RETURN)
     27     {
     28         return FALSE;
     29     }
     30     else if (wParam == VK_ESCAPE)
     31     {
     32         return TRUE;
     33     }
     34     return FALSE;
     35 }
     36 
     37 DuiLib::UILIB_RESOURCETYPE CLayeredWindow::GetResourceType() const
     38 {
     39     return UILIB_FILE;
     40 }
     41 
     42 DuiLib::CDuiString CLayeredWindow::GetSkinFile()
     43 {
     44     return _T("LayeredDlg.xml");
     45 }
     46 
     47 DuiLib::CDuiString CLayeredWindow::GetSkinFolder()
     48 {
     49     return _T("");
     50 }
     51 
     52 CControlUI* CLayeredWindow::CreateControl(LPCTSTR pstrClass)
     53 {
     54     return NULL;
     55 }
     56 
     57 void CLayeredWindow::InitWindow()
     58 {
     59     
     60     //加入WS_EX_LAYERED扩展属性
     61     SetWindowLong(this->GetHWND(),GWL_EXSTYLE,
     62         GetWindowLong(this->GetHWND(),GWL_EXSTYLE)^0x80000);
     63     HINSTANCE hInst = LoadLibrary(L"User32.DLL"); 
     64     if(hInst) 
     65     { 
     66         typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD); 
     67         MYFUNC fun = NULL;
     68         //取得SetLayeredWindowAttributes函数指针 
     69         fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
     70         if(fun)fun(this->GetHWND(),0,1,2); //0表示全透明,255表示不透明
     71         FreeLibrary(hInst);
    72 } 73 } 74 75 76 void CLayeredWindow::OnPrepare() 77 { 78 79 } 80 81 void CLayeredWindow::Notify(TNotifyUI& msg) 82 { 83 if( msg.sType == _T("windowinit") ) OnPrepare(); 84 85 if(msg.sType == _T("click")) 86 { 87 } 88 89 WindowImplBase::Notify(msg); 90 } 91 92 void CLayeredWindow::OnClick(TNotifyUI& msg) 93 { 94 __super::OnClick(msg); 95 } 96 97 //禁用双击标题栏窗口最大化 98 LRESULT CLayeredWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) 99 { 100 LRESULT lRes = 0; 101 BOOL bHandled = TRUE; 102 switch( uMsg) 103 { 104 case WM_NCLBUTTONDBLCLK: 105 { 106 return 0; 107 } 108 break; 109 default: 110 bHandled = FALSE; 111 } 112 return WindowImplBase::HandleMessage(uMsg,wParam,lParam); 113 }

    1.在主窗口InitWindow函数里面创建透明窗口

    2.在主窗口的WM_SIZE 和 WM_MOVE消息中移动这个透明窗口,让其跟随主窗口移动

    方法二:

     最好的办法是取消CEF浏览器对拖拽事件的处理,这样让外层Win32窗口处理拖拽事件

    研究了一下CEF源码,发现有一个类CefDragHandler,是浏览器拖拽事件,可以让你自己的CLientHandler继承这个类,然后重写它里面的虚函数

    virtual bool OnDragEnter(CefRefPtr<CefBrowser>browser,CefRefPtr<CefDragData> dragData,CefDragHandler::DragOperationsMask mask)
    {

        CEF_REQUIRE_UI_THREAD();

        // Forbid dragging of link URLs.
        if (mask & DRAG_OPERATION_LINK)
        return true;

       return false;

    }

    让其返回true,取消拖拽响应,刚开始只重写了这个虚函数,但在拖拽时还是无法禁止,最后发现少写一个获取拖拽事件处理器

    // CefClient 事件处理器,如果没有对应处理器则默认使用内部处理器

    virtual CefRefPtr<CefDragHandler> GetDragHandler()  {
            return this;
        }

    加上这个函数后,才能真正禁止拖拽事件

    方法三:

    如果在html页面中有拖拽操作的业务,使用方法二也会被禁止掉不能拖拽,所以想实现禁止从外部拖拽,同时在浏览器内部可以拖拽,就使用这种方法

    只在你的html中上这些代码,C++不需要处理拖拽事件了:

    <body  ondragover="event.preventDefault();" ondrop="event.preventDefault();"></body>
  • 相关阅读:
    C#winForm调用WebService的远程接口
    [C#] 走进异步编程的世界
    新手浅谈C#Task异步编程
    C#操作XML方法详解
    C# 实现生产者消费者队列
    c#多线程同步之EventWaitHandle使用
    C# 队列(Queue)和 堆栈(Stack)
    UVA-11925 Generating Permutations (逆向思维)
    UVA-11491 Erasing and Winning (单调队列)
    UVA-12545 Bits Equalizer (贪心)
  • 原文地址:https://www.cnblogs.com/chechen/p/6669466.html
Copyright © 2020-2023  润新知