窗口管理类:
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);
本文暂时没有评论,来添加一个吧(●'◡'●)