久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

教你怎么使用打印机(api)

發布時間:2024/2/2 综合教程 29 生活家
生活随笔 收集整理的這篇文章主要介紹了 教你怎么使用打印机(api) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用打印機

壹佰軟件開發小組整理編譯

為了處理文字和圖形而使用視訊顯示器時,設備無關的概念看來非常完美,但對于打印機,設備無關的概念又怎樣呢?

總的說來,效果也很好。在Windows程序中,用于視訊顯示器的GDI函數一樣可以在印表紙上打印文字和圖形,在以前討論的與設備無關的許多問題(多數都與平面顯示的尺寸、分辨率以及顏色數有關)都可以用相同的方法解決。當然,一臺打印機不像使用陰極射線管的顯示器那么簡單,它們使用的是印表紙。它們之間有一些比較大的差異。例如,我們從來不必考慮視訊顯示器沒有與顯示卡連結好,或者顯示器出現「屏幕空間不夠」的錯誤,但打印機off line和缺紙卻是經常會遇到的問題。

我們也不必擔心顯示卡不能執行某些圖形操作,更不用擔心顯示卡能否處理圖形,因為,如果它不能處理圖形,就根本不能使用Windows。但有些打印機不能打印圖形(盡管它們能在Windows環境中使用)。繪圖機盡管可以打印向量圖形,卻存在位圖塊的傳輸問題。

以下是其它一些需要考慮的問題:

打印機比視訊顯示器慢。盡管我們沒有機會將程序性能調整到最佳狀態,卻不必擔心視訊顯示器更新所需的時間。然而,沒有人想在做其它工作前一直等待打印機完成打印任務。
 

程序可以用新的輸出覆蓋原有的顯示輸出,以重新使用視訊顯示器表面。這對打印機是不可能的,打印機只能用完一整頁紙,然后在新一頁的紙上打印新的內容。
 

在視訊顯示器上,不同的應用程序都被窗口化。而對于打印機,不同應用程序的輸出必須分成不同的文件或打印作業。
 

為了在GDI的其余部分中加入打印機支持功能,Windows提供幾個只用于打印機的函數。這些限用在打印機上的函數(StartDoc、EndDoc、StartPage和EndPage)負責將打印機的輸出組織打印到紙頁上。而一個程序呼叫普通的GDI函數在一張紙上顯示文字和圖形,和在屏幕上顯示的方式一樣。

在第十五、十七和十八章有打印位圖、格式化的文字以及metafile的其它信息。

打印入門

當您在Windows下使用打印機時,實際上啟動了一個包含GDI32動態鏈接庫模塊、打印驅動程序動態連結模塊(帶.DRV擴展名)、Windows后臺打印程序,以及有用到的其它相關模塊。在寫打印機打印程序之前,讓我們先看一看這個程序是如何進行的。

打印和背景處理

當應用程序要使用打印機時,它首先使用CreateDC或PrintDlg來取得指向打印機設備內容的句柄,于是使得打印機設備驅動程序動態鏈接庫模塊被加載到內存(如果還沒有加載內存的話)并自己進行初始化。然后,程序呼叫StartDoc函數,通知說一個新文件開始了。StartDoc函數是由GDI模塊來處理的,GDI模塊呼叫打印機設備驅動程序中的Control函數告訴設備驅動程序準備進行打印。

打印一個文件的程序以StartDoc呼叫開始,以EndDoc呼叫結束。這兩個呼叫對于在文件頁面上書寫文字或者繪制圖形的GDI命令來說,其作用就像分隔頁面的書擋一樣。每頁本身是這樣來劃清界限的:呼叫StartPage來開始一頁,呼叫EndPage來結束該頁。

例如,如果應用程序想在一頁紙上畫出一個橢圓,它首先呼叫StartDoc開始打印任務,然后再呼叫StartPage通知這是新的一頁,接著呼叫Ellipse,正如同在屏幕上畫一個橢圓一樣。GDI模塊通常將程序對打印機設備內容做出的GDI呼叫儲存在磁盤上的metafile中,該文件名以字符串~EMF(代表「增強型metafile」)開始,且以.TMP為擴展名。然而,我在這里應該指出,打印機驅動程序可能會跳過這一步驟。

當繪制第一頁的GDI呼叫結束時,應用程序呼叫EndPage。現在,真正的工作開始了。打印機驅動程序必須把存放在metafile中的各種繪圖命令翻譯成打印機輸出數據。繪制一頁圖形所需的打印機輸出數據量可能非常大,特別是當打印機沒有高級頁面制作語言時,更是如此。例如,一臺每英寸600點且使用8.5×11英寸印表紙的激光打印機,如果要定義一個圖形頁,可能需要4百萬以上字節的數據。

為此,打印機驅動程序經常使用一種稱作「打印分帶」的技術將一頁分成若干稱為「輸出帶」的矩形。GDI模塊從打印機驅動程序取得每個輸出帶的大小,然后設定一個與目前要處理的輸出帶相等的剪裁區,并為metafile中的每個繪圖函數呼叫打印機設備驅動程序的Output函數,這個程序叫做「將metafile輸出到設備驅動程序」。對設備驅動程序所定義的頁面上的每個輸出帶,GDI模塊必須將整個metafile「輸出到」設備驅動程序。這個程序完成以后,該metafile就可以刪除了。

對每個輸出帶,設備驅動程序將這些繪圖函數轉換為在打印機上打印這些圖形所需要的輸出數據。這種輸出數據的格式是依照打印機的特性而異的。對點陣打印機,它將是包括圖形序列在內的一系列控制命令序列的集合(打印機驅動程序也能呼叫在GDI模塊中的各種「helper」輔助例程,用來協助這種輸出的構造)。對于帶有高階頁面制作語言(如PostScript)的激光打印機,打印機將用這種語言進行輸出。

打印驅動程序將打印輸出的每個輸出帶傳送到GDI模塊。隨后,GDI模塊將該打印輸出存入另一個臨時文件中,該臨時文件名以字符串~SPL開始,帶有.TMP擴展名。當處理好整頁之后,GDI模塊對后臺打印程序進行一個程序間呼叫,通知它一個新的打印頁已經準備好了。然后,應用程序就轉向處理下一頁。當應用程序處理完所有要打印的輸出頁后,它就呼叫EndDoc發出一個信號,表示打印作業已經完成。圖13-1顯示了應用程序、GDI模塊和打印驅動程序的交互作用程序。

 

圖13-1
應用程序、GDI模塊、打印驅動程序和打印隊列程序的交互作用過程

Windows后臺打印程序實際上是幾個組件的一種組合(見表13-1)。

表13-1

打印隊列程序組件

說明

打印請求隊列程序

將數據流傳遞給打印功能提供者

本地打印功能提供者

為本地打印機建立背景文件

網絡打印功能提供者

為網絡打印機建立背景文件

打印處理程序

將打印隊列中與設備無關的數據轉換為針對目的打印機的格式

打印端口監視程序

控件連結打印機的端口

打印語言監視程序

控件可以雙向通訊的打印機,設定設備設定并檢測打印機狀態

打印隊列程序可以減輕應用程序的打印負擔。Windows在啟動時就加載打印隊列程序,因此,當應用程序開始打印時,它已經是活動的了。當程序行印一個文件時,GDI模塊會建立包含打印輸出數據的文件。后臺打印程序的任務是將這些文件發往打印機。GDI模塊發出一個消息來通知它一個新的打印作業開始,然后它開始讀文件并將文件直接傳送到打印機。為了傳送這些文件,打印隊列程序依照打印機所連結的并列端口或串行埠使用各種不同的通信函數。在打印隊列程序向打印機發送文件的操作完成后,它就將包含輸出數據的臨時文件刪除。這個交互作用過程如圖13-2所示。

 

圖13-2 后臺打印程序的操作程序

這個程序的大部分對應用程序來說是透明的。從應用程序的角度來看,「打印」只發生在GDI模塊將所有打印輸出數據儲存到磁盤文件中的時候,在這之后(如果打印是由第二個線程來操作的,甚至可以在這之前)應用程序可以自由地進行其它操作。真正的文件打印操作成了后臺打印程序的任務,而不是應用程序的任務。通過打印機文件夾,使用者可以暫停打印作業、改變作業的優先級或取消打印作業。這種管理方式使應用程序能更快地將打印數據以實時方式打印,況且這樣必須等到打印完一頁后才能處理下一頁。

我們已經描述了一般的打印原理,但還有一些例外情況。其中之一是Windows程序要使用打印機時,并非一定需要后臺打印程序。使用者可以在打印機屬性表格的詳細數據屬性頁中關閉打印機的背景操作。

為什么使用者希望不使用背景操作呢?因為使用者可能使用了比Windows打印隊列程序更快的硬件或軟件后臺打印程序,也可能是打印機在一個自身帶有打印隊列器的網絡上使用。一般的規則是,使用一個打印隊列程序比使用兩個打印隊列程序更快。去掉Windows后臺打印程序可以加快打印速度,因為打印輸出數據不必儲存在硬盤上,而可以直接輸出到打印機,并被外部的硬件打印隊列器或軟件的后臺打印程序所接收。

如果沒有啟用Windows打印隊列程序,GDI模塊就不把來自設備驅動程序的打印輸出數據存入文件中,而是將這些輸出數據直接輸出到打印輸出埠。與打印隊列程序進行的打印不同,GDI進行的打印一定會讓應用程序暫停執行一段時間(特別是進行打印中的程序)直到打印完成。

還有另一個例外。通常,GDI模塊將定義一頁所需的所有函數存入一個增強型metafile中,然后替驅動程序定義的每個打印輸出帶輸出一遍該metafile到打印驅動程序中。然而,如果打印驅動程序不需要打印分帶的話,就不會建立這個metafile;GDI只需簡單地將繪圖函數直接送往驅動程序。進一步的變化是,應用程序也可能得承擔起對打印輸出數據進行打印分帶的責任,這就使得應用程序中的打印程序代碼更加復雜了,但卻免去了GDI模塊建立metafile的麻煩。這樣,GDI只需簡單地為每個輸出帶將函數傳到打印驅動程序。

或許您現在已經發現了從一個Windows應用程序進行打印操作要比使用視訊顯示器的負擔更大,這樣可能出現一些問題-特別是,如果GDI模塊在建立metafile或打印輸出文件時耗盡了磁盤空間。您可以更關切這些問題,并嘗試著處理這些問題并告知使用者,或者您當然也可以置之不理。

對于一個應用程序,打印文件的第一步就是如何取得打印機設備的內容。

打印機設備內容

正如在視訊顯示器上繪圖前需要得到設備內容句柄一樣,在打印之前,使用者必須取得一個打印機設備內容句柄。一旦有了這個句柄(并為建立一個新文件呼叫了StartDoc以及呼叫StartPage開始一頁),就可以用與使用視訊顯示設備內容句柄相同的方法來使用打印機設備內容句柄,該句柄即為各種GDI呼叫的第一個參數。

大多數應用程序經由呼叫PrintDlg函數打開一個標準的打印對話框(本章后面會展示該函數的用法)。這個函數還為使用者提供了一個在打印之前改變打印機或者指定其它特性的機會。然后,它將打印機設備內容句柄交給應用程序。該函數能夠省下應用程序的一些工作。然而,某些應用程序(例如Notepad)僅需要取得打印機設備內容,而不需要那個對話框。要做到這一點,需要呼叫CreateDC函數。

在第五章中,您已知道如何通過如下的呼叫來為整個視訊顯示器取得指向設備內容的句柄:

hdc = CreateDC (TEXT ("DISPLAY"), NULL, NULL, NULL) ;
        

您也可以使用該函數來取得打印機設備內容句柄。然而,對打印機設備內容,CreateDC的一般語法為:

hdc = CreateDC (NULL, szDeviceName, NULL, pInitializationData) ;
        

pInitializationData參數一般被設為NULL。szDeviceName參數指向一個字符串,以告訴Windows打印機設備的名稱。在設定設備名稱之前,您必須知道有哪些打印機可用。

一個系統可能有不只一臺連結著的打印機,甚至可以有其它程序,如傳真軟件,將自己偽裝成打印機。不論連結的打印機有多少臺,都只能有一臺被認為是「目前的打印機」或者「內定打印機」,這是使用者最近一次選擇的打印機。許多小型的Windows程序只使用內定打印機來進行打印。

取得內定打印機設備內容的方式不斷在改變。目前,標準的方法是使用EnumPrinters函數來獲得。該函數填入一個包含每個連結著的打印機信息的數組結構。根據所需的細節層次,您還可以選擇幾種結構之一作為該函數的參數。這些結構的名稱為PRINTER_INFO_x,x是一個數字。

不幸的是,所使用的函數還取決于您的程序是在Windows 98上執行還是在Windows NT上執行。程序13-1展示了GetPrinterDC函數在兩種操作系統上工作的用法。

程序13-1 GETPRNDC

        
GETPRNDC.C
        
/*----------------------------------------------------------------------
        
  GETPRNDC.C -- GetPrinterDC function
        
-----------------------------------------------------------------------*/
        
#include <windows.h>
        
HDC GetPrinterDC (void)
        
{
        
           DWORD                                                      dwNeeded, dwReturned ;
        
           HDC                                                         hdc ;
        
           PRINTER_INFO_4 *              pinfo4 ;
        
           PRINTER_INFO_5 *              pinfo5 ;
        

           if (GetVersion () & 0x80000000)      // Windows 98
        
           {
        
                          EnumPrinters (PRINTER_ENUM_DEFAULT, NULL, 5, NULL,
        
                   0, &dwNeeded, &dwReturned) ;
        
                          pinfo5 = malloc (dwNeeded) ;
        
                         EnumPrinters (PRINTER_ENUM_DEFAULT, NULL, 5, (PBYTE) pinfo5,
        
                   dwNeeded, &dwNeeded, &dwReturned) ;
        
                          hdc = CreateDC (NULL, pinfo5->pPrinterName, NULL, NULL) ;
        
                          free (pinfo5) ;
        
           }
        
           else
        
//Windows NT
        
   {
        
                          EnumPrinters (PRINTER_ENUM_LOCAL, NULL, 4, NULL,
        
                   0, &dwNeeded, &dwReturned) ;
        
                          pinfo4 = malloc (dwNeeded) ;
        
                          EnumPrinters (PRINTER_ENUM_LOCAL, NULL, 4, (PBYTE) pinfo4,
        
                   dwNeeded, &dwNeeded, &dwReturned) ;
        
                          hdc = CreateDC (NULL, pinfo4->pPrinterName, NULL, NULL) ;
        
                          free (pinfo4) ;
        
           }
        
           return hdc ; 
        
}
        

這些函數使用GetVersion函數來確定程序是執行在Windows 98上還是Windows NT上。不管是什么操作系統,函數呼叫EnumPrinters兩次:一次取得它所需結構的大小,一次填入結構。在Windows 98上,函數使用PRINTER_INFO_5結構;在Windows NT上,函數使用PRINTER_INFO_4結構。這些結構在EnumPrinters文件(/Platform SDK/Graphics and Multimedia Services/GDI/Printing and Print Spooler/Printing and Print Spooler Reference/Printing and Print Spooler Functions/EnumPrinters,范例小節的前面)中有說明,它們是「容易而快速」的。

修改后的DEVCAPS程序

第五章的DEVCAPS1程序只顯示了從GetDeviceCaps函數獲得的關于視訊顯示的基本信息。程序13-2所示的新版本顯示了關于視訊顯示和連結到系統之所有打印機的更多信息。

程序13-2 DEVCAPS2

        
DEVCAPS2.C
        
/*--------------------------------------------------------------------------
        
  DEVCAPS2.C --         Displays Device Capability Information (Version 2)
        
                                                                (c) Charles Petzold, 1998
        
---------------------------------------------------------------------------*/
        
#include <windows.h>
        
#include "resource.h"
        

LRESULT CALLBACK WndProc           (HWND, UINT, WPARAM, LPARAM) ;
        
void DoBasicInfo                          (HDC, HDC, int, int) ;
        
void DoOtherInfo                          (HDC, HDC, int, int) ;
        
void DoBitCodedCaps                       (HDC, HDC, int, int, int) ;
        

typedef struct
        
{
        
           int                           iMask ;
        
           TCHAR *               szDesc ;
        
}
        
BITS ;
        
#define IDM_DEVMODE     1000
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                                                                PSTR szCmdLine, int iCmdShow)
        
{
        
           static TCHAR          szAppName[] = TEXT ("DevCaps2") ;
        
           HWND                                         hwnd ;
        
           MSG                                         msg ;
        
           WNDCLASS                             wndclass ;
        
   
        
           wndclass.style                               = CS_HREDRAW | CS_VREDRAW ;
        
           wndclass.lpfnWndProc                         = WndProc ;
        
           wndclass.cbClsExtra                          = 0 ;
        
           wndclass.cbWndExtra                          = 0 ;
        
           wndclass.hInstance                           = hInstance ;
        
           wndclass.hIcon                               = LoadIcon (NULL, IDI_APPLICATION) ;
        
           wndclass.hCursor                             = LoadCursor (NULL, IDC_ARROW) ;
        
           wndclass.hbrBackground              = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
        
           wndclass.lpszMenuName                = szAppName ;
        
           wndclass.lpszClassName               = szAppName ;
        
   
        
           if (!RegisterClass (&wndclass))
        
           {
        
                  MessageBox (  NULL, TEXT ("This program requires Windows NT!"),
        
                                                                        szAppName, MB_ICONERROR) ;
        
                  return 0 ;
        
           }
        
   
        
           hwnd = CreateWindow (szAppName, NULL,
        
                         WS_OVERLAPPEDWINDOW,
        
                         CW_USEDEFAULT, CW_USEDEFAULT,
        
                         CW_USEDEFAULT, CW_USEDEFAULT,
        
                        NULL, NULL, hInstance, NULL) ;
        
   
        
           ShowWindow (hwnd, iCmdShow) ;
        
           UpdateWindow (hwnd) ;
        
   
        
           while (GetMessage (&msg, NULL, 0, 0))
        
           {
        
                          TranslateMessage (&msg) ;
        
                          DispatchMessage (&msg) ;
        
           }
        
           return msg.wParam ;
        
}
        

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
        
{
        
   static TCHAR                          szDevice[32], szWindowText[64] ;
        
    static int                           cxChar, cyChar,nCurrentDevice        = IDM_SCREEN,
        
       nCurrentInfo       = IDM_BASIC ;
        
           static DWORD                         dwNeeded, dwReturned ;
        
           static PRINTER_INFO_4 * pinfo4 ;
        
           static PRINTER_INFO_5 * pinfo5 ;
        
           DWORD                  i ;
        
           HDC                    hdc, hdcInfo ;
        
           HMENU                 hMenu ;
        
           HANDLE                 hPrint ;
        
           PAINTSTRUCT            ps ;
        
           TEXTMETRIC            tm ;
        
   
        
           switch (message)
        
           {
        
           case   WM_CREATE :
        
                          hdc =  GetDC (hwnd) ;
        
                   SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
        
                   GetTextMetrics (hdc, &tm) ;
        
                          cxChar = tm.tmAveCharWidth ;
        
                          cyChar = tm.tmHeight + tm.tmExternalLeading ;
        
                          ReleaseDC (hwnd, hdc) ;
        
// fall through
        
           case   WM_SETTINGCHANGE:
        
                          hMenu = GetSubMenu (GetMenu (hwnd), 0) ;
        
        
        
                          while (GetMenuItemCount (hMenu) > 1)
        
                                  DeleteMenu (hMenu, 1, MF_BYPOSITION) ;
        

                                  // Get a list of all local and remote printers
        
                                  //
        
                                 // First, find out how large an array we need; this
        
                                  //   call will fail, leaving the required size in dwNeeded
        
                                  //
        
                                 // Next, allocate space for the info array and fill it
        
                                  //
        
                                 // Put the printer names on the menu
        

            if (GetVersion () & 0x80000000)                                     // Windows 98
        
                  {
        
                                  EnumPrinters (PRINTER_ENUM_LOCAL, NULL, 5, NULL,
        
                       0, &dwNeeded, &dwReturned) ;
        

                                 pinfo5 = malloc (dwNeeded) ;
        

                                  EnumPrinters (PRINTER_ENUM_LOCAL, NULL, 5, (PBYTE) pinfo5,
        
                       dwNeeded, &dwNeeded, &dwReturned) ;
        

                                  for (i = 0 ; i < dwReturned ; i++)
        
                                  {
        
                                        AppendMenu (hMenu, (i+1) % 16 ? 0 : MF_MENUBARBREAK, i + 1,
        
                                                                                    pinfo5[i].pPrinterName) ;
        
                                  }
        
                                free (pinfo5) ;
        
          }
        
                  else
        
// Windows NT
        
         {
        
                                 EnumPrinters (PRINTER_ENUM_LOCAL, NULL, 4, NULL,
        
                       0, &dwNeeded, &dwReturned) ;
        
                                  pinfo4 = malloc (dwNeeded) ;
        
                                  EnumPrinters (PRINTER_ENUM_LOCAL, NULL, 4, (PBYTE) pinfo4,
        
                      dwNeeded, &dwNeeded, &dwReturned) ;
        
                                  for (i = 0 ; i < dwReturned ; i++)
        
                                         {
        
                                   AppendMenu (hMenu, (i+1) % 16 ? 0 : MF_MENUBARBREAK, i + 1,
        
                                        pinfo4[i].pPrinterName) ;
        
              }
        
                                         free (pinfo4) ;
        
                  }
        
        
        
                  AppendMenu (hMenu, MF_SEPARATOR, 0, NULL) ;
        
                  AppendMenu (hMenu, 0, IDM_DEVMODE, TEXT ("Properties")) ;
        
        
        
                  wParam = IDM_SCREEN ;
        
// fall through
        
           case   WM_COMMAND :
        
                          hMenu = GetMenu (hwnd) ;
        
        
        
                          if (   LOWORD (wParam) == IDM_SCREEN ||     // IDM_SCREEN & Printers
        
                                         LOWORD (wParam) < IDM_DEVMODE)     
        
                          {
        
                          CheckMenuItem (hMenu, nCurrentDevice, MF_UNCHECKED) ;
        
                          nCurrentDevice = LOWORD (wParam) ;
        
                          CheckMenuItem (hMenu, nCurrentDevice, MF_CHECKED) ;
        
                          }
        
                          else if (LOWORD (wParam) == IDM_DEVMODE)     // Properties selection
        
                          {
        
                                                 GetMenuString (hMenu, nCurrentDevice, szDevice,
        
                                  sizeof (szDevice) / sizeof (TCHAR), MF_BYCOMMAND);
        
             
        
                                                 if (OpenPrinter (szDevice, &hPrint, NULL))
        
                                                 {
        
                                                 PrinterProperties (hwnd, hPrint) ;
        
                                                 ClosePrinter (hPrint) ;
        
                                                 }
        
                          }
        
                          else
        
// info menu items
        
         {
        
                                         CheckMenuItem (hMenu, nCurrentInfo, MF_UNCHECKED) ;
        
                                         nCurrentInfo = LOWORD (wParam) ;
        
                                         CheckMenuItem (hMenu, nCurrentInfo, MF_CHECKED) ;
        
                          }
        
                          InvalidateRect (hwnd, NULL, TRUE) ;
        
                          return 0 ;
        
       
        
           case   WM_INITMENUPOPUP :
        
                          if (lParam == 0)
        
                                                EnableMenuItem (GetMenu (hwnd), IDM_DEVMODE,
        
                                                         nCurrentDevice == IDM_SCREEMF_GRAYED : MF_ENABLED) ;
        
                          return 0 ;
        
        
        
           case   WM_PAINT :
        
                          lstrcpy (szWindowText, TEXT ("Device Capabilities: ")) ;
        
        
        
                          if (nCurrentDevice == IDM_SCREEN)
        
                          {
        
                                         lstrcpy (szDevice, TEXT ("DISPLAY")) ;
        
                                         hdcInfo = CreateIC (szDevice, NULL, NULL, NULL) ;
        
                          }
        
                          else
        
                          {
        
                                         hMenu = GetMenu (hwnd) ;
        
                                         GetMenuString (hMenu, nCurrentDevice, szDevice,
        
                           sizeof (szDevice), MF_BYCOMMAND) ;
        
                                        hdcInfo = CreateIC (NULL, szDevice, NULL, NULL) ;
        
                          }
        
        
        
                          lstrcat (szWindowText, szDevice) ;
        
                          SetWindowText (hwnd, szWindowText) ;
        
        
        
                          hdc = BeginPaint (hwnd, &ps) ;
        
                          SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
        
        
        
                          if (hdcInfo)
        
                          {
        
                                         switch (nCurrentInfo)
        
                                                {
        
                                         case   IDM_BASIC :
        
                          DoBasicInfo (hdc, hdcInfo, cxChar, cyChar) ;
        
                                                         break ;
        
                  
        
                                  case   IDM_OTHER :
        
                          DoOtherInfo (hdc, hdcInfo, cxChar, cyChar) ;
        
                                                break ;
        
                  
        
                                 case   IDM_CURVE :
        
                                  case   IDM_LINE :
        
                                  case   IDM_POLY :
        
                                  case   IDM_TEXT :
        
                          DoBitCodedCaps (hdc, hdcInfo, cxChar, cyChar,
        
                                        nCurrentInfo - IDM_CURVE) ;
        
                                                 break ;
        
                                         }
        
                                  DeleteDC (hdcInfo) ;
        
                  }
        
        
        
                  EndPaint (hwnd, &ps) ;
        
                  return 0 ;
        
        
        
           case   WM_DESTROY :
        
                          PostQuitMessage (0) ;
        
                          return 0 ;
        
           }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        
   
        
void DoBasicInfo (HDC hdc, HDC hdcInfo, int cxChar, int cyChar)
        
{
        
  static struct
        
           {
        
                  int     nIndex ;
        
                  TCHAR * szDesc ;
        
  }
        
           info[] =
        
           {
        
                 HORZSIZE,                     TEXT ("HORZSIZE                   Width in millimeters:"),
        
                  VERTSIZE,                     TEXT ("VERTSIZE                   Height in millimeters:"),
        
                  HORZRES,                      TEXT ("HORZRES                   Width in pixels:"),
        
                  VERTRES,                     TEXT ("VERTRES                    Height in raster lines:"),
        
                  BITSPIXEL,                    TEXT ("BITSPIXEL                  Color bits per pixel:"),
        
                  PLANES,                       TEXT ("PLANES                              Number of color planes:"),
        
                  NUMBRUSHES,                   TEXT ("NUMBRUSHES                 Number of device brushes:"),
        
                  NUMPENS,                      TEXT ("NUMPENS                           Number of device pens:"),
        
                  NUMMARKERS,                   TEXT ("NUMMARKERS                 Number of device markers:"),
        
                  NUMFONTS,                     TEXT   ("NUMFONTS                        Number of device fonts:"),
        
                  NUMCOLORS,                    TEXT   ("NUMCOLORS                       Number of device colors:"),
        
                  PDEVICESIZE, TEXT("PDEVICESIZESize of device structure:"),
        
ASPECTX,       TEXT("ASPECTX Relative width of pixel:"),
        
ASPECTY,       TEXT("ASPECTY Relative height of pixel:"),
        
ASPECTXY,      TEXT("ASPECTXY Relative diagonal of pixel:"),
        
LOGPIXELSX,    TEXT("LOGPIXELSX Horizontal dots per inch:"),
        
LOGPIXELSY,   TEXT("LOGPIXELSY Vertical dots per inch:"),
        
SIZEPALETTE,   TEXT("SIZEPALETTE Number of palette entries:"),
        
NUMRESERVED,   TEXT("NUMRESERVED Reserved palette entries:"),
        
COLORRES,      TEXT("COLORRES Actual color resolution:"),
        
PHYSICALWIDTH, TEXT("PHYSICALWIDTH Printer page pixel "),
        
PHYSICALHEIGHT,TEXT("PHYSICALHEIGHT Printer page pixel height:"),
        
PHYSICALOFFSETX,TEXT("PHYSICALOFFSETX Printer page x offset:"),
        
PHYSICALOFFSETY,TEXT("PHYSICALOFFSETY Printer page y offset:")
        
  } ;
        
   int   i ;
        
  TCHAR szBuffer[80] ;
        
        
        
           for (i = 0 ; i < sizeof (info) / sizeof (info[0]) ; i++)
        
             TextOut (hdc, cxChar, (i + 1) * cyChar, szBuffer,
        
              wsprintf (szBuffer, TEXT ("%-45s%8d"), info[i].szDesc,
        
                   GetDeviceCaps (hdcInfo, info[i].nIndex))) ;
        
}
        
  
        
void DoOtherInfo (HDC hdc, HDC hdcInfo, int cxChar, int cyChar)
        
{
        
           static BITS clip[] =
        
           {
        
        CP_RECTANGLE, TEXT ("CP_RECTANGLE  Can Clip To Rectangle:")
        
           } ;
        
        
        
           static BITS raster[] =
        
    {
        
       RC_BITBLT,    TEXT ("RC_BITBLT  Capable of simple BitBlt:"),
        
           RC_BANDING,   TEXT ("RC_BANDING Requires banding support:"),
        
       RC_SCALING,   TEXT ("RC_SCALING Requires scaling support:"),
        
       RC_BITMAP64,  TEXT ("RC_BITMAP64  Supports bitmaps >64K:"),
        
       RC_GDI20_OUTPUT, TEXT ("RC_GDI20_OUTPUT Has 2.0 output calls:"),
        
       RC_DI_BITMAP, TEXT ("RC_DI_BITMAP  Supports DIB to memory:"),
        
           RC_PALETTE,   TEXT ("RC_PALETTE      Supports a palette:"),
        
          RC_DIBTODEV,  TEXT ("RC_DIBTODEV Supports bitmap conversion:"),
        
          RC_BIGFONT,   TEXT ("RC_BIGFONT  Supports fonts >64K:"),
        
           RC_STRETCHBLT,TEXT ("RC_STRETCHBLT Supports StretchBlt:"),
        
           RC_FLOODFILL, TEXT ("RC_FLOODFILL  Supports FloodFill:"),
        
          RC_STRETCHDIB,TEXT ("RC_STRETCHDIB Supports StretchDIBits:")
        
           } ;
        
        
        
           static TCHAR * szTech[]=      {      TEXT ("DT_PLOTTER (Vector plotter)"),
        
                       TEXT ("DT_RASDISPLAY (Raster display)"),
        
                        TEXT ("DT_RASPRINTER (Raster printer)"),
        
                        TEXT ("DT_RASCAMERA (Raster camera)"),
        
                        TEXT ("DT_CHARSTREAM (Character stream)"),
        
                       TEXT ("DT_METAFILE (Metafile)"),
        
                        TEXT ("DT_DISPFILE (Display file)") } ;
        
  int                                  i ;
        
   TCHAR                                szBuffer[80] ;
        
        
        
           TextOut (hdc, cxChar, cyChar, szBuffer,
        
         wsprintf (szBuffer, TEXT ("%-24s%04XH"), TEXT ("DRIVERVERSION:"),
        
              GetDeviceCaps (hdcInfo, DRIVERVERSION))) ;
        
  TextOut (hdc, cxChar, 2 * cyChar, szBuffer,
        
                          wsprintf (szBuffer, TEXT ("%-24s%-40s"), TEXT ("TECHNOLOGY:"),
        
                                         szTech[GetDeviceCaps (hdcInfo, TECHNOLOGY)])) ;
        
   TextOut (hdc, cxChar, 4 * cyChar, szBuffer,
        
                          wsprintf (szBuffer, TEXT ("CLIPCAPS (Clipping capabilities)"))) ;
        
           for (i = 0 ; i < sizeof (clip) / sizeof (clip[0]) ; i++)
        
                          TextOut (hdc, 9 * cxChar, (i + 6) * cyChar, szBuffer,
        
                                                wsprintf (szBuffer, TEXT ("%-45s %3s"), clip[i].szDesc,
        
                                                        GetDeviceCaps (hdcInfo, CLIPCAPS) & clip[i].iMask ?
        
                                                 TEXT ("Yes") : TEXT ("No"))) ;
        
           TextOut (hdc, cxChar, 8 * cyChar, szBuffer,
        
                  wsprintf (szBuffer, TEXT ("RASTERCAPS (Raster capabilities)"))) ;
        
   for (i = 0 ; i < sizeof (raster) / sizeof (raster[0]) ; i++)
        
           TextOut (hdc, 9 * cxChar, (i + 10) * cyChar, szBuffer,
        
                                                wsprintf (szBuffer, TEXT ("%-45s %3s"), raster[i].szDesc,
        
                                                         GetDeviceCaps (hdcInfo, RASTERCAPS) & raster[i].iMask ?
        
                                  TEXT ("Yes") : TEXT ("No"))) ;
        
}
        

void DoBitCodedCaps (      HDC hdc, HDC hdcInfo, int cxChar, int cyChar,int iType)
        
{
        
          static BITS curves[] =
        
           {
        
                  CC_CIRCLES,    TEXT ("CC_CIRCLES    Can do circles:"),
        
                  CC_PIE,        TEXT ("CC_PIE        Can do pie wedges:"),
        
                  CC_CHORD,      TEXT ("CC_CHORD      Can do chord arcs:"),
        
                  CC_ELLIPSES,  TEXT ("CC_ELLIPSES   Can do ellipses:"),
        
                  CC_WIDE,       TEXT ("CC_WIDE       Can do wide borders:"),
        
                  CC_STYLED,     TEXT ("CC_STYLED     Can do styled borders:"),
        
                 CC_WIDESTYLED, TEXT   ("CC_WIDESTYLED Can do wide and styled borders:"),
        
                  CC_INTERIORS,  TEXT ("CC_INTERIORS  Can do interiors:")
        
           } ;
        
   
        
           static BITS lines[] =
        
           {
        
                  LC_POLYLINE,   TEXT   ("LC_POLYLINE Can do polyline:"),
        
                  LC_MARKER,     TEXT   ("LC_MARKER Can do markers:"),
        
                  LC_POLYMARKER, TEXT   ("LC_POLYMARKER Can do polymarkers"),
        
                  LC_WIDE,       TEXT   ("LC_WIDE Can do wide lines:"),
        
                  LC_STYLED,     TEXT   ("LC_STYLED Can do styled lines:"),
        
                  LC_WIDESTYLED, TEXT   ("LC_WIDESTYLED       Can do wide and styled lines:"),
        
                  LC_INTERIORS,  TEXT ("LC_INTERIORS  Can do interiors:")
        
           } ;
        
   
        
           static BITS poly[] =
        
           {
        
                  PC_POLYGON,   
        
                                 TEXT ("PC_POLYGON     Can do alternate fill polygon:"),
        
                  PC_RECTANGLE,         TEXT   ("PC_RECTANGLE Can do rectangle:"),
        
           PC_WINDPOLYGON,
        
                                  TEXT ("PC_WINDPOLYGON Can do winding number fill polygon:"),
        
                  PC_SCANLINE,          TEXT ("PC_SCANLINE    Can do scanlines:"),
        
                  PC_WIDE,              TEXT ("PC_WIDE        Can do wide borders:"),
        
                  PC_STYLED,            TEXT ("PC_STYLED      Can do styled borders:"),
        
                  PC_WIDESTYLED,
        
                                 TEXT ("PC_WIDESTYLED  Can do wide and styled borders:"),
        
                 PC_INTERIORS,         TEXT ("PC_INTERIORS   Can do interiors:")
        
   } ;
        
   
        
           static BITS text[] =
        
           {
        
                  TC_OP_CHARACTER, TEXT ("TC_OP_CHARACTER      Can do character output precision:"),
        
                  TC_OP_STROKE,    TEXT ("TC_OP_STROKE  Can do stroke output precision:"),
        
                  TC_CP_STROKE,    TEXT ("TC_CP_STROKE  Can do stroke clip precision:"),
        
                  TC_CR_90,        TEXT ("TC_CP_90       Can do 90 degree character rotation:"),
        
                 TC_CR_ANY,       TEXT ("TC_CR_ANY      Can do any character rotation:"),
        
                  TC_SF_X_YINDEP,  TEXT ("TC_SF_X_YINDEP  Can do scaling independent of X and Y:"),
        
                  TC_SA_DOUBLE,    EXT ("TC_SA_DOUBLE    Can do doubled character for scaling:"),
        
                  TC_SA_INTEGER,   TEXT ("TC_SA_INTEGER   Can do integer multiples for scaling:"),
        
                  TC_SA_CONTIN,    TEXT ("TC_SA_CONTIN  Can do any multiples for exact scaling:"),
        
                  TC_EA_DOUBLE,    TEXT ("TC_EA_DOUBLE   Can do double weight characters:"),
        
                  TC_IA_ABLE,      TEXT ("TC_IA_ABLE     Can do italicizing:"),
        
                  TC_UA_ABLE,      TEXT ("TC_UA_ABLE     Can do underlining:"),
        
                  TC_SO_ABLE,      TEXT ("TC_SO_ABLE     Can do strikeouts:"),
        
                TC_RA_ABLE,      TEXT ("TC_RA_ABLE     Can do raster fonts:"),
        
                  TC_VA_ABLE,      TEXT ("TC_VA_ABLE     Can do vector fonts:")
        
           } ;
        
   
        
           static struct
        
           {
        
                  int                           iIndex ;
        
                  TCHAR *               szTitle ;
        
                  BITS                          (*pbits)[] ;
        
                  int                           iSize ;
        
  }
        
           bitinfo[] =
        
           {
        
                  CURVECAPS,    TEXT ("CURVCAPS (Curve Capabilities)"),
        
                                  (BITS (*)[]) curves, sizeof (curves) / sizeof (curves[0]),
        
                  LINECAPS,     TEXT ("LINECAPS (Line Capabilities)"),
        
                                  (BITS (*)[]) lines, sizeof (lines) / sizeof (lines[0]),
        
                  POLYGONALCAPS, TEXT ("POLYGONALCAPS (Polygonal Capabilities)"),
        
                                  (BITS (*)[]) poly, sizeof (poly) / sizeof (poly[0]),
        
                  TEXTCAPS,     TEXT ("TEXTCAPS (Text Capabilities)"),
        
                                  (BITS (*)[]) text, sizeof (text) / sizeof (text[0])
        
   } ;
        
   
        
           static TCHAR szBuffer[80] ;
        
           BITS                  (*pbits)[] = bitinfo[iType].pbits ;
        
           int                  i, iDevCaps = GetDeviceCaps (hdcInfo, bitinfo[iType].iIndex) ;
        
   
        
           TextOut (hdc, cxChar, cyChar, bitinfo[iType].szTitle,
        
                                                 lstrlen (bitinfo[iType].szTitle)) ;
        
           for (i = 0 ; i < bitinfo[iType].iSize ; i++)
        
           extOut (hdc, cxChar, (i + 3) * cyChar, szBuffer,
        
            wsprintf (szBuffer, TEXT ("%-55s %3s"), (*pbits)[i].szDesc,
        
            iDevCaps & (*pbits)[i].iMask ? TEXT ("Yes") : TEXT ("No")));
        
}
        

DEVCAPS2.RC (摘錄)

        
//Microsoft Developer Studio generated resource script.
        
#include "resource.h"
        
#include "afxres.h"
        
/////////////////////////////////////////////////////////////////////////////
        
// Menu
        
DEVCAPS2 MENU DISCARDABLE
        
BEGIN
        
   POPUP "&Device"
        
   BEGIN
        
                          MENUITEM "&Screen",IDM_SCREEN, CHECKED
        
   END
        
   POPUP "&Capabilities"
        
   BEGIN
        
                  MENUITEM "&Basic Information",IDM_BASIC
        
                          MENUITEM "&Other Information",IDM_OTHER
        
                          MENUITEM "&Curve Capabilities",IDM_CURVE
        
                          MENUITEM "&Line Capabilities",IDM_LINE
        
                          MENUITEM "&Polygonal Capabilities",IDM_POLY
        
                          MENUITEM "&Text Capabilities",IDM_TEXT
        
   END
        
END
        

RESOURCE.H (摘錄)

        
// Microsoft Developer Studio generated include file.
        
// Used by DevCaps2.rc
        
#define IDM_SCREEN       40001
        
#define IDM_BASIC         40002
        
#define IDM_OTHER         40003
        
#define IDM_CURVE         40004
        
#define IDM_LINE          40005
        
#define IDM_POLY         40006
        
#define IDM_TEXT          40007
        

因為DEVCAPS2只取得打印機的信息內容,使用者仍然可以從DEVCAPS2的菜單中選擇所需打印機。如果使用者想比較不同打印機的功能,可以先用打印機文件夾增加各種打印驅動程序。

PrinterProperties呼叫

DEVCAPS2的「Device」菜單中上還有一個稱為「Properties」的選項。要使用這個選項,首先得從 Device菜單中選擇一個打印機,然后再選擇Properties,這時彈出一個對話框。對話框從何而來呢?它由打印機驅動程序呼叫,而且至少還讓使用者選擇紙的尺寸。大多數打印機驅動也可以讓使用者在「直印(portrait)」或「橫印(landscape)」模式中進行選擇。在直印模式(一般為內定模式)下,紙的短邊是頂部。在橫印模式下,紙的長邊是頂部。如果改變該模式,則所作的改變將在DEVCAPS2程序從GetDeviceCaps函數取得的信息中反應出來:水平尺寸和分辨率將與垂直尺寸和分辨率交換。彩色繪圖機的「Properties」對話框內容十分廣泛,它們要求使用者輸入安裝在繪圖機上之畫筆的顏色和使用之繪圖紙(或透明膠片)的型號。

所有打印機驅動程序都包含一個稱為ExtDeviceMode的輸出函數,它呼叫對話框并儲存使用者輸入的信息。有些打印機驅動程序也將這些信息儲存在系統登錄的自己擁有的部分中,有些則不然。那些儲存信息的打印機驅動程序在下次執行Windows時將存取該信息。

允許使用者選擇打印機的Windows程序通常只呼叫PrintDlg(本章后面我會展示用法)。這個有用的函數在準備打印時負責和使用者之間所有的通訊工作,并負責處理使用者要求的所有改變。當使用者單擊「Properties」按鈕時,PrintDlg還會啟動屬性表格對話框。

程序還可以通過直接呼叫打印機驅動程序的ExtDeviceMode或ExtDeveModePropSheet函數,來顯示打印機的屬性對話框,然而,我不鼓勵您這樣做。像DEVCAPS2那樣,透過呼叫PrinterProperties來啟動對話框會好得多。

PrinterProperties要求打印機對象的句柄,您可以通過OpenPrinter函數來得到。當使用者取消屬性表格對話框時,PrinterProperties傳回,然后使用者通過呼叫ClosePrinter,釋放打印機句柄。DEVCAPS2就是這樣做到這一點的。

程序首先取得剛剛在Device菜單中選擇的打印機名稱,并將其存入一個名為szDevice的字符數組中。

GetMenuString (    hMenu, nCurrentDevice, szDevice,
        
                                                 sizeof (szDevice) / sizeof (TCHAR), MF_BYCOMMAND) ;
        

然后,使用OpenPrinter獲得該設備的句柄。如果呼叫成功,那么程序接著呼叫PrinterProperties啟動對話框,然后呼叫ClosePrinter釋放設備句柄:

if (OpenPrinter (szDevice, &hPrint, NULL))
        
{
        
           PrinterProperties (hwnd, hPrint) ;
        
           ClosePrinter (hPrint) ;
        
}
        

檢查BitBlt支持

您可以用GetDeviceCaps函數來取得頁中可打印區的尺寸和分辨率(通常,該區域不會與整張紙的大小相同)。如果使用者想自己進行縮放操作,也可以獲得相對的圖素寬度和高度。

打印機能力的大多數信息是用于GDI而不是應用程序的。通常,在打印機不能做某件事時,GDI會仿真出那項功能。然而,這是應用程序應該事先檢查的。

以RASTERCAPS(「位映像支持」)參數呼叫GetDeviceCaps,它傳回的RC_BITBLT位包含了另一個重要的打印機特性,該位標示設備是否能進行位塊傳送。大多數點陣打印機、激光打印機和噴墨打印機都能進行位塊傳送,而大多數繪圖機卻不能。不能處理位塊傳送的設備不支持下列GDI函數:CreateCompatibleDC、CreateCompatibleBitmap、PatBlt、BitBlt、StretchBlt、GrayString、DrawIcon、SetPixel、GetPixel、FloodFill、ExtFloodFill、FillRgn、FrameRgn、InvertRgn、PaintRgn、FillRect、FrameRect和InvertRect。這是在視訊顯示器上使用GDI函數與在打印機上使用它們的唯一重要區別。

最簡單的打印程序

現在可以開始打印了,我們盡可能簡單地開始。事實上,我們的第一個程序只是讓打印機走紙而已。程序13-3的FORMFEED程序,展示了打印所需的最小需求。

程序13-3 FORMFEED

        
FORMFEED.C
        
/*-----------------------------------------------------------------------
        
  FORMFEED.C -- Advances printer to next page
        
                                                         (c) Charles Petzold, 1998
        
------------------------------------------------------------------------*/
        
#include <windows.h>
        
HDC GetPrinterDC (void) ;
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                                         LPSTR lpszCmdLine, int iCmdShow)
        
{
        
           static DOCINFO di = { sizeof (DOCINFO), TEXT ("FormFeed") } ;
        
           HDC                                         hdcPrint = GetPrinterDC () ;
        
   
        
           if (hdcPrint != NULL)
        
           {
        
          if (StartDoc (hdcPrint, &di) > 0)
        
                                         if (StartPage (hdcPrint) > 0 && EndPage (hdcPrint) > 0)
        
                                                         EndDoc (hdcPrint) ;
        
                  DeleteDC (hdcPrint) ;
        
          }
        
           return 0 ;
        
}
        

這個程序也需要前面程序13-1中的GETPRNDC.C文件。

除了取得打印機設備內容(然后再刪除它)外,程序只呼叫了我們在本章前面討論過的四個打印函數。FORMFEED首先呼叫StartDoc開始一個新的文件,它測試從StartDoc傳回的值,只有傳回值是正數時,才繼續下去:

if (StartDoc (hdcPrint, &di) > 0)
        

StartDoc的第二個參數是指向DOCINFO結構的指針。該結構在第一個字段包含了結構的大小,在第二個字段包含了字符串「FormFeed」。當文件正在被打印或者在等待打印時,這個字符串將出現在打印機任務隊列中的「Document Name」列中。通常,該字符串包含進行打印的應用程序名稱和被打印的文件名稱。

如果StartDoc成功(由一個正的傳回值表示),那么FORMFEED呼叫StartPage,緊接著立即呼叫EndPage。這一程序將打印機推進到新的一頁,再次對傳回值進行測試:

if (StartPage (hdcPrint) > 0 && EndPage (hdcPrint) > 0)
        

最后,如果不出錯,文件就結束:

EndDoc (hdcPrint) ;
        

要注意的是,只有當沒出錯時,才呼叫EndDoc函數。如果其它打印函數中的某一個傳回錯誤代碼,那么GDI實際上已經中斷了文件的打印。如果打印機目前未打印,這種錯誤代碼通常會使打印機重新設定。測試打印函數的傳回值是檢測錯誤的最簡單方法。如果您想向使用者報告錯誤,就必須呼叫GetLastError來確定錯誤。

如果您寫過MS-DOS下的簡單利用打印機走紙的程序,就應該知道,對于大多數打印機,ASCII碼12啟動走紙。為什么不簡單地使用C的鏈接庫函數open,然后用write輸出ASCII碼12呢?當然,您完全可以這么做,但是必須確定打印機連結的是串行端口還是并列埠。然后您還要確定另外的程序(例如,打印隊列程序)是不是正在使用打印機。您并不希望在文件打印到一半時被別的程序把正在打印的那張紙送出打印機,對不對?最后,您還必須確定ASCII碼12是不是所連結打印機的走紙字符,因為并非所有打印機的走紙字符都是12。事實上,在PostScript中的走紙命令便不是12,而是單字showpage。

簡單地說,不要試圖直接繞過Windows;而應該堅持在打印中使用Windows函數。

打印圖形和文字

在一個Windows程序中,打印所需的額外負擔通常比FORMFEED程序高得多,而且還要用GDI函數來實際打印一些東西。我們來寫個打印一頁文字和圖形的程序,采用FORMFEED程序中的方法,并加入一些新的東西。該程序將有三個版本PRINT1、PRINT2和PRINT3。為避免程序代碼重復,每個程序都用前面所示的GETPRNDC.C文件和PRINT.C文件中的函數,如程序13-4所示。

程序13-4 PRINT

        
PRINT.C
        
/*------------------------------------------------------------------------
        
  PRINT.C -- Common routines for Print1, Print2, and Print3
        
--------------------------------------------------------------------------*/
        
#include <windows.h>
        
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
        
BOOL PrintMyPage (HWND) ;
        

extern HINSTANCE   hInst ;
        
extern TCHAR                       szAppName[] ;
        
extern TCHAR                       szCaption[] ;
        

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                          PSTR szCmdLine, int iCmdShow)
        
{
        
           HWND                  hwnd ;
        
           MSG                   msg ;
        
           WNDCLASS              wndclass ;
        
   
        
           wndclass.style                               = CS_HREDRAW | CS_VREDRAW ;
        
           wndclass.lpfnWndProc                         = WndProc ;
        
           wndclass.cbClsExtra                          = 0 ;
        
           wndclass.cbWndExtra                          = 0 ;
        
           wndclass.hInstance                           = hInstance ;
        
           wndclass.hIcon                               = LoadIcon (NULL, IDI_APPLICATION) ;
        
           wndclass.hCursor                             = LoadCursor (NULL, IDC_ARROW) ;
        
           wndclass.hbrBackground              = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
        
           wndclass.lpszMenuName                = NULL ;
        
          wndclass.lpszClassName               = szAppName ;
        
   
        
           if (!RegisterClass (&wndclass))
        
    {
        
                 MessageBox (  NULL, TEXT ("This program requires Windows NT!"),
        
                                                 szAppName, MB_ICONERROR) ;
        
                  return 0 ;
        
          }
        
   
        
           hInst = hInstance ;
        
           hwnd = CreateWindow (szAppName, szCaption,
        
                         WS_OVERLAPPEDWINDOW,
        
                         CW_USEDEFAULT, CW_USEDEFAULT,
        
                         CW_USEDEFAULT, CW_USEDEFAULT,
        
                        NULL, NULL, hInstance, NULL) ;
        
   
        
           ShowWindow (hwnd, iCmdShow) ;
        
           UpdateWindow (hwnd) ;
        
   
        
           while (GetMessage (&msg, NULL, 0, 0))
        
           {
        
                          TranslateMessage (&msg) ;
        
                          DispatchMessage (&msg) ;
        
           }
        
           return msg.wParam ;
        
}
        

void PageGDICalls (HDC hdcPrn, int cxPage, int cyPage)
        
{
        
           static TCHAR szTextStr[] = TEXT ("Hello, Printer!") ;
        
           Rectangle (hdcPrn, 0, 0, cxPage, cyPage) ;
        
           MoveToEx (hdcPrn, 0, 0, NULL) ;
        
           LineTo   (hdcPrn, cxPage, cyPage) ;
        
           MoveToEx (hdcPrn, cxPage, 0, NULL) ;
        
           LineTo   (hdcPrn, 0, cyPage) ;
        
   
        
           SaveDC (hdcPrn) ;
        
   
        
           SetMapMode                    (hdcPrn, MM_ISOTROPIC) ;
        
           SetWindowExtEx                (hdcPrn, 1000, 1000, NULL) ;
        
         SetViewportExtEx              (hdcPrn, cxPage / 2, -cyPage / 2, NULL) ;
        
           SetViewportOrgEx              (hdcPrn, cxPage / 2,  cyPage / 2, NULL) ;
        
   
        
           Ellipse (hdcPrn, -500, 500, 500, -500) ;
        
           SetTextAlign (hdcPrn, TA_BASELINE | TA_CENTER) ;
        
           TextOut (hdcPrn, 0, 0, szTextStr, lstrlen (szTextStr)) ;
        

           RestoreDC (hdcPrn, -1) ;
        
}
        

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
        
{
        
           static int            cxClient, cyClient ;
        
           HDC                   hdc ;
        
           HMENU                 hMenu ;
        
           PAINTSTRUCT           ps ;
        
   
        
           switch (message)
        
           {
        
           case   WM_CREATE:
        
                          hMenu = GetSystemMenu (hwnd, FALSE) ;
        
                          AppendMenu (hMenu, MF_SEPARATOR, 0, NULL) ;
        
                          AppendMenu (hMenu, 0, 1, TEXT ("&Print")) ;
        
                          return 0 ;
        
        
        
           case   WM_SIZE:
        
                          cxClient = LOWORD (lParam) ;
        
                          cyClient = HIWORD (lParam) ;
        
                        return 0 ;
        
        
        
           case   WM_SYSCOMMAND:
        
                          if (wParam == 1)
        
                  {
        
                                        if (!PrintMyPage (hwnd))
        
                                                 MessageBox (hwnd, TEXT ("Could not print page!"),
        
                                        szAppName, MB_OK | MB_ICONEXCLAMATION) ;
        
                                         return 0 ;
        
                  }
        
                  break ;
        
       
        
           case   WM_PAINT :
        
                  hdc = BeginPaint (hwnd, &ps) ;
        
        
        
                          PageGDICalls (hdc, cxClient, cyClient) ;
        
        
        
                          EndPaint (hwnd, &ps) ;
        
                         return 0 ;
        
        
        
           case   WM_DESTROY :
        
                          PostQuitMessage (0) ;
        
                          return 0 ;
        
           }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        

PRINT.C包括函數WinMain、WndProc以及一個稱為PageGDICalls的函數。PageGDICalls函數接收打印機設備內容句柄和兩個包含打印頁面寬度及高度的變量。這個函數還負責畫一個包圍整個頁面的矩形,有兩條對角線,頁中間有一個橢圓(其直徑是打印機高度和寬度中較小的那個的一半),文字「Hello, Printer!」位于橢圓的中間。

處理WM_CREATE消息時,WndProc將一個「Print」選項加到系統菜單上。選擇該選項將呼叫PrintMyPage,此函數的功能在程序的三個版本中將不斷增強。當打印成功時,PrintMyPage傳回TRUE值,如果遇到錯誤時則傳回FALSE。如果PrintMyPage傳回FALSE,WndProc就會顯示一個消息框以告知使用者發生了錯誤。

打印的基本程序

打印程序的第一個版本是PRINT1,見程序13-5。經編譯后即可執行此程序,然后從系統菜單中選擇「Print」。接著,GDI將必要的打印機輸出儲存在一個臨時文件中,然后打印隊列程序將它發送給打印機。

程序13-5 PRINT1

        
PRINT1.C
        
/*---------------------------------------------------------------------
        
  PRINT1.C -- Bare Bones Printing
        
                                                         (c) Charles Petzold, 1998
        
----------------------------------------------------------------------*/
        
#include <windows.h>
        
HDC         GetPrinterDC (void) ;                        // in GETPRNDC.C
        
void        PageGDICalls (HDC, int, int) ;               // in PRINT.C
        

HINSTANCE hInst ;
        
TCHAR              szAppName[] = TEXT ("Print1") ;
        
TCHAR              szCaption[] = TEXT ("Print Program 1") ;
        

BOOL PrintMyPage (HWND hwnd)
        
{
        
           static DOCINFO di = { sizeof (DOCINFO), TEXT ("Print1: Printing") } ;
        
    BOOL                          bSuccess = TRUE ;
        
           HDC                   hdcPrn ;
        
           int                   xPage, yPage ;
        
   
        
           if     (NULL == (hdcPrn = GetPrinterDC ()))
        
                          return FALSE ;
        
   xPage = GetDeviceCaps (hdcPrn, HORZRES) ;
        
  yPage = GetDeviceCaps (hdcPrn, VERTRES) ;
        
   
        
   if (StartDoc (hdcPrn, &di) > 0)
        
           {
        
                         if (StartPage (hdcPrn) > 0)
        
                          {
        
                                         PageGDICalls (hdcPrn, xPage, yPage) ;
        
             
        
                                         if (EndPage (hdcPrn) > 0)
        
                                                         EndDoc (hdcPrn) ;
        
                                         else
        
                                                 bSuccess = FALSE ;
        
                        }
        
           }
        
           else
        
                  bSuccess = FALSE ;
        
   
        
           DeleteDC (hdcPrn) ;
        
           return bSuccess ;
        
}
        

我們來看看PRINT1.C中的程序代碼。如果PrintMyPage不能取得打印機的設備內容句柄,它就傳回FALSE,并且WndProc顯示消息框指出錯誤。如果函數成功取得了設備內容句柄,它就通過呼叫GetDeviceCaps來確定頁面的水平和垂直大小(以圖素為單位)。

xPage = GetDeviceCaps (hdcPrn, HORZRES) ;
        
yPage = GetDeviceCaps (hdcPrn, VERTRES) ;
        

這不是紙的全部大小,只是紙的可打印區域。呼叫后,除了PRINT1在StartPage和EndPage呼叫之間呼叫PageGDICalls,PRINT1的PrintMyPage函數中的程序代碼在結構上與FORMFEED中的程序代碼相同。僅當呼叫StartDoc、StartPage和EndPage都成功時,PRINT1才呼叫EndDoc打印函數。

使用放棄程序來取消打印

對于大型文件,程序應該提供使用者在應用程序行印期間取消打印任務的便利性。也許使用者只要打印文件中的一頁,而不是打印全部的537頁。應該要能在印完全部的537頁之前糾正這個錯誤。

在一個程序內取消一個打印任務需要一種被稱為「放棄程序」的技術。放棄程序在程序中只是個較小的輸出函數,使用者可以使用SetAbortProc函數將該函數的地址傳給Windows。然后GDI在打印時,重復呼叫該程序,不斷地問:「我是否應該繼續打印?」

我們看看將放棄程序加到打印處理程序中去需要些什么,然后檢查一些旁枝末節。放棄程序一般命名為AbortProc,其形式為:

BOOL CALLBACK AbortProc (HDC hdcPrn, int iCode)
        
{
        
    //其它行程序
        
}
        

打印前,您必須通過呼叫SetAbortProc來登記放棄程序:

SetAbortProc (hdcPrn, AbortProc) ;
        

在呼叫StartDoc前呼叫上面的函數,打印完成后不必清除放棄程序。

在處理EndPage呼叫時(亦即,在將metafile放入設備驅動程序并建立臨時打印文件時),GDI常常呼叫放棄程序。參數hdcPrn是打印機設備內容句柄。如果一切正常,iCode參數是0,如果GDI模塊在生成臨時文件時耗盡了磁盤空間,iCode就是SP_OUTOFDISK。

如果打印作業繼續,那么AbortProc必須傳回TRUE(非零);如果打印作業異常結束,就傳回FALSE(零)。放棄程序可以被簡化為如下所示的形式:

BOOL CALLBACK AbortProc (HDC hdcPrn, int iCode)
        
{
        
           MSG   msg ;
        
           while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
        
           {
        
                  TranslateMessage (&msg) ;
        
                  DispatchMessage (&msg) ;
        
           }
        
           return TRUE ;
        
}
        

這個函數看起來有點特殊,其實它看起來像是消息循環。使用者會注意到,這個「消息循環」呼叫PeekMessage而不是GetMessage。我在第五章的RANDRECT程序中討論過PeekMessage。應該還記得,PeekMessage將會控制權返回給程序,而不管程序的消息隊列中是否有消息存在。

只要PeekMessage傳回TRUE,那么AbortProc函數中的消息循環就重復呼叫PeekMessage。TRUE值表示PeekMessage已經找到一個消息,該消息可以通過TranslateMessage和DispatchMessage發送到程序的窗口消息處理程序。若程序的消息隊列中沒有消息,則PeekMessage的傳回值為FALSE,因此AbortProc將控制權返回給Windows。

Windows如何使用AbortProc

當程序進行打印時,大部分工作發生在要呼叫EndPage時。呼叫EndPage前,程序每呼叫一次GDI繪圖函數,GDI模塊只是簡單地將另一個記錄加到磁盤上的metafile中。當GDI得到EndPage后,對打印頁中由設備驅動程序定義的每個輸出帶,GDI都將該metafile送入設備驅動程序中。然后,GDI將打印機驅動程序建立的打印輸出儲存到一個文件中。如果沒有啟用后臺打印,那么GDI模塊必須自動將該打印輸出寫入打印機。

在EndPage呼叫期間,GDI模塊呼叫您設定的放棄程序。通常iCode參數為0,但如果由于存在未打印的其它臨時文件,而造成GDI執行時磁盤空間不夠,iCode參數就為SP_OUTOFDISK(通常您不會檢查這個值,但是如果愿意,您可以進行檢查)。放棄程序隨后進入PeekMessage循環從自己的消息隊列中找尋消息。

如果在程序的消息隊列中沒有消息,PeekMessage會傳回FALSE,然后放棄程序跳出它的消息循環并給GDI模塊傳回一個TRUE值,指示打印應該繼續進行。然后GDI模塊繼續處理EndPage呼叫。

如果有錯誤發生,那么GDI將中止打印程序,這樣,放棄程序的主要目的是允許使用者取消打印。為此,我們還需要一個顯示「Cancel」按鈕的對話框,讓我們采用兩個獨立的步驟。首先,我們在建立PRINT2程序時增加一個放棄程序,然后在PRINT3中增加一個帶有「Cancel」按鈕的對話框,使放棄程序可用。

實作放棄程序

現在快速復習一下放棄程序的機制。可以定義一個如下所示的放棄程序:

BOOL CALLBACK AbortProc (HDC hdcPrn, int iCode)
        
{
        
           MSG  msg ;
        
           while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
        
           {
        
                  TranslateMessage (&msg) ;
        
                  DispatchMessage (&msg) ;
        
           }
        
           return TRUE ;
        
}
        

當您想打印什么時,使用下面的呼叫將指向放棄程序的指針傳給Windows:

SetAbortProc (hdcPrn, AbortProc) ;
        

在呼叫StartDoc之前進行這個呼叫就行了。

不過,事情沒有這么簡單。我們忽視了AbortProc程序中PeekMessage循環這個問題,它是個很大的問題。只有在程序處于打印程序時,AbortProc程序才會被呼叫。如果在AbortProc中找到一個消息并把它傳送給窗口消息處理程序,就會發生一些非常令人討厭的事情:使用者可以從菜單中再次選擇「Print」,但程序已經處于打印例程之中。程序在打印前一個文件的同時,使用者也可以把一個新文件加載到程序里。使用者甚至可以退出程序!如果這種情況發生了,所有使用者程序的窗口都將被清除。當打印例程執行結束時,除了退到不再有效的窗口例程之外,您無處可去。

這種東西會把人搞得暈頭轉向,而我們的程序對此并未做任何準備。正是由于這個原因,當設定放棄程序時,首先應禁止程序的窗口接受輸入,使它不能接受鍵盤和鼠標輸入。可以用以下的函數完成這項工作:

EnableWindow (hwnd, FALSE) ;
        

它可以禁止鍵盤和鼠標的輸入進入消息隊列。因此在打印程序中,使用者不能對程序做任何工作。當打印完成時,應重新允許窗口接受輸入:

EnableWindow (hwnd, TRUE) ;
        

您可能要問,既然沒有鍵盤或鼠標消息進入消息隊列,為什么我們還要進行AbortProc中的TranslateMessage和DispatchMessage呼叫呢?實際上并不一定非得需要TranslateMessage,但是,我們必須使用DispatchMessage,處理WM_PAINT消息進入消息隊列中的情況。如果WM_PAINT消息沒有得到窗口消息處理程序中的BeginPaint和EndPaint的適當處理,由于PeekMessage不再傳回FALSE,該消息就會滯留在隊列中并且妨礙工作。

當打印期間阻止窗口處理輸入消息時,您的程序不會進行顯示輸出。但使用者可以切換到其它程序,并在那里進行其它工作,而后臺打印程序則能繼續將輸出文件送到打印機。

程序13-6所示的PRINT2程序在PRINT1中增加了一個放棄程序和必要的支持-呼叫AbortProc函數并呼叫EnableWindow兩次(第一次阻止窗口接受輸入消息,第二次啟用窗口)。

程序13-6 PRINT2

        
PRINT2.C
        
/*---------------------------------------------------------------------
        
  PRINT2.C --   Printing with Abort Procedure
        
                                                         (c) Charles Petzold, 1998
        
----------------------------------------------------------------------*/
        
#include <windows.h>
        
HDC GetPrinterDC (void) ;                        // in GETPRNDC.C
        
void PageGDICalls (HDC, int, int) ;               // in PRINT.C
        

HINSTANCE hInst ;
        
TCHAR              szAppName[] = TEXT ("Print2") ;
        
TCHAR              szCaption[] = TEXT ("Print Program 2 (Abort Procedure)") ;
        

BOOL CALLBACK AbortProc (HDC hdcPrn, int iCode)
        
{
        
                  MSG msg ;
        
                  while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
        
           {
        
                          TranslateMessage (&msg) ;
        
                          DispatchMessage (&msg) ;
        
           }
        
           return TRUE ;
        
}
        

BOOL PrintMyPage (HWND hwnd)
        
{
        
           static DOCINFO di = { sizeof (DOCINFO), TEXT ("Print2: Printing") } ;
        
           BOOL                                 bSuccess = TRUE ;
        
           HDC                                  hdcPrn ;
        
           short                                xPage, yPage ;
        
   
        
          if (NULL == (hdcPrn = GetPrinterDC ()))
        
                          return FALSE ;
        
           xPage = GetDeviceCaps (hdcPrn, HORZRES) ;
        
           yPage = GetDeviceCaps (hdcPrn, VERTRES) ;
        
   
        
           EnableWindow (hwnd, FALSE) ;
        
           SetAbortProc (hdcPrn, AbortProc) ;
        
           if (StartDoc (hdcPrn, &di) > 0)
        
           {
        
                          if (StartPage (hdcPrn) > 0)
        
                          {
        
                                         PageGDICalls (hdcPrn, xPage, yPage) ;
        
                                         if (EndPage (hdcPrn) > 0)
        
                                                         EndDoc (hdcPrn) ;
        
                                        else
        
                                                         bSuccess = FALSE ;
        
                          }
        
  }
        
           else
        
                          bSuccess = FALSE ;
        
           EnableWindow (hwnd, TRUE) ;
        
           DeleteDC (hdcPrn) ;
        
           return bSuccess ;
        
}
        

增加打印對話框

PRINT2還不能令人十分滿意。首先,這個程序沒有直接指示出何時開始打印和何時結束打印。只有將鼠標指向程序并且發現它沒有反應時,才能斷定它仍然在處理PrintMyPage例程。PRINT2在進行背景處理時也沒有給使用者提供取消打印作業的機會。

您可能注意到,大多數Windows程序都為使用者提供了一個取消目前正在進行打印操作的機會。一個小的對話框出現在屏幕上,它包括一些文字和「Cancel」按鍵。在GDI將打印輸出儲存到磁盤文件或(如果停用打印隊列程序)打印機正在打印的整個期間,程序都顯示這個對話框。它是一個非系統模態對話框,您必須提供對話程序。

通常稱這個對話框為「放棄對話框」,稱這種對話程序為「放棄對話程序」。為了更清楚地把它和「放棄程序」區別開來,我們稱這種對話程序為「打印對話程序」。放棄程序(名為AbortProc)和打印對話程序(將命名為PrintDlgProc)是兩個不同的輸出函數。如果想以一種專業的Windows式打印方式進行打印工作,就必須擁有這兩個函數。

這兩個函數的交互作用方式如下:AbortProc中的PeekMessage循環得被修改,以便將非系統模態對話框的消息發送給對話框窗口消息處理程序。PrintDlgProc必須處理WM_COMMAND消息,以檢查「Cancel」按鈕的狀態。如果「Cancel」鈕被按下,就將一個叫做bUserAbort的整體變量設為TRUE。AbortProc傳回的值正好和bUserAbort相反。您可能還記得,如果AbortProc傳回TRUE會繼續打印,傳回FALSE則放棄打印。在PRINT2中,我們總是傳回TRUE。現在,使用者在打印對話框中按下「Cancel」按鈕時將傳回FALSE。程序13-7所示的PRINT3程序實作了這個處理方式。

程序13-7 PRINT3

        
PRINT3.C
        
/*-----------------------------------------------------------------
        
  PRINT3.C --   Printing with Dialog Box
        
                                                         (c) Charles Petzold, 1998
        
-------------------------------------------------------------------*/
        
#include <windows.h>
        
HDC GetPrinterDC (void) ;                        // in GETPRNDC.C
        
voidPageGDICalls (HDC, int, int) ;               // in PRINT.C
        

HINSTANCE hInst ;
        
TCHAR              szAppName[] = TEXT ("Print3") ;
        
TCHAR              szCaption[] = TEXT ("Print Program 3 (Dialog Box)") ;
        

BOOL bUserAbort ;
        
HWND hDlgPrint ;
        

BOOL CALLBACK PrintDlgProc (HWND hDlg, UINT message,
        
                           WPARAM wParam, LPARAM lParam)
        
{
        
           switch (message)
        
           {
        
    case   WM_INITDIALOG:
        
                          SetWindowText (hDlg, szAppName) ;
        
                          EnableMenuItem (GetSystemMenu (hDlg, FALSE), SC_CLOSE, MF_GRAYED) ;
        
                          return TRUE ;
        
        
        
           case   WM_COMMAND:
        
                          bUserAbort = TRUE ;
        
                          EnableWindow (GetParent (hDlg), TRUE) ;
        
                          DestroyWindow (hDlg) ;
        
                          hDlgPrint = NULL ;
        
                        return TRUE ;
        
           }
        
           return FALSE ;
        
}
        

BOOL CALLBACK AbortProc (HDC hdcPrn, int iCode)
        
{
        
           MSG msg ;
        
           while (!bUserAbort && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
        
           {
        
                  if (!hDlgPrint || !IsDialogMessage (hDlgPrint, &msg))
        
                  {
        
                                  TranslateMessage (&msg) ;
        
                                  DispatchMessage (&msg) ;
        
                 }
        
           }
        
  return !bUserAbort ;
        
}
        

BOOL PrintMyPage (HWND hwnd)
        
{
        
           static DOCINFO di = { sizeof (DOCINFO), TEXT ("Print3: Printing") } ;
        
           BOOL                          bSuccess = TRUE ;
        
           HDC                           hdcPrn ;
        
           int                           xPage, yPage ;
        
   
        
           if (NULL == (hdcPrn = GetPrinterDC ()))
        
                          return FALSE ;
        
           xPage = GetDeviceCaps (hdcPrn, HORZRES) ;
        
           yPage = GetDeviceCaps (hdcPrn, VERTRES) ;
        
   
        
           EnableWindow (hwnd, FALSE) ;
        
           bUserAbort = FALSE ;
        
           hDlgPrint = CreateDialog (hInst, TEXT ("PrintDlgBox"),
        
                                                                       hwnd, PrintDlgProc) ;
        
   SetAbortProc (hdcPrn, AbortProc) ;
        
           if (StartDoc (hdcPrn, &di) > 0)
        
           {
        
                  if (StartPage (hdcPrn) > 0)
        
                  {
        
                                  PageGDICalls (hdcPrn, xPage, yPage) ;
        
                                         if (EndPage (hdcPrn) > 0)
        
                                                         EndDoc (hdcPrn) ;
        
                                  else
        
                                         bSuccess = FALSE ;
        
                  }
        
           }
        
           else
        
                                  bSuccess = FALSE ;
        
           if (!bUserAbort)
        
    {
        
                          EnableWindow (hwnd, TRUE) ;
        
                         DestroyWindow (hDlgPrint) ;
        
    }
        
   
        
  DeleteDC (hdcPrn) ;
        
   return bSuccess && !bUserAbort ;
        
}
        
PRINT.RC (摘錄)
        
//Microsoft Developer Studio generated resource script.
        
#include "resource.h"
        
#include "afxres.h"
        
/////////////////////////////////////////////////////////////////////////////
        
// Dialog
        
PRINTDLGBOX DIALOG DISCARDABLE  20, 20, 186, 63
        
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
        
FONT 8, "MS Sans Serif"
        
BEGIN
        
   PUSHBUTTON                           "Cancel",IDCANCEL,67,42,50,14
        
   CTEXT                                                "Cancel Printing",IDC_STATIC,7,21,172,8
        
END
        

如果您使用PRINT3,那么最好臨時暫停使用后臺打印;否則,只有在打印隊列程序從PRINT3中接收數據時才可見到的「Cancel」按鈕可能會很快消失,讓您根本沒有機會去按它。如果您按「Cancel」按鈕時打印并不立即終止(特別是在一個慢速打印機上),不要驚訝。打印機有一個內部緩沖區,在打印機停止之前其中的數據必須全部送出,按「Cancel」只是告訴GDI不要向打印機的緩沖區發送更多的數據而已。

PRINT3增加了兩個整體變量:一個是叫做bUserAbort的布爾變量,另一個是叫做hDlgPrint的對話框窗口句柄。PrintMyPage函數將bUserAbort初始化為FALSE。與PRINT2一樣,程序的主窗口是不接收輸入消息的。指向AbortProc的指標用于SetAbortProc呼叫中,而指向PrintDlgProc的指標用于CreateDialog呼叫中。CreateDialog傳回的窗口句柄儲存在hDlgPrint中。

現在,AbortProc中的消息循環如下:

while (!bUserAbort && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
        
{
        
           if (!hDlgPrint || !IsDialogMessage (hDlgPrint, &msg))
        
          {
        
                  TranslateMessage (&msg) ;
        
                  DispatchMessage (&msg) ;
        
           }
        
}
        
return !bUserAbort ;
        

只有在bUserAbort為FALSE,也就是使用者還沒有終止打印工作時,這段程序代碼才會呼叫PeekMessage。IsDialogMessage函數用來將消息發送給非系統模態對話框。和普通的非系統模態對話框一樣,對話框窗口的句柄在這個呼叫之前受到檢查。AbortProc的傳回值正好與bUserAbort相反。開始時,bUserAbort為FALSE,因此AbortProc傳回TRUE,表示繼續進行打印;但是bUserAbort可能在打印對話程序中被設定為TRUE。

PrintDlgProc函數是相當簡單的。處理WM_INITDIALOG時,該函數將窗口標題設定為程序名稱,并且停用系統菜單上的「Close」選項。如果使用者按下了「Cancel」鈕,PrintDlgProc將收到WM_COMMAND消息:

case        WM_COMMAND :
        
           bUserAbort = TRUE ;
        
           EnableWindow (GetParent (hDlg), TRUE) ;
        
           DestroyWindow (hDlg) ;
        
           hDlgPrint = NULL ;
        
           return TRUE ;
        

將bUserAbort設定為TRUE,則說明使用者已經決定取消打印操作,主窗口被啟動,而對話框被清除(按順序完成這兩項活動是很重要的,否則,在Windows中執行其它程序之一將變成活動程序,而您的程序將消失到背景中)。與通常的情況一樣,將hDlgPrint設定為NULL,防止在消息循環中呼叫IsDialogMessage。

只有在AbortProc用PeekMessage找到消息,并用IsDialogMessage將它們傳送給對話框窗口消息處理程序時,這個對話框才接收消息。只有在GDI模塊處理EndPage函數時,才呼叫AbortProc。如果GDI發現AbortProc的傳回值是FALSE,它將控制權從EndPage傳回到PrintMyPage。它不傳回錯誤碼。至此,PrintMyPage認為打印頁已經發完了,并呼叫EndDoc函數。但是,由于GDI模塊還沒有完成對EndPage呼叫的處理,所以不會打印出什么東西來。

有些清除工作尚待完成。如果使用者沒在對話框中取消打印作業,那么對話框仍然會顯示著。PrintMyPage重新啟用它的主窗口并清除對話框:

if (!bUserAbort)
        
{
        
    EnableWindow (hwnd, TRUE) ;
        
    DestroyWindow (hDlgPrint) ;
        
}
        

兩個變量會通知您發生了什么事:bUserAbort可以告訴您使用者是否終止了打印作業,bSuccess會告訴您是否出了故障,您可以用這些變量來完成想做的工作。PrintMyPage只簡單地對它們進行邏輯上的AND運算,然后把值傳回給WndProc:

return bSuccess && !bUserAbort ;
        

為POPPAD增加打印功能

現在準備在POPPAD程序中增加打印功能,并且宣布POPPAD己告完畢。這需要第十一章中的各個POPPAD文件,此外,還需要程序13-8中的POPPRNT.C文件。

程序13-8 POPPRNT

        
POPPRNT.C
        
/*---------------------------------------------------------------------
        
  POPPRNT.C -- Popup Editor Printing Functions
        
-----------------------------------------------------------------------*/
        
#include <windows.h>
        
#include <commdlg.h>
        
#include "resource.h"
        

BOOL bUserAbort ;
        
HWND hDlgPrint ;
        

BOOL CALLBACK PrintDlgProc (       HWND hDlg, UINT msg, WPARAM wParam,LPARAM lParam)
        
{
        
           switch (msg)
        
           {
        
           case   WM_INITDIALOG :
        
                          EnableMenuItem (GetSystemMenu (hDlg, FALSE), SC_CLOSE, MF_GRAYED) ;
        
                          return TRUE ;
        
        
        
           case   WM_COMMAND :
        
                          bUserAbort = TRUE ;
        
                          EnableWindow (GetParent (hDlg), TRUE) ;
        
                          DestroyWindow (hDlg) ;
        
                          hDlgPrint = NULL ;
        
                          return TRUE ;
        
           }
        
           return FALSE ;
        
}       
        

BOOL CALLBACK AbortProc (HDC hPrinterDC, int iCode)
        
{
        
           MSG msg ;
        
           while (!bUserAbort && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
        
           {
        
                  if (!hDlgPrint || !IsDialogMessage (hDlgPrint, &msg))
        
                  {
        
                                  TranslateMessage (&msg) ;
        
                                  DispatchMessage (&msg) ;
        
                  }
        
           }
        
           return !bUserAbort ;
        
}
        

BOOL PopPrntPrintFile (HINSTANCE hInst, HWND hwnd, HWND hwndEdit,
        
                                                                                PTSTR szTitleName)
        
{
        
           static DOCINFO        di = { sizeof (DOCINFO) } ;
        
           static PRINTDLG       pd ;
        
           BOOL                  bSuccess ;
        
           int                   yChar, iCharsPerLine, iLinesPerPage, iTotalLines,
        
                                  iTotalPages, iPage, iLine, iLineNum ;
        
           PTSTR                 pstrBuffer ;
        
           TCHAR                 szJobName [64 + MAX_PATH] ;
        
           TEXTMETRIC            tm ;
        
           WORD                  iColCopy, iNoiColCopy ;
        

                                  // Invoke Print common dialog box
        
   
        
           pd.lStructSize                =      sizeof (PRINTDLG) ;
        
           pd.hwndOwner                  =      hwnd ;
        
           pd.hDevMode                   =      NULL ;
        
           pd.hDevNames                  =      NULL ;
        
           pd.hDC                        =      NULL ;
        
           pd.Flags                      =      PD_ALLPAGES | PD_COLLATE |
        
                                   PD_RETURNDC | PD_NOSELECTION ;
        
           pd.nFromPage                  =      0 ;
        
           pd.nToPage                    =      0 ;
        
           pd.nMinPage                   =      0 ;
        
           pd.nMaxPage                   =      0 ;
        
           pd.nCopies                    =      1 ;
        
           pd.hInstance                  =      NULL ;
        
           pd.lCustData                  =      0L ;
        
           pd.lpfnPrintHook              =      NULL ;
        
           pd.lpfnSetupHook              =      NULL ;
        
           pd.lpPrintTemplateName        =      NULL ;
        
           pd.lpSetupTemplateName        =      NULL ;
        
           pd.hPrintTemplate             =      NULL ;
        
           pd.hSetupTemplate             =      NULL ;
        
   
        
  if     (!PrintDlg (&pd))
        
                          return TRUE ;
        
   
        
  if     (0 == (iTotalLines = SendMessage (hwndEdit, EM_GETLINECOUNT, 0, 0)))
        
                          return TRUE ;
        

                                  // Calculate necessary metrics for file
        
   
        
           GetTextMetrics (pd.hDC, &tm) ;
        
           yChar = tm.tmHeight + tm.tmExternalLeading ;
        
   
        
           iCharsPerLine = GetDeviceCaps (pd.hDC, HORZRES) / tm.tmAveCharWidth ;
        
           iLinesPerPage = GetDeviceCaps (pd.hDC, VERTRES) / yChar ;
        
    iTotalPages   = (iTotalLines + iLinesPerPage - 1) / iLinesPerPage ;
        

                                  // Allocate a buffer for each line of text
        
   
        
           pstrBuffer    = malloc (sizeof (TCHAR) * (iCharsPerLine + 1)) ;
        

                                  // Display the printing dialog box
        
   
        
           EnableWindow (hwnd, FALSE) ;
        
           bSuccess                      = TRUE ;
        
           bUserAbort            = FALSE ;
        

           hDlgPrint             = CreateDialog (hInst, TEXT ("PrintDlgBox"),
        
                                                                                hwnd, PrintDlgProc) ;
        

           SetDlgItemText (hDlgPrint, IDC_FILENAME, szTitleName) ;
        
          SetAbortProc (pd.hDC, AbortProc) ;
        

                                  // Start the document
        
           GetWindowText (hwnd, szJobName, sizeof (szJobName)) ;
        
           di.lpszDocName = szJobName ;
        
           if (StartDoc (pd.hDC, &di) > 0)
        
           {
        
                                         // Collation requires this loop and iNoiColCopy
        
                  for (iColCopy = 0 ;
        
                                         iColCopy < ((WORD) pd.Flags & PD_COLLATE ? pd.nCopies : 1) ;
        
                                         iColCopy++)
        
                  {
        
                                  for (iPage = 0 ; iPage < iTotalPages ; iPage++)
        
                                  {
        
               for (iNoiColCopy = 0 ;
        
                    iNoiColCopy < (pd.Flags & PD_COLLATE ? 1 : pd.nCopies);
        
                                                                iNoiColCopy++)
        
                                         {
        
                                                                      // Start the page
        
                                                         if (StartPage (pd.hDC) < 0)
        
                                                         {
        
                                                                                bSuccess = FALSE ;
        
                                                                                break ;
        
                                                         }
        

              // For each page, print the lines
        
              for (iLine = 0 ; iLine < iLinesPerPage ; iLine++)
        
                                                         {
        
               iLineNum = iLinesPerPage * iPage + iLine ;
        
               if (iLineNum > iTotalLines)
        
                                                              break ;
        
               *(int *) pstrBuffer = iCharsPerLine ;
        
               TextOut    (pd.hDC, 0, yChar * iLine, pstrBuffer,
        
               (int) SendMessage (hwndEdit, EM_GETLINE,
        
                   (WPARAM) iLineNum, (LPARAM) pstrBuffer));
        
                                                               }
        
                           
        
                if (EndPage (pd.hDC) < 0)
        
                                                                {
        
                 bSuccess = FALSE ;
        
                 break ;
        
                                                                }
        
                      
        
                 if (bUserAbort)
        
                break ;
        
                                                         }
        
                  
        
                 if (!bSuccess || bUserAbort)
        
                 break ;
        
                                         }
        
             
        
                  if (!bSuccess || bUserAbort)
        
                 break ;
        
                          }
        
   }
        
           else
        
                          bSuccess = FALSE ;
        
          if     (bSuccess)
        
                          EndDoc (pd.hDC) ;
        
          
        
           if     (!bUserAbort)
        
    {
        
                          EnableWindow (hwnd, TRUE) ;
        
                          DestroyWindow (hDlgPrint) ;
        
           }
        
   
        
           free (pstrBuffer) ;
        
           DeleteDC (pd.hDC) ;
        
   
        
           return bSuccess && !bUserAbort ;
        
}
        

與POPPAD盡量利用Windows高階功能來簡化程序的方針一致,POPPRNT.C文件展示了使用PrintDlg函數的方法。這個函數包含在通用對話框鏈接庫(common dialog box library)中,使用一個PRINTDLG型態的結構。

通常,程序的「File」菜單中有個「Print」選項。當使用者選中「Print」選項時,程序可以初始化PRINTDLG結構的字段,并呼叫PrintDlg。

PrintDlg顯示一個對話框,它允許使用者選擇打印頁的范圍。因此,這個對話框特別適用于像POPPAD這樣能打印多頁文件的程序。這種對話框同時也給出了一個確定副本份數的編輯區和名為「Collate(逐份打印)」的復選框。「逐份打印」影響著多個副本頁的順序。例如,如果文件是3頁,使用者要求打印三份副本,則這個程序能以兩種順序之一打印它們。選擇逐份打印后的副本的頁碼順序為1、2、3、1、2、3、1、2、3,未選擇逐份打印的副本的頁碼順序是1、1、1、2、2、2、3、3、3。程序在這里應負起的責任就是以正確的順序打印副本。

這個對話框也允許使用者選擇非內定打印機,它包括一個標記為「Properties」的按鈕,可以啟動設備模式對話框。這樣,至少允許使用者選擇直印或橫印。

從PrintDlg函數傳回后,PRINTDLG結構的字段指明打印頁的范圍和是否對多個副本進行逐份打印。這個結構同時也給出了準備使用的打印機設備內容句柄。

在POPPRNT.C中,PopPrntPrintFile函數(當使用者在「File」菜單里選中「Print」選項時,它由POPPAD呼叫)呼叫PrintDlg,然后開始打印文件。PopPrntPrintFile完成某些計算,以確定一行能容納多少字符和一頁能容納多少行。這個程序涉及到呼叫GetDeviceCaps來確定頁的分辨率,呼叫GetTextMetrics來確定字符的大小。

這個程序通過發送一條EM_GETLINECOUNT消息給編輯控件來取得文件中的總行數(在變量iTotalLines中)。儲存各行內容的緩沖區配置在局部內存中。對每一行,緩沖區的第一個字被設定為該行中字符的數目。把EM_GETLINE消息發送給編輯控件可以把一行復制到緩沖區中,然后用TextOut把這一行送到打印機設備內容中(POPPRNT.C還沒有聰明到對超出打印寬度的文字換到下一行去處理。在 第十七章我們會討論這種文字繞行的技術)。

為了確定副本份數,應注意打印文字的處理方式包括兩個for循環。第一個for循環使用了一個叫作iColCopy的變量,當使用者指定將副本逐份打印時,它將會起作用。第二個for循環使用了一個叫作iNonColCopy的變量,當不對副本進行逐份打印時,它將起作用。

如果StartPage或EndPage傳回一個錯誤,或者如果bUserAbort為TRUE,那么這個程序退出增加頁號的那個for循環。如果放棄程序的傳回值是FALSE,則EndPage不傳回錯誤。正是由于這個原因,在下一頁開始之前,要直接測試bUserAbort。如果沒有報告錯誤,則進行EndDoc呼叫:

if (!bError)
        
           EndDoc (hdcPrn) ;
        

您可能想通過打印多頁文件來測試POPPAD。您可以從打印任務窗口中監視打印進展情況。在GDI處理完第一個EndPage呼叫之后,首先打印的文件將顯示在打印任務窗口中。此時,后臺打印程序開始把文件發送到打印機。然后,如果在POPPAD中取消打印作業,那么后臺打印程序將終止打印,這也就是放棄程序傳回FALSE的結果。當文件出現在打印任務窗口中,您也可以透過從「Document」菜單中選擇「Cancel Printing」來取消打印作業,在這種情況下, POPPAD中的EndPage呼叫會傳回一個錯誤。

Windows的程序設計的新手經常會抱住AbortDoc函數不放,但實際上這個函數幾乎不在打印中使用。像在POPPAD中看到的那樣,使用者幾乎隨時可以取消打印作業,或者通過POPPAD的打印對話框及通過打印任務窗口。這兩種方法都不需要程序使用AbortDoc函數。 POPPAD中允許AbortDoc的唯一時刻是在對StartDoc的呼叫和對EndPage的第一個呼叫之間,但是程序很快就會執行過去,以至不再需要AbortDoc。

圖13-3顯示出正確打印多頁文件之打印函數的呼叫順序。檢查bUserAbort的值是否為TRUE的最佳位置是在每個EndPage函數之后。只有當對先前的打印函數的呼叫沒有產生錯誤時,才使用EndDoc函數。實際上,如果任何一個打印函數的呼叫出現錯誤,那么表演就結束了,同時您也可以回家了。

 

圖13-3 打印一個文件時的函數呼叫順序

 

總結

以上是生活随笔為你收集整理的教你怎么使用打印机(api)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

天堂久久天堂av色综合 | 精品久久久无码中文字幕 | 一本无码人妻在中文字幕免费 | 国产麻豆精品精东影业av网站 | 狠狠色色综合网站 | 亚洲精品无码人妻无码 | 日韩欧美中文字幕在线三区 | 亚洲午夜久久久影院 | 少妇久久久久久人妻无码 | 东京热无码av男人的天堂 | 欧美乱妇无乱码大黄a片 | 捆绑白丝粉色jk震动捧喷白浆 | 日欧一片内射va在线影院 | 午夜福利试看120秒体验区 | 蜜臀aⅴ国产精品久久久国产老师 | 无套内谢的新婚少妇国语播放 | 色五月五月丁香亚洲综合网 | 国产农村妇女高潮大叫 | 国产亚洲精品精品国产亚洲综合 | 国产性生交xxxxx无码 | 午夜福利电影 | 丰满少妇女裸体bbw | 国产艳妇av在线观看果冻传媒 | 一本精品99久久精品77 | 久久zyz资源站无码中文动漫 | 又粗又大又硬又长又爽 | 最近的中文字幕在线看视频 | 亚洲精品欧美二区三区中文字幕 | 桃花色综合影院 | 亚洲综合另类小说色区 | 国产激情精品一区二区三区 | 国产午夜福利亚洲第一 | 亚洲熟女一区二区三区 | 国产特级毛片aaaaaa高潮流水 | 人妻中文无码久热丝袜 | 九九在线中文字幕无码 | 精品久久久无码中文字幕 | 亚洲精品一区二区三区在线 | 国产 浪潮av性色四虎 | 99久久久无码国产精品免费 | 中文无码成人免费视频在线观看 | 丰满妇女强制高潮18xxxx | 国产精品久久久久久亚洲毛片 | 国产真实伦对白全集 | 国产无套粉嫩白浆在线 | 久久婷婷五月综合色国产香蕉 | 亚洲一区二区三区偷拍女厕 | 久久伊人色av天堂九九小黄鸭 | 麻豆国产人妻欲求不满谁演的 | 一本久道久久综合狠狠爱 | 欧美日韩人成综合在线播放 | 国语精品一区二区三区 | 久久精品人妻少妇一区二区三区 | 波多野结衣aⅴ在线 | 男人扒开女人内裤强吻桶进去 | 老司机亚洲精品影院 | 亚洲另类伦春色综合小说 | 欧美人与牲动交xxxx | 欧美放荡的少妇 | 色综合视频一区二区三区 | 国产9 9在线 | 中文 | 国产精品久久久久久久影院 | 精品人人妻人人澡人人爽人人 | 中文字幕亚洲情99在线 | 亚洲精品午夜无码电影网 | 日韩人妻系列无码专区 | 国产免费无码一区二区视频 | 亚洲毛片av日韩av无码 | 欧美人与善在线com | 久久综合狠狠综合久久综合88 | 国产精品-区区久久久狼 | 国产一精品一av一免费 | 色五月五月丁香亚洲综合网 | 日本精品少妇一区二区三区 | 在线天堂新版最新版在线8 | 国产人妻久久精品二区三区老狼 | 精品国精品国产自在久国产87 | 99视频精品全部免费免费观看 | 国产乡下妇女做爰 | 色五月丁香五月综合五月 | 婷婷五月综合缴情在线视频 | 一本一道久久综合久久 | 国内精品人妻无码久久久影院 | 久久久无码中文字幕久... | 国产成人综合色在线观看网站 | 97夜夜澡人人双人人人喊 | 欧美怡红院免费全部视频 | 性啪啪chinese东北女人 | 狠狠亚洲超碰狼人久久 | 天堂亚洲2017在线观看 | 日韩精品无码一本二本三本色 | 一本大道久久东京热无码av | aa片在线观看视频在线播放 | 国精品人妻无码一区二区三区蜜柚 | 99久久精品日本一区二区免费 | 欧洲vodafone精品性 | 老熟妇乱子伦牲交视频 | 狠狠躁日日躁夜夜躁2020 | 少妇无码一区二区二三区 | 香港三级日本三级妇三级 | 在线看片无码永久免费视频 | 精品无码国产一区二区三区av | 国产精品内射视频免费 | 午夜福利试看120秒体验区 | 久久视频在线观看精品 | 欧美 日韩 亚洲 在线 | 午夜福利不卡在线视频 | 国内精品久久毛片一区二区 | 国产无套粉嫩白浆在线 | 一本色道久久综合亚洲精品不卡 | 日韩成人一区二区三区在线观看 | 久久亚洲日韩精品一区二区三区 | 青青青爽视频在线观看 | 国产亚洲tv在线观看 | 亚洲国产精品久久久天堂 | 乱人伦人妻中文字幕无码久久网 | 又粗又大又硬毛片免费看 | 亚洲日韩精品欧美一区二区 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 国产成人无码av片在线观看不卡 | 88国产精品欧美一区二区三区 | 任你躁在线精品免费 | 国产亲子乱弄免费视频 | 久久综合给合久久狠狠狠97色 | 日产精品高潮呻吟av久久 | 午夜无码区在线观看 | 精品人妻人人做人人爽夜夜爽 | aⅴ亚洲 日韩 色 图网站 播放 | 精品无码国产一区二区三区av | 又紧又大又爽精品一区二区 | 亚洲人成网站免费播放 | 亚洲日本一区二区三区在线 | 少妇高潮一区二区三区99 | 久久精品女人的天堂av | 国产精品久久久 | 亚洲精品久久久久久一区二区 | 亚洲成av人影院在线观看 | 亚洲精品无码国产 | 午夜福利不卡在线视频 | 国产精品亚洲lv粉色 | 国产精品理论片在线观看 | 国产真实伦对白全集 | 性色欲网站人妻丰满中文久久不卡 | 精品欧美一区二区三区久久久 | 精品夜夜澡人妻无码av蜜桃 | av在线亚洲欧洲日产一区二区 | 亚洲熟妇色xxxxx亚洲 | 精品无码av一区二区三区 | 国产亚洲精品久久久久久久 | 国产精品手机免费 | 又湿又紧又大又爽a视频国产 | 国产精品亚洲综合色区韩国 | 精品一区二区三区波多野结衣 | 国产在线精品一区二区高清不卡 | 一本色道久久综合狠狠躁 | 欧美丰满老熟妇xxxxx性 | 亚洲国产午夜精品理论片 | 日韩av无码中文无码电影 | 国产亚洲视频中文字幕97精品 | 国产亚洲精品久久久久久大师 | 国产乱人伦av在线无码 | 男人的天堂2018无码 | 特级做a爰片毛片免费69 | 天堂а√在线中文在线 | 日日碰狠狠躁久久躁蜜桃 | 在线亚洲高清揄拍自拍一品区 | 国产精品人人妻人人爽 | 一个人看的视频www在线 | 亚洲欧美日韩成人高清在线一区 | 国产精品无码久久av | 人妻aⅴ无码一区二区三区 | 日本精品久久久久中文字幕 | 乌克兰少妇性做爰 | 中文字幕无码av波多野吉衣 | 日韩少妇内射免费播放 | 给我免费的视频在线观看 | 99久久精品国产一区二区蜜芽 | 久久精品人妻少妇一区二区三区 | 亚洲精品综合一区二区三区在线 | 国产亚洲精品久久久久久 | 亚洲欧洲日本综合aⅴ在线 | 国产乱人无码伦av在线a | 美女黄网站人色视频免费国产 | 精品午夜福利在线观看 | 精品成在人线av无码免费看 | 午夜精品久久久久久久 | 亚洲国产一区二区三区在线观看 | 国产免费久久久久久无码 | 老头边吃奶边弄进去呻吟 | 少妇人妻偷人精品无码视频 | 国产av人人夜夜澡人人爽麻豆 | 国产亚洲人成在线播放 | 未满小14洗澡无码视频网站 | 婷婷六月久久综合丁香 | 日本熟妇乱子伦xxxx | 性欧美牲交xxxxx视频 | 国产精品无码一区二区桃花视频 | aa片在线观看视频在线播放 | 波多野结衣 黑人 | 国产一区二区三区精品视频 | 激情五月综合色婷婷一区二区 | 国产精品办公室沙发 | 97se亚洲精品一区 | 国产av无码专区亚洲awww | 日本va欧美va欧美va精品 | 欧美黑人性暴力猛交喷水 | 正在播放老肥熟妇露脸 | 精品无码成人片一区二区98 | 国产精品嫩草久久久久 | 欧美乱妇无乱码大黄a片 | 97夜夜澡人人双人人人喊 | 亚洲精品一区二区三区在线观看 | 亚洲人交乣女bbw | 国产精品久久久久久亚洲影视内衣 | 丰满肥臀大屁股熟妇激情视频 | 国产av无码专区亚洲a∨毛片 | 亚洲a无码综合a国产av中文 | 欧美人与动性行为视频 | 99久久无码一区人妻 | 日韩欧美中文字幕公布 | 99精品久久毛片a片 | 国产一区二区三区精品视频 | 亚洲精品国产精品乱码视色 | 中文精品无码中文字幕无码专区 | 97夜夜澡人人双人人人喊 | 丰满肥臀大屁股熟妇激情视频 | 国产精华av午夜在线观看 | 99久久精品国产一区二区蜜芽 | 亚洲中文字幕无码一久久区 | 超碰97人人射妻 | 日本欧美一区二区三区乱码 | 国产精品亚洲а∨无码播放麻豆 | 国产偷国产偷精品高清尤物 | 国产亚av手机在线观看 | 国产精品99久久精品爆乳 | 久久综合狠狠综合久久综合88 | 狂野欧美激情性xxxx | 麻豆人妻少妇精品无码专区 | 97精品国产97久久久久久免费 | 无码人妻久久一区二区三区不卡 | 中文无码精品a∨在线观看不卡 | 欧美真人作爱免费视频 | 中文字幕人妻丝袜二区 | 东京热无码av男人的天堂 | 内射老妇bbwx0c0ck | 国产亚洲精品久久久久久久久动漫 | 蜜臀aⅴ国产精品久久久国产老师 | 少妇无码av无码专区在线观看 | 国产又粗又硬又大爽黄老大爷视 | 狂野欧美激情性xxxx | 熟妇人妻无乱码中文字幕 | 亚洲无人区一区二区三区 | 少妇性俱乐部纵欲狂欢电影 | 欧美国产亚洲日韩在线二区 | 377p欧洲日本亚洲大胆 | 亚洲 激情 小说 另类 欧美 | 亚洲自偷精品视频自拍 | 天堂无码人妻精品一区二区三区 | 日本va欧美va欧美va精品 | 中文毛片无遮挡高清免费 | 一二三四社区在线中文视频 | 奇米影视7777久久精品人人爽 | 久久久久人妻一区精品色欧美 | 少妇无套内谢久久久久 | 99国产欧美久久久精品 | 中文无码伦av中文字幕 | 国产精品亚洲综合色区韩国 | 精品成人av一区二区三区 | 色妞www精品免费视频 | 一本久道高清无码视频 | 精品偷自拍另类在线观看 | 熟女体下毛毛黑森林 | 天天综合网天天综合色 | 澳门永久av免费网站 | 亚洲热妇无码av在线播放 | √天堂资源地址中文在线 | 天海翼激烈高潮到腰振不止 | 精品国产福利一区二区 | 成人av无码一区二区三区 | av小次郎收藏 | 国产在线精品一区二区高清不卡 | 亚洲中文字幕无码中文字在线 | 国产精品99久久精品爆乳 | 中文字幕乱码人妻无码久久 | 亚洲色欲久久久综合网东京热 | 午夜精品一区二区三区的区别 | 大地资源中文第3页 | 久久久精品欧美一区二区免费 | 人妻中文无码久热丝袜 | 午夜无码人妻av大片色欲 | 欧美黑人乱大交 | 亚洲爆乳大丰满无码专区 | 亚洲熟妇自偷自拍另类 | 蜜桃视频韩日免费播放 | 国内精品人妻无码久久久影院蜜桃 | 最近免费中文字幕中文高清百度 | 色婷婷香蕉在线一区二区 | 亚洲综合无码一区二区三区 | 少妇性荡欲午夜性开放视频剧场 | 国产精品香蕉在线观看 | 国产午夜福利100集发布 | 国产精品va在线观看无码 | 亚洲爆乳精品无码一区二区三区 | 少妇性俱乐部纵欲狂欢电影 | 国产午夜亚洲精品不卡下载 | 亚洲日本在线电影 | 国产成人一区二区三区在线观看 | 人人妻人人澡人人爽欧美一区九九 | 国产免费久久精品国产传媒 | 搡女人真爽免费视频大全 | 日韩精品无码一区二区中文字幕 | 国产综合色产在线精品 | 久久久精品欧美一区二区免费 | 欧美丰满老熟妇xxxxx性 | 久激情内射婷内射蜜桃人妖 | 欧美人妻一区二区三区 | 日本va欧美va欧美va精品 | 一本大道久久东京热无码av | 久久人人97超碰a片精品 | 国产高清av在线播放 | 成年美女黄网站色大免费视频 | 四虎影视成人永久免费观看视频 | 无码精品国产va在线观看dvd | 亚洲乱码国产乱码精品精 | 特黄特色大片免费播放器图片 | 免费网站看v片在线18禁无码 | 久久天天躁狠狠躁夜夜免费观看 | 99在线 | 亚洲 | 中文字幕无码日韩欧毛 | 欧美阿v高清资源不卡在线播放 | 红桃av一区二区三区在线无码av | 97se亚洲精品一区 | 麻豆人妻少妇精品无码专区 | 欧美日本精品一区二区三区 | 欧美丰满老熟妇xxxxx性 | 国产成人精品一区二区在线小狼 | 国产成人无码av片在线观看不卡 | 性色欲网站人妻丰满中文久久不卡 | 最近中文2019字幕第二页 | 久久久久免费精品国产 | 国产后入清纯学生妹 | 国产人妻久久精品二区三区老狼 | 国产人妻人伦精品 | 日日噜噜噜噜夜夜爽亚洲精品 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 无码纯肉视频在线观看 | 黑人巨大精品欧美一区二区 | 爽爽影院免费观看 | 亚洲 激情 小说 另类 欧美 | 色婷婷欧美在线播放内射 | 国产精品久久久av久久久 | 国产偷国产偷精品高清尤物 | 婷婷丁香六月激情综合啪 | 四虎影视成人永久免费观看视频 | 兔费看少妇性l交大片免费 | 日本熟妇人妻xxxxx人hd | 麻豆成人精品国产免费 | 麻豆国产人妻欲求不满谁演的 | 欧美成人午夜精品久久久 | 国产午夜无码视频在线观看 | 99久久无码一区人妻 | 亚洲精品欧美二区三区中文字幕 | 国产成人久久精品流白浆 | 色婷婷久久一区二区三区麻豆 | 久久久久久九九精品久 | 久久久久久a亚洲欧洲av冫 | 婷婷丁香六月激情综合啪 | 精品人妻人人做人人爽夜夜爽 | 国产激情一区二区三区 | 欧美 丝袜 自拍 制服 另类 | 伦伦影院午夜理论片 | 人人妻人人澡人人爽人人精品浪潮 | 鲁鲁鲁爽爽爽在线视频观看 | 四虎国产精品一区二区 | 亚洲精品久久久久久久久久久 | 国产肉丝袜在线观看 | 国产成人一区二区三区在线观看 | 在线a亚洲视频播放在线观看 | 亚洲中文字幕va福利 | 国产av无码专区亚洲awww | 国产精品无套呻吟在线 | 又大又紧又粉嫩18p少妇 | 国模大胆一区二区三区 | 精品无码一区二区三区的天堂 | 九一九色国产 | 久久午夜无码鲁丝片 | 亚洲欧美日韩国产精品一区二区 | 桃花色综合影院 | 欧美精品一区二区精品久久 | 宝宝好涨水快流出来免费视频 | 狂野欧美性猛交免费视频 | 正在播放老肥熟妇露脸 | 男人的天堂2018无码 | 日本精品久久久久中文字幕 | 天天躁日日躁狠狠躁免费麻豆 | 国产亚洲精品久久久闺蜜 | 欧洲vodafone精品性 | 思思久久99热只有频精品66 | 乱码av麻豆丝袜熟女系列 | 大色综合色综合网站 | 特黄特色大片免费播放器图片 | 国产精华av午夜在线观看 | 欧美日韩一区二区三区自拍 | 国产欧美亚洲精品a | 国产精品无码成人午夜电影 | 亚洲国产精品毛片av不卡在线 | 好爽又高潮了毛片免费下载 | 久久久久亚洲精品中文字幕 | 天天爽夜夜爽夜夜爽 | 丰满肥臀大屁股熟妇激情视频 | 伊人色综合久久天天小片 | 国产热a欧美热a在线视频 | 精品无码一区二区三区爱欲 | 曰本女人与公拘交酡免费视频 | 少妇性俱乐部纵欲狂欢电影 | 无码福利日韩神码福利片 | 国产情侣作爱视频免费观看 | 亚洲精品久久久久avwww潮水 | 国产色在线 | 国产 | 美女张开腿让人桶 | 亚洲爆乳精品无码一区二区三区 | 久久亚洲a片com人成 | 少妇的肉体aa片免费 | 亚洲精品一区二区三区婷婷月 | 美女黄网站人色视频免费国产 | 初尝人妻少妇中文字幕 | 亚洲日韩av一区二区三区中文 | 人人妻人人澡人人爽欧美一区九九 | 扒开双腿吃奶呻吟做受视频 | 色一情一乱一伦一区二区三欧美 | 欧美丰满老熟妇xxxxx性 | 天天综合网天天综合色 | 国内精品人妻无码久久久影院 | 亚洲国产欧美日韩精品一区二区三区 | 欧美猛少妇色xxxxx | 亚洲成色www久久网站 | 欧美熟妇另类久久久久久多毛 | 国产超碰人人爽人人做人人添 | 欧美三级a做爰在线观看 | 亚洲の无码国产の无码影院 | 中文字幕无码日韩欧毛 | 久久午夜夜伦鲁鲁片无码免费 | 初尝人妻少妇中文字幕 | 久久午夜无码鲁丝片午夜精品 | 97夜夜澡人人爽人人喊中国片 | 亚洲精品午夜无码电影网 | 色婷婷av一区二区三区之红樱桃 | 久久久久久av无码免费看大片 | 日产精品高潮呻吟av久久 | 精品国精品国产自在久国产87 | 久久亚洲国产成人精品性色 | 日韩av激情在线观看 | 日韩精品成人一区二区三区 | 牲欲强的熟妇农村老妇女 | 夜夜高潮次次欢爽av女 | 精品乱子伦一区二区三区 | 18禁黄网站男男禁片免费观看 | 成人亚洲精品久久久久 | 少妇性l交大片欧洲热妇乱xxx | 任你躁在线精品免费 | 久久久久免费精品国产 | 国产成人亚洲综合无码 | 三上悠亚人妻中文字幕在线 | 国产亚洲视频中文字幕97精品 | 四虎影视成人永久免费观看视频 | 中文亚洲成a人片在线观看 | 亚洲性无码av中文字幕 | 午夜福利不卡在线视频 | 亚洲日韩精品欧美一区二区 | 国产深夜福利视频在线 | 激情爆乳一区二区三区 | 色妞www精品免费视频 | 狠狠噜狠狠狠狠丁香五月 | 国产午夜福利亚洲第一 | 国产av久久久久精东av | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 一个人免费观看的www视频 | 亚洲精品中文字幕乱码 | 福利一区二区三区视频在线观看 | 18禁黄网站男男禁片免费观看 | 波多野结衣一区二区三区av免费 | 99久久婷婷国产综合精品青草免费 | 亚洲欧洲日本综合aⅴ在线 | 男人和女人高潮免费网站 | 久久久久国色av免费观看性色 | 88国产精品欧美一区二区三区 | 亚洲国产成人a精品不卡在线 | 欧洲vodafone精品性 | 熟女少妇人妻中文字幕 | 大地资源网第二页免费观看 | 欧美丰满熟妇xxxx性ppx人交 | 牛和人交xxxx欧美 | 女人高潮内射99精品 | 少妇无码av无码专区在线观看 | 四虎国产精品免费久久 | 性啪啪chinese东北女人 | 在线观看免费人成视频 | 男人和女人高潮免费网站 | 一本久道高清无码视频 | 2019nv天堂香蕉在线观看 | 樱花草在线播放免费中文 | 色综合久久久久综合一本到桃花网 | 日韩无码专区 | 亚洲精品成a人在线观看 | 精品国精品国产自在久国产87 | av人摸人人人澡人人超碰下载 | 亚洲国产精品一区二区第一页 | 国产人妻久久精品二区三区老狼 | 亚洲精品国产精品乱码不卡 | 粉嫩少妇内射浓精videos | 超碰97人人做人人爱少妇 | 国产真人无遮挡作爱免费视频 | 亚洲精品综合五月久久小说 | 97无码免费人妻超级碰碰夜夜 | 国产另类ts人妖一区二区 | 国产偷国产偷精品高清尤物 | 国产精品久久久午夜夜伦鲁鲁 | 精品国产av色一区二区深夜久久 | 久久视频在线观看精品 | 亚洲区小说区激情区图片区 | 在线亚洲高清揄拍自拍一品区 | 色综合久久久久综合一本到桃花网 | 国产香蕉97碰碰久久人人 | 国产网红无码精品视频 | 色一情一乱一伦一视频免费看 | 久久熟妇人妻午夜寂寞影院 | 国产精品.xx视频.xxtv | 女人和拘做爰正片视频 | 亚洲成色在线综合网站 | 国产成人精品久久亚洲高清不卡 | 乱人伦人妻中文字幕无码 | 精品国精品国产自在久国产87 | 亚洲精品国产品国语在线观看 | 夜夜夜高潮夜夜爽夜夜爰爰 | 中文字幕人妻无码一夲道 | 国内精品一区二区三区不卡 | 麻豆国产人妻欲求不满 | 欧美一区二区三区 | 沈阳熟女露脸对白视频 | 精品久久久久久人妻无码中文字幕 | 日日鲁鲁鲁夜夜爽爽狠狠 | 亚洲成a人片在线观看无码 | 牛和人交xxxx欧美 | 东北女人啪啪对白 | 狠狠色噜噜狠狠狠狠7777米奇 | 娇妻被黑人粗大高潮白浆 | 无码人妻av免费一区二区三区 | 人人妻人人澡人人爽欧美精品 | 中国女人内谢69xxxx | 精品厕所偷拍各类美女tp嘘嘘 | 欧美一区二区三区视频在线观看 | 亚洲春色在线视频 | 九月婷婷人人澡人人添人人爽 | 天堂а√在线地址中文在线 | 中文无码精品a∨在线观看不卡 | 久久亚洲中文字幕无码 | 欧美老妇交乱视频在线观看 | 国产精品对白交换视频 | 免费看男女做好爽好硬视频 | 亚洲第一网站男人都懂 | 理论片87福利理论电影 | 鲁大师影院在线观看 | 永久免费观看美女裸体的网站 | 亚洲精品综合一区二区三区在线 | av人摸人人人澡人人超碰下载 | 粗大的内捧猛烈进出视频 | 国产97人人超碰caoprom | 亚洲精品无码国产 | 亚洲日韩av一区二区三区四区 | 老司机亚洲精品影院无码 | 日韩av无码中文无码电影 | 国产精品久久久久无码av色戒 | 在线观看免费人成视频 | 人人妻人人藻人人爽欧美一区 | 亚洲国产精品美女久久久久 | 成人无码精品一区二区三区 | 人人妻人人澡人人爽欧美一区九九 | 欧美人妻一区二区三区 | 亚洲综合色区中文字幕 | 亚洲日韩精品欧美一区二区 | 2019nv天堂香蕉在线观看 | 精品国产一区av天美传媒 | 欧美日本精品一区二区三区 | 97色伦图片97综合影院 | 在线 国产 欧美 亚洲 天堂 | 精品人妻人人做人人爽夜夜爽 | 国产热a欧美热a在线视频 | 亚洲人成网站色7799 | 伊在人天堂亚洲香蕉精品区 | 色婷婷欧美在线播放内射 | 精品一区二区三区波多野结衣 | 成人精品一区二区三区中文字幕 | 久久久久人妻一区精品色欧美 | 在线天堂新版最新版在线8 | 亚洲日本一区二区三区在线 | 99久久人妻精品免费二区 | 欧美熟妇另类久久久久久不卡 | 国产在热线精品视频 | 动漫av一区二区在线观看 | 大地资源中文第3页 | 大肉大捧一进一出视频出来呀 | 无码乱肉视频免费大全合集 | 无码人妻丰满熟妇区五十路百度 | 狠狠色噜噜狠狠狠狠7777米奇 | 波多野结衣av一区二区全免费观看 | 欧美日本精品一区二区三区 | 亚洲欧洲日本综合aⅴ在线 | 精品成人av一区二区三区 | 天堂亚洲2017在线观看 | 国产精品手机免费 | 亚洲 激情 小说 另类 欧美 | 秋霞特色aa大片 | 婷婷色婷婷开心五月四房播播 | 日本熟妇人妻xxxxx人hd | 日本熟妇人妻xxxxx人hd | 亚洲一区二区观看播放 | 国产精品无码成人午夜电影 | 久久精品人人做人人综合试看 | 久久人妻内射无码一区三区 | 亚洲 高清 成人 动漫 | 成熟女人特级毛片www免费 | 亚洲精品午夜无码电影网 | 丝袜人妻一区二区三区 | 久久无码中文字幕免费影院蜜桃 | 未满小14洗澡无码视频网站 | 76少妇精品导航 | 丰满少妇高潮惨叫视频 | 小sao货水好多真紧h无码视频 | 日韩精品无码免费一区二区三区 | 国产香蕉尹人综合在线观看 | 红桃av一区二区三区在线无码av | 日本一卡2卡3卡四卡精品网站 | 中文无码精品a∨在线观看不卡 | 波多野结衣aⅴ在线 | 好男人www社区 | 欧美日韩一区二区综合 | 国产成人精品必看 | 日本精品人妻无码免费大全 | 亚洲一区二区三区含羞草 | 国产精品无码成人午夜电影 | 偷窥村妇洗澡毛毛多 | 少妇无套内谢久久久久 | 国产精品美女久久久网av | 亚洲精品国偷拍自产在线观看蜜桃 | 欧美老妇交乱视频在线观看 | 性欧美熟妇videofreesex | 在线天堂新版最新版在线8 | 亚洲精品国产品国语在线观看 | 少妇被粗大的猛进出69影院 | 国产av久久久久精东av | 红桃av一区二区三区在线无码av | 日日碰狠狠丁香久燥 | 午夜嘿嘿嘿影院 | 一本久道久久综合婷婷五月 | 偷窥村妇洗澡毛毛多 | 东京热一精品无码av | 亚洲午夜无码久久 | 一本色道久久综合亚洲精品不卡 | av人摸人人人澡人人超碰下载 | 色综合久久久无码中文字幕 | 欧美精品在线观看 | 亚洲爆乳精品无码一区二区三区 | 乱人伦中文视频在线观看 | 乌克兰少妇性做爰 | 国产另类ts人妖一区二区 | 国产一区二区不卡老阿姨 | 午夜性刺激在线视频免费 | 97久久精品无码一区二区 | 久久国产精品二国产精品 | 在线观看国产午夜福利片 | 无码av免费一区二区三区试看 | 精品国产精品久久一区免费式 | 精品国产福利一区二区 | 欧美 日韩 人妻 高清 中文 | 国产成人精品必看 | 久久精品中文闷骚内射 | 国产真人无遮挡作爱免费视频 | 免费观看又污又黄的网站 | 一二三四社区在线中文视频 | 成在人线av无码免观看麻豆 | 亚洲国精产品一二二线 | 国产又粗又硬又大爽黄老大爷视 | 97无码免费人妻超级碰碰夜夜 | 久久亚洲a片com人成 | 国产午夜无码精品免费看 | 国语精品一区二区三区 | 国产在线aaa片一区二区99 | 欧美激情综合亚洲一二区 | 午夜无码区在线观看 | 色一情一乱一伦 | 影音先锋中文字幕无码 | 国产成人精品优优av | 欧美一区二区三区 | 日韩精品一区二区av在线 | 又湿又紧又大又爽a视频国产 | 国产成人精品三级麻豆 | 国产另类ts人妖一区二区 | √8天堂资源地址中文在线 | 久久精品中文字幕大胸 | 九九热爱视频精品 | 无码一区二区三区在线 | 精品国产一区二区三区四区 | 日本又色又爽又黄的a片18禁 | 亚洲人亚洲人成电影网站色 | 亚洲中文字幕成人无码 | 欧美国产日韩久久mv | 国产一区二区不卡老阿姨 | 国模大胆一区二区三区 | 国产va免费精品观看 | 欧美黑人性暴力猛交喷水 | 波多野42部无码喷潮在线 | 成人免费视频在线观看 | 国产人妻久久精品二区三区老狼 | 国产无套粉嫩白浆在线 | 欧美一区二区三区 | 装睡被陌生人摸出水好爽 | 小泽玛莉亚一区二区视频在线 | 无遮挡啪啪摇乳动态图 | 色窝窝无码一区二区三区色欲 | 精品偷自拍另类在线观看 | 国产精品久久久久久久影院 | 国产乱人伦av在线无码 | 成人一在线视频日韩国产 | 乱人伦中文视频在线观看 | 亚洲乱码日产精品bd | 麻豆国产97在线 | 欧洲 | 国产精品va在线观看无码 | 久久精品国产99精品亚洲 | 曰本女人与公拘交酡免费视频 | 午夜不卡av免费 一本久久a久久精品vr综合 | 久久久久国色av免费观看性色 | 久久精品一区二区三区四区 | 日韩精品无码一本二本三本色 | 免费观看激色视频网站 | 成人免费视频视频在线观看 免费 | 亚洲成av人影院在线观看 | 亚洲国产欧美日韩精品一区二区三区 | 欧美日韩精品 | 亚洲男人av香蕉爽爽爽爽 | 亚洲色大成网站www | 国产乱子伦视频在线播放 | 色老头在线一区二区三区 | 任你躁国产自任一区二区三区 | 国产麻豆精品精东影业av网站 | 国产精品永久免费视频 | 图片区 小说区 区 亚洲五月 | 狠狠色欧美亚洲狠狠色www | 国产极品美女高潮无套在线观看 | 97久久精品无码一区二区 | 国产两女互慰高潮视频在线观看 | 亚洲午夜福利在线观看 | 无码人中文字幕 | 免费国产成人高清在线观看网站 | 内射白嫩少妇超碰 | 久久亚洲国产成人精品性色 | 2019午夜福利不卡片在线 | 久久久久亚洲精品男人的天堂 | 成人无码精品1区2区3区免费看 | 77777熟女视频在线观看 а天堂中文在线官网 | 亚洲国产av美女网站 | 正在播放东北夫妻内射 | 亚洲中文字幕av在天堂 | 国产精品久免费的黄网站 | 熟妇人妻无乱码中文字幕 | 天堂无码人妻精品一区二区三区 | 亚洲精品无码人妻无码 | 小泽玛莉亚一区二区视频在线 | 日日天干夜夜狠狠爱 | 强开小婷嫩苞又嫩又紧视频 | 无码纯肉视频在线观看 | 亚洲精品一区三区三区在线观看 | 亚洲精品一区二区三区在线观看 | 国产精品美女久久久网av | 中文字幕无码热在线视频 | 又粗又大又硬毛片免费看 | 熟女俱乐部五十路六十路av | 婷婷丁香六月激情综合啪 | 牛和人交xxxx欧美 | 免费观看又污又黄的网站 | 国产综合色产在线精品 | 中文字幕日韩精品一区二区三区 | 久久综合网欧美色妞网 | 一本加勒比波多野结衣 | 久久精品人人做人人综合 | 日韩精品无码一区二区中文字幕 | 亚洲欧美日韩综合久久久 | 扒开双腿吃奶呻吟做受视频 | 18黄暴禁片在线观看 | 无码人妻久久一区二区三区不卡 | 国产亚洲精品久久久久久大师 | 亚洲а∨天堂久久精品2021 | 乱人伦人妻中文字幕无码 | 在线a亚洲视频播放在线观看 | 久久无码中文字幕免费影院蜜桃 | 人人妻人人澡人人爽欧美一区九九 | 亚洲一区二区三区在线观看网站 | 国产精品亚洲一区二区三区喷水 | 亚洲日韩一区二区三区 | 一个人免费观看的www视频 | 久久久无码中文字幕久... | 美女扒开屁股让男人桶 | 欧美日本精品一区二区三区 | 久久久久免费精品国产 | 欧美丰满少妇xxxx性 | 日韩av无码一区二区三区不卡 | 丰满少妇女裸体bbw | 国产极品美女高潮无套在线观看 | 国产av一区二区三区最新精品 | 日本一区二区三区免费高清 | 撕开奶罩揉吮奶头视频 | 国产电影无码午夜在线播放 | 丝袜足控一区二区三区 | 无码精品人妻一区二区三区av | 国产成人精品久久亚洲高清不卡 | 久久精品视频在线看15 | 久久无码专区国产精品s | 99久久久无码国产aaa精品 | 国产色在线 | 国产 | 国产真人无遮挡作爱免费视频 | 国产精品高潮呻吟av久久 | 久久精品国产一区二区三区 | 亚洲一区二区三区播放 | 国内老熟妇对白xxxxhd | 久久国产精品偷任你爽任你 | 亚洲中文字幕无码一久久区 | 精品国产一区二区三区四区在线看 | 秋霞特色aa大片 | 高清无码午夜福利视频 | 丰满护士巨好爽好大乳 | 欧美成人免费全部网站 | 强辱丰满人妻hd中文字幕 | 国产成人精品一区二区在线小狼 | 亚洲一区二区三区香蕉 | 久久综合给合久久狠狠狠97色 | 亚洲欧美日韩国产精品一区二区 | 欧美日韩综合一区二区三区 | 日韩人妻系列无码专区 | 捆绑白丝粉色jk震动捧喷白浆 | 精品人人妻人人澡人人爽人人 | 乌克兰少妇性做爰 | а√天堂www在线天堂小说 | 免费男性肉肉影院 | 久久精品无码一区二区三区 | 精品无码一区二区三区爱欲 | 成熟女人特级毛片www免费 | 日本免费一区二区三区最新 | 性开放的女人aaa片 | 影音先锋中文字幕无码 | 亚洲无人区午夜福利码高清完整版 | 久久综合九色综合97网 | 四虎永久在线精品免费网址 | 无码毛片视频一区二区本码 | 亚洲人交乣女bbw | 亚洲爆乳精品无码一区二区三区 | 日日麻批免费40分钟无码 | 老太婆性杂交欧美肥老太 | 国产va免费精品观看 | 激情内射亚州一区二区三区爱妻 | 久久久久免费看成人影片 | 欧美zoozzooz性欧美 | 特级做a爰片毛片免费69 | 午夜精品一区二区三区的区别 | 麻豆精产国品 | 蜜臀aⅴ国产精品久久久国产老师 | 午夜肉伦伦影院 | 国产精品怡红院永久免费 | 老熟妇乱子伦牲交视频 | 亚洲一区二区三区含羞草 | 99精品无人区乱码1区2区3区 | 精品日本一区二区三区在线观看 | 亚洲综合伊人久久大杳蕉 | 亚洲爆乳无码专区 | 性欧美牲交xxxxx视频 | 中文字幕无码日韩欧毛 | 狂野欧美激情性xxxx | 亚洲爆乳精品无码一区二区三区 | 露脸叫床粗话东北少妇 | 少妇无码av无码专区在线观看 | 国产成人精品视频ⅴa片软件竹菊 | 日本护士xxxxhd少妇 | 久久久久久亚洲精品a片成人 | 中文字幕乱码中文乱码51精品 | 麻豆精品国产精华精华液好用吗 | 久久精品一区二区三区四区 | 久久久无码中文字幕久... | 中文字幕久久久久人妻 | 无码人妻精品一区二区三区不卡 | 国产三级久久久精品麻豆三级 | 国产精品无码一区二区桃花视频 | 国产超碰人人爽人人做人人添 | 中文字幕无码av波多野吉衣 | 亚洲精品一区三区三区在线观看 | 亚洲国产精品一区二区第一页 | 宝宝好涨水快流出来免费视频 | 99久久久无码国产aaa精品 | 黄网在线观看免费网站 | 国产人妻人伦精品1国产丝袜 | 欧美乱妇无乱码大黄a片 | 少妇无套内谢久久久久 | 国产乱人偷精品人妻a片 | 国产福利视频一区二区 | 国产亚洲精品久久久久久久 | 亚洲小说春色综合另类 | 成人亚洲精品久久久久 | 国产成人无码专区 | 7777奇米四色成人眼影 | 日日碰狠狠丁香久燥 | 国产精品毛片一区二区 | 99久久久无码国产精品免费 | 久久久www成人免费毛片 | 国产色在线 | 国产 | 无人区乱码一区二区三区 | 色综合视频一区二区三区 | 蜜桃av抽搐高潮一区二区 | 成人女人看片免费视频放人 | 亚洲精品国偷拍自产在线观看蜜桃 | 国产精品久久久久久久9999 | 丝袜美腿亚洲一区二区 | 人妻天天爽夜夜爽一区二区 | 色婷婷综合中文久久一本 | 日产精品99久久久久久 | 久久人人97超碰a片精品 | 国产精华av午夜在线观看 | 欧美兽交xxxx×视频 | 亚洲精品久久久久久一区二区 | 狠狠cao日日穞夜夜穞av | 精品厕所偷拍各类美女tp嘘嘘 | 大地资源中文第3页 | 日本爽爽爽爽爽爽在线观看免 | 97se亚洲精品一区 | 久久久久免费精品国产 | 久久精品成人欧美大片 | 麻豆国产人妻欲求不满谁演的 | 国产精品人人妻人人爽 | 亚洲性无码av中文字幕 | 久久精品国产99久久6动漫 | 国内揄拍国内精品人妻 | 国模大胆一区二区三区 | 一本久道久久综合狠狠爱 | а√天堂www在线天堂小说 | 精品国产麻豆免费人成网站 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 亚洲国产高清在线观看视频 | 麻豆精品国产精华精华液好用吗 | 欧洲熟妇精品视频 | 一本大道久久东京热无码av | 天海翼激烈高潮到腰振不止 | 国产亚洲精品久久久ai换 | 日本爽爽爽爽爽爽在线观看免 | 久久午夜无码鲁丝片 | 国产精品igao视频网 | 2019午夜福利不卡片在线 | 性生交大片免费看女人按摩摩 | 精品人妻中文字幕有码在线 | 亚洲精品国产精品乱码视色 | 老司机亚洲精品影院无码 | 亚洲欧洲日本无在线码 | 精品国产一区二区三区四区在线看 | 国内精品人妻无码久久久影院蜜桃 | 少妇人妻av毛片在线看 | 夜夜影院未满十八勿进 | 2020久久香蕉国产线看观看 | 亚洲狠狠婷婷综合久久 | 亚洲中文字幕乱码av波多ji | 麻豆md0077饥渴少妇 | 18无码粉嫩小泬无套在线观看 | 久久久精品欧美一区二区免费 | 又大又硬又爽免费视频 | 人妻插b视频一区二区三区 | 东京无码熟妇人妻av在线网址 | 亚洲日本va中文字幕 | 欧美日韩视频无码一区二区三 | 奇米影视7777久久精品 | 欧美成人免费全部网站 | 亚洲第一网站男人都懂 | 一个人看的www免费视频在线观看 | 99er热精品视频 | 国产一区二区三区精品视频 | 国产精品久久久久7777 | 日韩 欧美 动漫 国产 制服 | 国内综合精品午夜久久资源 | 亚洲va欧美va天堂v国产综合 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 乱码av麻豆丝袜熟女系列 | 亚洲国产精品一区二区第一页 | 一个人免费观看的www视频 | 领导边摸边吃奶边做爽在线观看 | 亚洲色偷偷偷综合网 | 无码吃奶揉捏奶头高潮视频 | 欧美xxxx黑人又粗又长 | 狠狠综合久久久久综合网 | 最近的中文字幕在线看视频 | 中文字幕日韩精品一区二区三区 | 亚洲国产欧美国产综合一区 | av小次郎收藏 | 欧美日韩一区二区免费视频 | 又粗又大又硬又长又爽 | 在线观看国产一区二区三区 | 99精品无人区乱码1区2区3区 | 欧美性猛交xxxx富婆 | 国产热a欧美热a在线视频 | 精品国产乱码久久久久乱码 | 成人免费无码大片a毛片 | 欧美精品一区二区精品久久 | 麻豆国产人妻欲求不满谁演的 | 国产97人人超碰caoprom | aⅴ在线视频男人的天堂 | 亚洲国产欧美在线成人 | 沈阳熟女露脸对白视频 | 亚洲 欧美 激情 小说 另类 | 亚洲aⅴ无码成人网站国产app | 国产精品国产自线拍免费软件 | 国产真实伦对白全集 | 性生交大片免费看女人按摩摩 | 少妇激情av一区二区 | 激情国产av做激情国产爱 | 亚洲s色大片在线观看 | 久久久久免费看成人影片 | 国产明星裸体无码xxxx视频 | 亚洲午夜无码久久 | 色一情一乱一伦一区二区三欧美 | 国内精品久久久久久中文字幕 | 亚洲精品中文字幕 | 乱人伦中文视频在线观看 | 国产精品自产拍在线观看 | 国产人妻人伦精品 | 国产97人人超碰caoprom | 日本高清一区免费中文视频 | 亚洲综合另类小说色区 | 国产av久久久久精东av | 鲁鲁鲁爽爽爽在线视频观看 | 一本久久伊人热热精品中文字幕 | 无码人妻丰满熟妇区毛片18 | 成人毛片一区二区 | 娇妻被黑人粗大高潮白浆 | 18黄暴禁片在线观看 | 国语精品一区二区三区 | 久久精品国产日本波多野结衣 | 无码午夜成人1000部免费视频 | 日本精品高清一区二区 | 最近的中文字幕在线看视频 | 亚洲色无码一区二区三区 | 亚洲va欧美va天堂v国产综合 | 欧美一区二区三区视频在线观看 | 欧美精品免费观看二区 | 婷婷五月综合激情中文字幕 | 国产精品亚洲а∨无码播放麻豆 | 自拍偷自拍亚洲精品10p | 激情爆乳一区二区三区 | 国产精品久久久午夜夜伦鲁鲁 | 中文字幕久久久久人妻 | 久久99久久99精品中文字幕 | 377p欧洲日本亚洲大胆 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 成人欧美一区二区三区黑人免费 | 久久五月精品中文字幕 | 久久久久99精品国产片 | 亚洲 日韩 欧美 成人 在线观看 | 成熟妇人a片免费看网站 | 高中生自慰www网站 | 亚洲国产精品久久人人爱 | 扒开双腿吃奶呻吟做受视频 | 麻豆国产97在线 | 欧洲 | 内射后入在线观看一区 | 亚洲精品成人福利网站 | 55夜色66夜色国产精品视频 | 日韩av激情在线观看 | 日韩精品无码免费一区二区三区 | 久久久久久九九精品久 | 免费无码的av片在线观看 | 激情人妻另类人妻伦 | 国产内射爽爽大片视频社区在线 | 国产另类ts人妖一区二区 | 欧美激情内射喷水高潮 | 精品国产成人一区二区三区 | 成人亚洲精品久久久久 | 欧美日韩亚洲国产精品 | 少妇无码av无码专区在线观看 | 亚洲另类伦春色综合小说 | 久久综合久久自在自线精品自 | 亚洲中文字幕在线无码一区二区 | 成人欧美一区二区三区 | 亚洲国产高清在线观看视频 | 欧美日韩人成综合在线播放 | 日韩av无码中文无码电影 | 亚洲国产av美女网站 | 最近的中文字幕在线看视频 | 成人无码精品1区2区3区免费看 | 爆乳一区二区三区无码 | 亚洲欧美综合区丁香五月小说 | 久久久久久亚洲精品a片成人 | 久久99精品久久久久婷婷 | 欧美精品无码一区二区三区 | 伊在人天堂亚洲香蕉精品区 | 色欲av亚洲一区无码少妇 | 久久午夜无码鲁丝片午夜精品 | 国产精品亚洲а∨无码播放麻豆 | 少妇高潮一区二区三区99 | 国产av久久久久精东av | 亚洲人成影院在线无码按摩店 | 国产精品久久久久久久9999 | 一本久久a久久精品vr综合 | 精品国产成人一区二区三区 | 亚洲一区二区三区国产精华液 | 国产精品久久久久影院嫩草 | 岛国片人妻三上悠亚 | 久久久久免费看成人影片 | 人人妻人人澡人人爽精品欧美 | 亚洲色在线无码国产精品不卡 | 影音先锋中文字幕无码 | 久久zyz资源站无码中文动漫 | 久久久久免费看成人影片 | 一二三四社区在线中文视频 | 少妇人妻大乳在线视频 | 国产精品丝袜黑色高跟鞋 | 国产特级毛片aaaaaaa高清 | 在线播放无码字幕亚洲 | 宝宝好涨水快流出来免费视频 | 久久久精品人妻久久影视 | 人妻尝试又大又粗久久 | 欧美freesex黑人又粗又大 | 国产 精品 自在自线 | 亚洲欧美日韩综合久久久 | 久久97精品久久久久久久不卡 | 亚洲成av人片天堂网无码】 | 国产成人精品视频ⅴa片软件竹菊 | 熟妇人妻中文av无码 | 亚洲欧洲日本无在线码 | 欧美老熟妇乱xxxxx | 狠狠亚洲超碰狼人久久 | 日日噜噜噜噜夜夜爽亚洲精品 | 无码人妻精品一区二区三区不卡 | 漂亮人妻洗澡被公强 日日躁 | √天堂资源地址中文在线 | 老司机亚洲精品影院无码 | 亚洲理论电影在线观看 | 青青久在线视频免费观看 | 亚洲熟妇色xxxxx欧美老妇 | 国产区女主播在线观看 | 国产精品99爱免费视频 | 亚洲人成人无码网www国产 | 97人妻精品一区二区三区 | 中文字幕乱码亚洲无线三区 | 97资源共享在线视频 | 午夜精品久久久久久久久 | 久久综合久久自在自线精品自 | 国产激情艳情在线看视频 | 亚洲va欧美va天堂v国产综合 | 亚洲の无码国产の无码影院 | 亚洲精品无码人妻无码 | 日本一卡二卡不卡视频查询 | 国产内射爽爽大片视频社区在线 | 一本无码人妻在中文字幕免费 | 天堂在线观看www | 久久久精品国产sm最大网站 | 精品久久久中文字幕人妻 | 国产精品18久久久久久麻辣 | 日韩在线不卡免费视频一区 | 九九热爱视频精品 | 欧美日韩精品 | 国产精品第一区揄拍无码 | 欧美性生交xxxxx久久久 | 国内老熟妇对白xxxxhd | 久久伊人色av天堂九九小黄鸭 | 欧美刺激性大交 | 欧美国产亚洲日韩在线二区 | 高潮毛片无遮挡高清免费 | 久久亚洲日韩精品一区二区三区 | 欧美日本免费一区二区三区 | 高清国产亚洲精品自在久久 | 性欧美疯狂xxxxbbbb | 精品国精品国产自在久国产87 | 亚洲精品中文字幕久久久久 | 亚洲精品成人福利网站 | 无码av免费一区二区三区试看 | 红桃av一区二区三区在线无码av | 免费乱码人妻系列无码专区 | 国产精品永久免费视频 | 亚洲欧美日韩成人高清在线一区 | 精品久久久久久人妻无码中文字幕 | 国产精品99久久精品爆乳 | 国产区女主播在线观看 | 两性色午夜免费视频 | 国产成人综合美国十次 | 大地资源中文第3页 | 日本一区二区三区免费播放 | 无码av最新清无码专区吞精 | 亚洲日本一区二区三区在线 | 国产精品久久久久久久影院 | 国产激情精品一区二区三区 | 日韩人妻系列无码专区 | 无码人妻出轨黑人中文字幕 | 精品国产青草久久久久福利 | 国产成人亚洲综合无码 | 在线观看国产午夜福利片 | 国产偷国产偷精品高清尤物 | 国产精品资源一区二区 | 夜夜影院未满十八勿进 | 波多野结衣av一区二区全免费观看 | 国产成人精品视频ⅴa片软件竹菊 | 中文字幕无码视频专区 | 麻豆果冻传媒2021精品传媒一区下载 | 成人欧美一区二区三区黑人免费 | 国产亚洲精品久久久久久久久动漫 | 人妻少妇精品久久 | 亚洲一区二区三区四区 | 伊在人天堂亚洲香蕉精品区 | 久久人人爽人人爽人人片ⅴ | 一本精品99久久精品77 | 成人一在线视频日韩国产 | 国产精品久久久久久亚洲毛片 | 久久久久久久女国产乱让韩 | 国产精品无码成人午夜电影 | 国产精品嫩草久久久久 | 中文字幕无码av波多野吉衣 | 日韩精品无码免费一区二区三区 | 综合人妻久久一区二区精品 | 大色综合色综合网站 | 一本一道久久综合久久 | 麻豆av传媒蜜桃天美传媒 | 久久亚洲中文字幕无码 | 人妻体内射精一区二区三四 | 国产亚洲精品久久久久久 | 国内精品人妻无码久久久影院 | 国产在线aaa片一区二区99 | 无码国内精品人妻少妇 | 国产日产欧产精品精品app | 国产精品无套呻吟在线 | 99久久精品午夜一区二区 | 久久国产精品_国产精品 | 国产亚洲日韩欧美另类第八页 | 日韩无套无码精品 | 色一情一乱一伦 | 国产精品久久国产三级国 | 亚洲精品鲁一鲁一区二区三区 | 小sao货水好多真紧h无码视频 | 玩弄人妻少妇500系列视频 | 噜噜噜亚洲色成人网站 | 国产美女精品一区二区三区 | 亚洲人成网站免费播放 | 强伦人妻一区二区三区视频18 | 亚洲综合另类小说色区 | 永久免费观看美女裸体的网站 | 精品国偷自产在线视频 | 亚洲中文字幕乱码av波多ji | 国产一区二区三区日韩精品 | 大肉大捧一进一出好爽视频 | 国产成人综合色在线观看网站 | 最新国产乱人伦偷精品免费网站 | 国产精品自产拍在线观看 | 日本高清一区免费中文视频 | 国产一区二区三区四区五区加勒比 | 亚洲性无码av中文字幕 | 亚洲春色在线视频 | 亚洲午夜福利在线观看 | 亚洲另类伦春色综合小说 | 亚洲日韩中文字幕在线播放 | 伊人色综合久久天天小片 | 波多野结衣av在线观看 | 丰满人妻一区二区三区免费视频 | 色欲人妻aaaaaaa无码 | 亚洲国产精品成人久久蜜臀 | 久久人人爽人人人人片 | 无码福利日韩神码福利片 | 色欲av亚洲一区无码少妇 | 综合网日日天干夜夜久久 | 免费无码一区二区三区蜜桃大 | 国产成人av免费观看 | 99riav国产精品视频 | 少妇高潮喷潮久久久影院 | 香港三级日本三级妇三级 | 无码帝国www无码专区色综合 | 亚洲综合无码久久精品综合 | 国产熟女一区二区三区四区五区 | 99久久久无码国产aaa精品 | 国产suv精品一区二区五 | 国产精品亚洲lv粉色 | www国产亚洲精品久久久日本 | 久久亚洲中文字幕精品一区 | 久久久久久av无码免费看大片 | 亚洲大尺度无码无码专区 | 国产亚洲欧美在线专区 | 国产香蕉尹人综合在线观看 | 免费人成在线观看网站 | 国产艳妇av在线观看果冻传媒 | 色综合久久久无码中文字幕 | 欧美国产日韩亚洲中文 | 福利一区二区三区视频在线观看 | 丝袜 中出 制服 人妻 美腿 | 一本色道婷婷久久欧美 | 国产精品美女久久久久av爽李琼 | 亚洲欧洲中文日韩av乱码 | 爽爽影院免费观看 | 少妇高潮一区二区三区99 | 少女韩国电视剧在线观看完整 | 正在播放东北夫妻内射 | 国产精品无码成人午夜电影 | 国产精品二区一区二区aⅴ污介绍 | 国产亚洲美女精品久久久2020 | 免费人成网站视频在线观看 | 成人女人看片免费视频放人 | 2019午夜福利不卡片在线 | 国产内射爽爽大片视频社区在线 | 国产午夜无码精品免费看 | 亚洲国产日韩a在线播放 | 噜噜噜亚洲色成人网站 | 18无码粉嫩小泬无套在线观看 | 鲁一鲁av2019在线 | 亚洲日韩av一区二区三区中文 | 日韩精品无码一本二本三本色 | 亚洲一区二区三区无码久久 | 国产精品无套呻吟在线 | 久久精品人人做人人综合试看 | 国产av久久久久精东av | 国产农村乱对白刺激视频 | 亚洲 激情 小说 另类 欧美 | 国产精品无码一区二区三区不卡 | 亚洲国产精华液网站w | 亚洲国产成人a精品不卡在线 | 性生交片免费无码看人 | 日本饥渴人妻欲求不满 | 少妇被粗大的猛进出69影院 | 性啪啪chinese东北女人 | 麻豆国产丝袜白领秘书在线观看 | 丁香花在线影院观看在线播放 | 国产欧美精品一区二区三区 | 欧美精品一区二区精品久久 | 久久综合网欧美色妞网 | 欧美国产日韩亚洲中文 | 亚洲 欧美 激情 小说 另类 | 久久精品一区二区三区四区 | 荡女精品导航 | 少妇人妻av毛片在线看 | 又湿又紧又大又爽a视频国产 | 亚洲精品成人福利网站 | 日本熟妇大屁股人妻 | 2019午夜福利不卡片在线 | 国内精品久久久久久中文字幕 | 在线观看欧美一区二区三区 | 国产手机在线αⅴ片无码观看 | 亚洲七七久久桃花影院 | av在线亚洲欧洲日产一区二区 | 3d动漫精品啪啪一区二区中 | 久久久久亚洲精品男人的天堂 | 曰本女人与公拘交酡免费视频 | 久久精品无码一区二区三区 | 强辱丰满人妻hd中文字幕 | 亚洲中文字幕久久无码 | 天天拍夜夜添久久精品大 | 日日碰狠狠躁久久躁蜜桃 | 高清不卡一区二区三区 | 亚洲一区二区三区四区 | 国产香蕉97碰碰久久人人 | 初尝人妻少妇中文字幕 | 毛片内射-百度 | 成人女人看片免费视频放人 | 久久精品视频在线看15 | 成人精品一区二区三区中文字幕 | 色窝窝无码一区二区三区色欲 | 丰满肥臀大屁股熟妇激情视频 | 亚洲国产精品美女久久久久 | 国产电影无码午夜在线播放 | 久久久久久久人妻无码中文字幕爆 | www国产亚洲精品久久久日本 | 性欧美大战久久久久久久 | 青青草原综合久久大伊人精品 | 国产精品久久久av久久久 | 中文字幕无码av波多野吉衣 | 国产精品无码mv在线观看 | 少妇性荡欲午夜性开放视频剧场 | 六月丁香婷婷色狠狠久久 | 国产在线精品一区二区三区直播 | 丝袜足控一区二区三区 | 人人妻人人澡人人爽人人精品 | 熟妇人妻无码xxx视频 | 亚洲人成影院在线无码按摩店 | 女人和拘做爰正片视频 | 亚洲综合无码一区二区三区 | 一本一道久久综合久久 | 国产精品无套呻吟在线 | 国产高清av在线播放 | 免费人成网站视频在线观看 | 一二三四在线观看免费视频 | 丰满少妇熟乱xxxxx视频 | 曰韩少妇内射免费播放 | 亚洲一区二区三区含羞草 | 日韩av激情在线观看 | 成人av无码一区二区三区 | 暴力强奷在线播放无码 | 亚洲一区二区三区四区 | 国产熟女一区二区三区四区五区 | 国产人妖乱国产精品人妖 | 四虎国产精品免费久久 | 亚洲阿v天堂在线 | 日日鲁鲁鲁夜夜爽爽狠狠 | 国产三级精品三级男人的天堂 | 伊人久久婷婷五月综合97色 | 欧美日韩一区二区综合 | 国产美女精品一区二区三区 | 又粗又大又硬毛片免费看 | 88国产精品欧美一区二区三区 | 在线观看国产一区二区三区 | 欧美激情内射喷水高潮 | 又湿又紧又大又爽a视频国产 | 中文亚洲成a人片在线观看 | 人妻人人添人妻人人爱 | 中文字幕无码人妻少妇免费 | 精品无人区无码乱码毛片国产 | 日本熟妇浓毛 | a片在线免费观看 | 粉嫩少妇内射浓精videos | 午夜无码人妻av大片色欲 | 丝袜美腿亚洲一区二区 | 日韩少妇内射免费播放 | 波多野42部无码喷潮在线 | 色妞www精品免费视频 | 国内老熟妇对白xxxxhd | 欧美xxxxx精品 | 大地资源网第二页免费观看 | 青青草原综合久久大伊人精品 | 无码国模国产在线观看 | 伊人久久婷婷五月综合97色 | 四虎4hu永久免费 | 久久99久久99精品中文字幕 | 永久黄网站色视频免费直播 | 日本乱偷人妻中文字幕 | 老司机亚洲精品影院 | 天堂а√在线地址中文在线 | 日本丰满熟妇videos | 亚洲a无码综合a国产av中文 | 中文字幕无线码 | 性欧美牲交xxxxx视频 | 国产成人无码区免费内射一片色欲 | 国产日产欧产精品精品app | 99久久人妻精品免费一区 | 一个人免费观看的www视频 | 2019nv天堂香蕉在线观看 | 99久久人妻精品免费一区 | 久久久久久亚洲精品a片成人 | 国产精品手机免费 | 亚洲日韩av片在线观看 | 无码人妻丰满熟妇区毛片18 | 亚洲欧洲日本综合aⅴ在线 | 免费国产黄网站在线观看 | yw尤物av无码国产在线观看 | 国精品人妻无码一区二区三区蜜柚 | 久久久婷婷五月亚洲97号色 | 强伦人妻一区二区三区视频18 | 精品国产成人一区二区三区 | 亚洲爆乳无码专区 | 色诱久久久久综合网ywww | 色欲久久久天天天综合网精品 | 久久久久久九九精品久 | 国产精品亚洲专区无码不卡 | 奇米影视888欧美在线观看 | 天堂а√在线地址中文在线 | 伊人久久大香线蕉午夜 | 扒开双腿疯狂进出爽爽爽视频 | 免费国产成人高清在线观看网站 | 国产精品-区区久久久狼 | 人妻体内射精一区二区三四 | 综合人妻久久一区二区精品 | 亚洲无人区午夜福利码高清完整版 | 国产人成高清在线视频99最全资源 | 精品亚洲成av人在线观看 | 色婷婷av一区二区三区之红樱桃 | 97久久国产亚洲精品超碰热 | 天天av天天av天天透 | 亚洲日本一区二区三区在线 | 免费看男女做好爽好硬视频 | 天堂亚洲免费视频 | 99久久久无码国产精品免费 | www成人国产高清内射 | 久久综合给久久狠狠97色 | 88国产精品欧美一区二区三区 | 99久久精品午夜一区二区 | 国产激情精品一区二区三区 | 国产精品沙发午睡系列 | 欧洲美熟女乱又伦 | 无码成人精品区在线观看 | 一本久久伊人热热精品中文字幕 | 亚洲精品美女久久久久久久 | 国产超碰人人爽人人做人人添 | 欧美日韩一区二区三区自拍 | 欧美人与动性行为视频 | 亚洲a无码综合a国产av中文 | 亚洲精品国偷拍自产在线麻豆 | 樱花草在线社区www | 亚洲精品鲁一鲁一区二区三区 | 亚洲经典千人经典日产 | 少妇人妻偷人精品无码视频 | 国产在线aaa片一区二区99 | 内射巨臀欧美在线视频 | 国産精品久久久久久久 | 中文字幕人妻无码一区二区三区 | 国产精品-区区久久久狼 | 国产成人无码av在线影院 | 亲嘴扒胸摸屁股激烈网站 | 真人与拘做受免费视频一 | 黑人巨大精品欧美一区二区 | 久久精品人妻少妇一区二区三区 | 美女张开腿让人桶 | 国产精品久久久久久亚洲影视内衣 | 欧美激情内射喷水高潮 | 大肉大捧一进一出视频出来呀 | 野外少妇愉情中文字幕 | 久久这里只有精品视频9 | 欧美阿v高清资源不卡在线播放 | 波多野结衣av一区二区全免费观看 | 午夜福利试看120秒体验区 | 欧美日韩一区二区免费视频 | 东京一本一道一二三区 | 久在线观看福利视频 | 在线成人www免费观看视频 | 人人超人人超碰超国产 | av无码电影一区二区三区 | 国产精品鲁鲁鲁 | 俺去俺来也www色官网 | 又湿又紧又大又爽a视频国产 | 精品人妻人人做人人爽 | 国产成人人人97超碰超爽8 | 无码福利日韩神码福利片 | 风流少妇按摩来高潮 | 2019午夜福利不卡片在线 | 色综合久久久久综合一本到桃花网 | 人人妻人人澡人人爽欧美精品 | 日本一卡二卡不卡视频查询 | 国产情侣作爱视频免费观看 | 2019nv天堂香蕉在线观看 | 亚洲精品国产第一综合99久久 | 一本一道久久综合久久 | 久久国产精品_国产精品 | av人摸人人人澡人人超碰下载 | 麻花豆传媒剧国产免费mv在线 | 国产精品久久久久无码av色戒 | 亚洲中文字幕成人无码 | 久久99精品久久久久婷婷 | 久久99久久99精品中文字幕 | 久久国内精品自在自线 | 国内精品人妻无码久久久影院蜜桃 | 5858s亚洲色大成网站www | 欧美怡红院免费全部视频 | 亚洲男人av香蕉爽爽爽爽 | 妺妺窝人体色www在线小说 | 国产 浪潮av性色四虎 | 久久亚洲国产成人精品性色 | 久久久成人毛片无码 | 18精品久久久无码午夜福利 | 丝袜美腿亚洲一区二区 | 国产精品久久久久久久9999 | 99久久精品国产一区二区蜜芽 | www成人国产高清内射 | 99久久精品午夜一区二区 | 少妇无码一区二区二三区 | 日本丰满护士爆乳xxxx | 女人和拘做爰正片视频 | 成人免费视频一区二区 | 青草视频在线播放 | 色欲人妻aaaaaaa无码 | 精品无码一区二区三区的天堂 | 精品午夜福利在线观看 | 精品少妇爆乳无码av无码专区 | 亚洲精品综合五月久久小说 | 国产精品久久久久影院嫩草 | 成人片黄网站色大片免费观看 | 人妻少妇精品视频专区 | 成人免费视频在线观看 | 2019午夜福利不卡片在线 | 欧美日韩久久久精品a片 | 亚洲一区二区三区国产精华液 | 色综合久久网 | 国产精品无码一区二区桃花视频 | 欧美 亚洲 国产 另类 | 麻豆果冻传媒2021精品传媒一区下载 | 少妇太爽了在线观看 | 国产农村乱对白刺激视频 | 亚洲精品成人福利网站 | 久久天天躁狠狠躁夜夜免费观看 | 亚洲精品中文字幕 | 久久久久99精品成人片 | 免费播放一区二区三区 | 熟妇人妻中文av无码 | 亚洲大尺度无码无码专区 | 国产无套内射久久久国产 | 真人与拘做受免费视频 | 婷婷五月综合激情中文字幕 | 国产综合色产在线精品 | 精品无码一区二区三区的天堂 | 国产精品二区一区二区aⅴ污介绍 | 麻豆国产人妻欲求不满谁演的 | 久久久久亚洲精品中文字幕 | 激情内射亚州一区二区三区爱妻 | 一个人免费观看的www视频 | 欧美黑人巨大xxxxx | 国产97在线 | 亚洲 | 骚片av蜜桃精品一区 | 亚洲欧美日韩国产精品一区二区 | 夫妻免费无码v看片 | 精品久久综合1区2区3区激情 | 亚欧洲精品在线视频免费观看 | av无码电影一区二区三区 | 精品亚洲韩国一区二区三区 | 水蜜桃av无码 | 成人av无码一区二区三区 | 成人精品天堂一区二区三区 | 国内少妇偷人精品视频免费 | 色 综合 欧美 亚洲 国产 | 丰满妇女强制高潮18xxxx | 亚洲gv猛男gv无码男同 | 中文字幕乱码中文乱码51精品 | 欧美丰满老熟妇xxxxx性 | 亚洲自偷自拍另类第1页 | 国产成人无码av在线影院 | 久久综合给合久久狠狠狠97色 | 日韩精品无码一区二区中文字幕 | 亚洲乱码国产乱码精品精 | 中国女人内谢69xxxx | 久久精品国产一区二区三区 | 性做久久久久久久免费看 | 国产日产欧产精品精品app | 亚洲精品综合一区二区三区在线 | 性生交大片免费看女人按摩摩 | 麻豆国产人妻欲求不满谁演的 | 99精品国产综合久久久久五月天 | 日日摸夜夜摸狠狠摸婷婷 | 精品偷拍一区二区三区在线看 | 在线a亚洲视频播放在线观看 | 日本饥渴人妻欲求不满 | 日韩人妻少妇一区二区三区 | 青青青手机频在线观看 | 精品一区二区三区波多野结衣 | 乌克兰少妇xxxx做受 | 亚洲无人区午夜福利码高清完整版 | 精品亚洲成av人在线观看 | 欧美老熟妇乱xxxxx | 日日碰狠狠躁久久躁蜜桃 | 中文字幕中文有码在线 | 国产超碰人人爽人人做人人添 | 黑人巨大精品欧美一区二区 | 亚洲国产精品久久久久久 | 亚洲春色在线视频 | 精品国产一区二区三区av 性色 | 秋霞成人午夜鲁丝一区二区三区 | 国产亚洲人成a在线v网站 | 欧美人与动性行为视频 | 少妇性l交大片欧洲热妇乱xxx | 亚洲成a人片在线观看无码 | 中文字幕色婷婷在线视频 | 丰满少妇女裸体bbw | 国产口爆吞精在线视频 | 欧美大屁股xxxxhd黑色 | 俺去俺来也www色官网 | 色情久久久av熟女人妻网站 | 欧美人与动性行为视频 | 欧美丰满熟妇xxxx | 国产艳妇av在线观看果冻传媒 | 中文久久乱码一区二区 | 久久国语露脸国产精品电影 | 国产激情无码一区二区 | 精品人妻人人做人人爽夜夜爽 | 日日鲁鲁鲁夜夜爽爽狠狠 | 国产凸凹视频一区二区 | 九九热爱视频精品 | 亚洲中文字幕va福利 | 久久久无码中文字幕久... | 亚洲熟熟妇xxxx | 精品国产一区二区三区av 性色 | 精品无码一区二区三区的天堂 | 国产激情精品一区二区三区 | 又粗又大又硬毛片免费看 | 久久久久亚洲精品中文字幕 | 久久久久av无码免费网 | 成人片黄网站色大片免费观看 | 亚洲码国产精品高潮在线 | 在线亚洲高清揄拍自拍一品区 | 图片区 小说区 区 亚洲五月 |