zl程序教程

您现在的位置是:首页 >  系统

当前栏目

reactos操作系统实现(180)

操作系统 实现 reactos 180
2023-09-14 09:10:38 时间

DefWndNCPaint函数实现窗口非客户区的显示部分,比如窗口的标题、最大化、最小化、关闭按钮、滚动条等等。

#001  LRESULT

#002  DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active)

#003  {

#004     HDC hDC;

#005     DWORD Style, ExStyle;

#006     HWND Parent;

#007     RECT ClientRect, WindowRect, CurrentRect, TempRect;

#008 

 

如果窗口不可见,就不用进行显示操作。

#009     if (!IsWindowVisible(hWnd))

#010        return 0;

#011 

 

获取窗口的类型。

#012     Style = GetWindowLongW(hWnd, GWL_STYLE);

#013 

 

获取窗口的设备。

#014     hDC = GetDCEx(hWnd, hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN);

#015     if (hDC == 0)

#016     {

#017        return 0;

#018     }

#019 

 

获取父窗口。

#020     Parent = GetParent(hWnd);

 

获取窗口扩展类型。

#021     ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);

 

判断当前窗口是否为有焦点的窗口。

#022     if (Active == -1)

#023     {

#024        if (ExStyle & WS_EX_MDICHILD)

#025        {

#026           Active = IsChild(GetForegroundWindow(), hWnd);

#027           if (Active)

#028              Active = (hWnd == (HWND)SendMessageW(Parent, WM_MDIGETACTIVE, 0, 0));

#029        }

#030        else

#031        {

#032           Active = (GetForegroundWindow() == hWnd);

#033        }

#034     }

 

获取窗口的位置和大小。

#035     GetWindowRect(hWnd, &WindowRect);

 

获取窗口客户区的大小。

#036     GetClientRect(hWnd, &ClientRect);

#037 

 

计算窗口的大小。

#038     CurrentRect.top = CurrentRect.left = 0;

#039     CurrentRect.right = WindowRect.right - WindowRect.left;

#040     CurrentRect.bottom = WindowRect.bottom - WindowRect.top;

#041 

 

如果窗口有边沿类型,就需要画边沿窗口。

#042     /* Draw outer edge */

#043     if (UserHasWindowEdge(Style, ExStyle))

#044     {

 

显示窗口的边沿线。

#045        DrawEdge(hDC, &CurrentRect, EDGE_RAISED, BF_RECT | BF_ADJUST);

#046     } else

#047     if (ExStyle & WS_EX_STATICEDGE)

#048     {

 

显示固定边沿线。

#049  #if 0

#050        DrawEdge(hDC, &CurrentRect, BDR_SUNKENINNER, BF_RECT | BF_ADJUST | BF_FLAT);

#051  #else

#052        SelectObject(hDC, GetSysColorBrush(COLOR_BTNSHADOW));

#053        PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, 1, PATCOPY);

#054        PatBlt(hDC, CurrentRect.left, CurrentRect.top, 1, CurrentRect.bottom - CurrentRect.top, PATCOPY);

#055 

#056        SelectObject(hDC, GetSysColorBrush(COLOR_BTNHIGHLIGHT));

#057        PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, 1, PATCOPY);

#058        PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, 1, CurrentRect.bottom - CurrentRect.top, PATCOPY);

#059 

#060        InflateRect(&CurrentRect, -1, -1);

#061  #endif

#062     }

#063 

 

显示窗口细边框的样式。

#064     /* Firstly the "thick" frame */

#065     if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))

#066     {

#067        DWORD Width =

#068           (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) *

#069           GetSystemMetrics(SM_CXBORDER);

#070        DWORD Height =

#071           (GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME)) *

#072           GetSystemMetrics(SM_CYBORDER);

#073 

#074        SelectObject(hDC, GetSysColorBrush(Active ? COLOR_ACTIVEBORDER :

#075           COLOR_INACTIVEBORDER));

#076 

#077        /* Draw frame */

#078        PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);

#079        PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);

#080  #ifdef __REACTOS__

#081        PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);

#082        PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);

#083  #else

#084        PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);

#085        PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);

#086  #endif

#087 

#088        InflateRect(&CurrentRect, -Width, -Height);

#089     }

#090 

 

显示框架部分。

#091     /* Now the other bit of the frame */

#092     if (Style & (WS_DLGFRAME | WS_BORDER) || ExStyle & WS_EX_DLGMODALFRAME)

#093     {

#094        DWORD Width = GetSystemMetrics(SM_CXBORDER);

#095        DWORD Height = GetSystemMetrics(SM_CYBORDER);

#096  

#097        SelectObject(hDC, GetSysColorBrush(

#098           (ExStyle & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) ? COLOR_3DFACE :

#099           (ExStyle & WS_EX_STATICEDGE) ? COLOR_WINDOWFRAME :

#100           (Style & (WS_DLGFRAME | WS_THICKFRAME)) ? COLOR_3DFACE :

#101           COLOR_WINDOWFRAME));

#102 

#103        /* Draw frame */

#104        PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);

#105        PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);

#106  #ifdef __REACTOS__

#107        PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);

#108        PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);

#109  #else

#110        PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);

#111        PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);

#112  #endif

#113 

#114        InflateRect(&CurrentRect, -Width, -Height);

#115     }

#116 

 

当窗口有标题时,就需要显示标题,也就是显示窗口最顶端的字符串。

#117     /* Draw caption */

#118     if ((Style & WS_CAPTION) == WS_CAPTION)

#119     {

#120        DWORD CaptionFlags = DC_ICON | DC_TEXT | DC_BUTTONS;

#121        HPEN PreviousPen;

#122        BOOL Gradient = FALSE;

#123 

#124        if(SystemParametersInfoW(SPI_GETGRADIENTCAPTIONS, 0, &Gradient, 0) && Gradient)

#125        {

#126          CaptionFlags |= DC_GRADIENT;

#127        }

#128 

#129        TempRect = CurrentRect;

#130 

#131        if (Active)

#132        {

#133           CaptionFlags |= DC_ACTIVE;

#134        }

#135 

 

如果是工具条窗口,就需要显示窗口标题为比较小。

#136        if (ExStyle & WS_EX_TOOLWINDOW)

#137        {

#138           CaptionFlags |= DC_SMALLCAP;

#139           TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSMCAPTION) - 1;

#140           CurrentRect.top += GetSystemMetrics(SM_CYSMCAPTION);

#141        }

#142        else

#143        {

#144           TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYCAPTION) - 1;

#145           CurrentRect.top += GetSystemMetrics(SM_CYCAPTION);

#146        }

#147 

 

下面调用函数NtUserDrawCaption来显示窗口标题。

#148        NtUserDrawCaption(hWnd, hDC, &TempRect, CaptionFlags);

#149 

 

下面显示系统的菜单按钮。

#150        /* Draw buttons */

#151        if (Style & WS_SYSMENU)

#152        {

#153           UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONCLOSE);

#154           if ((Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX)) && !(ExStyle & WS_EX_TOOLWINDOW))

#155           {

#156              UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMIN);

#157              UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMAX);

#158           }

#159        }

#160        if(!(Style & WS_MINIMIZE))

#161        {

#162          /* Line under caption */

#163          PreviousPen = SelectObject(hDC, GetSysColorPen(

#164             ((ExStyle & (WS_EX_STATICEDGE | WS_EX_CLIENTEDGE |

#165                          WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?

#166             COLOR_WINDOWFRAME : COLOR_3DFACE));

#167          MoveToEx(hDC, TempRect.left, TempRect.bottom, NULL);

#168          LineTo(hDC, TempRect.right, TempRect.bottom);

#169          SelectObject(hDC, PreviousPen);

#170        }

#171     }

#172 

#173     if(!(Style & WS_MINIMIZE))

#174     {

#175       HMENU menu = GetMenu(hWnd);

#176       /* Draw menu bar */

#177       if (menu && !(Style & WS_CHILD))

#178       {

#179          TempRect = CurrentRect;

#180          TempRect.bottom = TempRect.top + (UINT)NtUserSetMenuBarHeight(menu, 0);

#181          CurrentRect.top += MenuDrawMenuBar(hDC, &TempRect, hWnd, FALSE);

#182       }

#183 

 

显示客户区边界。

#184       if (ExStyle & WS_EX_CLIENTEDGE)

#185       {

#186          DrawEdge(hDC, &CurrentRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);

#187       }

#188 

 

显示窗口的滚动条。

#189       /* Draw the scrollbars */

#190       if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&

#191           IntIsScrollBarVisible(hWnd, OBJID_VSCROLL) && IntIsScrollBarVisible(hWnd, OBJID_HSCROLL))

#192       {

#193          RECT ParentClientRect;

#194 

#195          TempRect = CurrentRect;

#196          if (ExStyle & WS_EX_LEFTSCROLLBAR)

#197             TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);

#198          else

#199             TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);

#200          TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);

#201          FillRect(hDC, &TempRect, GetSysColorBrush(COLOR_BTNFACE));

#202          /* FIXME: Correct drawing of size-box with WS_EX_LEFTSCROLLBAR */

#203          if(Parent)

#204            GetClientRect(Parent, &ParentClientRect);

#205          if (HASSIZEGRIP(Style, ExStyle, GetWindowLongW(Parent, GWL_STYLE), WindowRect, ParentClientRect))

#206          {

#207             DrawFrameControl(hDC, &TempRect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);

#208          }

#209          IntDrawScrollBar(hWnd, hDC, SB_VERT);

#210          IntDrawScrollBar(hWnd, hDC, SB_HORZ);

#211       }

#212       else

#213       {

#214          if (Style & WS_VSCROLL && IntIsScrollBarVisible(hWnd, OBJID_VSCROLL))

#215             IntDrawScrollBar(hWnd, hDC, SB_VERT);

#216          else if (Style & WS_HSCROLL && IntIsScrollBarVisible(hWnd, OBJID_HSCROLL))

#217             IntDrawScrollBar(hWnd, hDC, SB_HORZ);

#218       }

#219     }

#220 

#221     ReleaseDC(hWnd, hDC);

#222 

#223     return 0;

#224  }