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} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |