reactos操作系统实现(160)

CreateWindowExW函数主要用来根据已经注册窗口类来创建一个窗口。它在User32.dll实现代码如下:

#001 HWND WINAPI

#002 CreateWindowExW(DWORD dwExStyle,

#003 LPCWSTR lpClassName,

#004 LPCWSTR lpWindowName,

#005 DWORD dwStyle,

#006 int x,

#007 int y,

#008 int nWidth,

#009 int nHeight,

#010 HWND hWndParent,

#011 HMENU hMenu,

#012 HINSTANCE hInstance,

#013 LPVOID lpParam)

#014 {

#015 MDICREATESTRUCTW mdi;

#016 HWND hwnd;

#017

如果创建的窗口是MDI的子窗口,就需要进入下面处理。

#018 if (dwExStyle & WS_EX_MDICHILD)

#019 {

#020 POINT mPos[2];

#021 UINT id = 0;

#022 HWND top_child;

#023

设置MDI窗口的属性

#024 /* lpParams of WM_[NC]CREATE is different for MDI children.

#025 * MDICREATESTRUCT members have the originally passed values.

#026 */

#027 mdi.szClass = lpClassName;

#028 mdi.szTitle = lpWindowName;

#029 mdi.hOwner = hInstance;

#030 mdi.x = x;

#031 mdi.y = y;

#032 mdi.cx = nWidth;

#033 mdi.cy = nHeight;

#034 mdi.style = dwStyle;

#035 mdi.lParam = (LParaM)lpParam;

#036

#037 lpParam = (LPVOID)&mdi;

#038

检查MDI的子窗口是否有不允许出现的窗口显示类型。

#039 if (getwindowlongW(hWndParent,GWL_STYLE) & Mdis_ALLCHILDSTYLES)

#040 {

#041 if (dwStyle & WS_POPUP)

#042 {

#043 WARN("WS_POPUP with Mdis_ALLCHILDSTYLES is not allowed/n");

#044 return(0);

#045 }

#046 dwStyle |= (WS_CHILD | WS_CLIPSIBLINGS);

#047 }

#048 else

#049 {

#050 dwStyle &= ~WS_POPUP;

#051 dwStyle |= (WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |

#052 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBox | WS_MAXIMIZEBox);

#053 }

#054

获取父窗口的子窗口。

#055 top_child = Getwindow(hWndParent,GW_CHILD);

#056

恢复当前显示的子窗口。

#057 if (top_child)

#058 {

#059 /* Restore current maximized child */

#060 if((dwStyle & WS_VISIBLE) && IsZoomed(top_child))

#061 {

#062 TRACE("Restoring current maximized child %p/n",top_child);

#063 SendMessageW( top_child,WM_SETREDRAW,FALSE,0 );

#064 ShowWindow(top_child,SW_RESTORE);

#065 SendMessageW( top_child,TRUE,0 );

#066 }

#067 }

#068

计算子窗口要显示的位置。

#069 MDI_CalcDefaultChildPos(hWndParent,-1,mPos,&id);

#070

如果不是弹出的窗口类型,窗口有菜单

#071 if (!(dwStyle & WS_POPUP)) hMenu = (HMENU)id;

#072

计算窗口的位置和窗口的大小。

#073 if (dwStyle & (WS_CHILD | WS_POPUP))

#074 {

#075 if (x == CW_USEDEFAULT || x == CW_USEDEFAULT16)

#076 {

#077 x = mPos[0].x;

#078 y = mPos[0].y;

#079 }

#080 if (nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16 || !nWidth)

#081 nWidth = mPos[1].x;

#082 if (nHeight == CW_USEDEFAULT || nHeight == CW_USEDEFAULT16 || !nHeight)

#083 nHeight = mPos[1].y;

#084 }

#085 }

#086

调用函数User32CreateWindowEx来更进一步窗口管理。

#087 hwnd = User32CreateWindowEx(dwExStyle,

#088 (LPCSTR) lpClassName,

#089 (LPCSTR) lpWindowName,

#090 dwStyle,

#091 x,

#092 y,

#093 nWidth,

#094 nHeight,

#095 hWndParent,

#096 hMenu,

#097 hInstance,

#098 lpParam,

#099 TRUE);

#100 return hwnd;

#101 }

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

#001 HWND WINAPI

#002 User32CreateWindowEx(DWORD dwExStyle,

#003 LPCSTR lpClassName,

#004 LPCSTR lpWindowName,

#008 int nWidth,

#010 HWND hWndParent,

#013 LPVOID lpParam,

#014 BOOL Unicode)

#015 {

#016 UNICODE_STRING WindowName;

#017 UNICODE_STRING ClassName;

#018 WNDCLASSEXA wceA;

#019 WNDCLASSEXW wceW;

#020 HWND Handle;

#021

#022 #if 0

#023 DbgPrint("[window] User32CreateWindowEx style %d,exstyle %d,parent %d/n",dwStyle,dwExStyle,hWndParent);

#024 #endif

#025

检查和转换窗口类的名称

#026 if (IS_ATOM(lpClassName))

#027 {

#028 RtlInitUnicodeString(&ClassName,NULL);

#029 ClassName.Buffer = (LPWSTR)lpClassName;

#030 }

#031 else

#032 {

#033 if(Unicode)

#034 RtlInitUnicodeString(&ClassName,(PCWSTR)lpClassName);

#035 else

#036 {

#037 if (!RtlCreateUnicodeStringFromAsciiz(&(ClassName),(PCSZ)lpClassName))

#038 {

#039 SetLastError(ERROR_OUTOFMEMORY);

#040 return (HWND)0;

#041 }

#042 }

#043 }

#044

检查和处理窗口的名称

#045 if (Unicode)

#046 RtlInitUnicodeString(&WindowName,(PCWSTR)lpWindowName);

#047 else

#048 {

#049 if (!RtlCreateUnicodeStringFromAsciiz(&WindowName,(PCSZ)lpWindowName))

#050 {

#051 if (!IS_ATOM(lpClassName))

#052 {

#053 RtlFreeUnicodeString(&ClassName);

#054 }

#055 SetLastError(ERROR_OUTOFMEMORY);

#056 return (HWND)0;

#057 }

#058 }

#059

从窗口类里获取菜单并加载。

#060 if(!hMenu && (dwStyle & (WS_OVERLAPPEDWINDOW | WS_POPUP)))

#061 {

#062 if(Unicode)

#063 {

#064 wceW.cbSize = sizeof(WNDCLASSEXW);

#065 if(GetClassInfoExW(hInstance,(LPCWSTR)lpClassName,&wceW) && wceW.lpszMenuName)

#066 {

#067 hMenu = LoadMenuW(hInstance,wceW.lpszMenuName);

#068 }

#069 }

#070 else

#071 {

#072 wceA.cbSize = sizeof(WNDCLASSEXA);

#073 if(GetClassInfoExA(hInstance,lpClassName,&wceA) && wceA.lpszMenuName)

#074 {

#075 hMenu = LoadMenuA(hInstance,wceA.lpszMenuName);

#076 }

#077 }

#078 }

#079

下面调用内核函数NtUserCreateWindowEx来创建窗口。

#080 Handle = NtUserCreateWindowEx(dwExStyle,

#081 &ClassName,

#082 &WindowName,

#083 dwStyle,

#084 x,

#085 y,

#086 nWidth,

#087 nHeight,

#088 hWndParent,

#089 hMenu,

#090 hInstance,

#091 lpParam,

#092 SW_SHOW,

#093 FALSE,

#094 0);

#095

#096 #if 0

#097 DbgPrint("[window] NtUserCreateWindowEx() == %d/n",Handle);

#098 #endif

#099

删除UNICODE占用的空间。

#100 if(!Unicode)

#101 {

#102 RtlFreeUnicodeString(&WindowName);

#103

#104 if (!IS_ATOM(lpClassName))

#105 {

#106 RtlFreeUnicodeString(&ClassName);

#107 }

#108 }

返回创建成功的窗口句柄。

#109 return Handle;

#110}

相关文章

一、前言 在组件方面react和Vue一样的,核心思想玩的就是组件...
前言: 前段时间学习完react后,刚好就接到公司一个react项目...
前言: 最近收到组长通知我们项目组后面新开的项目准备统一技...
react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...