📄 复件 (3) 新建 文本文档 (2).txt
字号:
MessageBox ( NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow ( szAppName, TEXT ("Shades of Gray #3"),
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 HPALETTE hPalette ;
static int cxClient, cyClient ;
HBRUSH hBrush ;
HDC hdc ;
int i ;
LOGPALETTE * plp ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE:
// Set up a LOGPALETTE structure and create a palette
plp = malloc (sizeof (LOGPALETTE) + 64 * sizeof (PALETTEENTRY)) ;
plp->palVersion = 0x0300 ;
plp->palNumEntries = 65 ;
for (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) ;
// Select and realize the palette in the device context
SelectPalette (hdc, hPalette, FALSE) ;
RealizePalette (hdc) ;
// Draw the fountain of grays
for (i = 0 ; i < 65 ; i++)
{
rect.left = i * cxClient / 64 ;
rect.top = 0 ;
rect.right = (i + 1) * cxClient / 64 ;
rect.bottom = cyClient ;
hBrush = CreateSolidBrush (PALETTEINDEX (i)) ;
FillRect (hdc, &rect, hBrush) ;
DeleteObject (hBrush) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_QUERYNEWPALETTE:
if (!hPalette)
return FALSE ;
hdc = GetDC (hwnd) ;
SelectPalette (hdc, hPalette, FALSE) ;
RealizePalette (hdc) ;
InvalidateRect (hwnd, NULL, FALSE) ;
ReleaseDC (hwnd, hdc) ;
return TRUE ;
case WM_PALETTECHANGED:
if (!hPalette || (HWND) wParam == hwnd)
break ;
hdc = GetDC (hwnd) ;
SelectPalette (hdc, hPalette, FALSE) ;
RealizePalette (hdc) ;
UpdateColors (hdc) ;
ReleaseDC (hwnd, hdc) ;
break ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
通常,使用调色盘管理器的第一步就是呼叫CreatePalette函数来建立逻辑调色盘。逻辑调色盘包含程序所需要的全部颜色-即236种颜色。GRAYS1程序在WM_CREATE消息处理期间处理此作业。它初始化LOGPALETTE(「logical palette:逻辑调色盘」)结构的字段,并将这个结构的指针传递给CreatePalette函数。CreatePalette传回逻辑调色盘的句柄,并将此句柄储存在静态变量hPalette中。
LOGPALETTE结构定义如下:
typedef struct
{
WORD palVersion ;
WORD palNumEntries ;
PALETTEENTRY palPalEntry[1] ;
}
LOGPALETTE, * PLOGPALETTE ;
第一个字段通常设为0x0300,表示兼容Windows 3.0。第二个字段设定为调色盘表中的项目数。LOGPALETTE结构中的第三个字段是一个PALETTEENTRY结构的数组,此结构也是一个调色盘项目。PALETTEENTRY结构定义如下:
typedef struct
{
BYTE peRed ;
BYTE peGreen ;
BYTE peBlue ;
BYTE peFlags ;
}
PALETTEENTRY, * PPALETTEENTRY ;
每个PALETTEENTRY结构都定义了一个我们要在调色盘中使用的RGB颜色值。
注意,LOGPALETTE中只能定义一个PALETTEENTRY结构的数组。您需要为LOGPALETTE结构和附加的PALETTEENTRY结构配置足够大的内存空间。GRAYS2需要65种灰阶,因此它为LOGPALETTE结构和64个附加的PALETTEENTRY结构配置了足够大的内存空间。GRAYS2将palNumEntries字段设定为65,然后从0到64循环,计算灰阶等级(一般是循环索引的4倍,但不超过255),将结构中的peRed、peGreen和peBlue字段设定为此灰阶等级。peFlags字段设为0。程序将指向这个内存块的指针传递给CreatePalette,在一个静态变量中储存该调色盘句柄,然后释放内存。
逻辑调色盘是GDI对象。程序应该删除它们建立的所有逻辑调色盘。WndProc透过在WM_DESTROY消息处理期间呼叫DeleteObject,仔细地删除了逻辑调色盘。
注意逻辑调色盘是独立的设备内容。在真正使用之前,必须确保将其选进设备内容。在WM_PAINT消息处理期间,SelectPalette将逻辑调色盘选进设备内容。除了含有第三个参数以外,此函数与SelectObject函数相似。通常,第三个参数设为FALSE。如果SelectPalette的第三个参数设为TRUE,那么调色盘将始终是「背景调色盘」,这意味着当其它所有程序都显现了各自的调色盘之后,该调色盘才可以获得仍位于系统调色盘中的一个未使用项目。
在任何时候都只有一个逻辑调色盘能选进设备内容。函数将传回前一个选进设备内容的逻辑调色盘句柄。如果您希望将此逻辑调色盘重新选进设备内容,则可以储存此句柄。
通过将颜色映像到系统调色盘,RealizePalette函数使Windows在设备内容中「显现」逻辑调色盘,而系统调色盘是与显示卡实际的实际调色盘相对应。实际工作在此函数呼叫期间进行。Windows必须决定呼叫函数的窗口是活动的还是非活动的,并尽可能将系统调色盘已改变通知给其它窗口(我们将简要说明一下通知的程序)。
回忆一下GRAYS1,它用RGB宏来指定纯色画刷的颜色。RGB宏建构一个32位长整数(记作COLORREF值),其中高字节是0,3个低字节是红、绿和蓝的亮度。
使用Windows调色盘管理器的程序可以继续使用RGB颜色值来指定颜色。不过,这些RGB颜色值将不能存取逻辑调色盘中的附加颜色。它们的作用与没有使用调色盘管理器相同。要在逻辑调色盘中使用附加的颜色,就要用到PALETTERGB宏。除了COLORREF值的高字节设为2而不是0以外,「调色盘RGB」颜色与RGB颜色很相似。
下面是重要的规则:
为了使用逻辑调色盘中的颜色,请用调色盘RGB值或调色盘索引来指定(我将简要讨论调色盘索引)。不要使用常规的RGB值。如果使用了常规的RGB值,您将得到一种标准颜色,而不是逻辑调色盘中的颜色。
没有将调色盘选进设备内容时,不要使用调色盘RGB值或调色盘索引。
尽管可以使用调色盘RGB值来指定逻辑调色盘中没有的颜色,但您还是要从逻辑调色盘获得颜色。
例如,在GRAYS2中处理WM_PAINT期间,当您选择并显现了逻辑调色盘之后,如果试图显示红色,则将显示灰阶。您必须用RGB颜色值来选择不在逻辑调色盘中的颜色。
注意,GRAYS2从不检查视讯显示驱动程序是否支持调色盘管理程序。在不支持调色盘管理程序的显示模式(即所有非256种颜色的显示模式)下执行GRAYS2时,GRAYS2的功能与GRASY1相同。
调色盘信息
如果程序在逻辑调色盘中指定一种颜色,该颜色又是20种保留颜色之一,那么Windows将把逻辑调色盘项目映像给该颜色。另外,如果两个或多个应用程序都在它们的逻辑调色盘中指定了同一种颜色,那么这些应用程序将共享系统调色盘项目。程序可以通过将PALETTEENTRY结构的peFlags字段指定为常数PC_NOCOLLAPSE来忽略该内定状态(其余两个可能的标记是PC_EXPLICIT(用于显示系统调色盘)和PC_RESERVED(用于调色盘动画),我将在本章的后面展示这两个标记)。
要帮助组织系统调色盘,Windows调色盘管理器含有两个发送给主窗口的消息。
第一个是QM_QUERYNEWPALETTE。当主窗口活动时,该消息发送给主窗口。如果程序在您的窗口上绘画时使用了调色盘管理器,则它必须处理该消息。GRAYS2展示具体的作法。程序获得设备内容句柄,并选进调色盘,呼叫RealizePalette,然后使窗口失效以产生WM_PAINT消息。如果显现了逻辑调色盘,则窗口消息处理程序从该消息传回TRUE,否则传回FALSE。
当系统调色盘改成与WM_QUERYNEWPALETTE消息的结果相同时,Windows将WM_PALETTECHANGED消息发送给由目前活动的窗口来启动并终止处理窗口链的所有主窗口。这允许前台窗口有优先权。传递给窗口消息处理程序的wParam值是活动窗口的句柄。只有当wParam不等于程序的窗口句柄时,使用调色盘管理器的程序才会处理该消息。
通常,在处理WM_PALETTECHANGED时,使用自订调色盘的任何程序都呼叫SelectPalette和RealizePalette。后续的窗口在消息处理期间呼叫RealizePalette时,Windows首先检查逻辑调色盘中的RGB颜色是否与已加载到系统调色盘中的RGB颜色相匹配。如果两个程序需要相同的颜色,那么这两个程序就共同使用一个系统调色盘项目。接下来,Windows检查未使用的系统调色盘项目。如果都已使用,则逻辑调色盘中的颜色从20种保留项目映像到最近的颜色。
如果不关心程序非活动时显示区域的外观,那么您不必处理WM_PALETTECHANGED消息。否则,您有两个选择。GRAYS2显示其中之一:在处理WM_QUERYNEWPALETTE消息时,它获得设备内容,选进调色盘,然后呼叫RealizePalette。这时就可以在处理WM_QUERYNEWPALETTE时呼叫InvalidateRect了。相反地,GRAYS2呼叫UpdateColors。这个函数通常比重新绘制窗口更有效,同时它改变窗口中图素的值来帮助保护以前的颜色。
使用调色盘管理器的许多程序都将让WM_QUERYNEWPALETTE和WM_PALETTECHANGED消息用GRAYS2所显示的方法来处理。
调色盘索引方法
程序16-3所示的GRAYS3程序与GRAYS2非常相似,只是在处理WM_PAINT期间使用了呼叫PALETTEINDEX的宏,而不是PALETTERGB。
程序16-3 GRAYS3
GRAYS3.C
/*---------------------------------------------------------------------------
GRAYS3.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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -