首页
社区
课程
招聘
[讨论]关于封装win32的一点感想和疑惑
发表于: 2013-5-29 21:32 13911

[讨论]关于封装win32的一点感想和疑惑

2013-5-29 21:32
13911
如何抽象win32 application为C++类?

今天看来这无疑是个尴尬的问题,因为MFC已经给出了答案,有些人觉得无法超越,有些人虽然可以回答的更完美,又会觉得这没有实质的价值,而大部分人根本没有思考过这个问题,以至于没有人再谈论这个问题。

相信我们在上第一堂C++课的时候,老师都会拿"人"这个对象说事,可是真的要去封装这个对象,
我猜1000人会封装出1000个样子,哪一个又是标准答案?我认为没有,怎么去封装一个对象,这取决于每个人的价值观和世界观,而它们是不能用正确和错误衡量的。

就拿我对上面问题的理解和实现来说吧:

一个win32 application对象,谁来创建?谁来销毁?有什么属性?又有什么方法?我的认知是:

用户移动鼠标双击或右键,启动win32 application,这个事件被系统内核捕获并处理此事件,我们姑且想象有一个名为:OnApplicationStartup的函数在做这项工作,其内部首先创建win32 application对象,至少要有一个CThread类型的属性标识主线程,线程回调函数内创建CModule对象(对pe格式可执行文件的封装),CModule对象调用方法创建主窗口
等等~(任何win32 application可以干的事),直到线程回调函数返回,销毁win32 application对象。



VOID OnApplicationStartup()
{
	CProcess theApp = new CProcess();

	theProcess.Create();
}



class CProcess 
{
public:
	CProcess()
	{

	}

	CThread * m_Thread;

	BOOL Create()
	{
		m_Thread = new CThread();

		m_Thread.ThreadProc();
	}

	~CProcess()
	{
		delete(m_Thread);
	}
};
/************************************************************************/
/*                                                                      */
/************************************************************************/
class CThread
{
public:
	CThread();

	DWORD WINAPI ThreadProc(LPVOID lpParam)
	{
		CModule thePE;

		thePE.CreateWindow();

		thePE.MessageLoop();

		//...
		//...
		return 0;
	}
	~CThread();
};
/************************************************************************/
/*                                                                      */
/************************************************************************/





如果这个认知没有错,进程对象中有线程对象,线程对象中有PE对象,PE对象中有个方法

叫winmain。

那么一个win32 application要如何封装呢? MFC的那种封装,在逻辑上又合理吗?

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (21)
雪    币: 2859
活跃值: (2663)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
2
一直受这个问题的困扰。求解
2013-5-29 22:09
0
雪    币: 53
活跃值: (528)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
你可以构造一个桩函数。
2013-6-2 22:57
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
已更新...
2013-6-16 00:53
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
已更新...
2013-7-31 02:59
0
雪    币: 1283
活跃值: (46)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
感觉楼主的理解有错误!一个Application一个应用程序,是一个进程,用户点击或者启动程序的时候,有API函数来创建进程,总的来说,就是将整个进程抽象成一个App对象,入口还是有的,只是这个APP对象最主要的就是消息的流通和派遣为主,然后就是程序图标等神马的。纵观qt的QApplication,C++的CApp,都是可以自己继承的,还有Delphi的TApplication对象,里面的抽象狠明确
2013-7-31 11:22
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
我上面说的win32 application对象就是一个CProcess类,最高层就是一个进程类,父类,类2代是CThread线程类,类3代为CModule可执行文件(PE)类,是这样一个逻辑结构,我没太明白
前辈指我哪一点理解错误? 能否详细再说一下?

另外以我现在学习研究成果来看,封装win32有2个难点, 1个是如何合理的封装回掉函数到类中,这一点我已经利用thunk技术解决。

另一点是类与类共享数据的问题,目前我还没想到一个漂亮的方法,

比如MFC中,CWnd和CThread这2类是平行关系, CWnd如何去读取CThread的成员呢?

MFC用的方法内部管理state,全局中间类,

就是那种A交换B,就需要利用C做中介
2013-7-31 13:42
0
雪    币: 196
活跃值: (96)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
8
封装是个聚集过程,前提是把东西都拆散了,然后拼装到一起,取决于抽象能力。比如win32 application,这个概念可以分为,进程/线程/UI/数据/网络/等等,其中每一个又可拆成更零碎的。 可以把这些都做成工具,然后根据具体需求拼装到一起,比如chrome就是一个application带多个process的。
封装回调好像最"完美"的就是thunk了。另外不知lz说的类共享数据是什么,shared_ptr?不知道Wnd和Thread线程之间共享了什么,还是lz只是举个例子。
我对架构比较有兴趣,希望能一起讨论。
2013-8-1 10:07
0
雪    币: 28
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
9
不清楚你说的Win32 application到底是指MFC中构建应用程序的模型,还是指一般意义上的windows应用程序。我觉得要首先区别开来,所考虑的到底是在应用程序内部代码级别的抽象,还是系统在运行时各组件之间的模块化抽象。

这里你模糊了两个概念,运行时的模块化抽象,以及属于应用程序内部尚在代码级别的抽象。
作为windows 应用程序,可以认为编写的时候有一个"底限",像入口函数,进程,线程,回调等,这是windows提供给你使用的最小单元了。也许你能换个名字,入口不叫main叫start,进程叫器官,线程叫组织,等等,但windows已经定义好了windows应用程序执行的方式,你再怎么改最终都会回到这些最基本的单元上来。这些都属于应用程序内部的抽象。
如果想改变应用程序的运行方式,在基本单元上进一步抽象,要么你去改变windows内核的运行方式,要么做个虚拟机,虚拟机内部"应用程序"的执行完全按照任意设计抽象、封装、执行,但虚拟机本身是要在windows上跑的,终究躲不开要使用基本单元的命运。

MFC不过就是提供了一种对Win32API的封装而已便于在编写应用程序时调用,可以比较一下和它最像的WxWidgets。
2013-8-1 10:10
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
我说的类与类共享数据是指:   

比如CreateWindow就需要传入实例举柄和父窗口句柄等参数,如果封装一个控件类和对话框类,

CStatusBar吧,不继承,不传参数的情况下,可以直接创建和启动对象,

CStatusBar    theBar;

theBar.Create();

实例句柄可以调用GetModuleHandle(NULL)来获取,可父窗口如何获取?

MFC里CThread类就保存着CWnd的指针,是InitInstance函数里创建主窗口后赋值的,

可是CStatusBar和CThread没有父子,朋友关系,如何获取CThread类中的CWnd成员呢?

MFC是使用STATE模板类来实现的
2013-8-2 10:18
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
噢,我没有前辈站的高,看得远, 我说的应该是运行时的模块抽象吧,就是像MFC那种帮助编成用的,
2013-8-2 10:27
0
雪    币: 28
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
那就和wx比较一下吧,wx比MFC更有助于理解
2013-8-2 11:02
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
谢谢前辈指点,我就去学习一下WxWidgets
2013-8-2 11:22
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
前辈我还是没找到,类与类共享数据的方法,

其实每个类都可以访问到的数据,就一定是全局的, 但是我不想像MFC一样,在库中申请全局

数据,  我觉得FS指向的TEB是系统维护的,我们所有的类都可以访问到。

通过NtCurrentTeb获取,在TEB结构中某个保留字段,写上CThread的this指针,

这样cwnd就可以访问到cthread类中的数据了,

可是有兼容问题,不同的系统TEB的结构会不会有不同。

不知道前辈可知道其他方法?
2013-8-2 16:15
0
雪    币: 28
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
15
我不是前辈,也就是大家一起探讨而已。
类之间共享数据要么全局,要么有接口。
TEB的结构是系统定义的,不同系统不同完全可能,不过只要你用恰当的API获得,用恰当的头文件获得其结构,兼容不同系统也不是问题。但不能写在TEB的reserved filed中,你不确定系统会用这些保留字段来做什么。你是希望把TEB用作全局变量,在cwnd和cthread之间传递数据么?那为什么不自己重新封装一下cthread,里面可以增加你需要的任何信息比如TEB,再弄个接口给cwnd访问呢?
2013-8-2 16:29
0
雪    币: 28
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
16
而且既然是封装抽象,cthread本该隐藏thread的细节,而只暴露被操作的接口给外部即可。如果cwnd都要访问cthread内部细节了,那这种封装从抽象上说对模块化设计无益处。
2013-8-2 16:31
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
我是想把TEB做全局变量的, 3人行必有我师,叫前辈是应该的,

前辈的意思,我再封装一个类, class MyTib public NT_TIB,(头文件找不到TEB,只有TIB)

MyTib *  theTib = NtCurrentTeb(),  此类的指针通过FS:[18]来获取,呵呵,这是个好方法

我去试试看,谢谢前辈了
2013-8-2 16:45
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
class MyTib public NT_TIB,这种方法恐怕不行哟,TEB尺寸是定义好的,如果继承它,在尾部

添加数据,就会冲掉原先其他的成员,

像MFC那样,MyApp 继承 CWinApp 继承 CThread

MyApp的this指针通过:

dwIndex = TlsAlloc()

TlsSetValue(dwIndex,this);

可是如果dwIndex不是全局的,其他类又如何获取呢?
2013-8-2 17:41
0
雪    币: 196
活跃值: (96)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
19
MyApp 的实例 为什么不做成全局变量
2013-8-2 18:39
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
嗯,我想,能不用全局,最好不用, 使用全局,当然是最简单直接的办法咯。
2013-8-3 07:01
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
苦思冥想中
2013-8-6 08:59
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
无人问津
2013-8-27 10:20
0
游客
登录 | 注册 方可回帖
返回
//