码迷,mamicode.com
首页 > 其他好文 > 详细

第16章 调色板管理器_16.1 调色板原理和使用

时间:2015-08-04 09:17:57      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:

16.1 调色板的使用

16.1.1 调色板原理

技术分享

 

注意:

  ①使用调色板前要创建逻辑调色板,选入并实现调色板。在映射过程中,逻辑调色板中的颜色会被相等匹配、或近似匹配、或新增加进系统调色板中(见后面分析)

  ②Windows规定,活动窗口(标题栏高亮显示的程序)的逻辑调色板(如果有的话)具有最高的实现优先权,这是因为活动窗口是当前与用户交互的窗口,应该保证其有最佳的颜色显示。非活动窗口的优先权是按Z顺序自上到下确定的(Z顺序就是重叠窗口的重叠顺序)。活动窗口有权将其逻辑调色板作为前景调色板实现,非活动窗口则只能实现背景调色板。前景调色板具有使用颜色的最高优先级,它有无条件占用系统调色板(20种保留颜色除外)的权力。也就是说,如果需要,前景调色板将覆盖系统调色板的236个表项,而不管这些表项是否正被别的窗口使用。背景调色板则无权破坏系统调色板中的已使用项,只能将自己的逻辑调色板的颜色匹配或加入到当前系统调色板中尚有空白项的地方。

  ③注意DIB颜色表与调色板的关系:(这里统称为调色板,因为实现了调色板后,逻辑与系统调色板基本可以认为是一致)

  A、对于24位的DIB来说,无颜色表,其像素数据就是RGB值,但在8位(256色)视频模式下显示时,会根据这些值,从调色板中匹配一个的颜色显示出来。

  B、而对于8位(256)色以下的DIB,其像素数据不再是RGB值,而是该像素在BITMAPINFO颜色表的索引。绘图时,需要利用该像素值(索引)X,去查找颜色表索引号为X的项存储的数据(是个RGB值)。然后再跟据这个RGB值去匹配调色板的颜色(有可能出现匹配不完全的情况),最终显示出来——显然这种方法本质上是利用颜色表的中RGB值去匹配调色板的RGB值的,速度会比较慢。而如果颜色表中存值的也是索引值时,则会根据该像素值(索引)设为X,就查找颜色表索引号为X的颜色项(设存储的值为Y,也是个索引),最后再利用这个索引Y去查找调色板相应的索引号所在项的RGB值来显示——这种方法本质上是利用索引号匹配颜色的,查找速度较快

  ④使用调色板的一个好处是不必改变视频内存中的值,只需改变调色板的颜色项就可快速地改变一幅图象的颜色或灰度。

 (1)系统调色板

  在16色或256色显示模式下,Windows会维护一个系统调色板。缺省的系统调色板只包含20种静态颜色,这些颜色用作显示Windows界面,同时这些颜色也不可改变。调色板的其它236项为空。应用程序要想使用新的颜色,必须将包含有所需颜色的逻辑调色板实现到系统调色板中。

像素位(索引)

RGB值

颜色名称

像素位

RGB值

颜色名称

0000 0000

00 00 00

1111 1111

FF FF FF

0000 0001

80 00 00

深红

1111 1110

00 FF FF

青色

0000 0010

00 80 00

深绿

1111 1101

FF 00 FF

紫红

0000 0011

80 80 00

暗黄

1111 1100

00 00 FF

0000 0100

00 00 80

深蓝

1111 1011

FF FF 00

0000 0101

80 00 80

深紫红

1111 1010

00 FF 00

绿

0000 0110

00 80 80

深青色

1111 1001

FF 00 00

0000 0111

C0 C0 C0

浅灰

1111 1000

80 80 80

深灰

0000 1000

C0 DC C0

美元绿

1111 0111

A0 A0 A0

中灰

0000 1001

A6 CA F0

天蓝

1111 0110

FF FB F0

乳白

(2)创建逻辑调色板——hPallete= CreatePallete(&logPallete);

   ①LOGPALETTE结构体

    typedef struct

    {

        WORD  palVersion;   //总是0x0300,表示与Windows3.0兼容

        WORD  palNumEntries;//颜色板查找表中的条目数,对于灰度图为256

        PALETTEENTRY palPalEntry[1]; //调色板中的颜色表项,只有1项,但可扩展

  } LOGPALETTE;

   ②PALETTEENTRY结构体

参数

含义

BYTE  peRed;

R的强度(0~255,下同)

BYTE  peGreen;

G分量值

BYTE  peBlue;

B分量值

BYTE  peFlags

0 :创建正常输入项。

PC_EXPLICIT :创建输入项指定到系统调色板的索引。用于显示系统调色板的颜色。

PC_NOCOLLAPSE  将输入项映射到系统调色板未使用的项,即使该颜色的输入项已经存在。用来确保颜色唯一。

PC_RESERVED:输入项被应用私有。添加到系统调色板后,即使颜色相匹配,也不会映射到其它逻辑调色板。

 注意:逻辑调色板是一个GDI对象,用完后要调用DeleteObject销毁

(2)选入和实现调色板

    SelectPallete(hdc,hPallete,FALSE); //将调色板选入DC

    RealizePalette(hdc);    //实现调色板,逻辑调色板与系统调色板建立映射关系。

  注意:

   ①前景调色板是唯一的。如果一个活动窗口同时要实现几个逻辑调色板,那么只能有一个调色板作为前景调色板实现,也即在调用SelectPalette时只能有一个bForceBackground被指定为FALSE,其它的bForceBackground必需为TRUE。通常是把具有输入焦点的窗口的调色板作为前景调色板实现,其它窗口只能使用背景调色板。如果活动窗口的子窗口全都使用前景调色板,则会导致程序的死循环。

  ②实现调色板的过程:A、首先将逻辑调色板中的项与系统调色板中的项作完全匹配,对于逻辑调色板中不能完全匹配的项将其加入到系统调色板的空白项中,系统调色板总共有236个空白项可供使用。B、如果系统调色板己满,则将逻辑调色板的剩余项匹配到系统调色板中尽可能接近的颜色上。如前面的“调色板原理图”中,逻辑调色板的索引1中的颜色与系统调色板中的第23号索引与其完全匹配,但逻辑调色板中的索引15和系统调色板中的索引46是不完全匹配的。

  ③在实现了系统调色板以后,Windows会向其他窗口发送消息,通知系统调色板正在改变。(见后面调色板消息的分析)

(3)GDI函数绘图:可用索引或RGB值来使用逻辑调色板中的颜色。如,hBrush =CreateSolidBrush(……);

CreateSolidBrush参数COLORREF设置及说明(COLORREF:共4个字节,最高及其余3字节含义如下)

COLORREF参数

各字节含义

说明

RGB(r,g,b)

最高字节为0x00,其余3字节为红、绿、蓝

该颜色来自标准的RGB颜色,而不是来自逻辑调色板的。在256色模式下,Windows将抖动20种保留的颜色来匹配指定的颜色。

PALETTEINDEX(wPaletteIndex)

最高字节为0x01,最低位字节含有逻辑调色板的索引

调色板索引引用。

Windows根据该索引在逻辑调色板中查找到所需的颜色。

PALETTERGB(r,g,b)

最高字节为0x02,3个低位字节含有红、绿、蓝色的强度

Windows会在逻辑调色板中找到最匹配的颜色

注意:①没把调色板选入设备时,不要使用PALETTERGB和PALETTEINDEX

     ②如果使用PALETTERGB指定的颜色值不在逻辑调色板中,则会选出一种相似的颜色出来。

16.1.2 调色板的消息

  为了协调各个窗口对系统调色板的使用,Windows在必要的时侯会向顶层窗口和重叠窗口发送消息WM_QUERYNEWPALETTE和WM_PALETTECHANGED。

 ①WM_QUERYNEWPALETTE消息

    A、当窗口被激活时,会收到WM_QUERYNEWPALETTE消息,该消息先于WM_PAINT消息。表示在重绘之前,留给应用程序一个机会实现自己的调色板。因为此时是活动窗口,因此该逻辑调色板一般作为前景调色板来实现,即RealizePalette的第3个参数为TRUE)。

    B、如果要实现自己的逻辑调色板,则应在该消息里用RealizePalette实现调色板,向窗口发送WM_PAINT消息重绘。最后返回TRUE,表示巳经实现了调色板。

 ②WM_PALETTECHANGED消息

    当活口窗口实现了前景调色板并改变了系统调色板时,会向所有的Windows窗口发送该消息。该消息为这些窗口提供了适应系统调色板变化的机会。

    A、wParam包含了改变系统调色板的窗口的句柄。显然,如果系统调色板是被该窗口本身改变的,则该消息就不作处理,因为己经在WM_QUERYNEWPALETTE消息中处理完了改变系统调色板的所有逻辑。如果wParam不是窗口本身,说明系统调色板己经被别的窗口改变,则本窗口适应要这种变化,重新实现自己的逻辑调色板,建立新的映射关系,并重绘自己,也正是因为如此,所以这里的RealizePallete第3个参数应设为FALSE。因为改变系统调色板的那个窗口是活动窗口,而本窗口是被动接受系统调色板改变的消息的。

  B、子窗口是收不到调色板消息的。因此,如果子窗口要使用自己的逻辑调色板,那么顶层窗口或重叠窗口应该及时通知子窗口与调色板有关的消息。

//显示灰色图程序
 【Grays1程序】
效果图

技术分享

/*------------------------------------------------------------
GRAYS1.C -- Gray Shades
(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("Grays1");
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    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 = NULL;
    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("Shades of Gray #1"), // 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);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc;
    PAINTSTRUCT ps;
    RECT        rect;
    static  int cxClient, cyClient;
    HBRUSH  hBrush;

    switch (message)
    {
    case WM_CREATE:

        return 0;
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        //画灰色渐变过渡带
        for (int i = 0; i < 65; i++)
        {
            rect.left = i*cxClient / 65;
            rect.top = 0;
            rect.right = (i + 1)*cxClient / 65;
            rect.bottom = cyClient;
            hBrush = CreateSolidBrush(RGB(min(255, 4 * i), min(255, 4 * i), min(255, 4 * i)));
            FillRect(hdc, &rect, hBrush);
            DeleteObject(hBrush);
        }

        EndPaint(hwnd, &ps);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

//调色板消息,调色板RGB、调色板索引
 【Grays2程序】——效果图与Grays1一样

/*------------------------------------------------------------
GRAYS2.C -- Gray Shades Using Palette Manager
(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("Grays2");
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    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 = NULL;
    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("Shades of Gray #2"), // 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);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc;
    PAINTSTRUCT ps;
    RECT        rect;

    static HPALETTE hPalette;
    LOGPALETTE* plp;
    static int cxClient, cyClient;
    HBRUSH  hBrush;

    switch (message)
    {
    case WM_CREATE:

        //设置并创建逻辑调色板,共65种颜色
        plp = malloc(sizeof(LOGPALETTE) + 64 * sizeof(PALETTEENTRY));
        plp->palVersion = 0x0300; //兼容Windows3.0
        plp->palNumEntries = 65;
        for (int i = 0; i < 65; i++)
        {
            plp->palPalEntry[i].peRed = (BYTE)min(255, 4 * i);
            plp->palPalEntry[i].peGreen = (BYTE)min(255, 4 * i);
            plp->palPalEntry[i].peBlue = (BYTE)min(255, 4 * i);
            plp->palPalEntry[i].peFlags = 0;
        }
        hPalette = CreatePalette(plp);
        free(plp);
        return 0;
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        //将逻辑调色板选入DC并实现调色板
        SelectPalette(hdc, hPalette, FALSE);
        RealizePalette(hdc);
        //画灰色渐变过渡带
        for (int i = 0; i < 65; i++)
        {
            rect.left = i*cxClient / 64;
            rect.top = 0;
            rect.right = (i + 1)*cxClient / 64;
            rect.bottom = cyClient;
            //注意下面用的是PALETTERGB,而不是RGB
            /*hBrush = CreateSolidBrush(PALETTERGB(min(255, 4 * i),
            min(255, 4 * i),
            min(255, 4 * i)));*/
            //使用调色板索引
            hBrush = CreateSolidBrush(PALETTEINDEX(i));
            FillRect(hdc, &rect, hBrush);
            DeleteObject(hBrush);
        }

        EndPaint(hwnd, &ps);
        return 0;

        //窗口被激活时处理WM_QUERYNEWPALETTE消息
    case WM_QUERYNEWPALETTE:
        if (!hPalette)
            return FALSE;
        hdc = GetDC(hwnd);
        SelectPalette(hdc, hPalette, FALSE); //FALSE表示作为背景调色板选入
        RealizePalette(hdc);
        InvalidateRect(hwnd, NULL, TRUE); //通知客户区,系统调色板己改变,需重绘。
        ReleaseDC(hwnd, hdc);
        return TRUE;  //表示己经自己实现了调色板

        //当系统调色板被其他窗口改变时,处理以下消息,以适应这种变化。
    case WM_PALETTECHANGED:
        if (!hPalette || (HWND)wParam == hwnd)  //wParam为改变系统调色板的窗口,如果是
            //本窗口改变了系统调色板,说明处理改变后
            //的逻辑己经在其他地方设置过了,就无须再
            //设置。如果是其他窗体改变了调色板,则
            break;
        hdc = GetDC(hwnd);
        SelectPalette(hdc, hPalette, FALSE); //FALSE表示作为背景调色板选入
        RealizePalette(hdc);
        UpdateColors(hdc);  //1、更新客户区的颜色,但效率比InvalideRect快,但因要转换颜色可能造成失真
        //2、收到该消息,必须马上调用该函数。
        ReleaseDC(hwnd, hdc);
        break;
    case WM_DESTROY:
        DeleteObject(hPalette);
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}
16.1.3 查询对调色板的支持

项目

函数调用

是否支持调色板管理器

RC_PALETTE& GetDeviceCaps(hdc,RASTERCAPS)

显卡调色板查找表的总大小

GetDeviceCaps(hdc,SIZEPALETTE);//调色板只用于8位像素的显示模式,所以该值是256

系统保留的颜色总数

GetDeviceCaps(hdc,NUMRESERVED);//一般为20

调色板查找表中RGB的分辩率

GetDeviceCaps(hdc,COLORRES);//一般8位ADC,返回24位。

16.1.4 系统调色板

GetSystemPaletteEntries(hdc,uStart,uNum,&pe)的两种使用方法:

①循环取出

 for (int i=0;i<256;i++)

GetSystemPaletteEntries(hdc,i,1,&pe);//pe指向一个PALETTEENTRY大小的内存

②一次性取出

    GetSystemPaletteEntries(hdc,0,256,&pe);pe指向多个PALETTEENTRY的空间

 16.1.5 其他调色板函数

(1)查询逻辑调色板的RGB值

GetPaletteEntries(hPalette,uStart,uNum,&pe);//第1个参数指向hPalette

(2)设置逻辑调色板的RGB值

SetPaletteEntries(hPalette,uStart,uNum,&pe);//该函数不会引起系统调色板变化。

(3)替换指定逻辑调色板上的入口点AnimatePalette(hPalette,uStart,uNum,&pe);//该函数会引起系统调色板变化。

  ①uStart:指定要被替换的第一个逻辑调色板入口点

  ②uNum:指定要被替换的入口点数目

  ③pe:指向PALETTEENTRY数组结构第一个元素的指针,用来替换当前的入口点

(4)获取逻辑调色板中指定颜色的索引——最接近cr颜色的索引:iIndex= GetNearestPaletteIndex(hPalette,cr);//cr为COLORREF值

(5)定义多于254种自定义颜色(多于236种):GetSystemPaletteUse

  //利用GetSystemPaletteEntries查看系统调色板

 【SysPal1程序】
 效果图

技术分享

/*------------------------------------------------------------
 SYSPAL1.C -- Displays System Palette
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static TCHAR szAppName[] = TEXT("SysPal1");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    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 = NULL;
    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("System Palette #1"), // 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);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
BOOL CheckDisplay(HWND hwnd)
{
    HDC hdc;
    int iPalSize;
    hdc = GetDC(hwnd);
    iPalSize = GetDeviceCaps(hdc, SIZEPALETTE);
    ReleaseDC(hwnd, hdc);
    if (iPalSize != 256)
    {
        MessageBox(hwnd, TEXT("This program requires that the video ")
                   TEXT("display mode have a 256-color palette."),
                   szAppName, MB_ICONERROR);
        return FALSE;
    }
    return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc;
    PAINTSTRUCT ps;
    static int cxClient, cyClient;
    static SIZE  sizeChar;
    PALETTEENTRY pe[256];
    TCHAR  szBuffer[16];
    switch (message)
    {
    case WM_CREATE:
        if (!CheckDisplay(hwnd))
            return -1;
        hdc = GetDC(hwnd);
        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
        GetTextExtentPoint32(hdc, TEXT("FF-FF-FF"), 10, &sizeChar); //10是为了格式化输出
        ReleaseDC(hwnd, hdc);
        return 0;
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

        GetSystemPaletteEntries(hdc, 0, 256, pe);
        for (int i = 0, x = 0, y = 0; i < 256; i++)
        {
            wsprintf(szBuffer, TEXT("%02X-%02X-%02X"),
                     pe[i].peRed,
                     pe[i].peGreen,
                     pe[i].peBlue);
            TextOut(hdc, x, y, szBuffer, lstrlen(szBuffer));
            if ((x += sizeChar.cx) + sizeChar.cx > cxClient)
            {
                x = 0;
                if ((y += sizeChar.cy) > cyClient)
                    break;
            }
        }
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DISPLAYCHANGE:
        if (!CheckDisplay(hwnd))
            DestroyWindow(hwnd);
        return 0;
    case WM_PALETTECHANGED:
        InvalidateRect(hwnd, NULL, FALSE);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}
 //利用索引读取系统调色板颜色(必须在256色模式下,兼容256模式下显示由黑到红过渡)

【SysPal2程序】
效果图

技术分享

/*------------------------------------------------------------
 SYSPAL1.C -- Displays System Palette
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static TCHAR szAppName[] = TEXT("SysPal1");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    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 = NULL;
    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("System Palette #1"), // 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);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
BOOL CheckDisplay(HWND hwnd)
{
    HDC hdc;
    int iPalSize;
    hdc = GetDC(hwnd);
    iPalSize = GetDeviceCaps(hdc, SIZEPALETTE);
    ReleaseDC(hwnd, hdc);
    if (iPalSize != 256)
    {
        MessageBox(hwnd, TEXT("This program requires that the video ")
                   TEXT("display mode have a 256-color palette."),
                   szAppName, MB_ICONERROR);
        return FALSE;
    }
    return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc;
    PAINTSTRUCT ps;
    static int cxClient, cyClient;
    static SIZE  sizeChar;
    PALETTEENTRY pe[256];
    TCHAR  szBuffer[16];
    switch (message)
    {
    case WM_CREATE:
        if (!CheckDisplay(hwnd))
            return -1;
        hdc = GetDC(hwnd);
        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
        GetTextExtentPoint32(hdc, TEXT("FF-FF-FF"), 10, &sizeChar); //10是为了格式化输出
        ReleaseDC(hwnd, hdc);
        return 0;
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

        GetSystemPaletteEntries(hdc, 0, 256, pe);
        for (int i = 0, x = 0, y = 0; i < 256; i++)
        {
            wsprintf(szBuffer, TEXT("%02X-%02X-%02X"),
                     pe[i].peRed,
                     pe[i].peGreen,
                     pe[i].peBlue);
            TextOut(hdc, x, y, szBuffer, lstrlen(szBuffer));
            if ((x += sizeChar.cx) + sizeChar.cx > cxClient)
            {
                x = 0;
                if ((y += sizeChar.cy) > cyClient)
                    break;
            }
        }
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DISPLAYCHANGE:
        if (!CheckDisplay(hwnd))
            DestroyWindow(hwnd);
        return 0;
    case WM_PALETTECHANGED:
        InvalidateRect(hwnd, NULL, FALSE);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

 //利用BitBlt或StrtchBlt允许直接用像素位来指定颜色(这两个函数是设备相关的)

【SysPal3程序】——效果图与SysPal2一样(可运行在兼容256模式下)

技术分享

/*------------------------------------------------------------
SYSPAL3.C -- Displays System Palette
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static TCHAR szAppName[] = TEXT("SysPal3");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    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 = NULL;
    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("System Palette #3"), // 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);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
BOOL CheckDisplay(HWND hwnd)
{
    HDC hdc;
    int iPalSize;
    hdc = GetDC(hwnd);
    iPalSize = GetDeviceCaps(hdc, SIZEPALETTE);
    ReleaseDC(hwnd, hdc);
    if (iPalSize != 256)
    {
        MessageBox(hwnd, TEXT("This program requires that the video ")
                   TEXT("display mode have a 256-color palette."),
                   szAppName, MB_ICONERROR);
        return FALSE;
    }
    return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc, hdcMem;
    PAINTSTRUCT ps;
    static int cxClient, cyClient;
    static HBITMAP hBitmap;
    BYTE bits[256];
    int i;
    switch (message)
    {
    case WM_CREATE:
        if (!CheckDisplay(hwnd))
            return -1;
        for (i = 0; i < 256; i++)
        {
            bits[i] = i;
        }

        //创建16*16的8位的DDB,像素位颜色值为0-255;
        hBitmap = CreateBitmap(16, 16, 1, 8, &bits);
        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);
        //将16*16位图放大到整个客户区大小
        StretchBlt(hdc, 0, 0, cxClient, cyClient,
                   hdcMem, 0, 0, 16, 16, SRCCOPY);
        DeleteDC(hdcMem);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DISPLAYCHANGE:
        if (!CheckDisplay(hwnd))
            DestroyWindow(hwnd);
        return 0;
    case WM_DESTROY:
        DeleteObject(hBitmap);
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

 

第16章 调色板管理器_16.1 调色板原理和使用

标签:

原文地址:http://www.cnblogs.com/5iedu/p/4700962.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!