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

reactos操作系统实现(162)

发布时间:2020-12-15 04:59:01 所属栏目:百科 来源:网络整理
导读: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

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

(编辑:李大同)

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

    推荐文章
      热点阅读