CWindowWnd代码在UIBase.h和UIBase.cpp文件里。主要实现的是一个基本窗口的创建与消息处理。

相关代码:

头文件:

class UILIB_API CWindowWnd
{
public:
CWindowWnd(); HWND GetHWND() const;
operator HWND() const; bool RegisterWindowClass();
bool RegisterSuperclass(); HWND Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, const RECT rc, HMENU hMenu = NULL);
HWND Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int cx = CW_USEDEFAULT, int cy = CW_USEDEFAULT, HMENU hMenu = NULL);
HWND CreateDuiWindow(HWND hwndParent, LPCTSTR pstrWindowName,DWORD dwStyle =, DWORD dwExStyle =);
HWND Subclass(HWND hWnd);
void Unsubclass();
void ShowWindow(bool bShow = true, bool bTakeFocus = true);
UINT ShowModal();
void Close(UINT nRet = IDOK);
void CenterWindow(); // 居中,支持扩展屏幕
void SetIcon(UINT nRes); LRESULT SendMessage(UINT uMsg, WPARAM wParam = , LPARAM lParam = 0L);
LRESULT PostMessage(UINT uMsg, WPARAM wParam = , LPARAM lParam = 0L);
void ResizeClient(int cx = -, int cy = -); protected:
virtual LPCTSTR GetWindowClassName() const = ;
virtual LPCTSTR GetSuperClassName() const;
virtual UINT GetClassStyle() const; virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual void OnFinalMessage(HWND hWnd); static LRESULT CALLBACK __WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK __ControlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); protected:
HWND m_hWnd;
WNDPROC m_OldWndProc;
bool m_bSubclassed;
};

源文件:

//////////////////////////////////////////////////////////////////////////
///
CWindowWnd::CWindowWnd() : m_hWnd(NULL), m_OldWndProc(::DefWindowProc), m_bSubclassed(false)
{
} HWND CWindowWnd::GetHWND() const
{
return m_hWnd;
} UINT CWindowWnd::GetClassStyle() const
{
return ;
} LPCTSTR CWindowWnd::GetSuperClassName() const
{
return NULL;
} CWindowWnd::operator HWND() const
{
return m_hWnd;
} HWND CWindowWnd::CreateDuiWindow( HWND hwndParent, LPCTSTR pstrWindowName,DWORD dwStyle /*=0*/, DWORD dwExStyle /*=0*/ )
{
return Create(hwndParent,pstrWindowName,dwStyle,dwExStyle,,,,,NULL);
} HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, const RECT rc, HMENU hMenu)
{
return Create(hwndParent, pstrName, dwStyle, dwExStyle, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hMenu);
} //调用创建win32创建窗口的API
//如果是控件则GetSuperClassName返回非NULL 调用RegisterSuperclass
//否则调用RegisterWindowClass
//然后使用CreateWindowEx创建窗口
HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, int x, int y, int cx, int cy, HMENU hMenu)
{
if( GetSuperClassName() != NULL && !RegisterSuperclass() ) return NULL;
if( GetSuperClassName() == NULL && !RegisterWindowClass() ) return NULL;
m_hWnd = ::CreateWindowEx(dwExStyle, GetWindowClassName(), pstrName, dwStyle, x, y, cx, cy, hwndParent, hMenu, CPaintManagerUI::GetInstance(), this);
ASSERT(m_hWnd!=NULL);
return m_hWnd;
} //子类化一个控件 m_OldWndProc 保存旧消息处理函数
HWND CWindowWnd::Subclass(HWND hWnd)
{
ASSERT(::IsWindow(hWnd));
ASSERT(m_hWnd==NULL);
m_OldWndProc = SubclassWindow(hWnd, __WndProc);
if( m_OldWndProc == NULL ) return NULL;
m_bSubclassed = true;
m_hWnd = hWnd;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(this));
return m_hWnd;
} //恢复之类化的控件
void CWindowWnd::Unsubclass()
{
ASSERT(::IsWindow(m_hWnd));
if( !::IsWindow(m_hWnd) ) return;
if( !m_bSubclassed ) return;
SubclassWindow(m_hWnd, m_OldWndProc);
m_OldWndProc = ::DefWindowProc;
m_bSubclassed = false;
} void CWindowWnd::ShowWindow(bool bShow /*= true*/, bool bTakeFocus /*= false*/)
{
ASSERT(::IsWindow(m_hWnd));
if( !::IsWindow(m_hWnd) ) return;
::ShowWindow(m_hWnd, bShow ? (bTakeFocus ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE) : SW_HIDE);
} //实现一个modal窗口
UINT CWindowWnd::ShowModal()
{
ASSERT(::IsWindow(m_hWnd));
UINT nRet = ;
HWND hWndParent = GetWindowOwner(m_hWnd);
::ShowWindow(m_hWnd, SW_SHOWNORMAL);
::EnableWindow(hWndParent, FALSE);
MSG msg = { };
while( ::IsWindow(m_hWnd) && ::GetMessage(&msg, NULL, , ) ) {
if( msg.message == WM_CLOSE && msg.hwnd == m_hWnd ) {
nRet = msg.wParam;
::EnableWindow(hWndParent, TRUE);
::SetFocus(hWndParent);
}
if( !CPaintManagerUI::TranslateMessage(&msg) ) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
if( msg.message == WM_QUIT ) break;
}
::EnableWindow(hWndParent, TRUE);
::SetFocus(hWndParent);
if( msg.message == WM_QUIT ) ::PostQuitMessage(msg.wParam);
return nRet;
} void CWindowWnd::Close(UINT nRet)
{
ASSERT(::IsWindow(m_hWnd));
if( !::IsWindow(m_hWnd) ) return;
PostMessage(WM_CLOSE, (WPARAM)nRet, 0L);
} void CWindowWnd::CenterWindow()
{
ASSERT(::IsWindow(m_hWnd));
ASSERT((GetWindowStyle(m_hWnd)&WS_CHILD)==);
RECT rcDlg = { };
::GetWindowRect(m_hWnd, &rcDlg);
RECT rcArea = { };
RECT rcCenter = { };
HWND hWnd=*this;
HWND hWndParent = ::GetParent(m_hWnd);
HWND hWndCenter = ::GetWindowOwner(m_hWnd);
if (hWndCenter!=NULL)
hWnd=hWndCenter; // 处理多显示器模式下屏幕居中
MONITORINFO oMonitor = {};
oMonitor.cbSize = sizeof(oMonitor);
::GetMonitorInfo(::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST), &oMonitor);
rcArea = oMonitor.rcWork; if( hWndCenter == NULL )
rcCenter = rcArea;
else
::GetWindowRect(hWndCenter, &rcCenter); int DlgWidth = rcDlg.right - rcDlg.left;
int DlgHeight = rcDlg.bottom - rcDlg.top; // Find dialog's upper left based on rcCenter
int xLeft = (rcCenter.left + rcCenter.right) / - DlgWidth / ;
int yTop = (rcCenter.top + rcCenter.bottom) / - DlgHeight / ; // The dialog is outside the screen, move it inside
if( xLeft < rcArea.left ) xLeft = rcArea.left;
else if( xLeft + DlgWidth > rcArea.right ) xLeft = rcArea.right - DlgWidth;
if( yTop < rcArea.top ) yTop = rcArea.top;
else if( yTop + DlgHeight > rcArea.bottom ) yTop = rcArea.bottom - DlgHeight;
::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -, -, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
} //从资源设置图标
void CWindowWnd::SetIcon(UINT nRes)
{
HICON hIcon = (HICON)::LoadImage(CPaintManagerUI::GetInstance(), MAKEINTRESOURCE(nRes), IMAGE_ICON,
(::GetSystemMetrics(SM_CXICON) + ) & ~, (::GetSystemMetrics(SM_CYICON) + ) & ~, // 防止高DPI下图标模糊
LR_DEFAULTCOLOR);
ASSERT(hIcon);
::SendMessage(m_hWnd, WM_SETICON, (WPARAM) ICON_SMALL, (LPARAM) hIcon); hIcon = (HICON)::LoadImage(CPaintManagerUI::GetInstance(), MAKEINTRESOURCE(nRes), IMAGE_ICON,
(::GetSystemMetrics(SM_CXICON) + ) & ~, (::GetSystemMetrics(SM_CYICON) + ) & ~, // 防止高DPI下图标模糊
LR_DEFAULTCOLOR);
ASSERT(hIcon);
::SendMessage(m_hWnd, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) hIcon);
} bool CWindowWnd::RegisterWindowClass()
{
WNDCLASS wc = { };
wc.style = GetClassStyle();
wc.cbClsExtra = ;
wc.cbWndExtra = ;
wc.hIcon = NULL;
wc.lpfnWndProc = CWindowWnd::__WndProc;
wc.hInstance = CPaintManagerUI::GetInstance();
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = GetWindowClassName();
ATOM ret = ::RegisterClass(&wc);
ASSERT(ret!=NULL || ::GetLastError()==ERROR_CLASS_ALREADY_EXISTS);
return ret != NULL || ::GetLastError() == ERROR_CLASS_ALREADY_EXISTS;
} //这里应该是创建一个控件类,子类化过的
bool CWindowWnd::RegisterSuperclass()
{
// Get the class information from an existing
// window so we can subclass it later on...
WNDCLASSEX wc = { };
wc.cbSize = sizeof(WNDCLASSEX);
if( !::GetClassInfoEx(NULL, GetSuperClassName(), &wc) ) {
if( !::GetClassInfoEx(CPaintManagerUI::GetInstance(), GetSuperClassName(), &wc) ) {
ASSERT(!"Unable to locate window class");
return NULL;
}
}
m_OldWndProc = wc.lpfnWndProc;
wc.lpfnWndProc = CWindowWnd::__ControlProc;
wc.hInstance = CPaintManagerUI::GetInstance();
wc.lpszClassName = GetWindowClassName();
ATOM ret = ::RegisterClassEx(&wc);
ASSERT(ret!=NULL || ::GetLastError()==ERROR_CLASS_ALREADY_EXISTS);
return ret != NULL || ::GetLastError() == ERROR_CLASS_ALREADY_EXISTS;
} //默认的消息处理函数 注册窗口时使用过
LRESULT CALLBACK CWindowWnd::__WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowWnd* pThis = NULL;
if( uMsg == WM_NCCREATE ) {
//首次创建窗口时调用
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
pThis = static_cast<CWindowWnd*>(lpcs->lpCreateParams);
pThis->m_hWnd = hWnd;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis));
}
else {
pThis = reinterpret_cast<CWindowWnd*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
//销毁窗口时调用
if( uMsg == WM_NCDESTROY && pThis != NULL ) {
//把消息传递到上一层
LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam);
::SetWindowLongPtr(pThis->m_hWnd, GWLP_USERDATA, 0L);
//如果已经子类化了,则恢复
if( pThis->m_bSubclassed ) pThis->Unsubclass();
pThis->m_hWnd = NULL;
//调用OnFinalMessage OnFinalMessage一般做最后的处理
pThis->OnFinalMessage(hWnd);
return lRes;
}
}
if( pThis != NULL ) {
//调用HandleMessage来处理消息
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
} //控件的消息处理函数
LRESULT CALLBACK CWindowWnd::__ControlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowWnd* pThis = NULL;
if( uMsg == WM_NCCREATE ) {
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
pThis = static_cast<CWindowWnd*>(lpcs->lpCreateParams);
::SetProp(hWnd, _T("WndX"), (HANDLE) pThis);
pThis->m_hWnd = hWnd;
}
else {
pThis = reinterpret_cast<CWindowWnd*>(::GetProp(hWnd, _T("WndX")));
if( uMsg == WM_NCDESTROY && pThis != NULL ) {
LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam);
if( pThis->m_bSubclassed ) pThis->Unsubclass();
::SetProp(hWnd, _T("WndX"), NULL);
pThis->m_hWnd = NULL;
pThis->OnFinalMessage(hWnd);
return lRes;
}
}
if( pThis != NULL ) {
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
} LRESULT CWindowWnd::SendMessage(UINT uMsg, WPARAM wParam /*= 0*/, LPARAM lParam /*= 0*/)
{
ASSERT(::IsWindow(m_hWnd));
return ::SendMessage(m_hWnd, uMsg, wParam, lParam);
} LRESULT CWindowWnd::PostMessage(UINT uMsg, WPARAM wParam /*= 0*/, LPARAM lParam /*= 0*/)
{
ASSERT(::IsWindow(m_hWnd));
return ::PostMessage(m_hWnd, uMsg, wParam, lParam);
} void CWindowWnd::ResizeClient(int cx /*= -1*/, int cy /*= -1*/)
{
ASSERT(::IsWindow(m_hWnd));
RECT rc = { };
if( !::GetClientRect(m_hWnd, &rc) ) return;
if( cx != - ) rc.right = cx;
if( cy != - ) rc.bottom = cy;
if( !::AdjustWindowRectEx(&rc, GetWindowStyle(m_hWnd), (!(GetWindowStyle(m_hWnd) & WS_CHILD) && (::GetMenu(m_hWnd) != NULL)), GetWindowExStyle(m_hWnd)) ) return;
::SetWindowPos(m_hWnd, NULL, , , rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
} //虚函数 用于在子类里重写此函数接管消息
LRESULT CWindowWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return ::CallWindowProc(m_OldWndProc, m_hWnd, uMsg, wParam, lParam);
} void CWindowWnd::OnFinalMessage(HWND /*hWnd*/)
{
} //////////////////////////////////////////////////////////////////////////

流程:

调用Create创建一个窗口,使用RegisterSuperclass或RegisterWindowClass注册类,调用CreateWindowEx创建窗口返回句柄。
RegisterSuperclass使用CWindowWnd::__ControlProc作为窗口消息处理函数,
RegisterWindowClass使用CWindowWnd::__WndProc作为消息处理函数。
两个消息处理函数除了WM_NCDESTROY以外其他消息都通过HandleMessage来处理,所以继承类中只要重载HandleMessage就可以处理大部分消息了。

CWindowWnd类源码分析的更多相关文章

  1. List 接口以及实现类和相关类源码分析

    List 接口以及实现类和相关类源码分析 List接口分析 接口描述 用户可以对列表进行随机的读取(get),插入(add),删除(remove),修改(set),也可批量增加(addAll),删除( ...

  2. Cocos2d-X3.0 刨根问底(六)----- 调度器Scheduler类源码分析

    上一章,我们分析Node类的源码,在Node类里面耦合了一个 Scheduler 类的对象,这章我们就来剖析Cocos2d-x的调度器 Scheduler 类的源码,从源码中去了解它的实现与应用方法. ...

  3. Java Properties类源码分析

    一.Properties类介绍 java.util.Properties继承自java.util.Hashtable,从jdk1.1版本开始,Properties的实现基本上就没有什么大的变动.从ht ...

  4. java中List接口的实现类 ArrayList,LinkedList,Vector 的区别 list实现类源码分析

    java面试中经常被问到list常用的类以及内部实现机制,平时开发也经常用到list集合类,因此做一个源码级别的分析和比较之间的差异. 首先看一下List接口的的继承关系: list接口继承Colle ...

  5. Java并发编程笔记之Unsafe类和LockSupport类源码分析

    一.Unsafe类的源码分析 JDK的rt.jar包中的Unsafe类提供了硬件级别的原子操作,Unsafe里面的方法都是native方法,通过使用JNI的方式来访问本地C++实现库. rt.jar ...

  6. String 类源码分析

    String 源码分析 String 类代表字符序列,Java 中所有的字符串字面量都作为此类的实例. String 对象是不可变的,它们的值在创建之后就不能改变,因此 String 是线程安全的. ...

  7. Cocos2d-X3.0 刨根问底(三)----- Director类源码分析

    上一章我们完整的跟了一遍HelloWorld的源码,了解了Cocos2d-x的启动流程.其中Director这个类贯穿了整个Application程序,这章随小鱼一起把这个类分析透彻. 小鱼的阅读源码 ...

  8. Java线程池ThreadPoolExecutor类源码分析

    前面我们在java线程池ThreadPoolExecutor类使用详解中对ThreadPoolExector线程池类的使用进行了详细阐述,这篇文章我们对其具体的源码进行一下分析和总结: 首先我们看下T ...

  9. Spring之WebContext不使用web.xml启动 初始化重要的类源码分析(Servlet3.0以上的)

    入口: org.springframework.web.SpringServletContainerInitializer implements ServletContainerInitializer ...

随机推荐

  1. VMWARE下CentOS7虚拟机网络配置

    注:本文仅针对新装的虚拟机,#ip addr 获取不到ip信息,无法连接网络的情况提供一种参考解决方案. 1.左上角点击“编辑”->“虚拟网络编辑器”.新建一个NAT模式的网络. 2.配置虚拟机 ...

  2. 【luogu P1262 间谍网络】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1262 注意: 1.缩点时计算出入度是在缩完点的图上用color计算.不要在原来的点上计算. 2.枚举出入度时 ...

  3. 【luogu P2298 Mzc和男家丁的游戏】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2298 对于迷宫问题,bfs是比较好的选择. 直接bfs模板 #include <iostream> ...

  4. 测试Storm的多源头锚定

    过程, Spout 发送msgid 1-10 一级Bolt, msgid1的tuple做为基本组合tuple, 其他8个和一组合, 然后发送给二级Bolt, 同时单个msgid对应的tuple都ack ...

  5. Django-rest-framework(二)serializers 使用

    简介 初次见到serializers文件,想必大家都会感到陌生,所以,我们不妨换个词来形容他的作用,那就是django 中的Form,这样是不是感觉熟悉了一点. 实际上,serializers 的作用 ...

  6. Sass 基础(七)

    Sass Maps 的函数-map-remove($map,$key),keywords($args) map-remove($map,$key) map-remove($map,$key)函数是用来 ...

  7. Maria-DB

    mysql客户端可用选项: -A, --no-auto-rehash 禁止补全 -u, --user= 用户名,默认为root -h, --host= 服务器主机,默认为localhost -p, - ...

  8. oracle约束约束状态和设计习惯

    oracle约束状态有几个项目,会让人迷惑,分别是: enable/disable--是否启用/禁用 validate/invalidate--确认/不确认 deferrable/not deferr ...

  9. Dockerfile中npm中Error: could not get uid/gid问题的解决方法

    dockerfile 中  使用 npm 的时候报错:   解决办法:https://github.com/tootsuite/mastodon/issues/802              

  10. 01javascript基础

    1.JavaScript:直接写入 HTML 输出流 实例:(只能在 HTML 输出中使用 document.write.如果在文档加载后使用该方法,会覆盖整个文档) <!DOCTYPE htm ...