编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

duilib 之窗口(duilib子窗口)

wxchong 2024-08-08 01:06:51 开源技术 27 ℃ 0 评论

窗口管理类:

duilib有一个窗口管理类:

class WindowsManager
{
public:
	SINGLETON_DEFINE(WindowsManager);
	WindowsManager();
	virtual ~WindowsManager();

	//根据窗口类名和id注册窗口
	bool RegisterWindow(const std::wstring wnd_class_name, const std::wstring wnd_id, WindowEx *wnd);
	//根据窗口类名和id注销窗口
	void UnRegisterWindow(const std::wstring &wnd_class_name, const std::wstring &wnd_id, WindowEx *wnd);
	//根据窗口类名和id获取窗口
	WindowEx* GetWindow(const std::wstring &wnd_class_name, const std::wstring &wnd_id);
	//获取所有窗口
	WindowList GetAllWindows();
	//获取指定class对应的所有窗口
	WindowList GetWindowsByClassName(LPCTSTR classname);
	//关闭所有窗口
	void DestroyAllWindows();
	//设置禁止窗口创建
	void SetStopRegister(bool stop=true){stop_register_ = stop;}
	//是否禁止窗口创建
	bool IsStopRegister(){return stop_register_;}

	template<typename WindowType>
	static WindowType* SingletonShow(const std::wstring& window_id,int nParam=-1,bool bSHow=true,HWND hParent=NULL)
	{
		if (nParam > 0)
			kClass_Param_map[WindowType::kClassName] = nParam;


		WindowType *window = (WindowType*)(WindowsManager::GetInstance()->GetWindow(WindowType::kClassName, window_id));
		if (!window)
		{
			window = new WindowType;
			window->Create(hParent, WindowType::kClassName, WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, 0);
			
			window->CenterWindow();
		
			if (bSHow)
			{
				window->ShowWindow();
			}
			
		}
		else
		{
			window->ActiveWindow();
		}

		return window;
	}

private:
	WindowsMap					windows_map_;	//所有窗口
	std::string					user_id_;
	bool						stop_register_;	//禁止窗口创建
public:
	static std::map<std::wstring, int> kClass_Param_map; // 窗口创建前,对应kClassName窗口中的参数,用此参数可以进行不同的初始化处理
};


其中,使用静态单例模板函数SingletonShow 来创建窗口

我们自己的写的窗口类,都是继承于 WindowEx

比如:

class HelpForm :public nim_comp::WindowEx
{
public:
	HelpForm();
	~HelpForm();


窗口基类:

class WindowEx : public ui::WindowImplBase
{
public:
	WindowEx();
	virtual ~WindowEx();

	virtual HWND Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, 
		bool isLayeredWindow = true, const ui::UiRect& rc = ui::UiRect(0, 0, 0, 0)) override;
	
	virtual LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	virtual void OnEsc(BOOL &bHandled);
		
	virtual std::wstring GetWindowClassName(void) const = 0;
	virtual std::wstring GetWindowId(void) const = 0;
	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);

	void ActiveWindow();  //激活窗口
	void SetTaskbarTitle(const std::wstring &title);

private:
	bool RegisterWnd();
	void UnRegisterWnd();
};


窗口的默认处理过程

WindowEx::WindowEx()
{
}

WindowEx::~WindowEx()
{
}

HWND WindowEx::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, bool isLayeredWindow, const ui::UiRect& rc)
{
	if (!RegisterWnd())
	{
		return NULL;
	}

	HWND hwnd = __super::Create(hwndParent, pstrName, dwStyle, dwExStyle, isLayeredWindow, rc);
	ASSERT(hwnd);
	return hwnd;
}

LRESULT WindowEx::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	UnRegisterWnd();
	return __super::OnDestroy(uMsg, wParam, lParam, bHandled);
}

void WindowEx::OnEsc( BOOL &bHandled )
{
	bHandled = FALSE;
}

bool WindowEx::RegisterWnd()
{
	std::wstring wnd_class_name = GetWindowClassName();
	std::wstring wnd_id = GetWindowId();
	if (!WindowsManager::GetInstance()->RegisterWindow(wnd_class_name, wnd_id, this))
	{
		return false;
	}
	return true;
}

void WindowEx::UnRegisterWnd()
{
	std::wstring wnd_class_name = GetWindowClassName();
	std::wstring wnd_id = GetWindowId();
	WindowsManager::GetInstance()->UnRegisterWindow(wnd_class_name, wnd_id, this);
}

LRESULT WindowEx::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if(uMsg == WM_CLOSE)
	{
		if(!::IsWindowEnabled(m_hWnd))
		{
			::SetForegroundWindow(m_hWnd);
			return FALSE;
		}
	}
	else if(uMsg == WM_KILLFOCUS)
	{
		KillFocus();
	}
	else if(uMsg == WM_KEYDOWN)
	{
		if(wParam == VK_ESCAPE)
		{
			BOOL bHandled = FALSE;
			OnEsc(bHandled);
			if( !bHandled )
				this->Close();
		}
	}
	return __super::HandleMessage(uMsg,wParam,lParam);
}

void WindowEx::ActiveWindow()
{
	if(::IsWindow(m_hWnd))
	{
		if(::IsIconic(m_hWnd))
			::ShowWindow(m_hWnd, SW_RESTORE);
		else 
			::SetForegroundWindow(m_hWnd);
	}
}

void WindowEx::SetTaskbarTitle( const std::wstring &title )
{
	::SetWindowTextW(m_hWnd, title.c_str());
}


POINT GetPopupWindowPos( WindowEx* window )
{
	ASSERT( window && IsWindow( window->GetHWND() ) );

	//屏幕大小
	MONITORINFO oMonitor = { sizeof(oMonitor) };
	::GetMonitorInfo( ::MonitorFromWindow( window->GetHWND(), MONITOR_DEFAULTTONEAREST ), &oMonitor );
	RECT screen = oMonitor.rcWork;

	ui::UiRect rect = window->GetPos(true);

	POINT pt = { 0, 0 };
	pt.x = screen.right - rect.GetWidth();
	pt.y = screen.bottom - rect.GetHeight();

	return pt;
}

void ToTopMost(HWND hwnd, bool forever)
{
	ASSERT(::IsWindow(hwnd));
	::SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
	if( !forever )
	{
		::SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
	}
}
}


窗口管理类 调用Create创建窗口

创建窗口,最重要的是这个静态模板函数

	template<typename WindowType>
	static WindowType* SingletonShow(const std::wstring& window_id,int nParam=-1,bool bSHow=true,HWND hParent=NULL)
	{
		if (nParam > 0)
			kClass_Param_map[WindowType::kClassName] = nParam;


		WindowType *window = (WindowType*)(WindowsManager::GetInstance()->GetWindow(WindowType::kClassName, window_id));
		if (!window)
		{
			window = new WindowType;
			window->Create(hParent, WindowType::kClassName, WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, 0);
			
			window->CenterWindow();
		
			if (bSHow)
			{
				window->ShowWindow();
			}
			
		}
		else
		{
			window->ActiveWindow();
		}

		return window;
	}


这里,window->Create(hParent, WindowType::kClassName, WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, 0);

调用的就是:

HWND WindowEx::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, bool isLayeredWindow, const ui::UiRect& rc){ if (!RegisterWnd()) { return NULL; }

HWND hwnd = __super::Create(hwndParent, pstrName, dwStyle, dwExStyle, isLayeredWindow, rc); ASSERT(hwnd); return hwnd;}


如果,需要重写Create,需要重载此函数,比如这个是默认分层窗口,CEF控件不能使用分层窗口,所以需要重载此函数

HWND CEFForm::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle,
	bool isLayeredWindow /*= true*/, const ui::UiRect& rc/* = ui::UiRect(0, 0, 0, 0)*/)
{
	//false 改为非分层窗口 以便加载CEF控件
	return __super::Create(hwndParent, pstrName, dwStyle, dwExStyle, false, rc);
}


一个完整的小示例:

XML

<?xml version="1.0" encoding="UTF-8"?>
<Window caption="0,0,0,40" mininfo="450,450" size="450,450" sizebox="4,4,6,6" shadowattached="false" >
    <VBox bkcolor="xnw_client" bordercolor="green" bordersize="1,1,1,1" padding="1,1,1,1">
        <!-- 客户端名称设置 -->
        <HBox height="40" bkcolor="white">
            <Control />
            <Label text="帮助" valign="center" font="2" normaltextcolor="black" />
            <Control />
            <Button class="btn_wnd_close_black" name="myClosebtn" margin="0,0,10,0" valign="center" />
        </HBox>
        <CefControl name="cef_control"/>
    </VBox>
</Window>


class HelpForm :public nim_comp::WindowEx
{
public:
	HelpForm();
	~HelpForm();

	virtual std::wstring GetSkinFolder() override;
	virtual std::wstring GetSkinFile() override;
	virtual std::wstring GetWindowClassName() const override;
	virtual std::wstring GetWindowId() const override;
	virtual UINT GetClassStyle() const override;

	virtual ui::UILIB_RESOURCETYPE GetResourceType() const;
	virtual std::wstring GetZIPFileName() const;


	virtual LRESULT OnClose(UINT u, WPARAM w, LPARAM l, BOOL &bHandled);
	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;

	virtual void InitWindow() override;
	virtual bool Notify(ui::EventArgs *msg);
	virtual bool OnClicked(ui::EventArgs *msg);

	virtual HWND Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle,
		bool isLayeredWindow = true, const ui::UiRect& rc = ui::UiRect(0, 0, 0, 0)) override;

	virtual ui::Control* CreateControl(const std::wstring& pstrClass) override;

public:
	static const LPCTSTR kClassName;
	std::wstring localFoldPathW;
	std::string localFoldPath;

	MyClassForm* pClassForm;
	ui::CefControlBase* cef_control_;
};


//封装win32控件  结合定时器适时更新控件位置
ui::Control* HelpForm::CreateControl(const std::wstring& pstrClass)
{

	// 扫描 XML 发现有名称为 CefControl 的节点,则创建一个 ui::CefControl 控件
	if (pstrClass == L"CefControl")
	{
		if (nim_cef::CefManager::GetInstance()->IsEnableOffsetRender())
			return new ui::CefControl;
		else
			return new ui::CefNativeControl;
	}
	return NULL;
}



using namespace ui;
const LPCTSTR HelpForm::kClassName = L"HelpForm";

HelpForm::HelpForm()
{



	localFoldPathW = appFolderW + L"\\themes\\default\\HelpForm\\";
	localFoldPath = appFolderA + "\\themes\\default\\HelpForm\\";

}

HelpForm::~HelpForm()
{


}

std::wstring HelpForm::GetSkinFolder()
{

	//return  L"DesktopTool";
	return L"HelpForm";
}

std::wstring HelpForm::GetSkinFile()
{
	//return  L"DesktopTool_2.xml";
	return L"HelpForm.xml";
}

ui::UILIB_RESOURCETYPE HelpForm::GetResourceType() const
{
	return ui::UILIB_FILE;
}

std::wstring HelpForm::GetZIPFileName() const
{
	return L"HelpForm.zip";
}

std::wstring HelpForm::GetWindowClassName() const
{
	return kClassName;
}

std::wstring HelpForm::GetWindowId() const
{
	return kClassName;
}

UINT HelpForm::GetClassStyle() const
{
	return (UI_CLASSSTYLE_FRAME | CS_DBLCLKS);
}

HWND HelpForm::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle,
	bool isLayeredWindow /*= true*/, const ui::UiRect& rc/* = ui::UiRect(0, 0, 0, 0)*/)
{
	//false 改为非分层窗口 以便加载CEF控件
	return __super::Create(hwndParent, pstrName, dwStyle, dwExStyle, false, rc);
}

LRESULT HelpForm::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam){






	return __super::HandleMessage(uMsg, wParam, lParam);
}


void HelpForm::InitWindow()
{
	//SetIcon(IDI_ICON);
	//SetTaskbarTitle(L"我的课");

	m_pRoot->AttachBubbledEvent(ui::kEventAll, nbase::Bind(&HelpForm::Notify, this, std::placeholders::_1));
	m_pRoot->AttachBubbledEvent(ui::kEventClick, nbase::Bind(&HelpForm::OnClicked, this, std::placeholders::_1));


	

	//不在任务栏显示
	LONG styleValue = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
	styleValue &= ~(WS_EX_APPWINDOW);//当窗口可见时将一个顶层窗口放置在任务栏上

	styleValue |= WS_EX_TOOLWINDOW; //工具条窗口样式
	//styleValue |= WS_EX_TOPMOST;    //最顶层
	SetWindowLong(m_hWnd, GWL_EXSTYLE, styleValue);



	::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);

	cef_control_ = dynamic_cast<ui::CefControlBase*>(FindControl(L"cef_control"));

	
	// 加载皮肤目录下的 html 文件
	std::wstring url = L"file://" + localFoldPathW + L"help.html";
	cef_control_->LoadURL(url);
	return;
}

LRESULT HelpForm::OnClose(UINT u, WPARAM w, LPARAM l, BOOL &bHandled){

	return __super::OnClose(u, w, l, bHandled);
}

bool HelpForm::Notify(ui::EventArgs* msg)
{
	std::wstring name = msg->pSender->GetName();

	msg->ptMouse;
	POINT pt;
	pt.x = msg->ptMouse.x;
	pt.y = msg->ptMouse.y;

//	ClientToScreen(m_hWnd, &pt);





	return true;
}

bool HelpForm::OnClicked(ui::EventArgs* msg)
{
	std::wstring name = msg->pSender->GetName();

	if (name == L"myClosebtn")
	{
		::ShowWindow(m_hWnd,SW_HIDE);
	}


	return true;
}


		HelpForm *pForm = (HelpForm*)nim_comp::WindowsManager::SingletonShow<HelpForm>(HelpForm::kClassName);


Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表