Windows程序设计-位图和位块传输

来源:互联网 发布:telnet登录端口 编辑:程序博客网 时间:2024/06/04 19:27

位块传输(BitBlt)

bitblt(bit block transfer)

BITBLT.C
位块传输

/*---------------------------------------   BITBLT.C -- BitBlt Demonstration               (c) Charles Petzold, 1998  ---------------------------------------*/#include <windows.h>LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName [] = TEXT ("BitBlt") ;     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_INFORMATION) ;     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 ;     }     hwnd = CreateWindow (szAppName, TEXT ("BitBlt 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 ;     int         x, y ;     PAINTSTRUCT ps ;     switch (message)     {     case WM_CREATE:          cxSource = GetSystemMetrics (SM_CXSIZEFRAME) +                     GetSystemMetrics (SM_CXSMICON) ;          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) ;          for (y = 0 ; y < cyClient ; y += cySource)          for (x = 0 ; x < cxClient ; x += cxSource)          {              // 位块传输               BitBlt (hdcClient, x, y, cxSource, cySource,                       hdcWindow, 0, 0, SRCCOPY) ;          }          ReleaseDC (hwnd, hdcWindow) ;          EndPaint (hwnd, &ps) ;          return 0 ;     case WM_DESTROY:          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}

拉伸位图(StretchBlt)

拉伸位图

/*----------------------------------------   STRETCH.C -- StretchBlt Demonstration                (c) Charles Petzold, 1998  ----------------------------------------*/#include <windows.h>LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName [] = TEXT ("Stretch") ;     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_INFORMATION) ;     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 ;     }     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_CXSMICON) ;          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) ;}

光栅(位映像)操作

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

  • Source 来源位图,拉伸或压缩(如果有必要)到目的矩形的尺寸。
  • 目标(Destination)在BitBlt或StretchBlt调用之前的目的矩形。
  • 图案(Pattern)在目标设备内容中选择的目前画刷,水平或垂直地不断重复复制到目的矩形范围内。

图案Blt(PatBlt)

Pattern block transfer 图案块传输

PatBlt (hdc, x, y, cx, cy, dwROP);

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

GDI位图对象

GDI位图对象有时也称为设备相关位图,或者DDB(device-dependent bitmap)。

不 要 用 CreateBitmap 、 CreateBitmapIndirect 或SetBitmapBits来设定彩色DDB的位,您只能安全地使用这些函数来设定单色DDB的位。

LoadBitmap

小图
LoadBitmap

/*----------------------------------------   BRICKS1.C -- LoadBitmap Demonstration                (c) Charles Petzold, 1998  ----------------------------------------*/#include <windows.h>LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName [] = TEXT ("Bricks1") ;     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 ;     }     hwnd = CreateWindow (szAppName, TEXT ("LoadBitmap 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 HBITMAP hBitmap ;     static int     cxClient, cyClient, cxSource, cySource ;     BITMAP         bitmap ;     HDC            hdc, hdcMem ;     HINSTANCE      hInstance ;     int            x, y ;     PAINTSTRUCT    ps ;     switch (message)     {     case WM_CREATE:          hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;          // 加载位图          hBitmap = LoadBitmap (hInstance, TEXT ("Bricks")) ;          // 获取对象信息,并填满BITMAP结构的bitmap          GetObject (hBitmap, sizeof (BITMAP), &bitmap) ;          cxSource = bitmap.bmWidth ;          cySource = bitmap.bmHeight ;          return 0 ;     case WM_SIZE:          cxClient = LOWORD (lParam) ;          cyClient = HIWORD (lParam) ;          return 0 ;     case WM_PAINT:          hdc = BeginPaint (hwnd, &ps) ;          // 创建一个与显示器兼容的内存设备内容          hdcMem = CreateCompatibleDC (hdc) ;          // 把位图选入内存设备内容          SelectObject (hdcMem, hBitmap) ;          for (y = 0 ; y < cyClient ; y += cySource)          for (x = 0 ; x < cxClient ; x += cxSource)          {               BitBlt (hdc, x, y, cxSource, cySource, hdcMem, 0, 0, SRCCOPY) ;          }          // 删除内存设备内容          DeleteDC (hdcMem) ;          EndPaint (hwnd, &ps) ;          return 0 ;     case WM_DESTROY:          DeleteObject (hBitmap) ;          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}

单色位图格式

未使用资源

/*-----------------------------------------   BRICKS2.C -- CreateBitmap Demonstration                (c) Charles Petzold, 1998  -----------------------------------------*/#include <windows.h>LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName [] = TEXT ("Bricks2") ;     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 ;     }     hwnd = CreateWindow (szAppName, TEXT ("CreateBitmap 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 BITMAP  bitmap = { 0, 8, 8, 2, 1, 1 } ;     static BYTE    bits [8][2] = { 0xFF, 0, 0x0C, 0, 0x0C, 0, 0x0C, 0,                                    0xFF, 0, 0xC0, 0, 0xC0, 0, 0xC0, 0 } ;     static HBITMAP hBitmap ;     static int     cxClient, cyClient, cxSource, cySource ;     HDC            hdc, hdcMem ;     int            x, y ;     PAINTSTRUCT    ps ;     switch (message)     {     case WM_CREATE:          bitmap.bmBits = bits ;          hBitmap = CreateBitmapIndirect (&bitmap) ;          cxSource = bitmap.bmWidth ;          cySource = bitmap.bmHeight ;          return 0 ;     case WM_SIZE:          cxClient = LOWORD (lParam) ;          cyClient = HIWORD (lParam) ;          return 0 ;     case WM_PAINT:          hdc = BeginPaint (hwnd, &ps) ;          hdcMem = CreateCompatibleDC (hdc) ;          SelectObject (hdcMem, hBitmap) ;          for (y = 0 ; y < cyClient ; y += cySource)          for (x = 0 ; x < cxClient ; x += cxSource)          {               BitBlt (hdc, x, y, cxSource, cySource, hdcMem, 0, 0, SRCCOPY) ;          }          DeleteDC (hdcMem) ;          EndPaint (hwnd, &ps) ;          return 0 ;     case WM_DESTROY:          DeleteObject (hBitmap) ;          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}

窗口类画刷

/*-----------------------------------------------   BRICKS3.C -- CreatePatternBrush Demonstration                (c) Charles Petzold, 1998  -----------------------------------------------*/#include <windows.h>LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName [] = TEXT ("Bricks3") ;     HBITMAP      hBitmap ;     HBRUSH       hBrush ;     HWND         hwnd ;     MSG          msg ;     WNDCLASS     wndclass ;     hBitmap = LoadBitmap (hInstance, TEXT ("Bricks")) ;     hBrush = CreatePatternBrush (hBitmap) ;     DeleteObject (hBitmap) ;     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 ;  // 窗口类画刷     wndclass.lpszMenuName  = NULL ;     wndclass.lpszClassName = szAppName ;     if (!RegisterClass (&wndclass))     {          MessageBox (NULL, TEXT ("This program requires Windows NT!"),                      szAppName, MB_ICONERROR) ;          return 0 ;     }     hwnd = CreateWindow (szAppName, TEXT ("CreatePatternBrush 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) ;     }     // 清除画刷     DeleteObject (hBrush) ;     return msg.wParam ;}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){     switch (message)     {     case WM_DESTROY:          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}

绘制画刷

绘制画刷

绘制画刷

HelloBit.rc

///////////////////////////////////////////////////////////////////////////////// Menu//HELLOBIT MENU DISCARDABLE BEGIN    POPUP "&Size"    BEGIN        MENUITEM "&Big",                        IDM_BIG, CHECKED        MENUITEM "&Small",                      IDM_SMALL    ENDEND

RESOURCE.H

#define IDM_BIG                         40001#define IDM_SMALL                       40002

HelloBit.c

/*-----------------------------------------   HELLOBIT.C -- Bitmap Demonstration                 (c) Charles Petzold, 1998  -----------------------------------------*/#include <windows.h>#include "resource.h"LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName [] = TEXT ("HelloBit") ;     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, TEXT ("HelloBit"),                           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 HBITMAP hBitmap ;     static HDC     hdcMem ;     static int     cxBitmap, cyBitmap, cxClient, cyClient, iSize = IDM_BIG ;     static TCHAR * szText = TEXT (" Hello, world! ") ;     HDC            hdc ;     HMENU          hMenu ;     int            x, y ;     PAINTSTRUCT    ps ;     SIZE           size ;     switch (message)     {     case WM_CREATE:          hdc = GetDC (hwnd) ;          hdcMem  = CreateCompatibleDC (hdc) ;          // 确定字符串像素尺寸          GetTextExtentPoint32 (hdc, szText, lstrlen (szText), &size) ;          cxBitmap = size.cx ;          cyBitmap = size.cy ;          // 创建与显示器兼容的位图          hBitmap = CreateCompatibleBitmap (hdc, cxBitmap, cyBitmap) ;          ReleaseDC (hwnd, hdc) ;          // 载入内存设备内容          SelectObject (hdcMem, hBitmap) ;          // 将文字显示在位图上          TextOut (hdcMem, 0, 0, szText, lstrlen (szText)) ;          return 0 ;     case WM_SIZE:          cxClient = LOWORD (lParam) ;          cyClient = HIWORD (lParam) ;          return 0 ;     case WM_COMMAND:          hMenu = GetMenu (hwnd) ;          switch (LOWORD (wParam))          {          case IDM_BIG:          case IDM_SMALL:               CheckMenuItem (hMenu, iSize, MF_UNCHECKED) ;               iSize = LOWORD (wParam) ;               CheckMenuItem (hMenu, iSize, MF_CHECKED) ;               InvalidateRect (hwnd, NULL, TRUE) ;               break ;          }          return 0 ;     case WM_PAINT:          hdc = BeginPaint (hwnd, &ps) ;          switch (iSize)          {          case IDM_BIG:               StretchBlt (hdc, 0, 0, cxClient, cyClient,                            hdcMem, 0, 0, cxBitmap, cyBitmap, SRCCOPY) ;               break ;          case IDM_SMALL:               for (y = 0 ; y < cyClient ; y += cyBitmap)               for (x = 0 ; x < cxClient ; x += cxBitmap)               {                    BitBlt (hdc, x, y, cxBitmap, cyBitmap,                             hdcMem, 0, 0, SRCCOPY) ;               }               break ;          }          EndPaint (hwnd, &ps) ;          return 0 ;     case WM_DESTROY:          DeleteDC (hdcMem) ;          DeleteObject (hBitmap) ;          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}

阴影位图

阴影位图

/*-----------------------------------------   SKETCH.C -- Shadow Bitmap Demonstration               (c) Charles Petzold, 1998  -----------------------------------------*/#include <windows.h>LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName [] = TEXT ("Sketch") ;     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 ;     }     hwnd = CreateWindow (szAppName, TEXT ("Sketch"),                           WS_OVERLAPPEDWINDOW,                           CW_USEDEFAULT, CW_USEDEFAULT,                          CW_USEDEFAULT, CW_USEDEFAULT,                          NULL, NULL, hInstance, NULL) ;     if (hwnd == NULL)     {          MessageBox (NULL, TEXT ("Not enough memory to create bitmap!"),                      szAppName, MB_ICONERROR) ;          return 0 ;     }     ShowWindow (hwnd, iCmdShow) ;     UpdateWindow (hwnd) ;     while (GetMessage (&msg, NULL, 0, 0))     {          TranslateMessage (&msg) ;          DispatchMessage (&msg) ;     }     return msg.wParam ;}void GetLargestDisplayMode (int * pcxBitmap, int * pcyBitmap){     DEVMODE devmode ;     int     iModeNum = 0 ;     * pcxBitmap = * pcyBitmap = 0 ;     ZeroMemory (&devmode, sizeof (DEVMODE)) ;     devmode.dmSize = sizeof (DEVMODE) ;     // EnumDisplaySettings使用DEVMODE结构来传回全部有效视讯显示模式的信息     while (EnumDisplaySettings (NULL, iModeNum++, &devmode))     {          * pcxBitmap = max (* pcxBitmap, (int) devmode.dmPelsWidth) ;          * pcyBitmap = max (* pcyBitmap, (int) devmode.dmPelsHeight) ;     }}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){     static BOOL    fLeftButtonDown, fRightButtonDown ;     static HBITMAP hBitmap ;     static HDC     hdcMem ;     static int     cxBitmap, cyBitmap, cxClient, cyClient, xMouse, yMouse ;     HDC            hdc ;     PAINTSTRUCT    ps ;     switch (message)     {     case WM_CREATE:          GetLargestDisplayMode (&cxBitmap, &cyBitmap) ;          hdc = GetDC (hwnd) ;          hBitmap = CreateCompatibleBitmap (hdc, cxBitmap, cyBitmap) ;          hdcMem  = CreateCompatibleDC (hdc) ;          ReleaseDC (hwnd, hdc) ;          if (!hBitmap)       // no memory for bitmap          {               DeleteDC (hdcMem) ;               return -1 ;          }          SelectObject (hdcMem, hBitmap) ;          PatBlt (hdcMem, 0, 0, cxBitmap, cyBitmap, WHITENESS) ;          return 0 ;     case WM_SIZE:          cxClient = LOWORD (lParam) ;          cyClient = HIWORD (lParam) ;          return 0 ;     case WM_LBUTTONDOWN:          if (!fRightButtonDown)               SetCapture (hwnd) ;          xMouse = LOWORD (lParam) ;          yMouse = HIWORD (lParam) ;          fLeftButtonDown = TRUE ;          return 0 ;     case WM_LBUTTONUP:          if (fLeftButtonDown)               SetCapture (NULL) ;          fLeftButtonDown = FALSE ;          return 0 ;     case WM_RBUTTONDOWN:          if (!fLeftButtonDown)               SetCapture (hwnd) ;          xMouse = LOWORD (lParam) ;          yMouse = HIWORD (lParam) ;          fRightButtonDown = TRUE ;          return 0 ;     case WM_RBUTTONUP:          if (fRightButtonDown)                SetCapture (NULL) ;          fRightButtonDown = FALSE ;          return 0 ;     case WM_MOUSEMOVE:          if (!fLeftButtonDown && !fRightButtonDown)               return 0 ;          hdc = GetDC (hwnd) ;          SelectObject (hdc,                GetStockObject (fLeftButtonDown ? BLACK_PEN : WHITE_PEN)) ;          SelectObject (hdcMem,               GetStockObject (fLeftButtonDown ? BLACK_PEN : WHITE_PEN)) ;          MoveToEx (hdc,    xMouse, yMouse, NULL) ;          MoveToEx (hdcMem, xMouse, yMouse, NULL) ;          xMouse = (short) LOWORD (lParam) ;          yMouse = (short) HIWORD (lParam) ;          LineTo (hdc,    xMouse, yMouse) ;          LineTo (hdcMem, xMouse, yMouse) ;          ReleaseDC (hwnd, hdc) ;          return 0 ;     case WM_PAINT:          hdc = BeginPaint (hwnd, &ps) ;          BitBlt (hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY) ;          EndPaint (hwnd, &ps) ;          return 0 ;     case WM_DESTROY:          DeleteDC (hdcMem) ;          DeleteObject (hBitmap) ;          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}

在菜单中使用位图

在顶层菜单中,Windows调整菜单列的高度以适应最高的位图。其它位图(或字符串)是根据菜单列的顶端对齐的。如果在顶层菜单中使用了位图,那么从使用常数SM_CYMENU的GetSystemMetrics得到的菜单列大小将不再有效。
执行GRAFMENU期间可以看到:在弹出式菜单中,您可使用带有位图菜单项的勾选标记,但勾选标记是正常尺寸。如果不满意,您可以建立一个自订的勾选标记,并使用SetMenuItemBitmaps。
在菜单中使用非文字(或者使用非系统字体的文字)的另一种方法是「拥有者绘制」菜单。
菜单的键盘接口是另一个问题。当菜单含有文字时,Windows会自动添加键盘接口。要选择一个菜单项,可以使用Alt与字符串中的一个字母的组合键。而一旦在菜单中放置了位图,就删除了键盘接口。即使位图表达了一定的含义,但Windows并不知道。
目前我们可以使用WM_MENUCHAR消息。 当您按下Alt和与菜单项不相符的一个字符键的组合键时,Windows将向您的窗口消息处理程序发送一个WM_MENUCHAR消息。
GRAFMENU需要截取WM_MENUCHAR消息并检查wParam的值(即按键的ASCII码)。
如果这个值对应一个菜单项,那么向Windows传回双字组:其中高字组为2,低字组是与该键相关的菜单项索引值。然后由Windows处理余下的事。

在顶层菜单中,Windows调整菜单列的高度以适应最高的位图。其它位图(或字符串)是根据
菜单列的顶端对齐的。如果在顶层菜单中使用了位图,那么从使用常数SM_CYMENU的
GetSystemMetrics得到的菜单列大小将不再有效。
执行GRAFMENU期间可以看到:在弹出式菜单中,您可使用带有位图菜单项的勾选标记,
但勾选标记是正常尺寸。如果不满意,您可以建立一个自订的勾选标记,并使用
SetMenuItemBitmaps。
在菜单中使用非文字(或者使用非系统字体的文字)的另一种方法是「拥有者绘制」菜单。
菜单的键盘接口是另一个问题。当菜单含有文字时,Windows会自动添加键盘接口。要选
择一个菜单项,可以使用Alt与字符串中的一个字母的组合键。而一旦在菜单中放置了位图,
就删除了键盘接口。即使位图表达了一定的含义,但Windows并不知道。
目前我们可以使用WM_MENUCHAR消息。 当您按下Alt和与菜单项不相符的一个字符键的
组合键时,Windows将向您的窗口消息处理程序发送一个WM_MENUCHAR消息。
GRAFMENU需要截取WM_MENUCHAR消息并检查wParam的值(即按键的ASCII码)。
如果这个值对应一个菜单项,那么向Windows传回双字组:其中高字组为2,低字组是与该键相关的菜单项索引值。然后由Windows处理余下的事。

菜单

菜单

菜单

GrafMenu.rc

///////////////////////////////////////////////////////////////////////////////// Menu//MENUFILE MENU DISCARDABLE BEGIN    MENUITEM "&New",                        IDM_FILE_NEW    MENUITEM "&Open...",                    IDM_FILE_OPEN    MENUITEM "&Save",                       IDM_FILE_SAVE    MENUITEM "Save &As...",                 IDM_FILE_SAVE_ASENDMENUEDIT MENU DISCARDABLE BEGIN    MENUITEM "&Undo",                       IDM_EDIT_UNDO    MENUITEM SEPARATOR    MENUITEM "Cu&t",                        IDM_EDIT_CUT    MENUITEM "&Copy",                       IDM_EDIT_COPY    MENUITEM "&Paste",                      IDM_EDIT_PASTE    MENUITEM "De&lete",                     IDM_EDIT_CLEAREND///////////////////////////////////////////////////////////////////////////////// Bitmap//BITMAPFONT              BITMAP  DISCARDABLE     "Fontlabl.bmp"BITMAPHELP              BITMAP  DISCARDABLE     "Bighelp.bmp"BITMAPEDIT              BITMAP  DISCARDABLE     "Editlabl.bmp"BITMAPFILE              BITMAP  DISCARDABLE     "Filelabl.bmp"#endif    // English (U.S.) resources/////////////////////////////////////////////////////////////////////////////

RESOURCE.H

#define IDM_FONT_COUR                   101#define IDM_FONT_ARIAL                  102#define IDM_FONT_TIMES                  103#define IDM_HELP                        104#define IDM_EDIT_UNDO                   40005#define IDM_EDIT_CUT                    40006#define IDM_EDIT_COPY                   40007#define IDM_EDIT_PASTE                  40008#define IDM_EDIT_CLEAR                  40009#define IDM_FILE_NEW                    40010#define IDM_FILE_OPEN                   40011#define IDM_FILE_SAVE                   40012#define IDM_FILE_SAVE_AS                40013

GrafMenu.c

/*----------------------------------------------   GRAFMENU.C -- Demonstrates Bitmap Menu Items                 (c) Charles Petzold, 1998  ----------------------------------------------*/#include <windows.h>#include "resource.h"LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;void    AddHelpToSys     (HINSTANCE, HWND) ;HMENU   CreateMyMenu     (HINSTANCE) ;HBITMAP StretchBitmap    (HBITMAP) ;HBITMAP GetBitmapFont    (int) ;void    DeleteAllBitmaps (HWND) ;TCHAR szAppName[] = TEXT ("GrafMenu") ;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 ;     }     hwnd = CreateWindow (szAppName, TEXT ("Bitmap Menu Demonstration"),                          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 iMsg, WPARAM wParam, LPARAM lParam){     HMENU      hMenu ;     static int iCurrentFont = IDM_FONT_COUR ;     switch (iMsg)     {     case WM_CREATE:          AddHelpToSys (((LPCREATESTRUCT) lParam)->hInstance, hwnd) ;          hMenu = CreateMyMenu (((LPCREATESTRUCT) lParam)->hInstance) ;          SetMenu (hwnd, hMenu) ;          CheckMenuItem (hMenu, iCurrentFont, MF_CHECKED) ;          return 0 ;     case WM_SYSCOMMAND:          switch (LOWORD (wParam))          {          case IDM_HELP:               MessageBox (hwnd, TEXT ("Help not yet implemented!"),                           szAppName, MB_OK | MB_ICONEXCLAMATION) ;               return 0 ;          }          break ;     case WM_COMMAND:          switch (LOWORD (wParam))          {          case IDM_FILE_NEW:          case IDM_FILE_OPEN:          case IDM_FILE_SAVE:          case IDM_FILE_SAVE_AS:          case IDM_EDIT_UNDO:          case IDM_EDIT_CUT:          case IDM_EDIT_COPY:          case IDM_EDIT_PASTE:          case IDM_EDIT_CLEAR:               MessageBeep (0) ;               return 0 ;          case IDM_FONT_COUR:          case IDM_FONT_ARIAL:          case IDM_FONT_TIMES:               hMenu = GetMenu (hwnd) ;               CheckMenuItem (hMenu, iCurrentFont, MF_UNCHECKED) ;               iCurrentFont = LOWORD (wParam) ;               CheckMenuItem (hMenu, iCurrentFont, MF_CHECKED) ;               return 0 ;          }          break ;     case WM_DESTROY:          DeleteAllBitmaps (hwnd) ;          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, iMsg, wParam, lParam) ;}/*----------------------------------------------------   AddHelpToSys: Adds bitmap Help item to system menu  ----------------------------------------------------*/void AddHelpToSys (HINSTANCE hInstance, HWND hwnd){     HBITMAP hBitmap ;     HMENU   hMenu ;     // 获取系统菜单     hMenu = GetSystemMenu (hwnd, FALSE);     // 载入位图     hBitmap = StretchBitmap (LoadBitmap (hInstance, TEXT ("BitmapHelp"))) ;     // 附加分割线     AppendMenu (hMenu, MF_SEPARATOR, 0, NULL) ;     // 附加位图菜单项     AppendMenu (hMenu, MF_BITMAP, IDM_HELP, (PTSTR) (LONG) hBitmap) ;}/*----------------------------------------------   CreateMyMenu: Assembles menu from components  ----------------------------------------------*/HMENU CreateMyMenu (HINSTANCE hInstance){     HBITMAP hBitmap ;     HMENU   hMenu, hMenuPopup ;     int     i ;     hMenu = CreateMenu () ;     hMenuPopup = LoadMenu (hInstance, TEXT ("MenuFile")) ;     hBitmap = StretchBitmap (LoadBitmap (hInstance, TEXT ("BitmapFile"))) ;     AppendMenu (hMenu, MF_BITMAP | MF_POPUP, (int) hMenuPopup,                        (PTSTR) (LONG) hBitmap) ;     hMenuPopup = LoadMenu (hInstance, TEXT ("MenuEdit")) ;     hBitmap = StretchBitmap (LoadBitmap (hInstance, TEXT ("BitmapEdit"))) ;     AppendMenu (hMenu, MF_BITMAP | MF_POPUP, (int) hMenuPopup,                        (PTSTR) (LONG) hBitmap) ;     hMenuPopup = CreateMenu () ;     for (i = 0 ; i < 3 ; i++)     {          hBitmap = GetBitmapFont (i) ;          AppendMenu (hMenuPopup, MF_BITMAP, IDM_FONT_COUR + i,                                   (PTSTR) (LONG) hBitmap) ;     }     hBitmap = StretchBitmap (LoadBitmap (hInstance, TEXT ("BitmapFont"))) ;     AppendMenu (hMenu, MF_BITMAP | MF_POPUP, (int) hMenuPopup,                        (PTSTR) (LONG) hBitmap) ;     return hMenu ;}/*----------------------------------------------------   StretchBitmap: Scales bitmap to display resolution  ----------------------------------------------------*/HBITMAP StretchBitmap (HBITMAP hBitmap1){     BITMAP     bm1, bm2 ;     HBITMAP    hBitmap2 ;     HDC        hdc, hdcMem1, hdcMem2 ;     int        cxChar, cyChar ;          // Get the width and height of a system font character     cxChar = LOWORD (GetDialogBaseUnits ()) ;     cyChar = HIWORD (GetDialogBaseUnits ()) ;          // Create 2 memory DCs compatible with the display     // 获得显示器设备内容     hdc = CreateIC (TEXT ("DISPLAY"), NULL, NULL, NULL) ;     hdcMem1 = CreateCompatibleDC (hdc) ;     hdcMem2 = CreateCompatibleDC (hdc) ;     DeleteDC (hdc) ;          // Get the dimensions of the bitmap to be stretched     GetObject (hBitmap1, sizeof (BITMAP), (PTSTR) &bm1) ;          // Scale these dimensions based on the system font size     bm2 = bm1 ;     bm2.bmWidth      = (cxChar * bm2.bmWidth)  / 4 ;     bm2.bmHeight     = (cyChar * bm2.bmHeight) / 8 ;     bm2.bmWidthBytes = ((bm2.bmWidth + 15) / 16) * 2 ;          // Create a new bitmap of larger size     hBitmap2 = CreateBitmapIndirect (&bm2) ;          // Select the bitmaps in the memory DCs and do a StretchBlt     SelectObject (hdcMem1, hBitmap1) ;     SelectObject (hdcMem2, hBitmap2) ;     // 根据显示器大小来拉伸变形     StretchBlt (hdcMem2, 0, 0, bm2.bmWidth, bm2.bmHeight,                 hdcMem1, 0, 0, bm1.bmWidth, bm1.bmHeight, SRCCOPY) ;          // Clean up     DeleteDC (hdcMem1) ;     DeleteDC (hdcMem2) ;     DeleteObject (hBitmap1) ;     return hBitmap2 ;}/*------------------------------------------------   GetBitmapFont: Creates bitmaps with font names  ------------------------------------------------*/HBITMAP GetBitmapFont (int i){     static TCHAR  * szFaceName[3] = { TEXT ("Courier New"), TEXT ("Arial"),                                        TEXT ("Times New Roman") } ;     HBITMAP         hBitmap ;     HDC             hdc, hdcMem ;     HFONT           hFont ;     SIZE            size ;     TEXTMETRIC      tm ;     // 获得显示器的设备内容     hdc = CreateIC (TEXT ("DISPLAY"), NULL, NULL, NULL) ;     GetTextMetrics (hdc, &tm) ;     hdcMem = CreateCompatibleDC (hdc) ;     // 创建字体     hFont  = CreateFont (2 * tm.tmHeight, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                          szFaceName[i]) ;     // 从内存设备内容载入字体     hFont = (HFONT) SelectObject (hdcMem, hFont) ;     // 获取字体大小     GetTextExtentPoint32 (hdcMem, szFaceName[i],                            lstrlen (szFaceName[i]), &size);     // 根据以上信息建立位图     hBitmap = CreateBitmap (size.cx, size.cy, 1, 1, NULL) ;     SelectObject (hdcMem, hBitmap) ;     // 书写文字     TextOut (hdcMem, 0, 0, szFaceName[i], lstrlen (szFaceName[i])) ;     // 收尾清除工作     DeleteObject (SelectObject (hdcMem, hFont)) ;     DeleteDC (hdcMem) ;     DeleteDC (hdc) ;     return hBitmap ;}/*-------------------------------------------------------    DeleteAllBitmaps: Deletes all the bitmaps in the menu  -------------------------------------------------------*/void DeleteAllBitmaps (HWND hwnd){     HMENU        hMenu ;     int          i ;     MENUITEMINFO mii = { sizeof (MENUITEMINFO), MIIM_SUBMENU | MIIM_TYPE } ;          // Delete Help bitmap on system menu     hMenu = GetSystemMenu (hwnd, FALSE);     GetMenuItemInfo (hMenu, IDM_HELP, FALSE, &mii) ;     DeleteObject ((HBITMAP) mii.dwTypeData) ;          // Delete top-level menu bitmaps     hMenu = GetMenu (hwnd) ;     for (i = 0 ; i < 3 ; i++)     {          GetMenuItemInfo (hMenu, i, TRUE, &mii) ;          DeleteObject ((HBITMAP) mii.dwTypeData) ;     }          // Delete bitmap items on Font menu     hMenu = mii.hSubMenu ;;     for (i = 0 ; i < 3 ; i++)     {          GetMenuItemInfo (hMenu, i, TRUE, &mii) ;          DeleteObject ((HBITMAP) mii.dwTypeData) ;     }}

非矩形位图图像

遮罩
遮罩
BitMask.rc

///////////////////////////////////////////////////////////////////////////////// Bitmap//MATTHEW                 BITMAP  DISCARDABLE     "matthew.bmp"

BitMask.c

/*-------------------------------------------   BITMASK.C -- Bitmap Masking Demonstration                (c) Charles Petzold, 1998  -------------------------------------------*/#include <windows.h>LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName [] = TEXT ("BitMask") ;     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 (LTGRAY_BRUSH) ;     wndclass.lpszMenuName  = NULL ;     wndclass.lpszClassName = szAppName ;     if (!RegisterClass (&wndclass))     {          MessageBox (NULL, TEXT ("This program requires Windows NT!"),                      szAppName, MB_ICONERROR) ;          return 0 ;     }     hwnd = CreateWindow (szAppName, TEXT ("Bitmap Masking 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 HBITMAP   hBitmapImag, hBitmapMask ;     static HINSTANCE hInstance ;     static int       cxClient, cyClient, cxBitmap, cyBitmap ;     BITMAP           bitmap ;     HDC              hdc, hdcMemImag, hdcMemMask ;     int              x, y ;     PAINTSTRUCT      ps ;     switch (message)     {     case WM_CREATE:          hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;               // Load the original image and get its size          // 获取原始图像句柄          hBitmapImag = LoadBitmap (hInstance, TEXT ("Matthew")) ;          // 获取图像宽高          GetObject (hBitmapImag, sizeof (BITMAP), &bitmap) ;          cxBitmap = bitmap.bmWidth ;          cyBitmap = bitmap.bmHeight ;               // Select the original image into a memory DC          // 选入内存设备内容          hdcMemImag  = CreateCompatibleDC (NULL) ;          SelectObject (hdcMemImag, hBitmapImag) ;               // Create the monochrome mask bitmap and memory DC          // 创建与原图一样大的遮罩          hBitmapMask = CreateBitmap (cxBitmap, cyBitmap, 1, 1, NULL) ;          hdcMemMask = CreateCompatibleDC (NULL) ;          // 选入内存设备内容          SelectObject (hdcMemMask, hBitmapMask) ;               // Color the mask bitmap black with a white ellipse          // 在遮罩上换一个黑色0矩形和白色1椭圆          SelectObject (hdcMemMask, GetStockObject (BLACK_BRUSH)) ;          Rectangle (hdcMemMask, 0, 0, cxBitmap, cyBitmap) ;          SelectObject (hdcMemMask, GetStockObject (WHITE_BRUSH)) ;          Ellipse (hdcMemMask, 0, 0, cxBitmap, cyBitmap) ;               // Mask the original image          // 用MaskBlt更方便 Win98不支持          // 用遮罩屏蔽原图像 AND操作          BitBlt (hdcMemImag, 0, 0, cxBitmap, cyBitmap,                   hdcMemMask, 0, 0, SRCAND) ;          DeleteDC (hdcMemImag) ;          DeleteDC (hdcMemMask) ;          return 0 ;     case WM_SIZE:          cxClient = LOWORD (lParam) ;          cyClient = HIWORD (lParam) ;          return 0 ;     case WM_PAINT:          hdc = BeginPaint (hwnd, &ps) ;               // Select bitmaps into memory DCs          hdcMemImag = CreateCompatibleDC (hdc) ;          SelectObject (hdcMemImag, hBitmapImag) ;          hdcMemMask = CreateCompatibleDC (hdc) ;          SelectObject (hdcMemMask, hBitmapMask) ;               // Center image          x = (cxClient - cxBitmap) / 2 ;          y = (cyClient - cyBitmap) / 2 ;               // Do the bitblts          // 屏蔽掉椭圆:D & ~S (反色来源,然后AND目标)          BitBlt (hdc, x, y, cxBitmap, cyBitmap, hdcMemMask, 0, 0, 0x220326) ;          // 绘制位图 OR          BitBlt (hdc, x, y, cxBitmap, cyBitmap, hdcMemImag, 0, 0, SRCPAINT) ;          DeleteDC (hdcMemImag) ;          DeleteDC (hdcMemMask) ;          EndPaint (hwnd, &ps) ;          return 0 ;     case WM_DESTROY:          DeleteObject (hBitmapImag) ;          DeleteObject (hBitmapMask) ;          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}

简单的动画

简单动画
高级动画选DirectX,就不要用GDI了。

/*---------------------------------------   BOUNCE.C -- Bouncing Ball Program               (c) Charles Petzold, 1998  ---------------------------------------*/#include <windows.h>#define ID_TIMER    1LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName[] = TEXT ("Bounce") ;     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 ;     }     hwnd = CreateWindow (szAppName, TEXT ("Bouncing Ball"),                          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 iMsg, WPARAM wParam, LPARAM lParam){     static HBITMAP hBitmap ;     static int     cxClient, cyClient, xCenter, yCenter, cxTotal, cyTotal,                    cxRadius, cyRadius, cxMove, cyMove, xPixel, yPixel ;     HBRUSH         hBrush ;     HDC            hdc, hdcMem ;     int            iScale ;     switch (iMsg)     {     case WM_CREATE:          hdc = GetDC (hwnd) ;          xPixel = GetDeviceCaps (hdc, ASPECTX) ;          yPixel = GetDeviceCaps (hdc, ASPECTY) ;          ReleaseDC (hwnd, hdc) ;          SetTimer (hwnd, ID_TIMER, 50, NULL) ;          return 0 ;     case WM_SIZE: // 重绘          xCenter = (cxClient = LOWORD (lParam)) / 2 ;          yCenter = (cyClient = HIWORD (lParam)) / 2 ;          iScale = min (cxClient * xPixel, cyClient * yPixel) / 16 ;          cxRadius = iScale / xPixel ;          cyRadius = iScale / yPixel ;          cxMove = max (1, cxRadius / 2) ;          cyMove = max (1, cyRadius / 2) ;          cxTotal = 2 * (cxRadius + cxMove) ;          cyTotal = 2 * (cyRadius + cyMove) ;          if (hBitmap)               DeleteObject (hBitmap) ;          hdc = GetDC (hwnd) ;          // 创建与显示器兼容内存设备内容          hdcMem = CreateCompatibleDC (hdc) ;          // 创建位图(小球)          hBitmap = CreateCompatibleBitmap (hdc, cxTotal, cyTotal) ;          ReleaseDC (hwnd, hdc) ;          // 选入内存设备内容          SelectObject (hdcMem, hBitmap) ;          // 位图背景设为白色          Rectangle (hdcMem, -1, -1, cxTotal + 1, cyTotal + 1) ;          hBrush = CreateHatchBrush (HS_DIAGCROSS, 0L) ;          SelectObject (hdcMem, hBrush) ;          SetBkColor (hdcMem, RGB (255, 0, 255)) ;          Ellipse (hdcMem, cxMove, cyMove, cxTotal - cxMove, cyTotal - cyMove) ;          DeleteDC (hdcMem) ;          DeleteObject (hBrush) ;          return 0 ;     case WM_TIMER:          if (!hBitmap)               break ;          hdc = GetDC (hwnd) ;          hdcMem = CreateCompatibleDC (hdc) ;          SelectObject (hdcMem, hBitmap) ;          // 使用ROP代码为SRCCOPY,来重画小球          BitBlt (hdc, xCenter - cxTotal / 2,                       yCenter - cyTotal / 2, cxTotal, cyTotal,                  hdcMem, 0, 0, SRCCOPY) ;          ReleaseDC (hwnd, hdc) ;          DeleteDC (hdcMem) ;          xCenter += cxMove ;          yCenter += cyMove ;          if ((xCenter + cxRadius >= cxClient) || (xCenter - cxRadius <= 0))               cxMove = -cxMove ;          if ((yCenter + cyRadius >= cyClient) || (yCenter - cyRadius <= 0))               cyMove = -cyMove ;          return 0 ;     case WM_DESTROY:          if (hBitmap)               DeleteObject (hBitmap) ;          KillTimer (hwnd, ID_TIMER) ;          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, iMsg, wParam, lParam) ;}

窗口外的位图

在窗口产生矩形位图

/*------------------------------------------------   SCRAMBLE.C -- Scramble (and Unscramble) Screen                 (c) Charles Petzold, 1998  ------------------------------------------------*/#include <windows.h>#define NUM 300LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static int iKeep [NUM][4] ;     HDC        hdcScr, hdcMem ;     int        cx, cy ;     HBITMAP    hBitmap ;     HWND       hwnd ;     int        i, j, x1, y1, x2, y2 ;     // LockWindowUpdate暂停其他程序更新屏幕     if (LockWindowUpdate (hwnd = GetDesktopWindow ()))     {         // 带DCX_LOCKWINDOWUPDATE,获得整个屏幕的设备内容          hdcScr  = GetDCEx (hwnd, NULL, DCX_CACHE | DCX_LOCKWINDOWUPDATE) ;          hdcMem  = CreateCompatibleDC (hdcScr) ;          // 使用长宽为1/10的屏幕大小来建立位图          cx      = GetSystemMetrics (SM_CXSCREEN) / 10 ;          cy      = GetSystemMetrics (SM_CYSCREEN) / 10 ;          hBitmap = CreateCompatibleBitmap (hdcScr, cx, cy) ;          SelectObject (hdcMem, hBitmap) ;          // 产生两个随机坐标          srand ((int) GetCurrentTime ()) ;          for (i = 0 ; i < 2   ; i++)          for (j = 0 ; j < NUM ; j++)          {               if (i == 0)               {                    iKeep [j] [0] = x1 = cx * (rand () % 10) ;                    iKeep [j] [1] = y1 = cy * (rand () % 10) ;                    iKeep [j] [2] = x2 = cx * (rand () % 10) ;                    iKeep [j] [3] = y2 = cy * (rand () % 10) ;               }               else               {                    x1 = iKeep [NUM - 1 - j] [0] ;                    y1 = iKeep [NUM - 1 - j] [1] ;                    x2 = iKeep [NUM - 1 - j] [2] ;                    y2 = iKeep [NUM - 1 - j] [3] ;               }               // 交换显示器上两个矩形中的内容:               // 将从第一个坐标点开始的矩形复制到内存设备内容               BitBlt (hdcMem,  0,  0, cx, cy, hdcScr, x1, y1, SRCCOPY) ;               // 将从第二坐标点开始的矩形复制到第一点开始的位置               BitBlt (hdcScr, x1, y1, cx, cy, hdcScr, x2, y2, SRCCOPY) ;               // 将内存设备内容中的矩形复制到第二个坐标点开始的区域               BitBlt (hdcScr, x2, y2, cx, cy, hdcMem,  0,  0, SRCCOPY) ;               Sleep (10) ;          }          DeleteDC (hdcMem) ;          ReleaseDC (hwnd, hdcScr) ;          DeleteObject (hBitmap) ;          LockWindowUpdate (NULL) ;     }     return FALSE ;}

截屏

Blowup.rc

//////////////////////////////////////////////////////////////////////////////// Menu//BLOWUP MENU DISCARDABLE BEGIN    POPUP "&Edit"    BEGIN        MENUITEM "Cu&t\tCtrl+X",                IDM_EDIT_CUT        MENUITEM "&Copy\tCtrl+C",               IDM_EDIT_COPY        MENUITEM "&Paste\tCtrl+V",              IDM_EDIT_PASTE        MENUITEM "De&lete\tDelete",             IDM_EDIT_DELETE    ENDEND///////////////////////////////////////////////////////////////////////////////// Accelerator//BLOWUP ACCELERATORS DISCARDABLE BEGIN    "C",            IDM_EDIT_COPY,          VIRTKEY, CONTROL, NOINVERT    "V",            IDM_EDIT_PASTE,         VIRTKEY, CONTROL, NOINVERT    VK_DELETE,      IDM_EDIT_DELETE,        VIRTKEY, NOINVERT    "X",            IDM_EDIT_CUT,           VIRTKEY, CONTROL, NOINVERTEND#endif

RESOURCE.H

#define IDM_EDIT_CUT                    40001#define IDM_EDIT_COPY                   40002#define IDM_EDIT_PASTE                  40003#define IDM_EDIT_DELETE                 40004

Blowup.c

/*---------------------------------------   BLOWUP.C -- Video Magnifier Program               (c) Charles Petzold, 1998  ---------------------------------------*/#include <windows.h>#include <windowsx.h>  //Added by translator#include <stdlib.h>      // for abs definition#include "resource.h"LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName [] = TEXT ("Blowup") ;     HACCEL       hAccel ;     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, TEXT ("Blow-Up Mouse Demo"),                           WS_OVERLAPPEDWINDOW,                           CW_USEDEFAULT, CW_USEDEFAULT,                          CW_USEDEFAULT, CW_USEDEFAULT,                          NULL, NULL, hInstance, NULL) ;     ShowWindow (hwnd, iCmdShow) ;     UpdateWindow (hwnd) ;     hAccel = LoadAccelerators (hInstance, szAppName) ;     while (GetMessage (&msg, NULL, 0, 0))     {          if (!TranslateAccelerator (hwnd, hAccel, &msg))          {               TranslateMessage (&msg) ;               DispatchMessage (&msg) ;          }     }     return msg.wParam ;}void InvertBlock (HWND hwndScr, HWND hwnd, POINT ptBeg, POINT ptEnd){     HDC hdc ;     hdc = GetDCEx (hwndScr, NULL, DCX_CACHE | DCX_LOCKWINDOWUPDATE) ;     ClientToScreen (hwnd, &ptBeg) ;     ClientToScreen (hwnd, &ptEnd) ;     PatBlt (hdc, ptBeg.x, ptBeg.y, ptEnd.x - ptBeg.x, ptEnd.y - ptBeg.y,             DSTINVERT) ;     ReleaseDC (hwndScr, hdc) ;}HBITMAP CopyBitmap (HBITMAP hBitmapSrc){     BITMAP  bitmap ;     HBITMAP hBitmapDst ;     HDC     hdcSrc, hdcDst ;     GetObject (hBitmapSrc, sizeof (BITMAP), &bitmap) ;     hBitmapDst = CreateBitmapIndirect (&bitmap) ;     hdcSrc = CreateCompatibleDC (NULL) ;     hdcDst = CreateCompatibleDC (NULL) ;     SelectObject (hdcSrc, hBitmapSrc) ;     SelectObject (hdcDst, hBitmapDst) ;     BitBlt (hdcDst, 0, 0, bitmap.bmWidth, bitmap.bmHeight,             hdcSrc, 0, 0, SRCCOPY) ;     DeleteDC (hdcSrc) ;     DeleteDC (hdcDst) ;     return hBitmapDst ;}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){     static BOOL    bCapturing, bBlocking ;     static HBITMAP hBitmap ;     static HWND    hwndScr ;     static POINT   ptBeg, ptEnd ;     BITMAP         bm ;     HBITMAP        hBitmapClip ;     HDC            hdc, hdcMem ;     int            iEnable ;     PAINTSTRUCT    ps ;     RECT           rect ;     switch (message)     {     case WM_LBUTTONDOWN:          if (!bCapturing)          {               if (LockWindowUpdate (hwndScr = GetDesktopWindow ()))               {                    bCapturing = TRUE ;                    SetCapture (hwnd) ;                    SetCursor (LoadCursor (NULL, IDC_CROSS)) ;               }               else                    MessageBeep (0) ;          }          return 0 ;     case WM_RBUTTONDOWN:          if (bCapturing)          {               bBlocking = TRUE ;               //ptBeg.x = LOWORD (lParam) ; //wrong code               //ptBeg.y = HIWORD (lParam) ;                ptBeg.x = GET_X_LPARAM(lParam) ; //added by translator: should use GET_X_LPARAM/GET_Y_LPARAM to retreive the co-ordination               ptBeg.y = GET_Y_LPARAM(lParam) ;               ptEnd = ptBeg ;               InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;          }          return 0 ;     case WM_MOUSEMOVE:          if (bBlocking)          {               InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;                //ptEnd.x = LOWORD (lParam) ;                //ptEnd.y = HIWORD (lParam) ;                ptEnd.x = GET_X_LPARAM(lParam) ;                ptEnd.y = GET_Y_LPARAM(lParam) ;               InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;          }          return 0 ;     case WM_LBUTTONUP:     case WM_RBUTTONUP:          if (bBlocking)          {               InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;               //ptEnd.x = LOWORD (lParam) ;               //ptEnd.y = HIWORD (lParam) ;                ptEnd.x = GET_X_LPARAM(lParam) ;                ptEnd.y = GET_Y_LPARAM(lParam) ;               if (hBitmap)               {                    DeleteObject (hBitmap) ;                    hBitmap = NULL ;               }               hdc = GetDC (hwnd) ;               hdcMem = CreateCompatibleDC (hdc) ;               hBitmap = CreateCompatibleBitmap (hdc,                                    abs (ptEnd.x - ptBeg.x),                                   abs (ptEnd.y - ptBeg.y)) ;               SelectObject (hdcMem, hBitmap) ;               StretchBlt (hdcMem, 0, 0, abs (ptEnd.x - ptBeg.x),                                         abs (ptEnd.y - ptBeg.y),                            hdc, ptBeg.x, ptBeg.y, ptEnd.x - ptBeg.x,                                                   ptEnd.y - ptBeg.y, SRCCOPY) ;               DeleteDC (hdcMem) ;               ReleaseDC (hwnd, hdc) ;               InvalidateRect (hwnd, NULL, TRUE) ;          }          if (bBlocking || bCapturing)          {               bBlocking = bCapturing = FALSE ;               SetCursor (LoadCursor (NULL, IDC_ARROW)) ;               ReleaseCapture () ;               LockWindowUpdate (NULL) ;          }          return 0 ;     case WM_INITMENUPOPUP:          iEnable = IsClipboardFormatAvailable (CF_BITMAP) ?                               MF_ENABLED : MF_GRAYED ;          EnableMenuItem ((HMENU) wParam, IDM_EDIT_PASTE, iEnable) ;          iEnable = hBitmap ? MF_ENABLED : MF_GRAYED ;          EnableMenuItem ((HMENU) wParam, IDM_EDIT_CUT,    iEnable) ;          EnableMenuItem ((HMENU) wParam, IDM_EDIT_COPY,   iEnable) ;          EnableMenuItem ((HMENU) wParam, IDM_EDIT_DELETE, iEnable) ;          return 0 ;     case WM_COMMAND:          switch (LOWORD (wParam))          {          case IDM_EDIT_CUT:          case IDM_EDIT_COPY:               if (hBitmap)               {                    hBitmapClip = CopyBitmap (hBitmap) ;                    OpenClipboard (hwnd) ;                    EmptyClipboard () ;                    SetClipboardData (CF_BITMAP, hBitmapClip) ;               }               if (LOWORD (wParam) == IDM_EDIT_COPY)                    return 0 ;                                        // fall through for IDM_EDIT_CUT          case IDM_EDIT_DELETE:               if (hBitmap)               {                    DeleteObject (hBitmap) ;                    hBitmap = NULL ;               }               InvalidateRect (hwnd, NULL, TRUE) ;               return 0 ;          case IDM_EDIT_PASTE:               if (hBitmap)               {                    DeleteObject (hBitmap) ;                    hBitmap = NULL ;               }               OpenClipboard (hwnd) ;               hBitmapClip = GetClipboardData (CF_BITMAP) ;               if (hBitmapClip)                    hBitmap = CopyBitmap (hBitmapClip) ;               CloseClipboard () ;               InvalidateRect (hwnd, NULL, TRUE) ;               return 0 ;          }          break ;     case WM_PAINT:          hdc = BeginPaint (hwnd, &ps) ;          if (hBitmap)          {               GetClientRect (hwnd, &rect) ;               hdcMem = CreateCompatibleDC (hdc) ;               SelectObject (hdcMem, hBitmap) ;               GetObject (hBitmap, sizeof (BITMAP), (PSTR) &bm) ;               SetStretchBltMode (hdc, COLORONCOLOR) ;               StretchBlt (hdc,    0, 0, rect.right, rect.bottom,                           hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY) ;               DeleteDC (hdcMem) ;          }          EndPaint (hwnd, &ps) ;          return 0 ;     case WM_DESTROY:          if (hBitmap)               DeleteObject (hBitmap) ;          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 适合脸大的男生发型 男生头发少适合什么发型 大圆脸适合什么发型男 男生脸大适合什么发型 头发硬适合什么发型 头大的人适合什么发型 脸圆的女生适合什么发型 男生头大适合什么发型 自来卷男生适合发型 脸大男生适合什么发型 头发多适合什么发型 男士两边剃掉的发型图 大圆脸适合什么发型 脸长的女生适合什么发型 男士方脸适合什么发型 脸宽的男生适合的发型 头大的男生适合什么发型 脸大的男生适合的发型 测试自己适合的发型 圆脸男生适合什么发型 脸圆的男生适合什么发型 圆脸女生适合什么发型 小眼睛适合什么发型 脸胖的人适合什么发型 板寸头男生短发发型 男士圆脸适合什么发型 发质硬适合什么发型 男胖子适合什么发型 什么脸型适合什么发型 男生头发软适合发型 方形脸适合什么发型男 流行的短发女生发型图片 脸大的女生适合什么发型 测一测你适合什么发型 男生大脸适合什么发型 头大脸大适合什么发型 头发少的女生适合什么发型 戴眼镜的男生适合什么发型 男生头大脸大适合什么发型 头发多的女生适合什么发型 脸小的女生适合什么样的发型