关于cbClsExtra和cbWndExtra的疑惑 如果说通过一个窗口类创建多个窗口,那么GWL_USERDATA又是什么呢?好像又重叠了。没人回,因为分少? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 代码没仔细看, 首先这个“类名”的历史,估计是 c++还没在windows上大行其道的时候,就引入了,所以别和面向对象中的类混在一块。第二:这个“类名”是不能够继承的, 可以说,我不明白继承这东西有什么意义 代码没仔细看, 首先这个“类名”的历史,估计是 c++还没在windows上大行其道的时候,就引入了,所以别和面向对象中的类混在一块。第二:这个“类名”是不能够继承的, 可以说,我不明白继承这东西有什么意义第一,代码没仔细看,就发表评论,会不会有些不负责任?第二,面向对象是编程思想,和C++有什么关系? 他俩是用等号联系吗?很多论文和书籍,都曾经提到,windows是按面向对象的思想设计的。第三,怎么就不能继承呢?难道必须语言内部支持,才可以实现面向对象的特性吗?lua那种用C实现的小巧脚本语言,同样可以把面向对象表现的淋漓尽致。至于有什么意义? 你可以不去做,但是必须要懂,刨根究底,是搞技术的好品质,只有懂的越多,遇到问题,才能想出更多的解决方案。 同样是程序员,高手和菜鸟用什么来区分? windows API函数没有采用OOP机制此类为窗口类,不是OOP中的类,不能继承,不要搞混了,虽然名字都是叫CLASS留下这两个字段的空间,是为了扩展性或者程序员自已定义使用。 代码没仔细看, 首先这个“类名”的历史,估计是 c++还没在windows上大行其道的时候,就引入了,所以别和面向对象中的类混在一块。第二:这个“类名”是不能够继承的, 可以说,我不明白继承这东西有什么意义第一,代码没仔细看,就发表评论,会不会有些不负责任?第二,面向对象是编程思想,和C++有什么关系? 他俩是用等号联系吗?很多论文和书籍,都曾经提到,windows是按面向对象的思想设计的。第三,怎么就不能继承呢?难道必须语言内部支持,才可以实现面向对象的特性吗?lua那种用C实现的小巧脚本语言,同样可以把面向对象表现的淋漓尽致。至于有什么意义? 你可以不去做,但是必须要懂,刨根究底,是搞技术的好品质,只有懂的越多,遇到问题,才能想出更多的解决方案。 同样是程序员,高手和菜鸟用什么来区分? windows是 面向对象?听谁说的 代码没仔细看, 首先这个“类名”的历史,估计是 c++还没在windows上大行其道的时候,就引入了,所以别和面向对象中的类混在一块。第二:这个“类名”是不能够继承的, 可以说,我不明白继承这东西有什么意义第一,代码没仔细看,就发表评论,会不会有些不负责任?第二,面向对象是编程思想,和C++有什么关系? 他俩是用等号联系吗?很多论文和书籍,都曾经提到,windows是按面向对象的思想设计的。第三,怎么就不能继承呢?难道必须语言内部支持,才可以实现面向对象的特性吗?lua那种用C实现的小巧脚本语言,同样可以把面向对象表现的淋漓尽致。至于有什么意义? 你可以不去做,但是必须要懂,刨根究底,是搞技术的好品质,只有懂的越多,遇到问题,才能想出更多的解决方案。 同样是程序员,高手和菜鸟用什么来区分? 你如果初步了解mfc中的CWnd这个类,就知道,什么时候该用继承,什么不该用了。说白了,那就是一个数据结构,不能够继承的,就这么简单。 getwindowlong是可以通过gwl_userdata获取user data。 这个数据即使你创建窗口的是用没有关联上,也会有数据,至于数据如何来的,不知道。参考:http://bbs.chinaunix.net/thread-2308241-1-1.html第4楼楼主,对这些问题别过于深究,深究意义不大,比如: registerclass后,那么windows如何维护 那些数据结构,你搞得清吗? 代码没仔细看, 首先这个“类名”的历史,估计是 c++还没在windows上大行其道的时候,就引入了,所以别和面向对象中的类混在一块。第二:这个“类名”是不能够继承的, 可以说,我不明白继承这东西有什么意义第一,代码没仔细看,就发表评论,会不会有些不负责任?第二,面向对象是编程思想,和C++有什么关系? 他俩是用等号联系吗?很多论文和书籍,都曾经提到,windows是按面向对象的思想设计的。第三,怎么就不能继承呢?难道必须语言内部支持,才可以实现面向对象的特性吗?lua那种用C实现的小巧脚本语言,同样可以把面向对象表现的淋漓尽致。至于有什么意义? 你可以不去做,但是必须要懂,刨根究底,是搞技术的好品质,只有懂的越多,遇到问题,才能想出更多的解决方案。 同样是程序员,高手和菜鸟用什么来区分? windows是 面向对象?听谁说的首先我说的不是API,我说的windows的设计思想,面向对象是一种思想,而不是形式,你可以拿windows内核源码看一下,这么庞大的操作系统,你们认为他没有一套设计思想?没有一套结构? 内核那么多种对象, 难道是想到哪,写到哪,想到什么,写什么?难道一定要语言支持的样式,才叫面向对象? 不能透过表象看实质嘛? 代码没仔细看, 首先这个“类名”的历史,估计是 c++还没在windows上大行其道的时候,就引入了,所以别和面向对象中的类混在一块。第二:这个“类名”是不能够继承的, 可以说,我不明白继承这东西有什么意义第一,代码没仔细看,就发表评论,会不会有些不负责任?第二,面向对象是编程思想,和C++有什么关系? 他俩是用等号联系吗?很多论文和书籍,都曾经提到,windows是按面向对象的思想设计的。第三,怎么就不能继承呢?难道必须语言内部支持,才可以实现面向对象的特性吗?lua那种用C实现的小巧脚本语言,同样可以把面向对象表现的淋漓尽致。至于有什么意义? 你可以不去做,但是必须要懂,刨根究底,是搞技术的好品质,只有懂的越多,遇到问题,才能想出更多的解决方案。 同样是程序员,高手和菜鸟用什么来区分? 你如果初步了解mfc中的CWnd这个类,就知道,什么时候该用继承,什么不该用了。说白了,那就是一个数据结构,不能够继承的,就这么简单。你这种心态就不太对,难道什么都得过且过,不求甚解,对进步有帮助?你对这个问题根本就不了解,所以给出的答案也让人哭笑不得,C++的类,难道不是数据结构? 他本质上就是,只是隐藏了第一成员,一个函数指针表而已。编译器为他传this指针。C语言模仿C++实现面向对象的所有特质,网上一搜一大把,麻烦你先去看一看。这已经不是天方夜谭了。只要你想知道内核是怎么维护的,可以去逆向win32k呀,我之所以没去,是想来碰碰运气,看看有没有前辈做过同样的事情,愿意分析成果的。 因为我不想造轮子。你说到MFC就更有意思了,它只是在win32上层稍作封装,并没有啥改动,只是用windows hook把窗口回调函数,指向自己而已, 而它的后辈WTL同样,只是用thunk改进了一下window hook消耗过大的问题,这说明什么? 这说明windows这窗口, 本身就有面向对象的精神,骨子里就是,所以根本不需要改,只是用C++这种语言上支持面向对象特性,给它再封装一下,使它变的更清晰一下。 看到楼主的想法,我尿了,楼主啥叫面向对象知道不?wndclass 只是一个名字而已,不是类。概念混淆 代码没仔细看, 首先这个“类名”的历史,估计是 c++还没在windows上大行其道的时候,就引入了,所以别和面向对象中的类混在一块。第二:这个“类名”是不能够继承的, 可以说,我不明白继承这东西有什么意义第一,代码没仔细看,就发表评论,会不会有些不负责任?第二,面向对象是编程思想,和C++有什么关系? 他俩是用等号联系吗?很多论文和书籍,都曾经提到,windows是按面向对象的思想设计的。第三,怎么就不能继承呢?难道必须语言内部支持,才可以实现面向对象的特性吗?lua那种用C实现的小巧脚本语言,同样可以把面向对象表现的淋漓尽致。至于有什么意义? 你可以不去做,但是必须要懂,刨根究底,是搞技术的好品质,只有懂的越多,遇到问题,才能想出更多的解决方案。 同样是程序员,高手和菜鸟用什么来区分? 你如果初步了解mfc中的CWnd这个类,就知道,什么时候该用继承,什么不该用了。说白了,那就是一个数据结构,不能够继承的,就这么简单。你这种心态就不太对,难道什么都得过且过,不求甚解,对进步有帮助?你对这个问题根本就不了解,所以给出的答案也让人哭笑不得,C++的类,难道不是数据结构? 他本质上就是,只是隐藏了第一成员,一个函数指针表而已。编译器为他传this指针。C语言模仿C++实现面向对象的所有特质,网上一搜一大把,麻烦你先去看一看。这已经不是天方夜谭了。只要你想知道内核是怎么维护的,可以去逆向win32k呀,我之所以没去,是想来碰碰运气,看看有没有前辈做过同样的事情,愿意分析成果的。 因为我不想造轮子。你说到MFC就更有意思了,它只是在win32上层稍作封装,并没有啥改动,只是用windows hook把窗口回调函数,指向自己而已, 而它的后辈WTL同样,只是用thunk改进了一下window hook消耗过大的问题,这说明什么? 这说明windows这窗口, 本身就有面向对象的精神,骨子里就是,所以根本不需要改,只是用C++这种语言上支持面向对象特性,给它再封装一下,使它变的更清晰一下。这个封装与windows与面向对象根本无关,它只是一些api和数据结构,只不过用 c++ 封装出来 getwindowlong是可以通过gwl_userdata获取user data。 这个数据即使你创建窗口的是用没有关联上,也会有数据,至于数据如何来的,不知道。参考:http://bbs.chinaunix.net/thread-2308241-1-1.html第4楼楼主,对这些问题别过于深究,深究意义不大,比如: registerclass后,那么windows如何维护 那些数据结构,你搞得清吗?还是我先给你启蒙一下吧,第一,WNDCLASS和C++那些类都是普通的数据结构,在内存中的布局是完全相同的。第二,WNDCLASS也和C++类的思想一样,有属性,什么style,光标,背景颜色等等。也有一系列方法,什么GetClassLong和SetClassLong之类,这种获取和设置属性的。当然还有CreateWindow这些, 那么Register和UnRegister就是它的new和delete只是它在系统内核里来分配内存。 为什么这些方法第一个参数,不是它的this,而是HWND呢? 这就是内核在维护,通过HWND作为索引来找到内核为他开辟的那片内存空间,这难道不是封装???你告诉我这和你那C++面向对象有什么分别?只能说你对面向对象理解的不够深刻,稍微一变化,你就看不到本质了 MFC你肯定用过吧? CRect 和CPoint 类肯定见过吧? 你告诉我 RECT和POINT是不是你所谓简单的数据结构?你再看看MFC为他们做了什么深奥的封装? 完全没有,换个外壳而已。在MFC里,你就认为那是对象? 那是类?在win32里你就体会不到?朋友你毕业了吗? 毕业后再来讨论吧 楼主这帖有意思cbClsExtra和cbWndExtra的价值绝对没有重叠,楼主也在#1提到了通过一个窗口类创建多个窗口其实就是共性与个性的问题,为窗口类分配的cbClsExtra大小的数据就好比C++类中的静态变量,在内存中只有一份,而为窗口分配的cbWndExtra大小的数据就相当于C++类中的一般的成员变量了,只有实例化后才分配内存,并且每个对象都分配了cbWndExtra大小的空间。至于GWL_USERDATA,它是不够用的,写界面库子类化窗口时使用GWL_USERDATA来储存数据时是否要考虑这个问题:如果这个界面库的dll要给其他人用,而人家的项目之前已经使用GWL_USERDATA储存了其它数据怎么办? 我还是不拿windows系统来说事吧,这对你们2位有些太神秘了。我举个简单的例子,我用C++按照面向对象的思想写一个动态链接库给你们2位来用,而我不喜欢导出一个类给你们,而是导出一些全局函数,比如Register(), 而我在Register内部调用new。 难道你们就不理解了?再举个例子吧,COM编程,你说它是不是面向对象? 你调用一个COM用new吗?只是需要给你们一个声明,你们才可以使用 Ixx -> xxx.你才知道有this指针可以用吗?那么我不声明,而且导出全局函数,通过HWND作为索引,才查找对象指针就不行?这就不是面向对象了?换个马甲就都不认识了?那就说明了解的还不够 啥都不说典型乱套按照说法, 面向对象不是所有都需要继承do you konw?举个极端例子:C#的main函数的那个类, 继承有什么意义?纯而继承而继承, 你就是这样理解面向对象的。还好意思 啥都不说典型乱套按照说法, 面向对象不是所有都需要继承do you konw?举个极端例子:C#的main函数的那个类, 继承有什么意义?纯而继承而继承, 你就是这样理解面向对象的。还好意思只是凭借语法技巧强行封装,强行继承,破坏事务的原理这样的面向对象不要也罢。面向对象只是解决问题的, 有的问题本神就不需要。你自己强奸windows,还 很高兴终于有一位就问题本质给出答案,昨晚看见,我好好琢磨了一下,现在才回复。首先,我没有win32k的源码,也不认识主创人员,所以无真相,只能大胆假设,小心求证。我假设它本身就是按照面向对象的思想设计的。(你认同这个假设吗?)struct CWindow{ UINT cbSize; UINT style; WNDPROC lpfnWndProc; //这个函数指针可以看成是纯虚函数,可由使用者实现。 int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; HICON hIconSm; //子类成员 SOCKET uPeople; HANDLE hEvent;};根据msdn给出的信息,系统会在Local Heap上根据cbClsExtra的值,并在CWindow的尾部,追加内存空间,这和类继承的特性是一样的,我们都知道class,struct和数组,在内存都是一样的线性排列,而子类在内存中,就是在父类尾部的。所以我认为RegisterClass就等于new CWindow,只是它不返回系统分配的内存指针,而是返回一个原子。CreateWindow第一个参数class name等于这个原子,传入字符串name正确,传入返回的ATOM也正确。就是PE结构里的导入表和导出表,可以通过字符串索引,也可以通过"编号"索引一样。如果说CreateWIndow是CWindow的成员方法,cbClsExtra也是为子类化而设计的话,那问题就来了。msdn说cbWndExtraThe number of extra bytes to allocate following the window instance.这句好像就颠覆了上面的架设。那么能不能麻烦你给出点伪代码,使我能更清晰一些,谢谢 啥都不说典型乱套按照说法, 面向对象不是所有都需要继承do you konw?举个极端例子:C#的main函数的那个类, 继承有什么意义?纯而继承而继承, 你就是这样理解面向对象的。还好意思只是凭借语法技巧强行封装,强行继承,破坏事务的原理这样的面向对象不要也罢。面向对象只是解决问题的, 有的问题本神就不需要。你自己强奸windows,还唉,秀才遇到兵,我也不想和你多说什么了,你也不用再回了,都是些小儿之见,我无视了。只是最后奉劝一句,谦虚点,就算你掌握的是真理。 何况还不是?动不动就一口咬定别人是错误的,可是又说不出个所以然,一句让人信服的论据都有,只能让人觉得你在胡说八道。要想来装,也要花点本钱,再多买几本书看看吧,增加点斗嘴的资本。你说的那些都太苍白,太无力了。还有别那么粗俗,好歹你也是受过高等教育的,一会尿了,一会又强奸, 你这样很难让人把你和有学问联系在一起。 啥都不说典型乱套按照说法, 面向对象不是所有都需要继承do you konw?举个极端例子:C#的main函数的那个类, 继承有什么意义?纯而继承而继承, 你就是这样理解面向对象的。还好意思只是凭借语法技巧强行封装,强行继承,破坏事务的原理这样的面向对象不要也罢。面向对象只是解决问题的, 有的问题本神就不需要。你自己强奸windows,还唉,秀才遇到兵,我也不想和你多说什么了,你也不用再回了,都是些小儿之见,我无视了。只是最后奉劝一句,谦虚点,就算你掌握的是真理。 何况还不是?动不动就一口咬定别人是错误的,可是又说不出个所以然,一句让人信服的论据都有,只能让人觉得你在胡说八道。要想来装,也要花点本钱,再多买几本书看看吧,增加点斗嘴的资本。你说的那些都太苍白,太无力了。还有别那么粗俗,好歹你也是受过高等教育的,一会尿了,一会又强奸, 你这样很难让人把你和有学问联系在一起。哈哈哈哈 我不认为RegisterClass等于new CWindow,虽然都有面向对象的思想,但它们面向的对象不同,一个是面向Class,一个是面向Window,据此,我认为CreateWindow类似于new,DestroyWindow类似于delete ,当然,只是思想上相同,都要为Window对象分配内存 struct CWindow{ UINT cbSize; UINT style; WNDPROC lpfnWndProc; //这个函数指针可以看成是纯虚函数,可由使用者实现。 int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; HICON hIconSm; //子类成员 SOCKET uPeople; HANDLE hEvent;};不好意思,我没注意你说的CWindow是指这个结构但WNDCLASSEX这个结构是为创造类而设计的,所以这个结构你命名为CWindow,感觉有点不妥,应该命名为CClass 我不认为RegisterClass等于new CWindow,虽然都有面向对象的思想,但它们面向的对象不同,一个是面向Class,一个是面向Window,据此,我认为CreateWindow类似于new,DestroyWindow类似于delete ,当然,只是思想上相同,都要为Window对象分配内存一个面向window,一个面向class,这说法,好像可以解释为什么有一个cbClsExtra又有一个cbWndExtra。可以面向class?这个命名会不会有些太过抽象哇,再者DestroyWindow好像是发WM_DESTROY消息给回调函数,而回调函数是WNDCLASS的成员,如果说WNDCLASS是一个对象,而WINDOW又是一个对象。他们之间是怎么样的关系呢? 父子? 模板? 在看雪有位前辈给出我这样的答案,你帮分析一下:class Class : public WNDCLASSEX{ public: ClsExtra = some_defined_data WndExtra = new byte [cbWndExtra]}hwnd = new Class 这代码给我的感觉是,cbWndExtra只是WNDCLASS里一个很普通的成员,它的目的是为了,某一天,某人通过这个类创建窗口,需要开辟一个buffer,来存放一些个性化的东西。struct CWindow{ UINT cbSize; UINT style; WNDPROC lpfnWndProc; //这个函数指针可以看成是纯虚函数,可由使用者实现。 int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; HICON hIconSm; //子类成员 SOCKET uPeople; HANDLE hEvent;};CWindow::CWindow(){ cbClsExtra = 8; cbWndExtra = 4;}ATOM CWindow::RegisterClass(){ return new CWindow()}HWND CWindow::CreateWindow(){ buffer = new BYTE[cbWndExtra];} 又或者说,下面这种代码,和上面那种代码,那一个更贴边,那一个更靠谱,那一个更接近真相?struct CWindow{ UINT cbSize; UINT style; WNDPROC lpfnWndProc; //这个函数指针可以看成是纯虚函数,可由使用者实现。 int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; HICON hIconSm; //子类成员 SOCKET uPeople; HANDLE hEvent;};CWindow::CWindow(){ cbClsExtra = 8; cbWndExtra = 4;}ATOM RegisterClass(){ CWindow * pThis = new CWindow(); return Insert(pThis); //通过内核某种存储表,插入数据,返回对应索引;}struct CWnd //另外一个面向窗口的对象{ CWindow * pcw;};HWND CreateWindow(ATOM atom){ CWindow * pcw = GetClassInfo(hInstance,atom); //atom = lpszClassName; CWnd * pwnd = new CWnd(); pwnd->pcw = pcw; //CWnd类保存CWindow指针; PVOID pChild = realloc(pwnd,pcw ->cbWndExtra); //cbWndExtra负责子类化CWnd return Insert(pChild); //通过内核某种存储表,插入数据,返回对应索引; }//那么接下来一切以HWND为第一参数的成员函数,都可以索引到CWnd和CWindow的所有内容如果说第一种靠谱,对于窗口,只有一个CWIndow类,那说它本身就是按面向对象设计的,就很契合了。如果说第二种靠谱,对于窗口,有2个结构CWindow和CWnd,那说它是面向对象就有点牵强了,窗口是一个对象,为什么要有2个结构来描述呢? 面向class,意思是说将窗口类作为一个对象来看,可能有点抽象,但它确实有自己的数据结构,而它的数据结构也不可能和窗口的数据结构相同,微软并没公开窗口的数据结构,只告诉你一个句柄和提供一系列的API,事实上,不只窗口,系统中很多东西都是用一个句柄来标识一个对象,只不过窗口类不是用句柄而是用ATOMWNDCLASS的lpfnWndProc成员只是默认使用,每个窗口都可以有自己的WindowProc如果要我用C++描述,就这样吧:class CWndClass : public WNDCLASSEX{ ATOM m_atom; CWndClass() { cbSize = sizeof(WNDCLASSEX); style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; lpfnWndProc = DefWindowProc; cbClsExtra = sizeof(CWndClass) - cbSize; cbWndExtra = 4; // hInstance = GetModuleHandle(NULL); hIcon = LoadIcon(NULL,IDI_APPLICATION); hCursor = LoadCursor(NULL,IDC_ARROW); hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); lpszMenuName = NULL; lpszClassName = TEXT("WHAT"); hIconSm = LoadIcon(NULL,IDI_EXCLAMATION); m_atom = RegisterClassEx(this); }};class CWindow{ HWND m_hWnd; static CWndClass s_WndClass; static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { // 自己处理了 // case ... } return CallWindowProc(s_WndClass.lpfnWndProc, hwnd, uMsg, wParam, lParam); } CWindow() { m_hWnd = CreateWindow(s_WndClass.m_atom, ...); // 每个窗口都可以有自己的WindowProc // 但我们不知道窗口内部的数据结构,所以只能微软提供的API函数SetWindowLong来修改 // 如果不修改,默认就是使用它所属窗口类的lpfnWndProc了 SetWindowLong(m_hWnd, GWL_WNDPROC, WindowProc); }};CWndClass CWindow::s_WndClass; 或者说WNDCLASS是一个基类,cbClsExtra这个成员为其预留扩展功能。CWND是其子类,cbWndExtra这个成员才是为了用户子类化CWnd用的。像MFC那样 CWnd是个相对基类,继承它有CFrame,CDialog,CView,CControl等等。而我最初的想象创建自己的窗口,应该继承WNDCLASS,其实不对,应该用cbWndExtra继承,就是继承CFrame; MFC获取某一窗口中所有控件句柄并操作 QQ聊天窗口的最大化效果是怎么做出来的? 同一工程中两个Dll有同名,调用时如何解决同名函数的冲突问题? 属性页! 在MFC或API中如何用C语言函数读写文件? 调用dll的时候,为何不能显示dll中的对话框(类CDlgComm)。 关于读取文件的问题 >>>>>>>会者不难!如果不用枚举系统中所有进程的话,如何知道一个程序何时运行?何时结束? 最爱看非技术区,散... HTTP隧道和SSL隧道区别 给自定义view类添加doc类 如何再局域网聊天室加上文件传输功能!
此类为窗口类,不是OOP中的类,不能继承,不要搞混了,虽然名字都是叫CLASS
留下这两个字段的空间,是为了扩展性或者程序员自已定义使用。
你如果初步了解mfc中的CWnd这个类,就知道,什么时候该用继承,什么不该用了。说白了,那就是一个数据结构,不能够继承的,就这么简单。
getwindowlong是可以通过gwl_userdata获取user data。 这个数据即使你创建窗口的是用没有关联上,也会有数据,至于数据如何来的,不知道。参考:http://bbs.chinaunix.net/thread-2308241-1-1.html第4楼楼主,对这些问题别过于深究,深究意义不大,比如: registerclass后,那么windows如何维护 那些数据结构,你搞得清吗?
代码没仔细看, 首先这个“类名”的历史,估计是 c++还没在windows上大行其道的时候,就引入了,所以别和面向对象中的类混在一块。第二:这个“类名”是不能够继承的, 可以说,我不明白继承这东西有什么意义第一,代码没仔细看,就发表评论,会不会有些不负责任?第二,面向对象是编程思想,和C++有什么关系? 他俩是用等号联系吗?很多论文和书籍,都曾经提到,windows是按面向对象的思想设计的。第三,怎么就不能继承呢?难道必须语言内部支持,才可以实现面向对象的特性吗?lua那种用C实现的小巧脚本语言,同样可以把面向对象表现的淋漓尽致。至于有什么意义? 你可以不去做,但是必须要懂,刨根究底,是搞技术的好品质,只有懂的越多,遇到问题,才能想出更多的解决方案。 同样是程序员,高手和菜鸟用什么来区分? windows是 面向对象?听谁说的
首先我说的不是API,我说的windows的设计思想,面向对象是一种思想,而不是形式,你可以拿windows内核源码看一下,这么庞大的操作系统,你们认为他没有一套设计思想?没有一套结构? 内核那么多种对象, 难道是想到哪,写到哪,想到什么,写什么?难道一定要语言支持的样式,才叫面向对象? 不能透过表象看实质嘛?
你如果初步了解mfc中的CWnd这个类,就知道,什么时候该用继承,什么不该用了。说白了,那就是一个数据结构,不能够继承的,就这么简单。你这种心态就不太对,难道什么都得过且过,不求甚解,对进步有帮助?
你对这个问题根本就不了解,所以给出的答案也让人哭笑不得,C++的类,难道不是数据结构? 他本质上就是,只是隐藏了第一成员,一个函数指针表而已。编译器为他传this指针。C语言模仿C++实现面向对象的所有特质,网上一搜一大把,麻烦你先去看一看。这已经不是天方夜谭了。
只要你想知道内核是怎么维护的,可以去逆向win32k呀,我之所以没去,是想来碰碰运气,看看有没有前辈做过同样的事情,愿意分析成果的。 因为我不想造轮子。
你说到MFC就更有意思了,它只是在win32上层稍作封装,并没有啥改动,只是用windows hook把窗口回调函数,指向自己而已, 而它的后辈WTL同样,只是用thunk改进了一下window hook消耗过大的问题,
这说明什么? 这说明windows这窗口, 本身就有面向对象的精神,骨子里就是,所以根本不需要改,
只是用C++这种语言上支持面向对象特性,给它再封装一下,使它变的更清晰一下。
wndclass 只是一个名字而已,不是类。概念混淆
你如果初步了解mfc中的CWnd这个类,就知道,什么时候该用继承,什么不该用了。说白了,那就是一个数据结构,不能够继承的,就这么简单。你这种心态就不太对,难道什么都得过且过,不求甚解,对进步有帮助?
你对这个问题根本就不了解,所以给出的答案也让人哭笑不得,C++的类,难道不是数据结构? 他本质上就是,只是隐藏了第一成员,一个函数指针表而已。编译器为他传this指针。C语言模仿C++实现面向对象的所有特质,网上一搜一大把,麻烦你先去看一看。这已经不是天方夜谭了。
只要你想知道内核是怎么维护的,可以去逆向win32k呀,我之所以没去,是想来碰碰运气,看看有没有前辈做过同样的事情,愿意分析成果的。 因为我不想造轮子。
你说到MFC就更有意思了,它只是在win32上层稍作封装,并没有啥改动,只是用windows hook把窗口回调函数,指向自己而已, 而它的后辈WTL同样,只是用thunk改进了一下window hook消耗过大的问题,
这说明什么? 这说明windows这窗口, 本身就有面向对象的精神,骨子里就是,所以根本不需要改,
只是用C++这种语言上支持面向对象特性,给它再封装一下,使它变的更清晰一下。这个封装与windows与面向对象根本无关,它只是一些api和数据结构,只不过用 c++ 封装出来
getwindowlong是可以通过gwl_userdata获取user data。 这个数据即使你创建窗口的是用没有关联上,也会有数据,至于数据如何来的,不知道。参考:http://bbs.chinaunix.net/thread-2308241-1-1.html第4楼楼主,对这些问题别过于深究,深究意义不大,比如: registerclass后,那么windows如何维护 那些数据结构,你搞得清吗?
还是我先给你启蒙一下吧,
第一,WNDCLASS和C++那些类都是普通的数据结构,在内存中的布局是完全相同的。第二,WNDCLASS也和C++类的思想一样,有属性,什么style,光标,背景颜色等等。也有一系列方法,什么GetClassLong和SetClassLong之类,这种获取和设置属性的。当然还有CreateWindow这些, 那么Register和UnRegister就是它的new和delete只是它在系统内核里来分配内存。 为什么这些方法第一个参数,不是它的this,而是HWND呢? 这就是内核在维护,通过HWND作为索引来找到内核为他开辟的那片内存空间,这难道不是封装???你告诉我这和你那C++面向对象有什么分别?只能说你对面向对象理解的不够深刻,稍微一变化,你就看不到本质了
其实就是共性与个性的问题,为窗口类分配的cbClsExtra大小的数据就好比C++类中的静态变量,在内存中只有一份,
而为窗口分配的cbWndExtra大小的数据就相当于C++类中的一般的成员变量了,只有实例化后才分配内存,并且每个对象都分配了cbWndExtra大小的空间。至于GWL_USERDATA,它是不够用的,写界面库子类化窗口时使用GWL_USERDATA来储存数据时是否要考虑这个问题:如果这个界面库的dll要给其他人用,而人家的项目之前已经使用GWL_USERDATA储存了其它数据怎么办?
这就不是面向对象了?换个马甲就都不认识了?那就说明了解的还不够
啥都不说典型乱套按照说法, 面向对象不是所有都需要继承do you konw?举个极端例子:C#的main函数的那个类, 继承有什么意义?纯而继承而继承, 你就是这样理解面向对象的。还好意思
啥都不说典型乱套按照说法, 面向对象不是所有都需要继承do you konw?举个极端例子:C#的main函数的那个类, 继承有什么意义?纯而继承而继承, 你就是这样理解面向对象的。还好意思只是凭借语法技巧强行封装,强行继承,破坏事务的原理这样的面向对象不要也罢。面向对象只是解决问题的, 有的问题本神就不需要。
你自己强奸windows,还
很高兴终于有一位就问题本质给出答案,昨晚看见,我好好琢磨了一下,现在才回复。首先,我没有win32k的源码,也不认识主创人员,所以无真相,只能大胆假设,小心求证。我假设它本身就是按照面向对象的思想设计的。(你认同这个假设吗?)struct CWindow
{
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc; //这个函数指针可以看成是纯虚函数,可由使用者实现。
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
//子类成员
SOCKET uPeople;
HANDLE hEvent;
};根据msdn给出的信息,系统会在Local Heap上根据cbClsExtra的值,并在CWindow的尾部,追加内存空间,这和类继承的特性是一样的,我们都知道class,struct和数组,在内存都是一样的线性排列,而子类在内存中,就是在父类尾部的。
所以我认为RegisterClass就等于new CWindow,只是它不返回系统分配的内存指针,而是返回一个原子。CreateWindow第一个参数class name等于这个原子,传入字符串name正确,传入返回的ATOM也正确。就是PE结构里的导入表和导出表,可以通过字符串索引,也可以通过"编号"索引一样。
如果说CreateWIndow是CWindow的成员方法,cbClsExtra也是为子类化而设计的话,那问题就来了。
msdn说cbWndExtraThe number of extra bytes to allocate following the window instance.这句好像就颠覆了上面的架设。
那么能不能麻烦你给出点伪代码,使我能更清晰一些,谢谢
啥都不说典型乱套按照说法, 面向对象不是所有都需要继承do you konw?举个极端例子:C#的main函数的那个类, 继承有什么意义?纯而继承而继承, 你就是这样理解面向对象的。还好意思只是凭借语法技巧强行封装,强行继承,破坏事务的原理这样的面向对象不要也罢。面向对象只是解决问题的, 有的问题本神就不需要。
你自己强奸windows,还
唉,秀才遇到兵,我也不想和你多说什么了,你也不用再回了,都是些小儿之见,我无视了。
只是最后奉劝一句,谦虚点,就算你掌握的是真理。 何况还不是?动不动就一口咬定别人是错误的,可是又说不出个所以然,一句让人信服的论据都有,只能让人觉得你在胡说八道。要想来装,也要花点本钱,再多买几本书看看吧,增加点斗嘴的资本。你说的那些都太苍白,太无力了。还有别那么粗俗,好歹你也是受过高等教育的,一会尿了,一会又强奸, 你这样很难让人把你和有学问联系在一起。
啥都不说典型乱套按照说法, 面向对象不是所有都需要继承do you konw?举个极端例子:C#的main函数的那个类, 继承有什么意义?纯而继承而继承, 你就是这样理解面向对象的。还好意思只是凭借语法技巧强行封装,强行继承,破坏事务的原理这样的面向对象不要也罢。面向对象只是解决问题的, 有的问题本神就不需要。
你自己强奸windows,还
唉,秀才遇到兵,我也不想和你多说什么了,你也不用再回了,都是些小儿之见,我无视了。
只是最后奉劝一句,谦虚点,就算你掌握的是真理。 何况还不是?动不动就一口咬定别人是错误的,可是又说不出个所以然,一句让人信服的论据都有,只能让人觉得你在胡说八道。要想来装,也要花点本钱,再多买几本书看看吧,增加点斗嘴的资本。你说的那些都太苍白,太无力了。还有别那么粗俗,好歹你也是受过高等教育的,一会尿了,一会又强奸, 你这样很难让人把你和有学问联系在一起。
哈哈哈哈
我不认为RegisterClass等于new CWindow,虽然都有面向对象的思想,但它们面向的对象不同,一个是面向Class,一个是面向Window,据此,我认为CreateWindow类似于new,DestroyWindow类似于delete ,当然,只是思想上相同,都要为Window对象分配内存
{
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc; //这个函数指针可以看成是纯虚函数,可由使用者实现。
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
//子类成员
SOCKET uPeople;
HANDLE hEvent;
};
不好意思,我没注意你说的CWindow是指这个结构
但WNDCLASSEX这个结构是为创造类而设计的,所以这个结构你命名为CWindow,感觉有点不妥,应该命名为CClass
我不认为RegisterClass等于new CWindow,虽然都有面向对象的思想,但它们面向的对象不同,一个是面向Class,一个是面向Window,据此,我认为CreateWindow类似于new,DestroyWindow类似于delete ,当然,只是思想上相同,都要为Window对象分配内存
一个面向window,一个面向class,这说法,好像可以解释为什么有一个cbClsExtra又有一个cbWndExtra。可以面向class?这个命名会不会有些太过抽象哇,再者DestroyWindow好像是发WM_DESTROY消息给回调函数,而回调函数是WNDCLASS的成员,如果说WNDCLASS是一个对象,而WINDOW又是一个对象。他们之间是怎么样的关系呢? 父子? 模板? 在看雪有位前辈给出我这样的答案,你帮分析一下:class Class : public WNDCLASSEX
{
public:
ClsExtra = some_defined_data
WndExtra = new byte [cbWndExtra]
}hwnd = new Class
这代码给我的感觉是,cbWndExtra只是WNDCLASS里一个很普通的成员,它的目的是为了,某一天,某人通过这个类创建窗口,需要开辟一个buffer,来存放一些个性化的东西。struct CWindow
{
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc; //这个函数指针可以看成是纯虚函数,可由使用者实现。
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
//子类成员
SOCKET uPeople;
HANDLE hEvent;
};CWindow::CWindow()
{
cbClsExtra = 8;
cbWndExtra = 4;
}ATOM CWindow::RegisterClass()
{
return new CWindow()
}HWND CWindow::CreateWindow()
{
buffer = new BYTE[cbWndExtra];
}
struct CWindow
{
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc; //这个函数指针可以看成是纯虚函数,可由使用者实现。
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
//子类成员
SOCKET uPeople;
HANDLE hEvent;
};CWindow::CWindow()
{
cbClsExtra = 8;
cbWndExtra = 4;
}ATOM RegisterClass()
{
CWindow * pThis = new CWindow(); return Insert(pThis); //通过内核某种存储表,插入数据,返回对应索引;
}
struct CWnd //另外一个面向窗口的对象
{
CWindow * pcw;
};
HWND CreateWindow(ATOM atom)
{ CWindow * pcw = GetClassInfo(hInstance,atom); //atom = lpszClassName;
CWnd * pwnd = new CWnd();
pwnd->pcw = pcw; //CWnd类保存CWindow指针;
PVOID pChild = realloc(pwnd,pcw ->cbWndExtra); //cbWndExtra负责子类化CWnd
return Insert(pChild); //通过内核某种存储表,插入数据,返回对应索引;
}
//那么接下来一切以HWND为第一参数的成员函数,都可以索引到CWnd和CWindow的所有内容如果说第一种靠谱,对于窗口,只有一个CWIndow类,那说它本身就是按面向对象设计的,就很契合了。如果说第二种靠谱,对于窗口,有2个结构CWindow和CWnd,那说它是面向对象就有点牵强了,
窗口是一个对象,为什么要有2个结构来描述呢?
WNDCLASS的lpfnWndProc成员只是默认使用,每个窗口都可以有自己的WindowProc
如果要我用C++描述,就这样吧:
class CWndClass : public WNDCLASSEX
{
ATOM m_atom; CWndClass()
{
cbSize = sizeof(WNDCLASSEX);
style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;
lpfnWndProc = DefWindowProc;
cbClsExtra = sizeof(CWndClass) - cbSize;
cbWndExtra = 4; //
hInstance = GetModuleHandle(NULL);
hIcon = LoadIcon(NULL,IDI_APPLICATION);
hCursor = LoadCursor(NULL,IDC_ARROW);
hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
lpszMenuName = NULL;
lpszClassName = TEXT("WHAT");
hIconSm = LoadIcon(NULL,IDI_EXCLAMATION);
m_atom = RegisterClassEx(this);
}
};class CWindow
{
HWND m_hWnd;
static CWndClass s_WndClass;
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
// 自己处理了
// case ... }
return CallWindowProc(s_WndClass.lpfnWndProc, hwnd, uMsg, wParam, lParam);
} CWindow()
{
m_hWnd = CreateWindow(s_WndClass.m_atom, ...); // 每个窗口都可以有自己的WindowProc
// 但我们不知道窗口内部的数据结构,所以只能微软提供的API函数SetWindowLong来修改
// 如果不修改,默认就是使用它所属窗口类的lpfnWndProc了
SetWindowLong(m_hWnd, GWL_WNDPROC, WindowProc);
}
};CWndClass CWindow::s_WndClass;
像MFC那样 CWnd是个相对基类,继承它有CFrame,CDialog,CView,CControl等等。
而我最初的想象创建自己的窗口,应该继承WNDCLASS,其实不对,应该用cbWndExtra继承,就是继承CFrame;