394 lines
10 KiB
C++
394 lines
10 KiB
C++
#include "multi_browser_manager.h"
|
||
#include "multi_browser_form.h"
|
||
#include "browser_box.h"
|
||
#include "dragdrop/drag_form.h"
|
||
#include "dragdrop/drag_drop.h"
|
||
|
||
namespace
|
||
{
|
||
const int kSplitFormXOffset = 20; //自动拆分浏览器窗口后新窗口的x偏移坐标
|
||
const int kSplitFormYOffset = 20; //自动拆分浏览器窗口后新窗口的y偏移坐标
|
||
const int kDragFormXOffset = -100; //拖拽出新浏览器窗口后的相对鼠标的x偏移坐标
|
||
const int kDragFormYOffset = -20; //拖拽出新浏览器窗口后的相对鼠标的y偏移坐标
|
||
}
|
||
|
||
BrowserBox* MultiBrowserManager::CreateBorwserBox(MultiBrowserForm *browser_form, const std::string &id, const std::wstring &url)
|
||
{
|
||
BrowserBox *browser_box = NULL;
|
||
// 如果启用了窗口合并功能,就把新浏览器盒子都集中创建到某一个浏览器窗口里
|
||
// 否则每个浏览器盒子都创建一个浏览器窗口
|
||
if (enable_merge_)
|
||
{
|
||
if (!browser_form)
|
||
{
|
||
browser_form = new MultiBrowserForm;
|
||
HWND hwnd = browser_form->Create(NULL, L"MultiBrowser", UI_WNDSTYLE_FRAME, 0, false);
|
||
if (hwnd == NULL)
|
||
{
|
||
browser_form = NULL;
|
||
return NULL;
|
||
}
|
||
|
||
browser_form->CenterWindow();
|
||
}
|
||
|
||
browser_box = browser_form->CreateBox(id, url);
|
||
if (NULL == browser_box)
|
||
return NULL;
|
||
}
|
||
else
|
||
{
|
||
browser_form = new MultiBrowserForm;
|
||
HWND hwnd = browser_form->Create(NULL, L"MultiBrowser", UI_WNDSTYLE_FRAME, 0, false);
|
||
if (hwnd == NULL)
|
||
return NULL;
|
||
|
||
browser_box = browser_form->CreateBox(id, url);
|
||
if (NULL == browser_box)
|
||
return NULL;
|
||
|
||
browser_form->CenterWindow();
|
||
}
|
||
|
||
box_map_[id] = browser_box;
|
||
return browser_box;
|
||
}
|
||
|
||
MultiBrowserManager::MultiBrowserManager()
|
||
{
|
||
enable_merge_ = true;
|
||
use_custom_drag_image_ = true;
|
||
}
|
||
|
||
MultiBrowserManager::~MultiBrowserManager()
|
||
{
|
||
|
||
}
|
||
|
||
bool MultiBrowserManager::IsBorwserBoxActive(const std::string& id)
|
||
{
|
||
BrowserBox *browser_box = FindBorwserBox(id);
|
||
if (NULL != browser_box)
|
||
{
|
||
MultiBrowserForm *parent_form = browser_box->GetBrowserForm();
|
||
return parent_form->IsActiveBox(browser_box);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
BrowserBox* MultiBrowserManager::FindBorwserBox( const std::string &id )
|
||
{
|
||
std::map<std::string, BrowserBox*>::const_iterator i = box_map_.find(id);
|
||
if (i == box_map_.end())
|
||
return NULL;
|
||
else
|
||
return i->second;
|
||
}
|
||
|
||
void MultiBrowserManager::RemoveBorwserBox( std::string id, const BrowserBox* box /*=NULL*/)
|
||
{
|
||
auto it_box = box_map_.find(id);
|
||
if (it_box == box_map_.end())
|
||
{
|
||
assert(0);
|
||
}
|
||
else
|
||
{
|
||
if (NULL == box || box == it_box->second)
|
||
{
|
||
box_map_.erase(it_box);
|
||
}
|
||
else
|
||
{
|
||
assert(0);
|
||
}
|
||
}
|
||
|
||
if (box_map_.empty())
|
||
nim_comp::CefManager::GetInstance()->PostQuitMessage(0);
|
||
}
|
||
|
||
void MultiBrowserManager::SetEnableMerge(bool enable)
|
||
{
|
||
if (enable_merge_ == enable)
|
||
return;
|
||
|
||
enable_merge_ = enable;
|
||
|
||
if (enable_merge_)
|
||
{
|
||
// 如果当前只有一个浏览器窗口或者浏览器盒子,就不需要进行合并操作
|
||
if (box_map_.size() <= 1)
|
||
return;
|
||
|
||
// 选择第一个浏览器盒子所属的窗口作为合并窗口
|
||
MultiBrowserForm *merge_form = box_map_.begin()->second->GetBrowserForm();
|
||
|
||
// 遍历所有浏览器盒子,脱离原浏览器窗口,再附加到合并窗口里
|
||
for (auto it_box : box_map_)
|
||
{
|
||
ASSERT(NULL != it_box.second);
|
||
MultiBrowserForm *parent_form = it_box.second->GetBrowserForm();
|
||
if (merge_form != parent_form)
|
||
{
|
||
if (parent_form->DetachBox(it_box.second))
|
||
{
|
||
merge_form->AttachBox(it_box.second);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 如果当前只有一个浏览器盒子,就不需要进行拆分操作
|
||
if (box_map_.size() <= 1)
|
||
return;
|
||
|
||
// 给新拆分的窗口设置坐标
|
||
bool first_sort = true;
|
||
ui::UiRect rect_old_form;
|
||
MultiBrowserForm *sort_form = NULL;
|
||
|
||
// 遍历所有浏览器盒子,脱离原浏览器窗口,创建新的浏览器窗口并附加浏览器盒子
|
||
for (auto it_box : box_map_)
|
||
{
|
||
ASSERT(NULL != it_box.second);
|
||
MultiBrowserForm *parent_form = it_box.second->GetBrowserForm();
|
||
if (1 == parent_form->GetBoxCount())
|
||
{
|
||
sort_form = parent_form;
|
||
}
|
||
else if (parent_form->DetachBox(it_box.second))
|
||
{
|
||
MultiBrowserForm *browser_form = new MultiBrowserForm;
|
||
HWND hwnd = browser_form->Create(NULL, L"MultiBrowser", UI_WNDSTYLE_FRAME, 0, false);
|
||
if (hwnd == NULL)
|
||
{
|
||
ASSERT(0);
|
||
continue;
|
||
}
|
||
|
||
if (!browser_form->AttachBox(it_box.second))
|
||
{
|
||
ASSERT(0);
|
||
continue;
|
||
}
|
||
|
||
sort_form = browser_form;
|
||
}
|
||
|
||
if (NULL != sort_form)
|
||
{
|
||
if (first_sort)
|
||
{
|
||
first_sort = false;
|
||
sort_form->CenterWindow();
|
||
rect_old_form = sort_form->GetPos(true);
|
||
}
|
||
else
|
||
{
|
||
rect_old_form.left += kSplitFormXOffset;
|
||
rect_old_form.top += kSplitFormXOffset;
|
||
sort_form->SetPos(rect_old_form, true, SWP_NOSIZE, NULL, true);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
bool MultiBrowserManager::IsEnableMerge() const
|
||
{
|
||
return enable_merge_;
|
||
}
|
||
|
||
void MultiBrowserManager::SetUseCustomDragImage(bool use)
|
||
{
|
||
use_custom_drag_image_ = use;
|
||
}
|
||
|
||
bool MultiBrowserManager::IsUseCustomDragImage() const
|
||
{
|
||
return use_custom_drag_image_;
|
||
}
|
||
|
||
bool MultiBrowserManager::IsDragingBorwserBox() const
|
||
{
|
||
return enable_merge_ && NULL != draging_box_;
|
||
}
|
||
|
||
void MultiBrowserManager::SetDropForm(MultiBrowserForm *browser_form)
|
||
{
|
||
if (NULL == browser_form)
|
||
return;
|
||
|
||
drop_browser_form_ = browser_form;
|
||
}
|
||
|
||
bool MultiBrowserManager::DoDragBorwserBox(BrowserBox *browser_box, HBITMAP bitmap, POINT pt_offset)
|
||
{
|
||
if (!enable_merge_)
|
||
return false;
|
||
|
||
SdkDropSource* drop_src = new SdkDropSource;
|
||
if (drop_src == NULL)
|
||
return false;
|
||
|
||
SdkDataObject* data_object = CreateDragDataObject(bitmap, pt_offset);
|
||
if (data_object == NULL)
|
||
return false;
|
||
|
||
// 无论什么时候都让拖拽时光标显示为箭头
|
||
drop_src->SetFeedbackCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));
|
||
|
||
OnBeforeDragBorwserBox(browser_box, bitmap, pt_offset);
|
||
|
||
// 此函数会阻塞直到拖拽完成
|
||
DWORD dwEffect;
|
||
HRESULT hr = ::DoDragDrop(data_object, drop_src, DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect);
|
||
|
||
OnAfterDragBorwserBox();
|
||
|
||
// 销毁位图
|
||
DeleteObject(bitmap);
|
||
drop_src->Release();
|
||
data_object->Release();
|
||
return true;
|
||
}
|
||
|
||
SdkDataObject* MultiBrowserManager::CreateDragDataObject(HBITMAP bitmap, POINT pt_offset)
|
||
{
|
||
SdkDataObject* data_object = new SdkDataObject;
|
||
if (data_object == NULL)
|
||
return NULL;
|
||
|
||
if (use_custom_drag_image_)
|
||
{
|
||
FORMATETC fmtetc = { 0 };
|
||
fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
fmtetc.lindex = -1;
|
||
fmtetc.cfFormat = CF_HDROP;
|
||
fmtetc.tymed = TYMED_NULL;
|
||
|
||
STGMEDIUM medium = { 0 };
|
||
medium.tymed = TYMED_NULL;
|
||
data_object->SetData(&fmtetc, &medium, FALSE);
|
||
}
|
||
else
|
||
{
|
||
FORMATETC fmtetc = { 0 };
|
||
fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
fmtetc.lindex = -1;
|
||
fmtetc.cfFormat = CF_BITMAP;
|
||
fmtetc.tymed = TYMED_GDI;
|
||
|
||
STGMEDIUM medium = { 0 };
|
||
medium.tymed = TYMED_GDI;
|
||
HBITMAP hBitmap = (HBITMAP)OleDuplicateData(bitmap, fmtetc.cfFormat, NULL);
|
||
medium.hBitmap = hBitmap;
|
||
data_object->SetData(&fmtetc, &medium, FALSE);
|
||
|
||
BITMAP bitmap_info;
|
||
GetObject(hBitmap, sizeof(BITMAP), &bitmap_info);
|
||
SIZE bitmap_size = { bitmap_info.bmWidth, bitmap_info.bmHeight };
|
||
SdkDragSourceHelper dragSrcHelper;
|
||
dragSrcHelper.InitializeFromBitmap(hBitmap, pt_offset, bitmap_size, data_object, RGB(255, 0, 255));
|
||
}
|
||
|
||
return data_object;
|
||
}
|
||
|
||
void MultiBrowserManager::OnBeforeDragBorwserBox(BrowserBox *browser_box, HBITMAP bitmap, POINT pt_offset)
|
||
{
|
||
// 获取当前被拖拽的浏览器盒子所属的浏览器窗口
|
||
draging_box_ = browser_box;
|
||
MultiBrowserForm *drag_browser_form = draging_box_->GetBrowserForm();
|
||
ASSERT(NULL != drag_browser_form);
|
||
|
||
// 获取被拖拽浏览器窗口中浏览器盒子的数量
|
||
int box_count = drag_browser_form->GetBoxCount();
|
||
ASSERT(box_count > 0);
|
||
drop_browser_form_ = NULL;
|
||
|
||
drag_browser_form->OnBeforeDragBoxCallback(nbase::UTF8ToUTF16(draging_box_->GetId()));
|
||
|
||
if (use_custom_drag_image_)
|
||
DragForm::CreateCustomDragImage(bitmap, pt_offset);
|
||
}
|
||
|
||
void MultiBrowserManager::OnAfterDragBorwserBox()
|
||
{
|
||
if (use_custom_drag_image_)
|
||
DragForm::CloseCustomDragImage();
|
||
|
||
if (NULL == draging_box_)
|
||
return;
|
||
|
||
// 获取当前被拖拽的浏览器盒子所属的浏览器窗口
|
||
MultiBrowserForm *drag_browser_form = draging_box_->GetBrowserForm();
|
||
ASSERT(NULL != drag_browser_form);
|
||
|
||
// 获取被拖拽浏览器窗口中浏览器盒子的数量
|
||
int box_count = drag_browser_form->GetBoxCount();
|
||
ASSERT(box_count > 0);
|
||
|
||
// 如果被拖拽的浏览器盒子放入到一个浏览器窗口里
|
||
if (NULL != drop_browser_form_)
|
||
{
|
||
if (drag_browser_form == drop_browser_form_)
|
||
{
|
||
drag_browser_form->OnAfterDragBoxCallback(false);
|
||
}
|
||
else
|
||
{
|
||
drag_browser_form->OnAfterDragBoxCallback(true);
|
||
if (drag_browser_form->DetachBox(draging_box_))
|
||
{
|
||
drop_browser_form_->AttachBox(draging_box_);
|
||
}
|
||
}
|
||
|
||
// 如果被拖拽的浏览器窗口包含多个浏览器盒子,就投递一个WM_LBUTTONUP消息给窗口
|
||
// (因为窗口被拖拽时触发了ButtonDown和ButtonMove消息,但是最终的ButtonUp消息会被忽略,这里补上)
|
||
// 如果只有一个浏览器盒子,则浏览器盒子脱离浏览器窗口时,浏览器窗口就会关闭,不需要投递
|
||
if (box_count > 1)
|
||
drag_browser_form->PostMessage(WM_LBUTTONUP, 0, 0);
|
||
}
|
||
// 如果没有被拖拽到另一个浏览器窗口里
|
||
else
|
||
{
|
||
// 如果被拖拽的浏览器窗口里只有一个浏览器盒子,则拖拽失败
|
||
if (1 == box_count)
|
||
{
|
||
drag_browser_form->OnAfterDragBoxCallback(false);
|
||
}
|
||
// 如果有多个浏览器盒子, 就把浏览器盒子脱离原浏览器窗口,附加到新的浏览器窗口,拖拽成功
|
||
else
|
||
{
|
||
drag_browser_form->OnAfterDragBoxCallback(true);
|
||
|
||
if (drag_browser_form->DetachBox(draging_box_))
|
||
{
|
||
MultiBrowserForm *browser_form = new MultiBrowserForm;
|
||
HWND hwnd = browser_form->Create(NULL, L"MultiBrowser", UI_WNDSTYLE_FRAME, 0, false);
|
||
if (hwnd != NULL)
|
||
{
|
||
if (browser_form->AttachBox(draging_box_))
|
||
{
|
||
// 这里设置新浏览器窗口的位置,设置到偏移鼠标坐标100,20的位置
|
||
POINT pt_mouse;
|
||
::GetCursorPos(&pt_mouse);
|
||
ui::UiRect rect(pt_mouse.x + kDragFormXOffset, pt_mouse.y + kDragFormYOffset, 0, 0);
|
||
browser_form->SetPos(rect, false, SWP_NOSIZE);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果没有被拖拽到另一个浏览器窗口里,这时不会有浏览器窗口被关闭,所以直接投递ButtonUp消息
|
||
drag_browser_form->PostMessage(WM_LBUTTONUP, 0, 0);
|
||
}
|
||
|
||
draging_box_ = NULL;
|
||
drop_browser_form_ = NULL;
|
||
} |