DC(device context)是一个图形对象、图形属性和影响图形输出的集合结构体。CreateDC函数用给定名称为指定的设备创建设备环境。CreateDC一般用于创建打印机的设备环境,也可以用来得到屏幕(硬件屏幕,而不是窗口的客户区)的设备环境。请小心使用这个函数,因为它允许应用程序在屏幕上任何位置绘图,而不仅仅是在窗口的边界内。请用GetDC或BeginPaint来获取屏幕窗口的设备环境。
#001 HDC
#002 WINAPI
#003 CreateDCW (
#004 LPCWSTR lpwszDriver,
#005 LPCWSTR lpwszDevice,
#006 LPCWSTR lpwszOutput,
#007 CONST DEVMODEW *lpInitData
#008 )
#009 {
#010
#011 return IntCreateDICW ( lpwszDriver,
#012 lpwszDevice,
#013 lpwszOutput,
#014 (PDEVMODEW) lpInitData,
#015 0 );
#016 }
lpwszDriver是指向空值结尾的字符串的指针,字符串说明设备驱动程序的文件名。比如“DISPLAY”指的是显示器驱动程序,而“WINSPOOL”就是指打印驱动程序。
lpwszDevice是批向空值结尾的字符串的指针,字符串指定了正在使用的专用输出设备的名称,比如打印管理程序名称。
lpwszOutput是没有使用参数,一般设置为NULL。
lpInitData是指向结构包含了设备驱动程序的设备专用初始化数据。设置为NULL时,就使用系统默认的初始化参数。
下面接着来分析函数IntCreateDICW的代码:
#001 HDC
#002 FASTCALL
#003 IntCreateDICW ( LPCWSTR lpwszDriver,
#004 LPCWSTR lpwszDevice,
#005 LPCWSTR lpwszOutput,
#006 PDEVMODEW lpInitData,
#007 ULONG iType )
#008 {
#009 UNICODE_STRING Device, Output;
#010 HDC hDC = NULL;
#011 BOOL Display = FALSE, Default = TRUE;
#012 ULONG UMdhpdev = 0;
#013
#014 HANDLE hspool = NULL;
#015
加载打印驱动程序。
#016 if ( !ghSpooler && !LoadTheSpoolerDrv())
#017 {
#018 DPRINT1("WinSpooler.Drv Did not load!/n");
#019 }
#020 else
#021 {
#022 DPRINT("WinSpooler.Drv Loaded! hMod -> 0x%x/n", ghSpooler);
#023 }
#024
根据设备名称判断获取什么样的设备。
#025 if ((!lpwszDevice) && (!lpwszDriver))
#026 {
设置缺省设备名称。
#027 Default = FALSE; // Ask Win32k to set Default device.
#028 Display = TRUE; // Most likely to be DISPLAY.
#029 }
#030 else
#031 {
#032 if ((lpwszDevice) && (wcslen(lpwszDevice) != 0)) // First
#033 {
判断是否获取显示设备。
#034 if (!_wcsnicmp(lpwszDevice, L"////.//DISPLAY",11)) Display = TRUE;
#035 RtlInitUnicodeString(&Device, lpwszDevice);
#036 }
#037 else
#038 {
#039 if (lpwszDriver) // Second
#040 {
#041 if ((!_wcsnicmp(lpwszDriver, L"DISPLAY",7)) ||
#042 (!_wcsnicmp(lpwszDriver, L"////.//DISPLAY",11))) Display = TRUE;
#043 RtlInitUnicodeString(&Device, lpwszDriver);
#044 }
#045 }
#046 }
#047
#048 if (lpwszOutput) RtlInitUnicodeString(&Output, lpwszOutput);
#049
#050 if (!Display)
#051 {
#052 //Handle Print device or something else.
#053 DPRINT1("Not a DISPLAY device! %wZ/n", &Device);
#054 }
#055
调用WIN32K内核NtGdiOpenDCW函数打开设备。
#056 hDC = NtGdiOpenDCW( (Default ? &Device : NULL),
#057 (PDEVMODEW) lpInitData,
#058 (lpwszOutput ? &Output : NULL),
#059 iType, // DCW 0 and ICW 1.
#060 Display,
#061 hspool,
#062 (PVOID) NULL, // NULL for now.
#063 (PVOID) &UMdhpdev );
#064 #if 0
#065 // Handle something other than a normal dc object.
#066 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
#067 {
#068 PDC_ATTR Dc_Attr;
#069 PLDC pLDC;
#070
#071 GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr);
#072
#073 pLDC = LocalAlloc(LMEM_ZEROINIT, sizeof(LDC));
#074
#075 Dc_Attr->pvLDC = pLDC;
#076 pLDC->hDC = hDC;
#077 pLDC->iType = LDC_LDC; // 1 (init) local DC, 2 EMF LDC
#078 DbgPrint("DC_ATTR Allocated -> 0x%x/n",Dc_Attr);
#079 }
#080 #endif
返回DC给应用程序。
#081 return hDC;
#082 }