⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 window.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
   }
}

static WNDPROC
IntGetWindowProc(IN PWINDOW_OBJECT Window,
                 IN BOOL Ansi)
{
    if (Window->IsSystem)
    {
        return (Ansi ? Window->WndProcExtra : Window->WndProc);
    }
    else
    {
        if (!Ansi == Window->Unicode)
        {
            return Window->WndProc;
        }
        else
        {
            if (Window->CallProc != NULL)
            {
                return GetCallProcHandle(Window->CallProc);
            }
            else
            {
                PCALLPROC NewCallProc, CallProc;

                /* NOTE: use the interlocked functions, as this operation may be done even
                         when only the shared lock is held! */
                NewCallProc = CreateCallProc(Window->ti->Desktop,
                                             Window->WndProc,
                                             Window->Unicode,
                                             Window->ti->kpi);
                if (NewCallProc == NULL)
                {
                    SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
                    return NULL;
                }

                CallProc = InterlockedCompareExchangePointer(&Window->CallProc,
                                                             NewCallProc,
                                                             NULL);
                if (CallProc != NULL)
                {
                    DestroyCallProc(Window->ti->Desktop,
                                    NewCallProc);
                }

                return GetCallProcHandle((CallProc == NULL ? NewCallProc : CallProc));
            }
        }
    }
}

BOOL FASTCALL
IntGetWindowInfo(PWINDOW_OBJECT Window, PWINDOWINFO pwi)
{
   pwi->cbSize = sizeof(WINDOWINFO);
   pwi->rcWindow = Window->WindowRect;
   pwi->rcClient = Window->ClientRect;
   pwi->dwStyle = Window->Style;
   pwi->dwExStyle = Window->ExStyle;
   pwi->dwWindowStatus = (UserGetForegroundWindow() == Window->hSelf); /* WS_ACTIVECAPTION */
   IntGetWindowBorderMeasures(Window, &pwi->cxWindowBorders, &pwi->cyWindowBorders);
   pwi->atomWindowType = (Window->Class ? Window->Class->Atom : 0);
   pwi->wCreatorVersion = 0x400; /* FIXME - return a real version number */
   return TRUE;
}

static BOOL FASTCALL
IntSetMenu(
   PWINDOW_OBJECT Window,
   HMENU Menu,
   BOOL *Changed)
{
   PMENU_OBJECT OldMenu, NewMenu = NULL;

   if ((Window->Style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
   {
      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
      return FALSE;
   }

   *Changed = (Window->IDMenu != (UINT) Menu);
   if (! *Changed)
   {
      return TRUE;
   }

   if (Window->IDMenu)
   {
      OldMenu = IntGetMenuObject((HMENU) Window->IDMenu);
      ASSERT(NULL == OldMenu || OldMenu->MenuInfo.Wnd == Window->hSelf);
   }
   else
   {
      OldMenu = NULL;
   }

   if (NULL != Menu)
   {
      NewMenu = IntGetMenuObject(Menu);
      if (NULL == NewMenu)
      {
         if (NULL != OldMenu)
         {
            IntReleaseMenuObject(OldMenu);
         }
         SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
         return FALSE;
      }
      if (NULL != NewMenu->MenuInfo.Wnd)
      {
         /* Can't use the same menu for two windows */
         if (NULL != OldMenu)
         {
            IntReleaseMenuObject(OldMenu);
         }
         SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
         return FALSE;
      }

   }

   Window->IDMenu = (UINT) Menu;
   if (NULL != NewMenu)
   {
      NewMenu->MenuInfo.Wnd = Window->hSelf;
      IntReleaseMenuObject(NewMenu);
   }
   if (NULL != OldMenu)
   {
      OldMenu->MenuInfo.Wnd = NULL;
      IntReleaseMenuObject(OldMenu);
   }

   return TRUE;
}


/* INTERNAL ******************************************************************/


VOID FASTCALL
co_DestroyThreadWindows(struct _ETHREAD *Thread)
{
   PW32THREAD WThread;
   PLIST_ENTRY Current;
   PWINDOW_OBJECT Wnd;
   USER_REFERENCE_ENTRY Ref;
   WThread = (PW32THREAD)Thread->Tcb.Win32Thread;

   while (!IsListEmpty(&WThread->WindowListHead))
   {
      Current = WThread->WindowListHead.Flink;
      Wnd = CONTAINING_RECORD(Current, WINDOW_OBJECT, ThreadListEntry);

      DPRINT("thread cleanup: while destroy wnds, wnd=0x%x\n",Wnd);

      /* window removes itself from the list */

      /*
      fixme: it is critical that the window removes itself! if now, we will loop
      here forever...
      */

      //ASSERT(co_UserDestroyWindow(Wnd));

      UserRefObjectCo(Wnd, &Ref);//faxme: temp hack??
      if (!co_UserDestroyWindow(Wnd))
      {
         DPRINT1("Unable to destroy window 0x%x at thread cleanup... This is _VERY_ bad!\n", Wnd);
      }
      UserDerefObjectCo(Wnd);//faxme: temp hack??
   }
}



/*!
 * Internal function.
 * Returns client window rectangle relative to the upper-left corner of client area.
 *
 * \note Does not check the validity of the parameters
*/
VOID FASTCALL
IntGetClientRect(PWINDOW_OBJECT Window, PRECT Rect)
{
   ASSERT( Window );
   ASSERT( Rect );

   Rect->left = Rect->top = 0;
   Rect->right = Window->ClientRect.right - Window->ClientRect.left;
   Rect->bottom = Window->ClientRect.bottom - Window->ClientRect.top;
}


#if 0
HWND FASTCALL
IntGetFocusWindow(VOID)
{
   PUSER_MESSAGE_QUEUE Queue;
   PDESKTOP_OBJECT pdo = IntGetActiveDesktop();

   if( !pdo )
      return NULL;

   Queue = (PUSER_MESSAGE_QUEUE)pdo->ActiveMessageQueue;

   if (Queue == NULL)
      return(NULL);
   else
      return(Queue->FocusWindow);
}
#endif

PMENU_OBJECT FASTCALL
IntGetSystemMenu(PWINDOW_OBJECT Window, BOOL bRevert, BOOL RetMenu)
{
   PMENU_OBJECT Menu, NewMenu = NULL, SysMenu = NULL, ret = NULL;
   PW32THREAD W32Thread;
   HMENU hNewMenu, hSysMenu;
   ROSMENUITEMINFO ItemInfo;

   if(bRevert)
   {
      W32Thread = PsGetCurrentThreadWin32Thread();

      if(!W32Thread->Desktop)
         return NULL;

      if(Window->SystemMenu)
      {
         Menu = UserGetMenuObject(Window->SystemMenu);
         if(Menu)
         {
            IntDestroyMenuObject(Menu, FALSE, TRUE);
            Window->SystemMenu = (HMENU)0;
         }
      }

      if(W32Thread->Desktop->WindowStation->SystemMenuTemplate)
      {
         /* clone system menu */
         Menu = UserGetMenuObject(W32Thread->Desktop->WindowStation->SystemMenuTemplate);
         if(!Menu)
            return NULL;

         NewMenu = IntCloneMenu(Menu);
         if(NewMenu)
         {
            Window->SystemMenu = NewMenu->MenuInfo.Self;
            NewMenu->MenuInfo.Flags |= MF_SYSMENU;
            NewMenu->MenuInfo.Wnd = Window->hSelf;
            ret = NewMenu;
            //IntReleaseMenuObject(NewMenu);
         }
      }
      else
      {
         hSysMenu = UserCreateMenu(FALSE);
         if (NULL == hSysMenu)
         {
            return NULL;
         }
         SysMenu = IntGetMenuObject(hSysMenu);
         if (NULL == SysMenu)
         {
            UserDestroyMenu(hSysMenu);
            return NULL;
         }
         SysMenu->MenuInfo.Flags |= MF_SYSMENU;
         SysMenu->MenuInfo.Wnd = Window->hSelf;
         hNewMenu = co_IntLoadSysMenuTemplate();
         if(!hNewMenu)
         {
            IntReleaseMenuObject(SysMenu);
            UserDestroyMenu(hSysMenu);
            return NULL;
         }
         Menu = IntGetMenuObject(hNewMenu);
         if(!Menu)
         {
            IntReleaseMenuObject(SysMenu);
            UserDestroyMenu(hSysMenu);
            return NULL;
         }

         NewMenu = IntCloneMenu(Menu);
         if(NewMenu)
         {
            NewMenu->MenuInfo.Flags |= MF_SYSMENU | MF_POPUP;
            IntReleaseMenuObject(NewMenu);
            UserSetMenuDefaultItem(NewMenu, SC_CLOSE, FALSE);

            ItemInfo.cbSize = sizeof(MENUITEMINFOW);
            ItemInfo.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_SUBMENU;
            ItemInfo.fType = MF_POPUP;
            ItemInfo.fState = MFS_ENABLED;
            ItemInfo.dwTypeData = NULL;
            ItemInfo.cch = 0;
            ItemInfo.hSubMenu = NewMenu->MenuInfo.Self;
            IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo);

            Window->SystemMenu = SysMenu->MenuInfo.Self;

            ret = SysMenu;
         }
         IntDestroyMenuObject(Menu, FALSE, TRUE);
      }
      if(RetMenu)
         return ret;
      else
         return NULL;
   }
   else
   {
      if(Window->SystemMenu)
         return IntGetMenuObject((HMENU)Window->SystemMenu);
      else
         return NULL;
   }
}


BOOL FASTCALL
IntIsChildWindow(PWINDOW_OBJECT Parent, PWINDOW_OBJECT BaseWindow)
{
   PWINDOW_OBJECT Window;

   Window = BaseWindow;
   while (Window)
   {
      if (Window == Parent)
      {
         return(TRUE);
      }
      if(!(Window->Style & WS_CHILD))
      {
         break;
      }

      Window = Window->Parent;
   }

   return(FALSE);
}

BOOL FASTCALL
IntIsWindowVisible(PWINDOW_OBJECT BaseWindow)
{
   PWINDOW_OBJECT Window;

   Window = BaseWindow;
   while(Window)
   {
      if(!(Window->Style & WS_CHILD))
      {
         break;
      }
      if(!(Window->Style & WS_VISIBLE))
      {
         return FALSE;
      }

      Window = Window->Parent;
   }

   if(Window && Window->Style & WS_VISIBLE)
   {
      return TRUE;
   }

   return FALSE;
}


/* link the window into siblings and parent. children are kept in place. */
VOID FASTCALL
IntLinkWindow(
   PWINDOW_OBJECT Wnd,
   PWINDOW_OBJECT WndParent,
   PWINDOW_OBJECT WndPrevSibling /* set to NULL if top sibling */
)
{
   PWINDOW_OBJECT Parent;

   Wnd->Parent = WndParent;
   if ((Wnd->PrevSibling = WndPrevSibling))
   {
      /* link after WndPrevSibling */
      if ((Wnd->NextSibling = WndPrevSibling->NextSibling))
         Wnd->NextSibling->PrevSibling = Wnd;
      else if ((Parent = Wnd->Parent))
      {
         if(Parent->LastChild == WndPrevSibling)
            Parent->LastChild = Wnd;
      }
      Wnd->PrevSibling->NextSibling = Wnd;
   }
   else
   {
      /* link at top */
      Parent = Wnd->Parent;
      if ((Wnd->NextSibling = WndParent->FirstChild))
         Wnd->NextSibling->PrevSibling = Wnd;
      else if (Parent)
      {
         Parent->LastChild = Wnd;
         Parent->FirstChild = Wnd;
         return;
      }
      if(Parent)
      {
         Parent->FirstChild = Wnd;
      }
   }

}

HWND FASTCALL
IntSetOwner(HWND hWnd, HWND hWndNewOwner)
{
   PWINDOW_OBJECT Wnd, WndOldOwner, WndNewOwner;
   HWND ret;

   Wnd = IntGetWindowObject(hWnd);
   if(!Wnd)
      return NULL;

   WndOldOwner = IntGetWindowObject(Wnd->hOwner);
   if (WndOldOwner)
   {
      ret = WndOldOwner->hSelf;
      UserDerefObject(WndOldOwner);
   }
   else
   {
      ret = 0;
   }

   if((WndNewOwner = UserGetWindowObject(hWndNewOwner)))
   {
      Wnd->hOwner = hWndNewOwner;
   }
   else
      Wnd->hOwner = NULL;

   UserDerefObject(Wnd);
   return ret;
}

PWINDOW_OBJECT FASTCALL
co_IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent)
{
   PWINDOW_OBJECT WndOldParent, Sibling, InsertAfter;
//   HWND hWnd, hWndNewParent;
   BOOL WasVisible;

   ASSERT(Wnd);
   ASSERT(WndNewParent);
   ASSERT_REFS_CO(Wnd);
   ASSERT_REFS_CO(WndNewParent);

//   hWnd = Wnd->hSelf;
//   hWndNewParent = WndNewParent->hSelf;

   /*
    * Windows hides the window first, then shows it again
    * including the WM_SHOWWINDOW messages and all
    */
   WasVisible = co_WinPosShowWindow(Wnd, SW_HIDE);

//   /* Validate that window and parent still exist */
//   if (!IntIsWindow(hWnd) || !IntIsWindow(hWndNewParent))
//      return NULL;

   /* Window must belong to current process */
   if (Wnd->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
      return NULL;

   WndOldParent = Wnd->Parent;

   if (WndOldParent) UserRefObject(WndOldParent); /* caller must deref */

   if (WndNewParent != WndOldParent)
   {
      IntUnlinkWindow(Wnd);
      InsertAfter = NULL;
      if (0 == (Wnd->ExStyle & WS_EX_TOPMOST))
      {
         /* Not a TOPMOST window, put after TOPMOSTs of new parent */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -