windows 打印机管理机制(任务后台等待机制)

转载 2013年12月02日 13:45:14
1.1--打印机编程

1.1 .1 打印机介绍

1.打印术语
   cpi(characters Per Inch) 每英寸内所含的字符数,用来表示字符的大小、
   间距。

   cpl(Characters Per Line) 每行中所含的字符个数,用来在横向表示字符
   的宽度和间距。
   cps(Character Per Second):每秒所能打印的字符个数,用来表示打印机的打
   印速度。当然它和打印的字符大小与笔划有关。一般以10cpi的西文字符为基准
   来计算打印速度.

   dpi(Dot Per Inch)每英寸所打印的点数(或线数),用来表示打印机打印分辨.这是
   衡量打印机打印精度的主要参数之一.该值越大表明打印机的打印精度越高.
   lpi(Lines Per Inch): 每英寸所含的行数,用来表示在垂直方向字符的大小
   间距.

   ppm(Papers Per Minute):每分钟打印的页数,这是衡量打印机打印速度的
   重要参数,是指连续打印时的平均速度.

  
   在大多数的Internet及多媒体应用软件中,为使画面下载速度增快,大都是采
   用72dpi或75dpi的低解析度影像,如果仅从屏幕上观看,画质还可以,但是当
   使用解析度较高的打印机打印出来时,就会发生如锯齿状或是模糊不清的问题.
   这主要的原因在于原始影像本身的像素不能呈现高解析度的输出品质.
   因此,无论使用的打印机品质或解析度多高,打印品质仍不理想.使用HP SmartFocus
   智慧聚焦技术的打印机驱动程序,将低品质的影像自动地做解析度提升的处理.
   这样一来,就可以打印出较清晰的影像.
  
   sRGB:(standard Red Green Blue)是一种彩色语言协定.它提供了一个标准方法来定义
   色彩.让计算机的周边设备与应用软件对于色彩有一个共通的语言.sRGB是由HP和微软
   共同推出的开放业界标准.

2.打印机技术指标
  (1) 打印质量
  衡量图像清晰程度最重要的指标就是分辨率(dpi每平方英寸多少个点).
  300dpi是人眼分辨打印文本与图像的边缘是否有锯齿的临界点.再考虑
  到其他的一些因素,只有360dpi以上的打印效果才能基本令人满意
.要将
  基色组成的色点转换成印刷上由四色墨水喷出的各种色彩效果,就需要
  由色彩转换的驱动程序来实现.目前各打印机厂商均有自已的图像调整技术.
 
  (2)打印速度
  打印机的打印速度是每分钟打印多少页纸(PPM),打印机速度与打印的色彩和
  打印分辨有关.
 
  (3)色彩数目
  更多的彩色墨盒数就意味着更丰富的色彩.有红、黄、蓝三色单墨盒。还有
  黑、淡蓝和淡红的六色打印机。
 
  1.1.2 分辨率
  分辨率是一个表示平面图像精细程序的概念,通常它是以横向和纵向点的数量来衡量的,
  表示成:水平点数*垂直点数的形式.在一个固定的平面内,分辨率越高,图像越细致.
  分辨率有多种.在显示器上有表示显示精度的显示分辨率,在打印机上有表示打印精度的
  打印机分辨率.
 
  1、显示分辨率
  显示分辨率是显示器在显示图像时的分辨率。显示分辨率的数值是指整个显示器所有
  可视面积上水平像素和垂直像素的数量.例如:800*600的分辨率是指在整个屏幕上水平
  显示800个像素,垂直显示600个像素.显示分辨率的水平像素和垂直像素的总数总是成一
  定的比例:一般为4:3,5:4,8:5
 
  2、打印机分辨率
  打印机分辨率直接关系到打印机输出图像或文字的质量好坏。打印机分辨率用dpi(dot per inch)
  来表示。喷墨打印机和激光打印机的分辨率通常是相同的.例如:打印机分辨率为600dpi,
  是指打印机在一平方英寸的区域内垂直打印600个点,水平打印600个点.总共可打印360000个点.

 

 

1.2--打印机编程基础(未完)

1.2编程基础
  下面将了解打印编程中至关重要的两个概念"设备环境"和"映射模式"
  1.2.1设备环境
  设备环境本身是GDI(Graphics Device interface)对象.每个C++设备对象有一个相关的设备环境.它由
  一个32位HDC类型句柄来标识.GDI是Windows核心DLL中的一组接口函数.这些函数处于硬件的驱动程序
  之上.当应用程序调用这些函数的时候,它们再调用驱动程序提供的接口函数.
 
  1.CDC类
  使用MFC编程,所用的设备环境不是CDC就是从CDC派生的。CDC类中有两个与底层
  GDI对象有关的句柄m_hDC和m_hAttribDC.与m_hDC相关的GDI对象处理绘图函数的所有
  输出流;与m_hAttribDC句柄有关的GDI对象处理所有与绘图属性有关的操作。如颜色属性
  和绘图模式。
 
  每个窗口、控件都拥有一个覆盖窗口或控件的设备环境。我们可以使用任何一个控件的设备环境,
  从而绘制控件或者改善倥件的外观。
 
  获得设备环境对象指针需要调用GetDC函数。在构造一个CDC对象,并且对它处理完之后,务必使用
  ReleaseDC()函数将CDC对象释放。
 
  GetDC()函数和ReleaseDC()函数是CWnd类的成员函数,任何CWnd类及其派生类都可以通过调用它获得
  和释放设备环境对象。
 
  2. CClientDC和CWindowDC
  窗口客户区不包括边框、标题栏和菜单栏,创建CClientDC对象将获得客户区的设备
  环境。构造CClientDC对象,只需要向它传递一个指向窗口的指针,GetDC()函数会被
  自动调用。当ClientDC对象被销毁时,它会自动调用ReleaseDC()函数。
 
  CClientDC派生于CDC,在构造时调用了Windows函数GetDC,在析构时调用了ReleaseDC.
  和CClientDC对象相关的设备上下文是窗口的客户区.
 
  CClientDC 构造一个连接到CWnd上的CClientDC对象.
  CClientDC(CWnd *pWnd);
  throw (CResourceException);
  参数:
  pWnd:设备上下文将要存取的客户区所在的窗口.
 
  CWindowDC能够在整个应用程序窗口上绘图,包括标题栏和窗口边框。一般情况下CWindowDC
  对象很少用,但是当读者不欢喜Windows标准窗口标题栏的样式和按钮,就可以应用它了。
 
  CWindowDC类是从CDC继承的,它在构造的时候调用Windows函数GetWindowDC,在销毁的时候调用ReleaseDC.
  这意味着CWindowDC对象可以访问CWnd的全部屏幕区域(包括客户区和非客户区).
 
 
  AfxGetMainWnd()函数用于获得框架(包括标题栏、菜单栏、状态栏、边框)窗口的指针。
  AfxGetMainWnd()获得主框架窗口指针。
 
 
 
  3、CPaintDC
  CPaintDC类是一个特殊的设备环境封装类。它用来处理来自Windows的WM_PAINT消息。
  当窗口上覆盖的其他窗口移走,或者窗口最小化后又最大化时,窗口就会收一个系统
  发来的WM_PAINT消息,这时应用程序就会重画可见的区域。这个被重画的区域,我们称
  它为无效区域。WM_PAINT消息发出后,Windows会帮助用户判断哪些区域需要重画,哪些
  区域保持不变,从而加快窗口的显示速度。
 
  CPaintDC类有一个成员变量m_ps,m_ps有一个RECT类型的成员变量rcPaint.这个矩形变量
  保存了需要重画的矩形区域,即无效区域。m_ps是一个PAINTSTRUCT结构类型的变量。
 
  PAINTSTRUCT结构的定义如下所示:
  typedef struct tagPAINTSTRUCT
  {
     HDC hDC;
     BOOL fErase;
     RECT rcPaint;
     BOOL fRestore;
     BOOL fIncUpdate;
     byte rgbReserved[32];
  }PAINTSTRUCT;
 
  hdc是底层的GDI设备环境对象的句柄.Ferase标志判断背景是否被清除,如果这个标志
  被设置为TRUE,在重画之前将清除背景.rcPaint 保存了窗口无效区域(即需要重画的
  区域).最后三个变量被声明为保留变量.一般不改动.
 
  4、内存设备环境
  内存设备环境是一个没有设备与它联系的环境。我们一般利用与某个标准设备环境兼容
  的内存设备环境把一个位图复制到屏幕上去。为此可以先创建一个与某个标准设备环境兼容
  的内存设备环境,然后把所要显示的位图复制到内存设备环境中,最后再从内存设备环境复
  制到真正的设备环境,从而把位图显示出来。
  还可以创建内存设备环境对象,使用该对象在内存中绘图来代替在屏幕上绘图,绘制完成后,
  再调用BitBlt()函数把它复制到屏幕上去。这种方法绘图可以克服屏幕闪烁现象。
 
  CGdiObject::GetObject 把描述了将Windows GDI对象附加给CGdiObject对象的数据填充到缓冲区。
  int GetObject(int nCount,LPVOID lpObject)const;
  返回值:获取的字节数。如果发生错误,则返回0
  参数:
  nCount 指定要拷贝到lpObject缓冲区的字节数
  lpObject 指向用户应用缓冲区的指针以接收信息。
  说明:
  用定义指定对象的数据填充缓冲区。函数获得一个类型由图像对象决定
  的数据结构,列表如下所示:
  LoadBitmap  从应用的可执行文件中加载一个命名的位图资源来初始化位图对象。
 
  CDC::BitBlt 从指定设备上下文拷贝位图
  BOOL BitBlt(int x,int y,int nWidth,int nHeight,CDC *pSrcDC,int xSrc,int ySrc,DWORD dwRop);
  返回值:函数成功,返回非零值,否则为0
 
  参数:x 指定目标矩形左上角的逻辑x坐标
        y 指定目标矩形左上角的逻辑y坐标
        nWidth 指定目标矩形矩形和源位图的宽度(逻辑单位)
        nHeight 指定目标矩形和源位图的高度(逻辑单位)
        pSrcDC  指向CDC对象的指针,标识待拷贝位图的设备上下文。
        xSrc    指定源位图左上角的逻辑x坐标
        ySrc    指定源位图左上角的逻辑y坐标
        dwRop   指定要执行的光栅操作。
  CDC::CreateCompatibleDC 创建内存设备上下文,与另一个设备上下文匹配。可以
  用它在内存中准备图像。
  virtual BOOL CreateCompatibleDC(CDC *pDC);
  返回值:如果成功,则返回非零值,否则为0
  参数:
  pDC 设备上下文指针。如果pDC为NULL,函数将产生与系统兼容的内存设备上下文。
  说明:
  产生与pDC指定设备兼容的设备上下文内存,设备上下文内存包含显示表面的信息,
  它用于在向实际的兼容设备表面发送图像之前在内存中作好准备。
 
  void CPrintProjView::OnDrawBitmap()
  {
    CBitmap bitmap;
    bitmap.LoadBitmap(IDB_BITMAP1);
    BITMAP bmpInfo;
    CDC *pDC = GetDC();
    CDC memDC;
    memDC.CreateCompatibleDC();
    CBitmap *pBitmap = memDC.SelectObject(&bitmap);
    bitmap.GetObejct(sizeof(bmpInfo),&bmpInfo);
    pDC->BitBlt(0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,&memDC,0,0,SRCCOPY);
     memDC.DeleteDC();
     ReleaseDC(pDC);
  }
  上面这段程序,先获得视图的设备环境,然后声明了一个内存设备环境memDC.
  memDC调用了CreateCompatibleDC()函数,作用是设置内存设备环境的大小等各种属性,
  从而使内存设备环境与屏幕窗口兼容。Bitmap是位图对象,它调用成员函数LoadBitmap
  载入位图;bmpInfo是BITMAP结构类型的变量,它保存了位图的长、宽等信息。
 
  BitBlt()函数把内存设备环境复制到屏幕设备环境。BitBlt()是一个图像复制函数。
  当向函数传递需要复制区域的宽、高度、开始偏移和复制模式这些参数时,它会将需要复制的
  矩形区域从内存设备环境复制到屏幕上。
 
  注意:
  程序中使用的位图类型是GDI位图。有两种类型的Windows位图:GDI位图和DIB位图。
  GDI位图对象是由MFC库的CBitmap类表示的。GDI位图对象有一个与之相关的Windows
  数据结构,它在Windows GDI模块内进行维护,它是与设备相关的。对于GDI位图来说,
  显示器的“位图”实际上就是显示器表面的映像,打印机设备的“位图”是打印机本身。
  因此,不能将位图选入显示设备环境或打印设备环境,这就是为什么必须使用
  CDC::CreateCompatibleDC函数创建一个特殊的内存设备环境。
 
  5、打印机设备上下文
  CDC::CreateDC 为指定设备创建设备上下文
  virtual BOOL CreateDC(LPCTSTR lpszDriverName,
                        LPCTSTR lpszDeviceName,
                        LPCTSTR lpszOutput,
                        const void *lpInitData)
  返回值:如果成功,则返回非零值,否则为0
  参数:
  lpszDriverName:指向空终止字符串的指针,字符串为设备驱动程序的文件名(不带扩展名,
  例如:"EPSON")也可以为该参数传递CString对象。
 
  lpszDeviceName:指向空终止字符串的指针,字符串为支持特定设备的文件名(例如:
  "EPSON FX-80")
  lpszOutput:指向空终止字符串的指针。字符串为指定了物理输出媒介的文件和设备名
  (文件或输出端口).也可以为该参数传递CString对象。
 
  lpInitData:指向DEVMODE结构的指针,该结构包含有指定设备驱动程序的初始数据,Windows
  的DocumentProperties函数从该结构中获得指定设备的信息。如果设备驱动程序使用用户
  在控制面板的缺省值,lpInitData参数一定要设置为NULL.
 
  说明:
  为指定的设备创建设备上下文。
  如果使用DEVMODE结构,就需要PRINT.H头文件。
 
  或者参数作如下说明:
  lpszDriverName是打印机所用的设备驱动程序。
  lpszDeviceName是进行打印的打印设备名称。设备驱动程序可以支持多种打印设备。
  lpszOutput:指定设备的串口名。
  lpInitData:是设备专用的初始化数据。
  使用打印机设备环境之后,必须调用DeleteDC()成员函数销毁它。但是,如果在堆栈
  中创建CDC类,程序返回时,设备环境自动删除。

  至此Windows提供的五个公共设备环境已经全部介绍完了。

1.2.2 映射模式

 /////////////////////////////////////////////////
 1.2.2 映射模式样
 vc++中采用的坐标映射方式使得用户图形坐标和输出设备的像素完全一致,当屏幕的像素大
 小为800*600时,每逻辑英寸包含的屏幕像素数为96,而打印机则需要多出
 好几倍的点数才能到达同样的逻辑尺寸。
例如:HP打印机每逻辑英寸包含的打印机点数为600,
 也就是说打印机的清晰度比屏幕要高很多。
这样的后果就是在屏幕上显示出来的满屏幕的图像
 在打印出来的纸上却只有一点点,怎么解决这个问题呢?一种简单的方法就是转换坐标映射方式,
 
使得打印时采用的坐标比例比显示时采用的坐标比例相应地大若干倍.
 
 映射模式的意思是在屏幕或者打印机上绘图的时候,可以使用英寸或者毫米作为单位,这样更加直观.
 
 这其中要注意设备单位和逻辑单位的区别:逻辑单位是传递给绘图函数的x和y值,它们可以表示英寸和
 毫米,而设备单位是x和y在屏幕上的像素数,或是打印机上的点阵数。
单击鼠标以设备单位返回。如果
 想知道鼠标单击位图的什么位置,需要将设备单位转化为逻辑单位。
表1-5所示是可用的映射模式。
 
 映射模式        逻辑单位
 MM_TEXT         一个像素
 MM_LOMETRIC     0.1毫米
 MM_HIMETRIC     0.01毫米
 MM_LOENGLISH    0.01英寸
 MM_HIENGLISH    0.001英寸
 MM_TWIPS        1/1440英寸
 MM_ISOTROPIC    用户定义的值,但是x和y方向相等
 MM_ANISOTROPIC  用户定义的值,但是x和yy方向任意
 
 映射模式通过设备环境类的一个成员函数SetMapMode()来设置.只要把上述标志当作参数
 传入函数即可.设置映射模式后,传给任何绘图函数的坐标值都通过GDI内部的映射机制转
 换成设备坐标.如果把映射模式设置为MM_LOENGLISH,然后向绘图函数传递一个100的逻辑
 单位值,映射模式知道用户实际想要的是100*0.1mm,也就是1cm。
 
 映射模式MM_ISOTROPIC和MM_ANISOTROPIC允许改变比例因子和原点,使用这些模式改变窗
 口大小时,绘制的内容也会改变大小。
 
 使用MM_ISOTROPIC方式,x和y始终保持1:1的比例。如果在屏幕上画了一个圆,无论比例因
 子如何改变,始终还是圆,而在MM_ANISOTROPIC方式中,x和y比例因子可分别改变,圆会被
 压成椭圆。
 
 有一点需要注意:当使用MM_TEXT映射模式时候,y轴的正方向是沿屏幕垂直向下的,x轴是沿屏幕
 向右的.然而,其他的映射模式的y轴正方向是沿屏幕向上的,x轴正方向也是向右的.这一点特别容易
 搞混了.
 
 我们定义两个矩形,设置从逻辑环境到设备环境的转换。第一个矩形以逻辑单位表示绘制区域的大小,
 windows术语称之为窗口,第二个矩形以设备单位(即像素)表示第一个矩形大小代表的设备范围大小,
 在Windows术语中称之为视口,两种关系如图:
 1、设置视口到视图的客户区,并可忘记它。SetViewportOrg(0,0);SetViewPortExt(100,50);
 2、把窗口的初始位置设置在想在逻辑环境中看到的地方:SetWindowOrg(100,100);
 3、要缩小图形,只要缩小窗口的范围。要放大图形,只要增大窗口范围。要滚动图形,只要改变
 窗口的初始位置。
 
 SetWindowOrg()用来改变窗口坐标(逻辑坐标)的原点,SetViewPortOrg()用来改变视口坐标(设备坐标)
 的原点。
 void CPrintProjView::OnDraw(CDC *pDC)
 {
    pDC->SetMapMode(MM_TEXT);
    pDC->SetViewPortOrg(50,50);
    pDC->SetWindowPortOrg(200,200);
    CPen myPen(PS_SOLD,1,RGB(0,255,0));
    Cpen *pOldPen = pDC->SelectObject(&myPen);
    pDC->TextOut(200,200,_T("窗口映射模式"));
    pDC->Rectangle(200,200,400,400);
    pDC->SelectObject(pOldPen);
    myPen.DeleteObject();
 }
 这段代码,把视口原点设置为设置坐标(50,50),把窗口原点设置为逻辑坐标(200,200),
 然后通过窗口原点(200,200)绘制一个长宽各为200的方框.逻辑点(200,200)映射到设备
 点(50,50),即把窗口原点映射到视口原点.
 
 SetWindowExt()用来设定逻辑环境的大小,SetViewPortOrg()用来设定设备环境的大小.映射
 模式MM_ISOTROPIC和MM_ANISOTROPIC允许调用SetWindowExt()和SetViewPortExt()函数来设置
 设备坐标和逻辑坐标之间的比例.
 
 可以用下面的公式实现逻辑单位到设备单位的转换:
 x比例因子 = x视口长度/x窗口长度
 y比例因子 = y视口长度/y窗口长度
 设备x = 逻辑x * x比例因子 + x原点偏移量
 设备y = 逻辑y * y比例因子 + y原点偏移量
 设备环境本身提供了两个函数实现逻辑坐标和设备坐标之间的互换.DPtoLP()函数,可以
 接受一个指向CPoint类或者CRect类对象的指针作为参数,然后把它所指向的对象从设备
 坐标转换为逻辑坐标,LPtoDP的作用正好相反.
 
 下面这段程序根据GetClientRect()函数返回窗口客户矩形,函数SetWindowExt和SetViewportExt
 一起设置比例,结果窗口大小恰好是800*800,SetViewPortOrg函数把原点放置在窗口中心.这样椭
 圆恰好充满整个屏幕.
 
 void CPrintProjView::OnDraw(CDC *pDC)
 {
   CRect rcClient;
   GetClientRect(&rcClient);
   pDC->SetMapMode(MM_ANISOTROPIC);
   pDC->SetWindowExt(800,800);
   pDC->SetViewportExt(rcClient.right/2,rcClient.bottom/2);
   CPen myPen(PS_SOLID,1,RGB(255,0,0));
   CPen *pOldPen = pDC->SelectObject(&myPen);
   pDC->Ellipse(-400,-400,400,400);
   pDC->SelectObject(pOldPen);
   myPen.DeleteObject();
 }
 注意:SetWindowExt()和SetViewPortExt()函数只有在MM_ANISOTROPIC和MM_ISOTROPIC模式下才有效,
 在其他模式下,对它们的调用将被忽略。无论彩用哪种映射模式,GetClientRect()和GetWindowRect()
 函数返回的都是设备坐标(即像素)。

2.1.2监测当前打印机状态

2。1。2监测当前打印机状态
  Windows标准的打印机监测程序。通过该程序,我们可以了解当前打印机的状态,包括打印机任务队列,
  各项任务状态、所有者、进度和开始时间,并且可以及时暂停、清除打印任务。

  监控打印机就有必要对Windows后台打印机制有所了解。后台程序可以减轻应用程序的打印负担。Windows在启动时就加载后台
  打印程序。因此,当应用程序开始打印时,它已经是活动的了。当程序打印一个文件时,GDI模块创建打印的数据文件。后台
  打印程序的任务是将这些文件发往打印机。GDI模块发出一个消息来通知它开始一个新的打印作业。然后打印机开始读文件,
  并将文件传送到打印机。为了传送打印文件,后台程序为打印机所连接的并口和串口提供各种通信函数。在后台程序向打
  印机发送文件操作结束的命令后,它就删除包含输出数据的临时文件。

               后台打印程序的组合。
  ----------------------------------------
  打印请求后台程序     | 将数据流传递给打印机
  本地打印提供者       | 为本地打印机创建后台文件
  网络打印提供者       | 为网络打印机创建后台文件。
  打印处理程序         | 将后台的设备无关数据转换为特定打印机的格式
  端口监视程序         | 控制连接打印机的端口
  语言监视程序         | 控制双向通信的打印机,配置并检测打印机的状态

  使用后台打印程序,真正的文件打印操作是后台打印程序的任务,而不是应用程序的任务。
  我们可以暂停打印作业、改变作业的优先级或者取消打印作业。这种管理方式使得应用程序
  可能比下面的这种情况“打印”得更快。即作业以实时方式打印,且必须等到打印完一页后
  才能处理下一页。

  但是如果我们拥有更好的打印机软硬件或者在网络打印机等某些特殊的情况下,可以去掉Windows后台打印程序。
  去掉Windows后以中打印程序可以加快打印速度。因为打印输出不必保存在硬盘上,而可以直接输出到打印机,并被
  外部硬件或软件后台程序所接受。

  实现类似Windows打印监测试程序的功能,需要调用Win32假脱机(SPOOL)枚举API函数。"[使用Win32假脱机枚举函数需要调用
  两次所需的函数。这些API函数通常要填充一组结构。但是,这些结构通常包含指向字符串和其他类型数据的指针。
  这些外来的数据必须存储在返回的内存中,使得字符串和其他数据存储在结构中。所以简单的在堆栈中声明一组结构变量
  不足以为API函数返回的信息设置足够的内存。]"

  因此,正确的函数调用是:首先调用API函数确定需要的内存空间,在随后的调用中传入一个指针,该指针指向了一块动态
  分配的大小合适内存空间。需要进行该类处理的枚举函数包括:
  EnumForms(),EnumJobs(),EnumMonitors(),EnumPorts(),EnumPrinterDrivers(),EnumPrinters()和EnumPrinterProcessors()

  下面这段程序,使用EnumJobs()API函数,枚举出所选打印机当前的打印任务。关于其他打印监控函数的使用大家可以参考
  微软平台SDK中关于打印函数和打印假脱机枚举函数的文档。

  注意:独占设备是指在一个程序(作业、用户)的整个运行其间独占的设备,直到该程序(作业、用户)完成。系统的独占设备是
  有限的(譬如一台计算机只能连接一台打印机),往往不能满足多进程的要求,会引起大量进程由于等待某些独占设备而阻塞,
  成为系统的“瓶颈”。另一方面,申请到独占设备的进程在其整个运行期间虽然占有设备,利用率却常常很低,设备还是经常
  处于空闲状态。为了解决这种矛盾,最常用的方法就是用共享设备来模拟独占设备,从而提高系统地效率和设备利用率.这种
  技术称为虚拟设备技术.实现这一技术的软、硬件系统被称为假脱机(Simultaneous Peripaheral Operation On Line SPOOL)
  系统。打印机是典型的独占设备。引入SPOOL技术后,用户的打印请求传递给SPOOL系统,而不是真正的把打印机分配给用户。
  SPOOL系统的输出进程是先磁盘上申请一个空闲区域,把需要打印的数据传输到里面,再把用户的打印请求挂到打印机队列上。
  如果打印机空闲,就会从打印机队列中取出一个打印请求,再从磁盘上的指定区域取出数据,执行打印操作。由于磁盘是共享
  的,SPOOL系统可以随时响应打印请求并把数据缓存起来,这样独占设备改造成了共享设备,从而提高了设备的利用率和系统
  利用率。

   /*
   OpenPrinter
   Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA"(ByVal pPrinterName As String,phPrinter As Long,
   pDefault As PRINTER_DEFAULTS)As Long

   说明:
   打开指定的打印机,并获取打印机的句柄。
   返回值:
   Long,非零表示成功,零表示失败。会设置GetLastError
   参数表:
   pPrinterName  String,要打开的打印机的名字
   phPrinter     Long,用于装载打印机的句柄。
   pDefault      PRINTER_DEFAULT,这个结构保存要载入的打印机信息。
   */
   /*
   Declare Function EnumJobs Lib "winspool.drv"Alias "EnumJobsA"(ByVal hPrinter As Long,
   ByVal First Job As Long,ByVal NoJobs As Long,ByVal Level As Long,pJob As Byte,ByVal cdBuf As Long
   ,pcbNeeded As Long,pcReturned As Long)As Long

   说明:
   枚举打印队列中的作业
   返回值:
   Long,非零表示成功,零表示失败。 可以通过GetLastError获取错误信息。
   hPrinter:  Long,一个已打开的打印机对象的句柄(用OpenPrinter获得)
   FirstJob:  Long,作业列表中要枚举的第一个作业的索引(注意编号从0开始)
   NoJobs     Long,要枚举的作业数量。
   Level      Long,1或2
   pJob       Byte,包含JOB_INFO_1或JOB_INFO_2结构的缓冲区
   cbBuf      Long,pJob缓冲区中的字符数量。
   pcbNeeded  Long,指向一个LONG型变量的指针,该变量用于保存请求的缓冲区长度
              或者实际读入的字节数量。
   pcReturned Long,载入缓冲区的结构数量(用于那些能返回多个结构的函数)。
   */
   /*
   GetLastError
   Declare Function GetLastError lib "kernel32"Alias "GetLastError"As Long
   说明:
   针对之前调用的api函数,用这个函数取得扩展错误信息
   返回值:Long,由api函数决定.请参考api32.txt文件,其中列出了一系列错误常数;都以ERROR_前
   缀起头.常用的错误代码见下表:
   ERROR_INVALID_HANDLE:无效的句柄作为一个参数传递。
   ERROR_CALL_NOT_IMPLEMENTED  在win95下调用专为win nt设计的win32 api函数
   ERROR_INVALID_PARAMETER   函数中有个参数不正确。
   */
   /*
   EnumJobs
   Declare Function EnumJobs Lib "winspool.drv" alias "EnumJobsA"(ByVal hPrinter As Long,ByVal FirstJob As Long,ByVal NoJobs As Long,By Level As Long
   pJob As Byte,ByVal cdBuf As Long,pcbNeeded As Long,pcReturned As Long) As Long

   说明:
   枚举打印队列中的作业
   返回值:
   Long,非零表示成功,零表示失败。可以通过GetLastError获取错误信息
   参数表:
   hPrinter         Long,一个已打开的打印机对象的句柄(用OpenPrinter获得)
   FirstJob         Long,作业列表中要枚举的第一个作业的索引(注意编号从0开始)
   NoJobs           Long,要枚举的作业数量。
   Level            Long,1或2
   pJob             Byte,包含JOB_INFO_1或JOB_INFO_2结构的缓冲区。
   cbBuf            Long,pJob缓冲区中的字符数量。
   pcbNeeded        Long,指向一个Long型变量的指针,该变量用于保存请求的缓冲区长度,或者实际读入的字节数。
   pcbReturned      Long,载入缓冲区的结构数量。
   */

   BOOL CPrintListDlg::PrintJobList(LPCTSTR szPrintName)
   {
    HANDLE   hPrinter;
    DWORD    dwNeeded,dwReturned,i;
    JOB_INFO_1  *pJobInfo;

    if(!OpenPrinter(szPrinterName,&hPrinter,NULL))
     return FALSE;
    if(EnumJobs(hPrinter,0,0xFFFFFFFF,NULL,1,NULL,0,&dwNeeded,&dwReturned))
    {
     if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
     {
      ClosePrinter(hPrinter);
      return FALSE;
     }
    }
    if((pJobInfo = (JOB_INFO_1*)malloc(dwNeeded)) == NULL)
    {
     ClosePrinter(hPrinter);
     return FALSE;
    }
    if(!EnumJobs(hPrinter,0,0xFFFFFFFF,1,(LPBYTE)pJobInfo,dwNeeded,&dwNeeded,&dwReturned))
    {
     ClosePrinter(hPrinter);
     free(pJobInfo);
     return FALSE;
    }
    ClosePrinter(hPrinter);
   
    for(UINT i = 0; i < dwReturned; i++)
    {
     m_listBox2.AddString(pJobInfo[i].pDocument);
    }
    free(pJobInfo);
    return TRUE;
   }
   void CPrintListDlg::OnSelchangePrinters()
   {
    int nIndex = m_listBox.GetCurSel();
    CString strPrinterName;
    if(nIndex != CB_ERR)
    {
     m_listBox.GetText(nIndex,strPrinterName);
     if(strPrinterName.IsEmpty())
     {
      PrintJobList((LPCTSTRstrPrinterName));
     }
    }
   }
   /*
   这个例子启发我们,应用打印枚举API函数可以对打印机进行有效的监控。
   */

 

相关文章推荐

任务管理机制二

本文是为了续前面的任务管理机制的。 六.内部任务 在uC/OS-III 初始化的时候,它会创建至少2 个内部的任务(OS_IdleTask()和OS_TickTask()),3 个可选择的任务(OS...

C语言-Windows内存管理机制

  • 2009-07-28 17:44
  • 129KB
  • 下载

全面介绍Windows内存管理机制及C++内存分配实例(二):内存状态查询

转载自:http://blog.csdn.net/yeming81/article/details/2046207 本文背景: 在编程中,很多Windows或C++的内存函数不知道有什...

Windows 2000XP外存管理机制

  • 2009-09-14 05:12
  • 134KB
  • 下载

Windows内存管理机制

  • 2013-01-08 19:31
  • 129KB
  • 下载

全面介绍Windows内存管理机制及C++内存分配实例

转自:http://blog.csdn.net/yeming81/article/details/2046193 本文基本上是windows via c/c++上的内容,笔记做得不错。。 本文背景...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)