reactos操作系统实现(162)
co_IntCreateWindowEx函数主要用创建一个显示的窗口,具体实现代码如下: #001 HWND APIENTRY #002 co_IntCreateWindowEx(DWORD dwExStyle, #003 PUNICODE_STRING ClassName, #004 PUNICODE_STRING WindowName, #005 DWORD dwStyle, #006 LONG x, #007 LONG y, #008 LONG nWidth, #009 LONG nHeight, #010 HWND hWndParent, #011 HMENU hMenu, #012 HINSTANCE hInstance, #013 LPVOID lpParam, #014 DWORD dwShowMode, #015 BOOL bUnicodeWindow) #016 { #017 PWINSTATION_OBJECT WinSta; #018 PWINDOW Wnd = NULL; #019 PWINDOWCLASS *ClassLink,Class = NULL; #020 RTL_ATOM ClassAtom; #021 PWINDOW_OBJECT Window = NULL; #022 PWINDOW_OBJECT ParentWindow = NULL,OwnerWindow; #023 HWND ParentWindowHandle; #024 HWND OwnerWindowHandle; #025 PMENU_OBJECT SystemMenu; #026 HWND hWnd; #027 POINT Pos; #028 SIZE Size; #029 PW32THREADINFO ti = NULL; #030 #if 0 #031 #032 POINT MaxSize,MaxPos,MinTrack,MaxTrack; #033 #else #034 #035 POINT MaxPos; #036 #endif #037 CREATESTRUCTW Cs; #038 CBT_CREATEWNDW CbtCreate; #039 LRESULT Result; #040 BOOL MenuChanged; #041 DECLARE_RETURN(HWND); #042 BOOL HasOwner; #043 USER_REFERENCE_ENTRY ParentRef,Ref; #044 PTHREADINFO pti; #045
获取当前运行的线程。 #046 pti = PsGetCurrentThreadWin32Thread();
获取桌面窗口作为父窗口。 #047 ParentWindowHandle = pti->Desktop->DesktopWindow; #048 OwnerWindowHandle = NULL; #049
是否为创建消息窗口。 #050 if (hWndParent == HWND_MESSAGE) #051 { #052 /* #053 * native ole32.OleInitialize uses HWND_MESSAGE to create the #054 * message window (style: WS_POPUP|WS_DISABLED) #055 */ #056 DPRINT1("FIXME - Parent is HWND_MESSAGE/n"); #057 // ParentWindowHandle set already. #058 }
是否已经父窗口。 #059 else if (hWndParent) #060 { #061 if ((dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) #062 { //temp hack #063 PWINDOW_OBJECT Par = UserGetWindowObject(hWndParent),Root; #064 if (Par && (Root = UserGetAncestor(Par,GA_ROOT))) #065 OwnerWindowHandle = Root->hSelf; #066 } #067 else #068 ParentWindowHandle = hWndParent; #069 }
如果又设置为子窗口属性,但又没有父窗口,就提示出错返回。 #070 else if ((dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD) #071 { #072 SetLastWin32Error(ERROR_TLW_WITH_WSCHILD); #073 RETURN( (HWND)0); /* WS_CHILD needs a parent,but WS_POPUP doesn't */ #074 } #075
获取父窗口对象。 #076 // if (NULL != ParentWindowHandle) #077 // { #078 ParentWindow = UserGetWindowObject(ParentWindowHandle); #079 #080 if (ParentWindow) UserRefObjectCo(ParentWindow,&ParentRef); #081 // } #082 // else #083 // { #084 // ParentWindow = NULL; #085 // } #086 #087 /* FIXME: parent must belong to the current process */ #088
检查WINDOWS的线程信息。 #089 /* Check the window station. */ #090 ti = GetW32ThreadInfo(); #091 if (ti == NULL || pti->Desktop == NULL) #092 { #093 DPRINT1("Thread is not attached to a desktop! Cannot create window!/n"); #094 RETURN( (HWND)0); #095 } #096 #097 /* Check the class. */ #098
检查要创建的窗口类是否已经注册好。 #099 ClassAtom = IntGetClassAtom(ClassName, #100 hInstance, #101 ti->kpi, #102 &Class, #103 &ClassLink); #104 #105 if (ClassAtom == (RTL_ATOM)0) #106 { #107 if (IS_ATOM(ClassName->Buffer)) #108 { #109 DPRINT1("Class 0x%p not found/n",(DWORD_PTR) ClassName->Buffer); #110 } #111 else #112 { #113 DPRINT1("Class /"%wZ/" not found/n",ClassName); #114 } #115 #116 SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS); #117 RETURN((HWND)0); #118 } #119
增加已经注册好的窗口类引用计数。 #120 Class = IntReferenceClass(Class, #121 ClassLink, #122 pti->Desktop); #123 if (Class == NULL) #124 { #125 DPRINT1("Failed to reference window class!/n"); #126 RETURN(NULL); #127 } #128
获取桌面工作站。 #129 WinSta = pti->Desktop->WindowStation; #130 #131 //FIXME: Reference thread/desktop instead #132 ObReferenceObjectByPointer(WinSta,KernelMode,ExWindowStationObjectType,0); #133
调用函数UserCreateObject创建窗口对象。 #134 /* Create the window object. */ #135 Window = (PWINDOW_OBJECT) #136 UserCreateObject(gHandleTable,(PHANDLE)&hWnd, #137 otWindow,sizeof(WINDOW_OBJECT)); #138 if (Window) #139 {
分配窗口所占用的堆空间。 #140 Window->Wnd = DesktopHeapAlloc(pti->Desktop, #141 sizeof(WINDOW) + Class->WndExtra); #142 if (!Window->Wnd) #143 goto AllocErr; #144 RtlZeroMemory(Window->Wnd, #145 sizeof(WINDOW) + Class->WndExtra); #146 Window->Wnd->hdr.Handle = hWnd; /* FIXME: Remove hack */ #147 Wnd = Window->Wnd; #148 #149 Wnd->ti = ti; #150 Wnd->pi = ti->kpi; #151 Wnd->pdesktop = pti->Desktop; #152 Wnd->hWndLastActive = hWnd; #153 } #154
检查是否创建窗口对象成功。 #155 DPRINT("Created object with handle %X/n",hWnd); #156 if (!Window) #157 { #158 AllocErr: #159 ObDereferenceObject(WinSta); #160 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); #161 RETURN( (HWND)0); #162 } #163
增加引用窗口计数。 #164 UserRefObjectCo(Window,&Ref); #165 #166 ObDereferenceObject(WinSta); #167
如果还没有桌面窗口,说明当前创建的窗口就是桌面窗口。 #168 if (NULL == pti->Desktop->DesktopWindow) #169 { #170 /* If there is no desktop window yet,we must be creating it */ #171 pti->Desktop->DesktopWindow = hWnd; #172 pti->Desktop->DesktopInfo->Wnd = Wnd; #173 } #174
填写窗口描述结构。 #175 /* #176 * Fill out the structure describing it. #177 */ #178 Window->ti = ti; #179 Wnd->Class = Class; #180 Class = NULL; #181 #182 Window->SystemMenu = (HMENU)0; #183 Wnd->ContextHelpId = 0; #184 Wnd->IDMenu = 0; #185 Wnd->Instance = hInstance; #186 Window->hSelf = hWnd; #187
设置窗口消息队列。 #188 Window->MessageQueue = pti->MessageQueue; #189 IntReferenceMessageQueue(Window->MessageQueue); #190 Window->Parent = ParentWindow; #191 Wnd->Parent = ParentWindow ? ParentWindow->Wnd : NULL; #192 if (Wnd->Parent != NULL && hWndParent != 0) #193 { #194 Wnd->HideFocus = Wnd->Parent->HideFocus; #195 Wnd->HideAccel = Wnd->Parent->HideAccel; #196 } #197
设置属于那一个窗口。 #198 if((OwnerWindow = UserGetWindowObject(OwnerWindowHandle))) #199 { #200 Window->hOwner = OwnerWindowHandle; #201 Wnd->Owner = OwnerWindow->Wnd; #202 HasOwner = TRUE; #203 } #204 else #205 { #206 Window->hOwner = NULL; #207 Wnd->Owner = NULL; #208 HasOwner = FALSE; #209 } #210
窗口用户数据设置为0. #211 Wnd->UserData = 0; #212 #213 Wnd->IsSystem = Wnd->Class->System; #214 #215 /* BugBoy Comments: Comment below say that System classes are always created as UNICODE. #216 In windows,creating a window with the ANSI version of CreateWindow sets the window #217 to ansi as verified by testing with IsUnicodeWindow API. #218 #219 No where can I see in code or through testing does the window change back to ANSI #220 after being created as UNICODE in ROS. I didnt do more testing to see what problems this would cause.*/ #221 // See NtUserDefSetText! We convert to Unicode all the time and never use Mix. (jt)
根据是否系统里定义的窗口类来选择是否使用UNICODE的窗口。 #222 if (Wnd->Class->System) #223 { #224 /* NOTE: Always create a unicode window for system classes! */ #225 Wnd->Unicode = TRUE; #226 Wnd->WndProc = Wnd->Class->WndProc; #227 Wnd->WndProcExtra = Wnd->Class->WndProcExtra; #228 } #229 else #230 { #231 Wnd->Unicode = Wnd->Class->Unicode; #232 Wnd->WndProc = Wnd->Class->WndProc; #233 Wnd->CallProc = NULL; #234 } #235
设置当前窗口的线程。 #236 Window->OwnerThread = PsGetCurrentThread(); #237 Window->FirstChild = NULL; #238 Window->LastChild = NULL; #239 Window->PrevSibling = NULL; #240 Window->NextSibling = NULL; #241 Wnd->ExtraDataSize = Wnd->Class->WndExtra; #242 #243 InitializeListHead(&Wnd->PropListHead); #244 InitializeListHead(&Window->WndObjListHead); #245
设置窗口的名称。 #246 if (NULL != WindowName->Buffer && WindowName->Length > 0) #247 { #248 Wnd->WindowName.Buffer = DesktopHeapAlloc(Wnd->pdesktop, #249 WindowName->Length + sizeof(UNICODE_NULL)); #250 if (Wnd->WindowName.Buffer == NULL) #251 { #252 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); #253 RETURN( (HWND)0); #254 } #255 #256 Wnd->WindowName.Buffer[WindowName->Length / sizeof(WCHAR)] = L'/0'; #257 _SEH2_TRY #258 { #259 RtlCopyMemory(Wnd->WindowName.Buffer, #260 WindowName->Buffer, #261 WindowName->Length); #262 Wnd->WindowName.Length = WindowName->Length; #263 } #264 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) #265 { #266 WindowName->Length = 0; #267 Wnd->WindowName.Buffer[0] = L'/0'; #268 } #269 _SEH2_END; #270 } #271
检查是否创建对话框窗口。 #272 /* #273 * This has been tested for WS_CHILD | WS_VISIBLE. It has not been #274 * tested for WS_POPUP #275 */ #276 if ((dwExStyle & WS_EX_DLGMODALFRAME) || #277 ((!(dwExStyle & WS_EX_STATICEDGE)) && #278 (dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))) #279 dwExStyle |= WS_EX_WINDOWEDGE; #280 else #281 dwExStyle &= ~WS_EX_WINDOWEDGE; #282
检查不是子窗口的属性是否对。 #283 /* Correct the window style. */ #284 if (!(dwStyle & WS_CHILD)) #285 { #286 dwStyle |= WS_CLIPSIBLINGS; #287 DPRINT("3: Style is now %lx/n",dwStyle); #288 if (!(dwStyle & WS_POPUP)) #289 { #290 dwStyle |= WS_CAPTION; #291 Window->Flags |= WINDOWOBJECT_NEED_SIZE; #292 DPRINT("4: Style is now %lx/n",dwStyle); #293 } #294 } #295
创建窗口系统菜单。 #296 /* create system menu */ #297 if((dwStyle & WS_SYSMENU) )//&& (dwStyle & WS_CAPTION) == WS_CAPTION) #298 { #299 SystemMenu = IntGetSystemMenu(Window,TRUE,TRUE); #300 if(SystemMenu) #301 { #302 Window->SystemMenu = SystemMenu->MenuInfo.Self; #303 IntReleaseMenuObject(SystemMenu); #304 } #305 } #306
设置窗口菜单。 #307 /* Set the window menu */ #308 if ((dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) #309 { #310 if (hMenu) #311 IntSetMenu(Window,hMenu,&MenuChanged); #312 else #313 { #314 hMenu = Wnd->Class->hMenu; #315 if (hMenu) IntSetMenu(Window,&MenuChanged); #316 } #317 } #318 else #319 Wnd->IDMenu = (UINT) hMenu; #320
把窗口添加到线程队列里。 #321 /* Insert the window into the thread's window list. */ #322 InsertTailList (&pti->WindowListHead,&Window->ThreadListEntry); #323
为窗口分配设备DC,可以分配窗口类的DC,也可以是窗口的DC。这里调用驱动程序来创建一个设备。 #324 /* Handle "CS_CLASSDC",it is tested first. */ #325 if ((Wnd->Class->Style & CS_CLASSDC) && !(Wnd->Class->Dce)) // One DCE per class to have CLASS. #326 Wnd->Class->Dce = DceAllocDCE(Window,DCE_CLASS_DC); #327 /* Allocate a DCE for this window. */ #328 else if ( Wnd->Class->Style & CS_OWNDC) #329 Window->Dce = DceAllocDCE(Window,DCE_WINDOW_DC); #330
设置窗口的位置和大小。 #331 Pos.x = x; #332 Pos.y = y; #333 Size.cx = nWidth; #334 Size.cy = nHeight; #335 #336 Wnd->ExStyle = dwExStyle; #337 Wnd->Style = dwStyle & ~WS_VISIBLE; #338
设置窗口HOOK。 #339 /* call hook */ #340 Cs.lpCreateParams = lpParam; #341 Cs.hInstance = hInstance; #342 Cs.hMenu = hMenu; #343 Cs.hwndParent = hWndParent; //Pass the original Parent handle! #344 Cs.cx = Size.cx; #345 Cs.cy = Size.cy; #346 Cs.x = Pos.x; #347 Cs.y = Pos.y; #348 Cs.style = Wnd->Style; #349 Cs.lpszName = (LPCWSTR) WindowName; #350 Cs.lpszClass = (LPCWSTR) ClassName; #351 Cs.dwExStyle = dwExStyle; #352 CbtCreate.lpcs = &Cs; #353 CbtCreate.hwndInsertAfter = HWND_TOP; #354 if (co_HOOK_CallHooks(WH_CBT,HCBT_CREATEWND,(WPARAM) hWnd,(LPARAM) &CbtCreate)) #355 { #356 /* FIXME - Delete window object and remove it from the thread windows list */ #357 /* FIXME - delete allocated DCE */ #358 DPRINT1("CBT-hook returned !0/n"); #359 RETURN( (HWND) NULL); #360 } #361 #362 x = Cs.x; #363 y = Cs.y; #364 nWidth = Cs.cx; #365 nHeight = Cs.cy; #366
计算重叠窗口位置和大小。 #367 /* default positioning for overlapped windows */ #368 if(!(Wnd->Style & (WS_POPUP | WS_CHILD))) #369 { #370 RECT rc,WorkArea; #371 PRTL_USER_PROCESS_PARAMETERS ProcessParams; #372 BOOL CalculatedDefPosSize = FALSE; #373 #374 IntGetDesktopWorkArea(((PTHREADINFO)Window->OwnerThread->Tcb.Win32Thread)->Desktop,&WorkArea); #375 #376 rc = WorkArea; #377 ProcessParams = PsGetCurrentProcess()->Peb->ProcessParameters; #378 #379 if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16) #380 { #381 CalculatedDefPosSize = IntCalcDefPosSize(ParentWindow,Window,&rc,TRUE); #382 #383 if(ProcessParams->WindowFlags & STARTF_USEPOSITION) #384 { #385 ProcessParams->WindowFlags &= ~STARTF_USEPOSITION; #386 Pos.x = WorkArea.left + ProcessParams->StartingX; #387 Pos.y = WorkArea.top + ProcessParams->StartingY; #388 } #389 else #390 { #391 Pos.x = rc.left; #392 Pos.y = rc.top; #393 } #394 #395 /* #396 According to wine,the ShowMode is set to y if x == CW_USEDEFAULT(16) and #397 y is something else. and Quote! #398 */ #399 #400 /* Never believe Microsoft's documentation... CreateWindowEx doc says #401 * that if an overlapped window is created with WS_VISIBLE style bit #402 * set and the x parameter is set to CW_USEDEFAULT,the system ignores #403 * the y parameter. However,disassembling NT implementation (WIN32K.SYS) #404 * reveals that #405 * #406 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16 #407 * 2) it does not ignore the y parameter as the docs claim; instead,it #408 * uses it as second parameter to ShowWindow() unless y is either #409 * CW_USEDEFAULT or CW_USEDEFAULT16. #410 * #411 * The fact that we didn't do 2) caused bogus windows pop up when wine #412 * was running apps that were using this obscure feature. Example - #413 * calc.exe that comes with Win98 (only Win98,it's different from #414 * the one that comes with Win95 and NT) #415 */ #416 if(y != CW_USEDEFAULT && y != CW_USEDEFAULT16) #417 { #418 dwShowMode = y; #419 } #420 } #421 if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16) #422 { #423 if(!CalculatedDefPosSize) #424 { #425 IntCalcDefPosSize(ParentWindow,FALSE); #426 } #427 if(ProcessParams->WindowFlags & STARTF_USESIZE) #428 { #429 ProcessParams->WindowFlags &= ~STARTF_USESIZE; #430 Size.cx = ProcessParams->CountX; #431 Size.cy = ProcessParams->CountY; #432 } #433 else #434 { #435 Size.cx = rc.right - rc.left; #436 Size.cy = rc.bottom - rc.top; #437 } #438 #439 /* move the window if necessary */ #440 if(Pos.x > rc.left) #441 Pos.x = max(rc.left,0); #442 if(Pos.y > rc.top) #443 Pos.y = max(rc.top,0); #444 } #445 } #446 else #447 { #448 /* if CW_USEDEFAULT(16) is set for non-overlapped windows,both values are set to zero) */ #449 if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16) #450 { #451 Pos.x = 0; #452 Pos.y = 0; #453 } #454 if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16) #455 { #456 Size.cx = 0; #457 Size.cy = 0; #458 } #459 } #460
初始化窗口显示的大小。 #461 /* Initialize the window dimensions. */ #462 Wnd->WindowRect.left = Pos.x; #463 Wnd->WindowRect.top = Pos.y; #464 Wnd->WindowRect.right = Pos.x + Size.cx; #465 Wnd->WindowRect.bottom = Pos.y + Size.cy; #466 if (0 != (Wnd->Style & WS_CHILD) && ParentWindow) #467 { #468 IntGdiOffsetRect(&(Wnd->WindowRect),ParentWindow->Wnd->ClientRect.left, #469 ParentWindow->Wnd->ClientRect.top); #470 } #471 Wnd->ClientRect = Wnd->WindowRect; #472 #473 /* #474 * Get the size and position of the window. #475 */ #476 if ((dwStyle & WS_THICKFRAME) || !(dwStyle & (WS_POPUP | WS_CHILD))) #477 { #478 POINT MaxSize,MaxTrack; #479 #480 /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */ #481 co_WinPosGetMinMaxInfo(Window,&MaxSize,&MaxPos,&MinTrack, #482 &MaxTrack); #483 if (MaxSize.x < Size.cx) #484 Size.cx = MaxSize.x; #485 if (MaxSize.y < Size.cy) #486 Size.cy = MaxSize.y; #487 if (Size.cx < MinTrack.x ) #488 Size.cx = MinTrack.x; #489 if (Size.cy < MinTrack.y ) #490 Size.cy = MinTrack.y; #491 if (Size.cx < 0) #492 Size.cx = 0; #493 if (Size.cy < 0) #494 Size.cy = 0; #495 } #496 #497 Wnd->WindowRect.left = Pos.x; #498 Wnd->WindowRect.top = Pos.y; #499 Wnd->WindowRect.right = Pos.x + Size.cx; #500 Wnd->WindowRect.bottom = Pos.y + Size.cy; #501 if (0 != (Wnd->Style & WS_CHILD) && ParentWindow) #502 { #503 IntGdiOffsetRect(&(Wnd->WindowRect), #504 ParentWindow->Wnd->ClientRect.top); #505 }
窗口客户区的大小。 #506 Wnd->ClientRect = Wnd->WindowRect; #507 #508 /* FIXME: Initialize the window menu. */ #509 #510 /* Send a NCCREATE message. */ #511 Cs.cx = Size.cx; #512 Cs.cy = Size.cy; #513 Cs.x = Pos.x; #514 Cs.y = Pos.y; #515 #516 DPRINT("[win32k.window] IntCreateWindowEx style %d,exstyle %d,parent %d/n",Cs.style,Cs.dwExStyle,Cs.hwndParent); #517 DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)/n",x,y,Size.cx,Size.cy); #518 DPRINT("IntCreateWindowEx(): About to send NCCREATE message./n");
发送创建窗口的WM_NCCREATE消息。 #519 Result = co_IntSendMessage(Window->hSelf,WM_NCCREATE,(LPARAM) &Cs); #520 if (!Result) #521 { #522 /* FIXME: Cleanup. */ #523 DPRINT1("IntCreateWindowEx(): NCCREATE message failed. No cleanup performed!/n"); #524 RETURN((HWND)0); #525 } #526
计算非窗户客户端的大小。 #527 /* Calculate the non-client size. */ #528 MaxPos.x = Window->Wnd->WindowRect.left; #529 MaxPos.y = Window->Wnd->WindowRect.top; #530 #531 #532 DPRINT("IntCreateWindowEx(): About to get non-client size./n"); #533 /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */ #534 Result = co_WinPosGetNonClientSize(Window, #535 &Window->Wnd->WindowRect, #536 &Window->Wnd->ClientRect); #537 #538 IntGdiOffsetRect(&Window->Wnd->WindowRect, #539 MaxPos.x - Window->Wnd->WindowRect.left, #540 MaxPos.y - Window->Wnd->WindowRect.top); #541 #542
如果父窗口不为空,说明本窗口是子窗口。 #543 if (NULL != ParentWindow) #544 {
把本窗口连接到父窗口列表里。 #545 /* link the window into the parent's child list */ #546 if ((dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) #547 { #548 PWINDOW_OBJECT PrevSibling; #549 #550 PrevSibling = ParentWindow->LastChild; #551 #552 /* link window as bottom sibling */ #553 IntLinkWindow(Window,ParentWindow,PrevSibling /*prev sibling*/); #554 } #555 else #556 { #557 /* link window as top sibling (but after topmost siblings) */ #558 PWINDOW_OBJECT InsertAfter,Sibling; #559 if (!(dwExStyle & WS_EX_TOPMOST)) #560 { #561 InsertAfter = NULL; #562 Sibling = ParentWindow->FirstChild; #563 while (Sibling && (Sibling->Wnd->ExStyle & WS_EX_TOPMOST)) #564 { #565 InsertAfter = Sibling; #566 Sibling = Sibling->NextSibling; #567 } #568 } #569 else #570 { #571 InsertAfter = NULL; #572 } #573 #574 IntLinkWindow(Window,InsertAfter /* prev sibling */); #575 #576 } #577 } #578
发送创建窗口的WM_CREATE消息。 #579 /* Send the WM_CREATE message. */ #580 DPRINT("IntCreateWindowEx(): about to send CREATE message./n"); #581 Result = co_IntSendMessage(Window->hSelf,WM_CREATE,(LPARAM) &Cs); #582 #583 if (Result == (LRESULT)-1) #584 { #585 /* FIXME: Cleanup. */ #586 DPRINT1("IntCreateWindowEx(): send CREATE message failed. No cleanup performed!/n"); #587 IntUnlinkWindow(Window); #588 RETURN((HWND)0); #589 } #590 #if 0 #591 Result = IntNotifyWinEvent(EVENT_OBJECT_CREATE,OBJID_WINDOW,0); #592 #593 if (Result == (LRESULT)-1) #594 { #595 /* FIXME: Cleanup. */ #596 DPRINT1("IntCreateWindowEx(): event CREATE hook failed. No cleanup performed!/n"); #597 IntUnlinkWindow(Window); #598 RETURN((HWND)0); #599 } #600 #endif
发送窗口设置大小的WM_SIZE消息。 #601 /* Send move and size messages. */ #602 if (!(Window->Flags & WINDOWOBJECT_NEED_SIZE)) #603 { #604 LONG lParam; #605 #606 DPRINT("IntCreateWindow(): About to send WM_SIZE/n"); #607 #608 if ((Window->Wnd->ClientRect.right - Window->Wnd->ClientRect.left) < 0 || #609 (Window->Wnd->ClientRect.bottom - Window->Wnd->ClientRect.top) < 0) #610 { #611 DPRINT("Sending bogus WM_SIZE/n"); #612 } #613 #614 lParam = MAKE_LONG(Window->Wnd->ClientRect.right - #615 Window->Wnd->ClientRect.left, #616 Window->Wnd->ClientRect.bottom - #617 Window->Wnd->ClientRect.top); #618 co_IntSendMessage(Window->hSelf,WM_SIZE,SIZE_RESTORED, #619 lParam); #620 #621 DPRINT("IntCreateWindow(): About to send WM_MOVE/n"); #622
发送窗口移动到某位置的WM_MOVE消息。 #623 if (0 != (Wnd->Style & WS_CHILD) && ParentWindow) #624 { #625 lParam = MAKE_LONG(Wnd->ClientRect.left - ParentWindow->Wnd->ClientRect.left, #626 Wnd->ClientRect.top - ParentWindow->Wnd->ClientRect.top); #627 } #628 else #629 { #630 lParam = MAKE_LONG(Wnd->ClientRect.left, #631 Wnd->ClientRect.top); #632 } #633 #634 co_IntSendMessage(Window->hSelf,WM_MOVE,lParam); #635 #636 /* Call WNDOBJ change procs */ #637 IntEngWindowChanged(Window,WOC_RGN_CLIENT); #638 } #639
设置窗口最大化或最小化显示。 #640 /* Show or maybe minimize or maximize the window. */ #641 if (Wnd->Style & (WS_MINIMIZE | WS_MAXIMIZE)) #642 { #643 RECT NewPos; #644 UINT16 SwFlag; #645 #646 SwFlag = (Wnd->Style & WS_MINIMIZE) ? SW_MINIMIZE : #647 SW_MAXIMIZE; #648 #649 co_WinPosMinMaximize(Window,SwFlag,&NewPos); #650 #651 SwFlag = ((Wnd->Style & WS_CHILD) || UserGetActiveWindow()) ? #652 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED : #653 SWP_NOZORDER | SWP_FRAMECHANGED; #654 #655 DPRINT("IntCreateWindow(): About to minimize/maximize/n"); #656 DPRINT("%d,%d %dx%d/n",NewPos.left,NewPos.top,NewPos.right,NewPos.bottom); #657 co_WinPosSetWindowPos(Window, #658 NewPos.right,NewPos.bottom,SwFlag); #659 } #660
如果是创建子窗口,通知父窗口已经创建了一个子窗口。 #661 /* Notify the parent window of a new child. */ #662 if ((Wnd->Style & WS_CHILD) && #663 (!(Wnd->ExStyle & WS_EX_NOPARENTNOTIFY)) && ParentWindow) #664 { #665 DPRINT("IntCreateWindow(): About to notify parent/n"); #666 co_IntSendMessage(ParentWindow->hSelf, #667 WM_PARENTNOTIFY, #668 MAKEWPARAM(WM_CREATE,Wnd->IDMenu), #669 (LPARAM)Window->hSelf); #670 } #671 #672 if ((!hWndParent) && (!HasOwner)) #673 { #674 DPRINT("Sending CREATED notify/n"); #675 co_IntShellHookNotify(HSHELL_WINDOWCREATED,(LPARAM)hWnd); #676 } #677 else #678 { #679 DPRINT("Not sending CREATED notify,%x %d/n",HasOwner); #680 } #681
设置窗口的滚动条。 #682 /* Initialize and show the window's scrollbars */ #683 if (Wnd->Style & WS_VSCROLL) #684 { #685 co_UserShowScrollBar(Window,SB_VERT,TRUE); #686 } #687 if (Wnd->Style & WS_HSCROLL) #688 { #689 co_UserShowScrollBar(Window,SB_HORZ,TRUE); #690 } #691
设置窗口显示方式。 #692 if (dwStyle & WS_VISIBLE) #693 { #694 if (Wnd->Style & WS_MAXIMIZE) #695 dwShowMode = SW_SHOW; #696 else if (Wnd->Style & WS_MINIMIZE) #697 dwShowMode = SW_SHOWMINIMIZED; #698 #699 DPRINT("IntCreateWindow(): About to show window/n"); #700 co_WinPosShowWindow(Window,dwShowMode); #701 #702 if (Wnd->ExStyle & WS_EX_MDICHILD) #703 { #704 co_IntSendMessage(ParentWindow->hSelf,WM_MDIREFRESHMENU,0); #705 /* ShowWindow won't activate child windows */ #706 co_WinPosSetWindowPos(Window,HWND_TOP,SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); #707 } #708 } #709
#710 /* BugBoy Comments: if the window being created is a edit control,ATOM 0xC007, #711 then my testing shows that windows (2k and XP) creates a CallProc for it immediately #712 Dont understand why it does this. */ #713 if (ClassAtom == 0XC007) #714 { #715 PCALLPROC CallProc; #716 //CallProc = CreateCallProc(NULL,Wnd->WndProc,bUnicodeWindow,Wnd->ti->kpi); #717 CallProc = CreateCallProc(NULL,Wnd->Unicode,Wnd->ti->kpi); #718 #719 if (!CallProc) #720 { #721 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); #722 DPRINT1("Warning: Unable to create CallProc for edit control. Control may not operate correctly! hwnd %x/n",hWnd); #723 } #724 else #725 { #726 UserAddCallProcToClass(Wnd->Class,CallProc); #727 Wnd->CallProc = CallProc; #728 Wnd->IsSystem = FALSE; #729 } #730 } #731
返回创建窗口的句柄。 #732 DPRINT("IntCreateWindow(): = %X/n",hWnd); #733 DPRINT("WindowObject->SystemMenu = 0x%x/n",Window->SystemMenu); #734 RETURN(hWnd); #735
下面是清除失败时分配的资源。 #736 CLEANUP: #737 if (!_ret_ && Window && Window->Wnd && ti) #738 UserFreeWindowInfo(ti,Window); #739 if (Window) #740 { #741 UserDerefObjectCo(Window); #742 UserDereferenceObject(Window); #743 } #744 if (ParentWindow) UserDerefObjectCo(ParentWindow); #745 if (!_ret_ && ti != NULL) #746 { #747 if (Class != NULL) #748 { #749 IntDereferenceClass(Class, #750 ti->Desktop, #751 ti->kpi); #752 } #753 } #754 END_CLEANUP; #755 } #756 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |