第15章 设备相关位图_15.3 DIB和DDB的结合

15.3.1 从DIB创建DDB

(1)hBitmap =CreateDIBitmap(…)——注意这名称会误导,实际上创建的是DDB


参数


说明


hdc


设备环境句柄,可以为NULL。


pInfoHdr


指向DIB信息头的指针,即BITMAPINFOHEADER


fInit


0或CBM_INIT。CBM_INIT指定用后面3个参数来初始化DDB中的像素位


pBits


DIB像素位的指针


pInfo


DIB信息指针,即BITMAPINFO(包含BITMAPINFOHEADER和颜色表)


fClrUse


颜色使用标志位:DIB_RGB_COLORS(0)或DIB_PAL_COLORS(1)

注意:①返回值:跟CreateBitmap一样都返回一个GDI位图对象,可以直接选入DC中,并在上面绘图,以改变像素位。

     ②名称会误导,它是从一个DIB中创建一个DDB。

(2)CreateDIBitmap函数内部大致的代码实现

HBITMAP CreateDIBitmap(HDC hdc, CONST BITMAPINFOHEADER* pbmih,
     DWORD fInit, CONST VOID* pBits,CONST BITMAPINFO* pbmi, UINT fUsage)
{
     HBITMAP hBitmap;
     HDC     hdc,hdcMem;

     int     cx, cy, iBitCount;

     //从第2个参数读取DIB信息头的信息
     if (pbmih->biSize == sizeof(BITMAPCOREHEADER))
     {
         cx = ((PBITMAPCOREHEADER)pbmih)->bcWidth;
         cy = ((PBITMAPCOREHEADER)pbmih)->bcHeight;

         iBitCount = ((PBITMAPCOREHEADER)pbmih)->bcBitCount;
     }
     else
     {
         cx = pbmih->biWidth;
         cy = pbmih->biHeight;
         iBitCount = pbmih->biBitCount;
     }

     //创建DDB
     if (hdc)
         hBitmap = CreateCompatibleBitmap(hdc, cx, cy);
     else
         hBitmap = CreateBitmap(cx, cy, 1, 1, NULL);//单色位图

     //后面4个参数是用来初始化DDB的
     if (fInit == CBM_INIT)
     {
         hdcMem = CreateCompatibleDC(hdc);
         SelectObject(hdcMem, hBitmap);

         //在内存位图表面绘图,注意这里是DDB位图,己被选入内存DC
         SetDIBitsToDevice(hdcMem, 0, 0, cx, cy, 0, 0, 0, cy, pBits, pbmi, fUsage);
         DeleteDC(hdcMem);
     }
     return hBitmap;
}

(3)应用举例

  ①创建单色GDI位图:hBitmap =CreateDIBitmap(NULL,pbmih,0,NULL,NULL,0);

  ②DC兼容位图:hBitmap = CreateDIBitmap(hdc,pbmih,0,NULL,NULL,0);//未初始化

(4)当CreateDIBitmap时未初始化像素位,后期可调用SetDIBits初始化DDB像素位


参数


说明


hdc


设备环境句柄,当DIB_PAL_COLORS时才需要设备hdc


hBitmap


要设置像素位的位图句柄


yScan


要转换的第一行扫描线


cyScans


扫描线的行数


pBits


将该像素位设给hBitmap的像素位。


pInfo


指向DIB信息头的指针


fClrUse


颜色使用标志

【DIBCONV程序】

/*------------------------------------------------------------
DIBCONV.C --Converts a DIB to a DDB
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static TCHAR szAppName[] = TEXT("DibConv");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    HACCEL       hAccel;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = szAppName;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,                  // window class name
                        TEXT("DIB to DDB Conversion"), // window caption
                        WS_OVERLAPPEDWINDOW,        // window style
                        CW_USEDEFAULT,              // initial x position
                        CW_USEDEFAULT,              // initial y position
                        CW_USEDEFAULT,              // initial x size
                        CW_USEDEFAULT,              // initial y size
                        NULL,                       // parent window handle
                        NULL,                       // window menu handle
                        hInstance,                  // program instance handle
                        NULL);                     // creation parameters

    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;
}
HBITMAP   CreateBitmapObjectFromDibFile(HDC hdc, PTSTR szFileName)
{
    HBITMAP hBitmap;
    BITMAPFILEHEADER* pbmfh;
    BOOL    bSuccess;
    HANDLE  hFile;
    DWORD   dwFileSize, dwHighSize, dwBytesRead;
    //打开位图,可读可写
    hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                       OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
        return NULL;
    //读入整个文件
    dwFileSize = GetFileSize(hFile, &dwHighSize);
    if (dwHighSize)
    {
        CloseHandle(hFile);
        return NULL;
    }
    pbmfh = malloc(dwFileSize);
    if (!pbmfh)
    {
        CloseHandle(hFile);
        return NULL;
    }
    bSuccess = ReadFile(hFile, pbmfh, dwFileSize, &dwBytesRead, NULL);
    CloseHandle(hFile);
    //检验是否是位图
    if (!bSuccess || (dwBytesRead != dwFileSize) || (pbmfh->bfType != *(WORD*)"BM"))
    {
        free(pbmfh);
        return NULL;
    }
    //创建DDB——注意,这里读入整个文件,并从该DIB文件读入信息头、像素位等信息
    hBitmap = CreateDIBitmap(hdc, (BITMAPINFOHEADER*)(pbmfh + 1),
                             CBM_INIT,
                             (BYTE*)pbmfh + pbmfh->bfOffBits,
                             (BITMAPINFO*)(pbmfh + 1),
                             DIB_RGB_COLORS);
    free(pbmfh);
    return hBitmap;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static TCHAR szFilter[] = TEXT("Bitmap File(*.bmp)\0*.bmp\0")
        TEXT("All Files(*.*)\0*.*\0\0");
    static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
    static cxClient, cyClient;
    static HBITMAP hBitmap;
    HDC         hdc, hdcMem;
    PAINTSTRUCT ps;
    BITMAP  bitmap;
    static OPENFILENAME  ofn;
    switch (message)
    {
    case WM_CREATE:
        memset(&ofn, 0, sizeof(OPENFILENAME));
        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.hwndOwner = hwnd;
        ofn.lpstrFilter = szFilter;
        ofn.lpstrFile = szFileName;
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrTitle = szTitleName;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrDefExt = TEXT("*.bmp");
        return 0;
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDM_FILE_OPEN:
            //显示打开对话框
            if (!GetOpenFileName(&ofn))
                return 0;
            //删除己经打开的位图
            if (hBitmap)
            {
                DeleteObject(hBitmap);
                hBitmap = NULL;
            }
            SetCursor(LoadCursor(NULL, IDC_WAIT));
            ShowCursor(TRUE);
            //从DIB位图文件中创建DDB
            hdc = GetDC(hwnd);
            hBitmap = CreateBitmapObjectFromDibFile(hdc, szFileName);
            ReleaseDC(hwnd, hdc);
            ShowCursor(FALSE);
            SetCursor(LoadCursor(NULL, IDC_ARROW));
            //更新客户区内容
            InvalidateRect(hwnd, NULL, TRUE);
            //错误提示
            if (hBitmap == NULL)
            {
                MessageBox(hwnd, TEXT("Cannot load DIB file"), szAppName, MB_OK | MB_ICONEXCLAMATION);
            }
            return 0;
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        if (hBitmap)
        {
            GetObject(hBitmap, sizeof(BITMAP), &bitmap);
            hdcMem = CreateCompatibleDC(hdc);
            SelectObject(hdcMem, hBitmap);
            BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, 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);
}

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 DIBConv.rc 使用
//
#define IDM_FILE_OPEN                   40001
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        103
#define _APS_NEXT_COMMAND_VALUE         40004
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

//DibConv.rc

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif    // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
DIBCONV MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Open...\tCtrl+O", IDM_FILE_OPEN
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
DIBCONV ACCELERATORS
BEGIN
"^O", IDM_FILE_OPEN, ASCII, NOINVERT
END
#endif    // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

15.3.2 从DDB到DIB

(1)GetDIBits函数——将DDB转成DIB(即从hBitmap中获得pInfo,pBits等信息)


参数


说明


hdc


设备环境句柄


hBitmap


要获取像素位的位图句柄


yScan


要转换的第一行扫描线


cyScans


扫描线的行数


pBits


将hBitmap的像素位读入该内存中。


pInfo


指向DIB信息头的指针


fClrUse


颜色使用标志

注意:

①这个函数并不是SetDIBits的简单逆运算而己。因为DIB转为设备相关的格式时,会有信息的丢失。

②实际上很少用到这个函数,因为如果有能拿hBitmap句柄,却没有位图数据信息的情况很少(如剪贴板),但剪贴板提供了自动转换为DIB的功能。

15.3.3 DIB 区块(DIB Section)

(1)DDB和DIB的区别


区别


DDB(Windows内部结构)


DIB(数据结构是己公布的)


颜色组织


必须是黑白或与实际输出设备一样的格式(不含颜色表,,像素值表示索引或黑白,因数据结构未公布,不能直接访问像素位)


采用几种颜色格式之一(可以有自己的颜色表,像素位可直接访问)


每行像素数


2的倍数


4的倍数


对象构成


一个GDI位图对象,要通过选入内存dc来更改像素位或绘图.用一个hBitmap位图句柄来表示。

使用方法:

//加载或创建DDB,而资源位图本身是DIB

hBitmap =LoadBitmap(…)

//创建兼容DC,因为是设备相关的。

hdcMem = CreateCompatibleDC(hdc);

//选入dc

SelectObject(hdc,hBitmap);

//画图,改变hBitmap像素位

Rectange(hdcMem…)

//显示到设备环境中

BitBlt(hdc,…,hdcMem…,SRCCOPY);

//删除等

DeleteDC(hdcMem);


是个文件或内存区域,内存结构与文件结构类似,可直接通过pBits更改像素位。

使用方法:

//读入位图文件

hFile = CreateFile(…);

//从文件中DIB位图读入整个或部分DIB的信息

//分配文件头内存,读入信息

pbmhf =malloc(…);//文件头

pbmi = malloc(…);//信息头

pBits = malloc(…); //像素位数据

//读入各部分的信息

ReadFile(hFile,&pbmhf,….)

//显示

SetDIBtoDevice(hdc,…);//输出,可以不需要内存兼容DC(因为设备无关)


存在形式


只能存在于内存中


可存在于内存或文件中


转换


可相互转换,但涉及设备无关的像素位与设备相关像素位的转换

(2)CreateDIBSection函数——返回的对象是个“杂种”:即是GDI位图对象(DDB),又更像DIB(有pBits和pInfo),意味着可以选入设备环境修改像素位,也可以直接修改像素位。


参数


说明


hdc


设备环境句柄,只有在fClrUse设为DIB_PAL_COLORS时才可以要设置hdc。当fClrUse设为DIB_RGB_COLORS时,hdc将被忽略。


pInfo


指向DIB信息的指针


fClrUse


颜色使用标志——DIB_RGB_COLORS或DIB_PAL_COLORS。


ppBits


指向像素位指针的指针。

1、该函数调用时,会把pBits设置成指向某个内存块的指针(该内存由系统管理,DeleteObject(hBitmap)时自动释放,调用函数时,实际上并未为该空间预留大小,只有在赋值时,才会占用空间,我们的程序也不需要自己为pBits分配空间),在调用该函数完后,程序可以从DIB文件中读入像素位到pBits指向的这块内存里。

2、可以将位图选入内存设备中,然后用GDI在上面绘图,其结果反映在由pBits指向的DIB像素位中,但因GDI采用批量处理,所以绘图结束后,要调用GDIFlush,以便真正的保存起来,也可以“手工”地访问像素位。


hSection


文件映射对象句柄


dwOffSet


像素位数据在上述对象中的偏移。MSDN指出,这个参数必须是4的倍数。


注意:创建出来的位图对象,是每行的字节数是4的倍数,也就是更像DIB。

(3)应用举例

   /*创建384*256像素的DIB,每个像素为24位*/
     BITMAPINFOHEADER bmih;
     BYTE*            pBits;
     HBITMAP          hBitmap;

     bmih.biSize = sizeof(BITMAPINFOHEADER);
     bmih.biWidth = 384;
     bmih.biHeight = 256;
     bmih.biPlanes = 1;
     bmih.biBitCount = 24;
     bmih.biCompression = BI_RGB;
     bmih.biSizeImage = 0;
     bmih.biXPelsPerMeter = 0;
     bmih.biYPelsPerMeter = 0;
     bmih.biClrUsed = 0;
     bmih.biClrImportant = 0;
     /*
      1、因24位,没颜色表,所以可以直接将bmih指针转为BITMAPINFO指针。
      2、初始时pBits等于NULL,该函数会把pBits指针掰过来指向由系统维护的某内存块,我们的程序不必为pBits分配空间大小,在赋值是操作系统会自行分配,删除位图对象后该空间也会自行释放,程序不必自己释放。
     */
     hBitmap = CreateDIBSection(NULL, (BITMAPINFO*)&bmih, 0, &pBits, NULL, 0);
         //从DIB文件中读入像素位到pBits中。
     ReadFile(hFile, &pBits, ...);

(4)获取DIB区块信息——GetObject(hBitmap,sizeof(DIBSECTION),&dibsection);


DIBSECTION字段


含义


BITMAP dsBm


BITMAP结构


BITMAPINFOHEADER dsBmih


DIB信息头


DWORD    dsBitfields[3]


颜色遮罩


HANDLE   dshSection


文件映射对象句柄


DWORD    dsOffset


像素位数据的位移


注意:

1、该函数只能用在CreateDIBSection创建的位图对象,不能用在其他创建位图的函数返回的句柄上。

2、CreateDIBSection也可以通过GetObject(hBitmap,sizeof(BITMAP),&bm)返回位图信息。

3、该结构体不包括颜色表,如果用获得颜色表,可以将位图选入内存DC后,调用GetDIBColorTable来获得。

(5)DIB显示到屏幕——必须从设备无关的像素转换到设备相关的像素


函数


格式转换时机


SetDIBitsToDevice

StretchDIBits


发生在函数中


CreateDIBitmap

SetDIBits


1、未设置CBM_INIT时,发生在用 BitBlt或StretchBlt显示的时候或SetDIBits时

2、设置CBM_INIT时:发生在CreateDIBitmap函数中


CreateDIBSection创建区块


发生在用BitBlt或StretchBlt显示函数中。(注意:CreateDIBSection返回句柄实际上是DIB,但可以用BitBlt和StretchBlt函数显示),再次说明该返回值是个杂种,兼有DDB和DIB的特点。

(6)文件映射选项——CreateDIBSection的最后两个参数

①文件映射:把文件当作是己经存在于内存中,可以通过内存指针来访问,但并不需要把文件完全放到内存中。

②这项技术可减少内存需要。DIB像素位可保存在磁盘上,但却可以像内存一样的访问。但像素位必须保存在另外的文件中,不能是实际DIB文件的一部分。

  hFile = CreateFile(szFileName,…);

  …… //读入文件头(BITMAPFILEINFO)和信息头(BITMAPINFOHEADER)

  hFileMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,NULL);

  hBitmap = CreateDIBSection(NULL,pbmi,DIB_RGB_COLORS,&pBits,

  hFileMap,bmfh.bfOffBits);//bfOffBits永远不会是4的倍数!

//与MSDN要求不符,该代码不能用。

【DIBSecion程序】
效果图

/*------------------------------------------------------------
DIBSECTION.C --Displays a DIB Section in the Client area
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static TCHAR szAppName[] = TEXT("DibSection");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    HACCEL       hAccel;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = szAppName;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,                  // window class name
                        TEXT("DIB Section Display"), // window caption
                        WS_OVERLAPPEDWINDOW,        // window style
                        CW_USEDEFAULT,              // initial x position
                        CW_USEDEFAULT,              // initial y position
                        CW_USEDEFAULT,              // initial x size
                        CW_USEDEFAULT,              // initial y size
                        NULL,                       // parent window handle
                        NULL,                       // window menu handle
                        hInstance,                  // program instance handle
                        NULL);                     // creation parameters

    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;
}
HBITMAP   CreateDibSectionFromDibFile(PTSTR szFileName)
{
    HBITMAP hBitmap;
    BITMAPFILEHEADER  bmfh;
    BITMAPINFO*       pbmi;
    BYTE*             pBits;
    BOOL    bSuccess;
    HANDLE  hFile;
    DWORD   dwInfoSize, dwBytesRead;
    //打开位图,可读可写
    hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                       OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
        return NULL;
    //与前一个程序(DIBConv)不同,这里不读入整个文件,而是只读取文件头
    bSuccess = ReadFile(hFile, &bmfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL);
    if (!bSuccess || (dwBytesRead != sizeof(BITMAPFILEHEADER))
        || (bmfh.bfType != *(WORD*)"BM"))
    {
        CloseHandle(hFile);
        return NULL;
    }
    //为BITMAPINFO分配内存,并读入数据
    dwInfoSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
    pbmi = malloc(dwInfoSize);
    bSuccess = ReadFile(hFile, pbmi, dwInfoSize, &dwBytesRead, NULL);
    //创建DDB——函数调用后,pBits指针会被掰向,一个存放像素数的内存,该内存由系统维护。
    hBitmap = CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0);
    //为像素位内存写入像素数据
    ReadFile(hFile, pBits, bmfh.bfSize - bmfh.bfOffBits, &dwBytesRead, NULL);

    free(pbmi);
    CloseHandle(hFile);
    return hBitmap;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static TCHAR szFilter[] = TEXT("Bitmap File(*.bmp)\0*.bmp\0")
        TEXT("All Files(*.*)\0*.*\0\0");
    static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
    static cxClient, cyClient;
    static HBITMAP hBitmap;
    HDC         hdc, hdcMem;
    PAINTSTRUCT ps;
    BITMAP  bitmap;
    static OPENFILENAME  ofn;
    switch (message)
    {
    case WM_CREATE:
        memset(&ofn, 0, sizeof(OPENFILENAME));
        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.hwndOwner = hwnd;
        ofn.lpstrFilter = szFilter;
        ofn.lpstrFile = szFileName;
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrTitle = szTitleName;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrDefExt = TEXT("*.bmp");
        return 0;
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDM_FILE_OPEN:
            //显示打开对话框
            if (!GetOpenFileName(&ofn))
                return 0;
            //删除己经打开的位图
            if (hBitmap)
            {
                DeleteObject(hBitmap);
                hBitmap = NULL;
            }
            SetCursor(LoadCursor(NULL, IDC_WAIT));
            ShowCursor(TRUE);
            //从DIB位图文件中创建DDB(或DIB区块)
            hdc = GetDC(hwnd);
            hBitmap = CreateDibSectionFromDibFile(szFileName);
            ReleaseDC(hwnd, hdc);
            ShowCursor(FALSE);
            SetCursor(LoadCursor(NULL, IDC_ARROW));
            //更新客户区内容
            InvalidateRect(hwnd, NULL, TRUE);
            //错误提示
            if (hBitmap == NULL)
            {
                MessageBox(hwnd, TEXT("Cannot load DIB file"), szAppName, MB_OK | MB_ICONEXCLAMATION);
            }
            return 0;
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        if (hBitmap)
        {
            GetObject(hBitmap, sizeof(BITMAP), &bitmap);
            hdcMem = CreateCompatibleDC(hdc);
            SelectObject(hdcMem, hBitmap);
            BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, 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);
}

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 DIBSection.rc 使用
//
#define IDM_FILE_OPEN                   40001
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        103
#define _APS_NEXT_COMMAND_VALUE         40004
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

//DibSection.rc

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif    // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
DIBSECTION MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Open...\tCtrl+O", IDM_FILE_OPEN
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
DIBSECTION ACCELERATORS
BEGIN
"^O", IDM_FILE_OPEN, ASCII, NOINVERT
END
#endif    // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED
时间: 2024-07-30 15:05:16

第15章 设备相关位图_15.3 DIB和DDB的结合的相关文章

第15章 设备相关位图_15.1 DIB文件格式

15.1 DIB文件格式(一种文件格式,扩展名为BMP) 15.1.1 OS/2风格的DIB 文件格式 字段 说明 文件头 (BITMAPFILEHEADER) 1.共14个字节 2.缩写建议用bmfh WORD  bfType 文件签名,表示位图文件,以0x4D42,即字母“BM”打头 DWORD bfSize 整个文件的大小(含文件头的大小).单位:字节 WORD  bfReserved1 以下这两个字段必须为0.鼠标指针文件,格式类似于DIB但这两个字段表示了“热点”的位置. WORD  

第15章 设备相关位图_15.2 显示和打印DIB

15.2.1 探究DIB (1)DIB文件的结构 整个文件 紧凑DIB(整个文件除文件头) 文件头(File Header) 信息头(Information Header) 信息头(Information Header) 颜色表(Color Table) 颜色表(Color Table) 像素位(Pixel Bits) 像素位(Pixel Bits) 注意:①紧凑DIB在内存中是连续的,即整个DIB存在单个内存块中 ②DIB载入内存时,像素位与信息头可以分别存在两个内存块,即内存不连续. (2)

【大话存储II】学习笔记(15章),文件级集群系统

[大话存储II]学习笔记(15章),块级集群存储系统里面分析的主要是块集群系统,同样文件级存储也可以集群化. 因为NAS系统的前端网络是以太网,速度比较低,导致NAS主要用于一些非关键业务中,比如文件共享.但是一些特殊应用也需要多主机同时访问某个大文件,比如3D渲染集群等.如果我们使用块集群存储系统,则会存在一个问题,需要在应用程序上引入文件锁,而NAS的文件系统一般都自带有文件锁机制,所以还不如把NAS存储系统进行集群化. 在谈怎么样把NAS系统进行集群化之前,我们说说集群文件系统的架构.集群

《白帽子讲WEB安全》学习笔记之第15章 web server配置安全

第15章 web server配置安全 15.1 apache安全 在linux部署安装web Server时候一定主要要使用"最小权限原则".尽量不要使用root部署. 15.2 nginx安全 Nginx 安全配置指南技术手册 PDF 下载 免费下载地址在http://linux.linuxidc.com/ 用户名与密码都是www.linuxidc.com 具体下载目录在 /pub/服务器相关教程/Nginx/Nginx 安全配置指南技术手册/ 参考资料:http://my.osc

第15章 就不能换DB吗?—抽象工厂模式

由于抽象工厂在我们编程当中经常使用和常见,所有本篇文章对<大话设计模式>中的15章做了很详细的比较.通过一个Dao层可以更换访问任意数据库的例子来学习抽象工厂模式.例如:Dao层可以访问Sqlserver数据库,也可以访问Access数据库,当程序新增访问Oracle数据库时,无需修改现有代码,只需要添加访问Oracle相关的类就可以,实现了开闭原则.本篇文章的例子中每种数据库上都有User和Department表,我们Dao层对这两个表进行查询和插入操作. 最基本数据库访问 一下是访问Sql

第12 13 14 15章总结与感悟

第12章 用户体验 12.1用户体验的要素 1.1用户的第一印象 1.2从用户的角度考虑问题,这需要“同理心”(理解别人的处境,心理,动机和能力) 用户需要帮助,但是用户没那么笨 光吃狗食也不够 1.3软件服务始终记住用户的选择 1.4短期刺激和长期影响 1.5不让用户犯简单的错误 1.6用户体验和质量 1.7情感设计 12.2用户体验设计的步骤和目标 12.3评价标准 1.尽快提供可感触的反馈 2.系统界面符合用户的现实管理 3.用户有控制权 4.一致性和标准化 5.适合各种类型的用户 6.帮

3.30日第八次作业,第14章,采购管理,15章,信息文档和配置管理

3.30日第八次作业,第14章,采购管理,15章,信息文档和配置管理   第14章.采购管理1.采购管理包括哪些过程?(记)P382-383 答:1).编制采购计划.2).编制询价计划.3).询价.招投标.4).供方选择.5).合同管理.6).合同收尾. 2.编制采购计划过程的成果是什么?P386-387 答:1).采购管理计划.2).采购工作说明书. 3.判断:每个采购工作说明书都来自于项目范围基准.P387 答:是的. 4.结合P388页表14-1,工作说明书应该清楚地描述哪些内容?P388

java第15章示例代码

import java.util.Scanner; /** * * @author asus第15章示例代码1 全桂群2017.4.9 * */public class Registter { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); String uname, pw

【Android】15.0 第15章 广播和通知&mdash;本章示例主界面

分类:C#.Android.VS2015: 创建日期:2016-02-28 一.简介 广播(Broadcast):其功能类似于收音机的广播,你只要调到那个台(只要在接收的类中注册了要接收的广播),就能收到这个台播放的信息. 通知(Notifications):安卓的服务组件(Android Service,后面章节再细讲)本来是在后台运行的,可是,用户可能希望关注某个后台任务当前正在执行的状态或者结果,此时就可以利用"通知"在前台告诉用户. 二.本章示例主界面 1.运行截图 这个截图也