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 }