转载: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>