UserDrawCaption函数是用来实现窗口标题显示。具体代码如下:
#001 BOOL UserDrawCaption(
#002 PWINDOW_OBJECT pWnd,
#003 HDC hDc,
#004 LPCRECT lpRc,
#005 HFONT hFont,
#006 HICON hIcon,
#007 const PUNICODE_STRING str,
#008 UINT uFlags)
#009 {
#010 BOOL Ret = FALSE;
#011 HBITMAP hMemBmp = NULL,hOldBmp = NULL;
#012 HBRUSH hOldBrush = NULL;
#013 HDC hMemDc = NULL;
#014 ULONG Height;
#015 UINT VCenter = 0,Padding = 0;
#016 RECT r = *lpRc;
#017 LONG ButtonWidth,IconWidth;
#018 BOOL HasIcon;
#019 PWINDOW Wnd = NULL;
#020
#021 //ASSERT(pWnd != NULL);
#022
获取窗口句柄。
#023 if (pWnd)
#024 Wnd = pWnd->Wnd;
#025
创建兼容DC的内存位图。
#026 hMemBmp = NtGdiCreateCompatibleBitmap(hDc,
#027 lpRc->right - lpRc->left,
#028 lpRc->bottom - lpRc->top);
#029
#030 if(!hMemBmp)
#031 {
#032 DPRINT1("%s: NtGdiCreateCompatibleBitmap() Failed!/n",__FUNCTION__);
#033 return FALSE;
#034 }
#035
创建兼容的内存设备。
#036 hMemDc = NtGdiCreateCompatibleDC(hDc);
#037 if(!hMemDc)
#038 {
#039 DPRINT1("%s: NtGdiCreateCompatibleDC() Failed!/n",__FUNCTION__);
#040 goto cleanup;
#041 }
#042
关联内存设备和位图设备。
#043 hOldBmp = NtGdiSelectBitmap(hMemDc,hMemBmp);
#044 if(!hOldBmp)
#045 {
#046 DPRINT1("%s: NtGdiSelectBitmap() Failed!/n",__FUNCTION__);
#047 goto cleanup;
#048 }
#049
#050 Height = UserGetSystemMetrics(SM_CYCAPTION) - 1;
#051 VCenter = (lpRc->bottom - lpRc->top) / 2;
#052 Padding = VCenter - (Height / 2);
#053
#054 if ((!hIcon) && (Wnd != NULL))
#055 {
#056 HasIcon = (uFlags & DC_ICON) && (Wnd->Style & WS_SYSMENU)
#057 && !(uFlags & DC_SMALLCAP) && !(Wnd->ExStyle & WS_EX_DLGMODALFRAME)
#058 && !(Wnd->ExStyle & WS_EX_TOOLWINDOW);
#059 }
#060 else
#061 HasIcon = (BOOL) hIcon;
#062
获取图标的宽度。
#063 IconWidth = UserGetSystemMetrics(SM_CXSIZE) + Padding;
#064
#065 r.left = Padding;
#066 r.right = r.left + (lpRc->right - lpRc->left);
#067 r.top = Padding;
#068 r.bottom = r.top + (Height / 2);
#069
#070 // Draw the caption background
#071 if(uFlags & DC_INBUTTON)
#072 {
#073 hOldBrush = NtGdiSelectBrush(hMemDc,
#074 IntGetSysColorBrush(COLOR_3DFACE));
#075
#076 if(!hOldBrush)
#077 {
#078 DPRINT1("%s: NtGdiSelectBrush() Failed!/n",__FUNCTION__);
#079 goto cleanup;
#080 }
#081
#082 if(!NtGdiPatBlt(hMemDc,
#083 lpRc->right - lpRc->left,
#084 lpRc->bottom - lpRc->top,
#085 PATCOPY))
#086 {
#087 DPRINT1("%s: NtGdiPatBlt() Failed!/n",__FUNCTION__);
#088 goto cleanup;
#089 }
#090
#091 if(HasIcon) r.left+=IconWidth;
#092 }
#093 else
#094 {
#095 r.right = (lpRc->right - lpRc->left);
#096 if(uFlags & DC_SMALLCAP)
#097 ButtonWidth = UserGetSystemMetrics(SM_CXSMSIZE) - 2;
#098 else ButtonWidth = UserGetSystemMetrics(SM_CXSIZE) - 2;
#099
#100 hOldBrush = NtGdiSelectBrush(hMemDc,
#101 IntGetSysColorBrush(uFlags & DC_ACTIVE ?
#102 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
#103
#104 if(!hOldBrush)
#105 {
#106 DPRINT1("%s: NtGdiSelectBrush() Failed!/n",__FUNCTION__);
#107 goto cleanup;
#108 }
#109
#110 if(HasIcon && (uFlags & DC_GRADIENT))
#111 {
#112 NtGdiPatBlt(hMemDc,
#113 IconWidth+1,
#114 lpRc->bottom - lpRc->top,
#115 PATCOPY);
#116 r.left+=IconWidth;
#117 }
#118 else
#119 {
#120 NtGdiPatBlt(hMemDc,
#121 lpRc->right - lpRc->left,
#122 lpRc->bottom - lpRc->top,
#123 PATCOPY);
#124 }
#125
#126 if(uFlags & DC_GRADIENT)
#127 {
#128 static GRADIENT_RECT gcap = {0,1};
#129 TRIVERTEX vert[2];
#130 COLORREF Colors[2];
#131 PDC pMemDc;
#132
#133 if (Wnd != NULL)
#134 {
#135 if(Wnd->Style & WS_SYSMENU)
#136 {
#137 r.right -= 3 + ButtonWidth;
#138 if(!(uFlags & DC_SMALLCAP))
#139 {
#140 if(Wnd->Style & (WS_MAXIMIZEBox | WS_MINIMIZEBox))
#141 r.right -= 2 + 2 * ButtonWidth;
#142 else r.right -= 2;
#143 r.right -= 2;
#144 }
#145
显示按钮背景颜色。
#146 //Draw buttons background
#147 if(!NtGdiSelectBrush(hMemDc,
#148 IntGetSysColorBrush(uFlags & DC_ACTIVE ?
#149 COLOR_GRADIENTACTIVECAPTION:COLOR_GRADIENTINACTIVECAPTION)))
#150 {
#151 DPRINT1("%s: NtGdiSelectBrush() Failed!/n",__FUNCTION__);
#152 goto cleanup;
#153 }
#154
#155 NtGdiPatBlt(hMemDc,
#156 r.right,
#157 0,
#158 lpRc->right - lpRc->left - r.right,
#159 lpRc->bottom - lpRc->top,
#160 PATCOPY);
#161 }
#162 }
#163
#164 Colors[0] = IntGetSysColor((uFlags & DC_ACTIVE) ?
#165 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
#166
#167 Colors[1] = IntGetSysColor((uFlags & DC_ACTIVE) ?
#168 COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION);
#169
#170 vert[0].x = r.left;
#171 vert[0].y = 0;
#172 vert[0].Red = (WORD)Colors[0]<<8;
#173 vert[0].Green = (WORD)Colors[0] & 0xFF00;
#174 vert[0].Blue = (WORD)(Colors[0]>>8) & 0xFF00;
#175 vert[0].Alpha = 0;
#176
#177 vert[1].x = r.right;
#178 vert[1].y = lpRc->bottom - lpRc->top;
#179 vert[1].Red = (WORD)Colors[1]<<8;
#180 vert[1].Green = (WORD)Colors[1] & 0xFF00;
#181 vert[1].Blue = (WORD)(Colors[1]>>8) & 0xFF00;
#182 vert[1].Alpha = 0;
#183
#184 pMemDc = DC_LockDc(hMemDc);
#185 if(!pMemDc)
#186 {
#187 DPRINT1("%s: Can't lock dc!/n",__FUNCTION__);
#188 goto cleanup;
#189 }
#190
#191 if(!IntGdiGradientFill(pMemDc,vert,2,&gcap,
#192 1,GRADIENT_FILL_RECT_H))
#193 {
#194 DPRINT1("%s: IntGdiGradientFill() Failed!/n",__FUNCTION__);
#195 }
#196
#197 DC_UnlockDc(pMemDc);
#198 } //if(uFlags & DC_GRADIENT)
#199 }
#200
#201 if(HasIcon)
#202 {
#203 r.top ++;
#204 r.left -= --IconWidth;
#205 /* FIXME: Draw the Icon when pWnd == NULL but hIcon is valid */
#206 if (pWnd != NULL)
#207 UserDrawSysMenuButton(pWnd,hMemDc,&r,FALSE);
#208 r.left += IconWidth;
#209 r.top --;
#210 }
#211
#212 r.top ++;
#213 r.left += 2;
#214
#215 r.bottom = r.top + Height;
#216
#217 if((uFlags & DC_TEXT))
#218 {
#219 if(!(uFlags & DC_GRADIENT))
#220 {
#221 r.right = (lpRc->right - lpRc->left);
#222
#223 if(uFlags & DC_SMALLCAP)
#224 ButtonWidth = UserGetSystemMetrics(SM_CXSMSIZE) - 2;
#225 else ButtonWidth = UserGetSystemMetrics(SM_CXSIZE) - 2;
#226
#227 if ((Wnd != NULL) && (Wnd->Style & WS_SYSMENU))
#228 {
#229 r.right -= 3 + ButtonWidth;
#230 if(! (uFlags & DC_SMALLCAP))
#231 {
#232 if(Wnd->Style & (WS_MAXIMIZEBox | WS_MINIMIZEBox))
#233 r.right -= 2 + 2 * ButtonWidth;
#234 else r.right -= 2;
#235 r.right -= 2;
#236 }
#237 }
#238 }
#239
调用函数UserDrawCaptionText显示标题字符串。
#240 /* FIXME: hFont isn't handled */
#241 if (str)
#242 UserDrawCaptionText(hMemDc,str,uFlags);
#243 else if (pWnd != NULL)
#244 UserDrawCaptionText(hMemDc,&pWnd->Wnd->WindowName,uFlags);
#245 }
#246
#247 if(!NtGdiBitBlt(hDc,lpRc->left,lpRc->top,
#248 lpRc->right - lpRc->left,lpRc->bottom - lpRc->top,
#249 hMemDc,SRCCOPY,0))
#250 {
#251 DPRINT1("%s: NtGdiBitBlt() Failed!/n",__FUNCTION__);
#252 goto cleanup;
#253 }
#254
#255 Ret = TRUE;
#256
删除创建的DC资源。
#257 cleanup:
#258 if (hOldBrush) NtGdiSelectBrush(hMemDc,hOldBrush);
#259 if (hOldBmp) NtGdiSelectBitmap(hMemDc,hOldBmp);
#260 if (hMemBmp) NtGdiDeleteObject(hMemBmp);
#261 if (hMemDc) NtGdiDeleteObjectApp(hMemDc);
#262
#263 return Ret;
#264}