⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 14. 位图和bitblt.txt

📁 本书介绍了在Microsoft Windows 98、Microsoft Windows NT 4.0和Windows NT 5.0下程序写作的方法
💻 TXT
📖 第 1 页 / 共 5 页
字号:
           {
        
                  MessageBox (  NULL, TEXT ("This program requires Windows NT!"),
        
                                                                        szAppName, MB_ICONERROR) ;
        
                  return 0 ;
        
    }
        
   
        
    hwnd = CreateWindow (szAppName, TEXT ("StretchBlt Demo"),
        
                         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 int            cxClient, cyClient, cxSource, cySource ;
        
           HDC                          hdcClient, hdcWindow ;
        
           PAINTSTRUCT           ps ;
        
   
        
           switch (message)
        
           {
        
           case   WM_CREATE:
        
                          cxSource = GetSystemMetrics (SM_CXSIZEFRAME) +
        
                   GetSystemMetrics (SM_CXSIZE) ;
        

                          cySource = GetSystemMetrics (SM_CYSIZEFRAME) +
        
                   GetSystemMetrics (SM_CYCAPTION) ;
        
                          return 0 ;
        

           case   WM_SIZE:
        
                          cxClient = LOWORD (lParam) ;
        
                          cyClient = HIWORD (lParam) ;
        
                          return 0 ;
        

           case   WM_PAINT:
        
                          hdcClient = BeginPaint (hwnd, &ps) ;
        
                          hdcWindow = GetWindowDC (hwnd) ;
        

                          StretchBlt (hdcClient, 0, 0, cxClient, cyClient,
        
                   hdcWindow, 0, 0, cxSource, cySource, MERGECOPY) ;
        

                          ReleaseDC (hwnd, hdcWindow) ;
        
                          EndPaint (hwnd, &ps) ;
        
                          return 0 ;
        

           case   WM_DESTROY:
        
                          PostQuitMessage (0) ;
        
                          return 0 ;
        
    }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        
此程序只有呼叫了StretchBlt函数一次,但是利用此函数以系统菜单图标填充了整个显示区域,如图14-2所示。


 



图14-2 STRETCH的屏幕显示
 

BitBlt和StretchBlt函数中所有的坐标与大小都是依据逻辑单位的。但是当您在BitBlt函数中定义了两个不同的设备内容,而这两个设备内容虽然参考同一个实际设备,却各自有着不同的映像模式,这时将发生什么结果呢?如果出现这种情况,呼叫BitBlt产生的结果就显得不明确了:cx和cy参数都是逻辑单位,而它们同样应用于来源设备内容和目的设备内容中的矩形区。所有的坐标和尺寸必须在实际的位传输之前转换为设备坐标。因为cx和cy值同时用于来源和目的设备内容,所以此值必须转换为设备内容自己的单位。

当来源和目的设备内容相同,或者两个设备内容都使用MM_TEXT图像模式时,设备单位下的矩形尺寸在两个设备内容中会是相同的,然后才由Windows进行图素对图素的转换。不过,如果设备单位下的矩形尺寸在两个设备内容中不同时,则Windows就把此工作转交给更通用的StretchBlt函数。

StretchBlt也允许水平或垂直翻转图像。如果cxSrc和cxDst标记(转换成设备单位以后)不同,那么StretchBlt就建立一个镜像:左右翻转。在STRETCH程序中,通过将xDst参数改为cxClient并将cxDst参数改成-cxClient,您就可以做到这一点。如果cySrc和cyDst不同,则StretchBlt会上下翻转图像。要在STRETCH程序中测试这一点,可将yDst参数改为cyClient并将cyDst参数改成-cyClient。

StretchBlt模式


使用StretchBlt会碰到一些与位图大小缩放相关的一些根本问题。在扩展一个位图时,StretchBlt必须复制图素行或列。如果放大倍数不是原图的整数倍,那么此操作会造成产生的图像有些失真。

如果目的矩形比来源矩形小,那么StretchBlt在缩小图像时就必须把两行(或列)或者多行(或列)的图素合并到一行(或列)。完成此操作有四种方法,它根据设备内容伸展模式属性来选择其中一种方法。您可使用SetStretchBltMode函数来修改这个属性。

SetStretchBltMode (hdc, iMode) ;
        
iMode可取下列值:

BLACKONWHITE或者STRETCH_ANDSCANS(内定)如果两个或多个图素得合并成一个图素,那么StretchBlt会对图素执行一个逻辑AND运算。这样的结果是只有全部的原始图素是白色时该图素才为白色,其实际意义是黑色图素控制了白色图素。这适用于白背景中主要是黑色的单色位图。
  
WHITEONBLACK或STRETCH_ORSCANS 如果两个或多个图素得合并成一个图素,那么StretchBlt执行逻辑OR运算。这样的结果是只有全部的原始图素都是黑色时才是黑色,也就是说由白色图素决定颜色。这适用于黑色背景中主要是白色的单色位图。
  
COLORONCOLOR或STRETCH_DELETESCANS StretchBlt简单地消除图素行或列,而没有任何逻辑组合。这是通常是处理彩色位图的最佳方法。
  
HALFTONE或STRETCH_HALFTONE Windows根据组合起来的来源颜色来计算目的的平均颜色。这将与半调调色盘联合使用, 第十六章将展示这一程序。
  
Windows还包括用于取得目前伸展模式的GetStretchBltMode函数。

位映像操作


BITBLT和STRETCH程序简单地将来源位图复制给了目的位图,在过程中也可能进行了缩放。这是把SRCCOPY作为BitBlt和StretchBlt函数最后一个参数的结果。SRCCOPY只是您能在这些函数中使用的256个位映像操作中的一个。让我们先在STRETCH程序中做一个别的实验,然后再系统地研究位映像操作。

尽量用NOTSRCCOPY来代替SRCCOPY。与它们名称一样,位映像操作在复制位图时转换其颜色。在显示区域窗口,所有的颜色转换:黑色变成白色、白色变成黑色,蓝色变成黄色。现在试一下SRCINVERT,您将得到同样效果。如果试一下BLACKNESS,正如其名称一样,整个显示区域都将变成黑色,而WHITENESS则使其变成白色。

现在试一试用下列三条叙述来代替StretchBlt呼叫:

SelectObject (hdcClient, CreateHatchBrush (HS_DIAGCROSS, RGB (0, 0, 0)));
        
StretchBlt (hdcClient, 0, 0, cxClient, cyClient,
        
                                  hdcWindow, 0, 0, cxSource, cySource, MERGECOPY) ;
        
DeleteObject (hdcClient, GetStockObject (WHITE_BRUSH)) ;
        
这次,您将在图像上看到一个菱形的画刷,这是什么?

我在前面说过,BitBlt和StretchBlt函数不是简单的位块传输。此函数实际在下面三种图像间执行位操作。

Source 来源位图,拉伸或压缩(如果有必要)到目的矩形的尺寸。
  
Destination 在BitBlt或StretchBlt呼叫之前的目的矩形。
  
Pattern 在目的设备内容中选择的目前画刷,水平或垂直地复制到目的矩形范围内。
  
结果是复制到了目的矩形中。

位映像操作与我们在第五章遇到的绘图模式在概念上相似。绘图模式采用图像对象的控件方式,例如一条线就组合成一个目的。我们知道有16种绘图模式-也就是说,对象中的0和1画出时,唯一结果就是目的中0和1的组合。

使用BitBlt和StretchBlt的位映像操作包含了三个对象的组合,这将产生256种位映像操作。有256种方法来组合来源位图、目的位图和图案。有15种位映像操作已经命名-其中一些名称其实还不能够清楚清楚说明其意义-它们定义在WINGDI.H里头,其余的都有数值,列在/Platform SDK/Graphics and Multimedia Services/GDI/Raster Operation Codes/Ternary Raster Operations之中。

有名称的15种ROP代码见表14-4。

表14-4
 


图案(P):1 1 1 1 0 0 0 0

来源(s):1 1 0 0 1 1 0 0

目的(D):1 0 1 0 1 0 1 0
 布尔操作
 ROP代码
 名称
 
结果:
 0 0 0 0 0 0 0 0
 0
 0x000042
 BLACKNESS
 
 0 0 0 1 0 0 0 1
 ~(S?#160;D)
 0x1100A6
 NOTSRCERASE
 
 0 0 1 1 0 0 1 1
 ~S
 0x330008
 NOTSRCCOPY
 
 0 1 0 0 0 1 0 0
 S & ~D
 0x440328
 SRCERASE
 
 0 1 0 1 0 1 0 1
 ~D
 0x550009
 DSTINVERT
 
 0 1 0 1 1 0 1 0
 P ^ D
 0x5A0049
 PATINVERT
 
 0 1 1 0 0 1 1 0
 S ^ D
 0x660046
 SRCINVERT
 
 1 0 0 0 1 0 0 0
 S & D
 0x8800C6
 SRCAND
 
 1 0 1 1 1 0 1 1
 ~S?#160;D
 0xBB0226
 MERGEPAINT
 
 1 1 0 0 0 0 0 0
 P & S
 0xC000CA
 MERGECOPY
 
 1 1 0 0 1 1 0 0
 S
 0xCC0020
 SRCCOPY
 
 1 1 1 0 1 1 1 0
 S?#160;D
 0xEE0086
 SRCPAINT
 
 1 1 1 1 0 0 0 0
 P
 0xF00021
 PATCOPY
 
 1 1 1 1 1 0 1 1
 P?#160; ~S?#160; D
 0xFB0A09
 PATPAINT
 
 1 1 1 1 1 1 1 1
 1
 0xFF0062
 WHITENESS
 

此表格对于理解和使用位映像操作非常重要,因此我们应花点时间来研究。

在这个表格中,「ROP代码」行的值将传递给BitBlt或StretchBlt的最后一个参数;在「名称」行中的值在WINGDI.H定义。ROP代码的低字组协助设备驱动程序传输位映像操作。高字组是0到255之间的数值。此数值与第2列的图案的位相同,这是在图案、来源和显示在顶部的目的之间进行位操作的结果。「布尔运算」列按C语法显示图案、来源和目的的组合方式。

要开始了解此表,最简单的办法是假定您正处理一个单色系统(每图素1位)其中0代表黑色,1代表白色。BLACKNESS操作的结果是不管是来源、目的和图案是什么,全部为零,因此目的将显示黑色。类似地,WHITENESS总导致目的呈白色。

现在假定您使用位映像操作PATCOPY。这导致结果位与图案位相同,而忽略了来源和目的位图。换句话说,PATCOPY简单地将目前图案复制给了目的矩形。

PATPAINT位映像操作包含一个更复杂的操作。其结果相同于在图案、目的和反转的来源之间进行位或操作。当来源位图是黑色(0)时,其结果总是白色(1);当来源是白色(1)时,只要图案或目的为白色,则结果就是白色。换句话说,只有来源为白色而图案和目的都是黑色时,结果才是黑色。

彩色显示时每个图素都使用了多个位。BitBlt和StretchBlt函数对每个颜色位都分别提供了位操作。例如,如果目的是红色而来源为蓝色,SRCPAINT位映像操作把目的变成洋红色。注意,操作实际是按显示卡内储存的位执行的。这些位所对应的颜色取决于显示卡的调色盘的设定。Windows完成了此操作,以便位映像操作能达到您预计的结果。不过,如果您修改了调色盘(我将在第十六章讨论),位映像操作将产生无法预料的结果。

如要得到位映像操作较好的应用程序,请参见本章后面的「非矩形位图图像」一节。

图案Blt


除了BitBlt和StretchBlt以外,Windows还包括一个称为PatBlt (「pattern block transfer:图案块传输」)的函数。这是三个「blt」函数中最简单的。与BitBlt和StretchBlt不同,它只使用一个目的设备内容。PatBlt语法是:

PatBlt (hdc, x, y, cx, cy, dwROP) ;
        
x、y、cx和cy参数字于逻辑单位。逻辑点(x,y)指定了矩形的左上角。矩形宽为cx单位,高为cy单位。这是PatBlt修改的矩形区域。PatBlt在画刷与目的设备内容上执行的逻辑操作由dwROP参数决定,此参数是ROP代码的子集-也就是说,您可以只使用那些不包括来源目的设备内容的ROP代码。下表列出了PatBlt支持的16个位映像操作:

表14-5
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -