赞助

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>

 

posted @ 2017-04-05 16:48  车臣  阅读(2225)  评论(0编辑  收藏  举报