<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog.html" frameborder="0" width="728" scrolling="no" height="90"></iframe>
概述
我们已经介绍了Windows SDK的Hello程序,它的流程主要分为三个步骤:
- 注册窗口类(RegisterClass)。并且我们详细解释了为何要有窗口类,为何要RegisterClass。
- 创建并显示窗口(CreateWindow and ShowWindow)。
- 消息循环(MessageLoop)。即:取得消息 -> 分派消息 -> 处理消息。
这里,我们就要结合WINX的Hello程序,把整个流程串一遍。
作为比较,我想温习一下ATL/WTL的Hello程序。我们在此提供了几篇剖析ATL/WTL的Hello程序的好文章:
WINX的Hello程序
#defineWINX_USE_APPMODULE
#includewinx.h>
classCHelloMainFrame:publicwinx::MainFrameCHelloMainFrame>
{
WINX_CLASS("CHelloMainFrame");
public:
voidOnPaint(HWNDhWnd)
{
winx::PaintDCdc(hWnd);
dc.TextOut(1,1,_T("Hello,WINX!"));
}
};
winx::CAppModule_Module;
intAPIENTRYWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPSTRlpCmdLine,
intnCmdShow)
{
CAppModuleInitmodule;
CHelloMainFrame::RegisterClass();
CHelloMainFramewndMain;
wndMain.Create(NULL,_T("Hello"));
returnmodule.Run();
}
WINX的编程模型
1. 注册窗口类(RegisterClass)
WINX中RegisterClass是需要主动调用的,这倒省了象ATL/WTL那样解释半天:-)
区别于已知的所有C++界面库(MFC、ATL/WTL、SmartWin、wxWidgets等等,甚至包括我早期写的SW系统),WINX倾向于把RegisterClass概念告诉用户。并且,为此我专门写了一篇“Windows精解:窗口类释疑”来解释相关概念的重要性。这一切与WINX的可视化策略有关,我们在“WINX如何做到可视化界面开发”中详述这一点。
以下这些宏与WINX的RegisterClass有关:
- WINX_CLASS / WINX_CLASS_EX
- WINX_CLASS_STYLE
- WINX_DEFAULT_BKGND / WINX_DEFAULT_COLOR / WINX_DEFAULT_BRUSH
- WINX_DEFAULT_CURSOR / WINX_DEFAULT_SYSCURSOR
它们分别对应Windows窗口类(WNDCLASSEX)中的成员:
- lpszClassName
- style
- hbrBackground
- hCursor
大家已经熟悉用WINX_CLASS指定窗口类的名称,其他宏的用法完全一致。例如,默认鼠标光标是箭头(IDC_ARROW),要改为象Edit控件一样使用IDC_IBEAM,很容易:
classCHelloMainFrame:publicwinx::MainFrameCHelloMainFrame>
{
WINX_DEFAULT_SYSCURSOR(IDC_IBEAM);
...
};
2. 初始化类(InitClass)
WINX引入了许多小巧的初始化类。大致有:
- CComAppInit-COM初始化类,即CoInitialize/CoUninitialize对。
- COleAppInit - OLE初始化类,即OleInitialize/OleUninitialize对。
- CDebugAppInit - 启动内存泄漏调试(仅Debug版本,Release版本为空类)。
- CComModuleInit - CComModule Init/Term。
- CAppModuleInit - CAppModule Init/Term。
- GdiplusAppInit - GdiplusStartup/GdiplusShutdown。
这些初始化类代码简单,但是抽象得恰到好处。在WINX之前,我曾经试图把这些初始化过程包装起来不让用户看到,但是最终不得不放弃。
3. 消息循环(MessageLoop)
目前,WINX并未提供自己的消息循环。我们借用WTL的CMessageLoop::Run。你没有在WINX的例子中见到CMessageLoop,是因为它被CAppModuleInit 类隐藏起来了。
classCAppModuleInit:publicWTL::CMessageLoop
{
public:
CAppModuleInit(
_ATL_OBJMAP_ENTRY*p=NULL,
HINSTANCEhInst=GetThisModule(),
constGUID*plibid=NULL)
{
_Module.Init(p,hInst,plibid);
_Module.AddMessageLoop(this);
}
~CAppModuleInit()
{
_Module.Term();
}
};
4. 窗口过程(WindowProc)
消息循环中,消息最终被Windows发送到窗口过程(WindowProc)中。那么WINX的窗口过程在哪?
templateclassWindowClass,classHandleClass=DefaultWindowHandle>
classWindow
{
public:
staticLRESULTCALLBACKWindowProc(
HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)
{
WindowClass*pWnd=(WindowClass*)WindowMap::GetWindow(hWnd);
if(pWnd==NULL)
{
if(message!=WM_NCCREATE)
returnpWnd->InternalDefault(hWnd,message,wParam,lParam);
LPCREATESTRUCTlpCS=(LPCREATESTRUCT)lParam;
if(lpCS->lpCreateParams){
pWnd=(WindowClass*)lpCS->lpCreateParams;
lpCS->lpCreateParams=NULL;
}
else{
if(WindowClass::StackWindowObject){
WINX_ASSERT("WindowClass::StackWindowObject-unexpected!");
returnFALSE;
}
else{
pWnd=WINX_NEW(WindowClass);
}
}
WindowMap::SetWindow(hWnd,pWnd);
}
returnpWnd->ProcessMessage(hWnd,message,wParam,lParam);
}
};
这里面有几个细节需要解释:
- WindowMap::GetWindow/SetWindow是什么?在介绍“SW系统的窗口类”时,我们提到:
- MFC通过一个全局的HashMap建立窗口句柄(hWnd)到窗口对象(pWnd)的映射。
- SW系统通过窗口的UserData建立窗口句柄(hWnd)到窗口对象(pWnd)的映射。
在WINX中,建立两者映射的策略是任选的。除了以上两者中外,还有第三种选择:
- 使用SetProp/GetProp建立映射。并且这是WINX默认的选择。
- 你自己实现的其他方式。
我们简单分析一下,这些方式的利弊。
- 通过HashMap建立映射,问题在于这个HashMap对象如何在其他的DLL中取到?这导致bug或者强耦合的结构。
- 通过窗口的UserData建立映射,问题在于如果UserData已经被占用怎么办?这导致机制上不安全的隐患。
- 使用SetProp/GetProp建立映射,性能比UserData方式慢,但极其安全。
- WindowClass::StackWindowObject是什么?我们知道,对象(当然包括C++窗口对象)有两种创建方式:
- 创建在栈(Stack)上。即以局部自动变量方式创建。
- 创建在堆(Heap)上。即通过new/delete创建。
WINX允许你为窗口类选择其中一种。详细我们在以后由专文叙述。
- 最后,窗口消息被pWnd->ProcessMessage(hWnd,message,wParam,lParam)处理。ProcessMessage进行了最终的消息分派。这一块是WINX消息机制的核心,前面我们我们已经仔仔细细作了讲解:
-WINX的消息分派机制
- WINX的消息分派机制(续)
- WINX的消息分派机制(续2)
-WINX的消息分派机制(终结篇)
相关推荐
mysql winx64 mysql winx64 mysql winx64 mysql winx64
winx64_12102_database_1of2.zip winx64_12102_database_2of2.zip 适用于Windows 64位系统,文件分割成 3个 压缩包,必须集齐3个 文件后才能一起解压一起使用: winx64_12102_database.part3.rar ...
LQ-630KII_WINX64_13 EPSON针式打印驱动程序
mysql-5.6.36-winx64.zip mysql-5.6.36-winx64.zip mysql-5.6.36-winx64.zip
该资源内含:1. MySQL教学资源(数据库基础,DML&DQL;,数据高级查询)并提供测试语句和数据表。2. MySQL winx64安装程序包及安装教程
WinX32 Automation 3.X for Visual Basic PI CCD编程控制手册
oracle 12 C (winx64_12102_client.zip)
mariadb-10.3.7-winx64 MYSQL的完美替代品,mariadb-10.3.7-winx64为稳定版本
MySQL_5.5.20_winx64下载下载
MySQL_5.5.20_winx64.zip
winx64_12102_database_1of2.zip winx64_12102_database_2of2.zip 适用于Windows 64位系统,文件分割成 3个 压缩包,必须集齐3个 文件后才能一起解压一起使用: winx64_12102_database.part3.rar ...
mysql-5.7.32-winx64.msi
mysql-8.0.21-winx64.zip.zip mysql-8.0.21-winx64.zip.zip mysql-8.0.21-winx64.zip.zip
Oracle Database 12c 适用于Windows 64位系统, winx64_12102_database文件分割成 三个 压缩包,必须集齐 三个 文件后才能一起解压一起使用: Oracle Database 12c (winx64_12102_database.part3.rar) ...
mysql-workbench-community-8.0.19-winx64.zipmysql-workbench-community-8.0.19-winx64.zipmysql-workbench-community-8.0.19-winx64.zipmysql-workbench-community-8.0.19-winx64.zipmysql-workbench-community-...
MySQL-5.7.36-winx64
MySQL-5.5.28-winx64安装包以及说明文档,欢迎下载阅读
MySQL数据库Windows版本:mysql-8.0.26-winx64.zip
最新版windows mariadb-10.5.4-winx64.zip最新版windows mariadb-10.5.4-winx64.zip
最新版windows mysql-8.1.0-winx64.zip最新版windows mysql-8.1.0-winx64.zip最新版windows mysql-8.1.0-winx64.zip最新版windows mysql-8.1.0-winx64.zip