加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

reactos操作系统实现(158)

发布时间:2020-12-15 04:59:07 所属栏目:百科 来源:网络整理
导读:在 ReactOS 的应用程序里,每个有窗口的应用程序都需要注册一个窗口类,然后根据窗口类来创建窗口。注册窗口的调用函数就是 RegisterClassW ,这个函数是 UNICODE 的版本,其实还有多节字版本,但代码是差不多的。这里主要分析 UNICODE 版本的实现,其代码如

ReactOS的应用程序里,每个有窗口的应用程序都需要注册一个窗口类,然后根据窗口类来创建窗口。注册窗口的调用函数就是RegisterClassW,这个函数是UNICODE的版本,其实还有多节字版本,但代码是差不多的。这里主要分析UNICODE版本的实现,其代码如下:

#001 ATOM WINAPI

#002 RegisterClassW(CONST WNDCLASSW *lpWndClass)

#003 {

lpWndClass是应用程序定义窗口类的结构指针。

声明一个扩展窗口类。

#004 WNDCLASSEXW Class;

#005

检查窗口类的指针是否为空,如果为空就是非法,直接返回。

#006 if (lpWndClass == NULL)

#007 return 0;

#008

拷贝老版本的窗口类结构到扩展窗口类结构里。

#009 RtlCopyMemory(&Class.style,lpWndClass,sizeof(WNDCLASSW));

#010 Class.cbSize = sizeof(WNDCLASSEXW);

#011 Class.hIconSm = NULL;

#012

调用函数RegisterClassExW来注册窗口类。

#013 return RegisterClassExW(&Class);

#014 }

接着来分析函数RegisterClassExW的实现,它的代码如下:

#001 ATOM WINAPI

#002 RegisterClassExW(CONST WNDCLASSEXW *lpwcx)

#003 {

#004 ATOM Atom;

#005 WNDCLASSEXW WndClass;

#006 UNICODE_STRING ClassName;

#007 UNICODE_STRING MenuName = {0};

#008 HMENU hMenu = NULL;

#009

判断输入的结构是否有效。

#010 if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||

#011 lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||

#012 lpwcx->lpszClassName == NULL)

#013 {

#014 SetLastError(ERROR_INVALID_PARAMETER);

#015 return 0;

#016 }

#017

#018 /*

#019 * On real Windows this looks more like:

#020 * if (lpwcx->hInstance == User32Instance &&

#021 * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)

#022 * But since I have no idea what the magic field in the

#023 * TEB structure means,I rather decided to omit that.

#024 * -- Filip Navara

#025 */

如果窗口的实例句柄是用户的句柄,就退出。

#026 if (lpwcx->hInstance == User32Instance)

#027 {

#028 SetLastError(ERROR_INVALID_PARAMETER);

#029 return 0;

#030 }

#031

如果实例句柄为空,就使用函数GetModuleHandleW获取当前模板的句柄。

#032 /* Yes,this is correct. We should modify the passed structure. */

#033 if (lpwcx->hInstance == NULL)

#034 ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL);

#035

拷贝窗口类的结构。

#036 RtlCopyMemory(&WndClass,lpwcx,sizeof(WNDCLASSEXW));

#037

如果应用程序没有创建小图标,那么这里就创建一个默认的小图标。

#038 if (NULL == WndClass.hIconSm)

#039 {

#040 WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);

#041 }

#042

如果有系统菜单,就需要加载系统菜单。

#043 if (WndClass.lpszMenuName != NULL)

#044 {

转换菜单的名称。

#045 if (!IS_INTRESOURCE(WndClass.lpszMenuName))

#046 {

#047 if (WndClass.lpszMenuName[0])

#048 {

#049 RtlInitUnicodeString(&MenuName,WndClass.lpszMenuName);

#050 }

#051 }

#052 else

#053 {

#054 MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;

#055 }

#056

从资源里加载菜单。

#057 if (MenuName.Buffer != NULL)

#058 hMenu = LoadMenuW(WndClass.hInstance,WndClass.lpszMenuName);

#059 }

#060

转换窗口类的名称。

#061 if (IS_ATOM(WndClass.lpszClassName))

#062 {

#063 ClassName.Length =

#064 ClassName.MaximumLength = 0;

#065 ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;

#066 }

#067 else

#068 {

#069 RtlInitUnicodeString(&ClassName,WndClass.lpszClassName);

#070 }

#071

通过系统中断调用内核函数NtUserRegisterClassEx

#072 Atom = (ATOM)NtUserRegisterClassEx(&WndClass,

#073 &ClassName,

#074 &MenuName,

#075 NULL,

#076 0,

#077 hMenu);

#078

#079 TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p/n",

#080 Atom,lpwcx->lpfnWndProc,lpwcx->hInstance,lpwcx->hbrBackground,

#081 lpwcx->style,lpwcx->cbClsExtra,lpwcx->cbWndExtra,WndClass);

#082

#083 return Atom;

#084 }

从前面的分析可以知道,函数NtUserRegisterClassEx调用,也是通过系统中断来调用内核函数,也就是调用Win32k.sys文件里的函数。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读