📄 16. 调色盘管理器.txt
字号:
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE:
if (!CheckDisplay (hwnd))
return -1 ;
plp = malloc (sizeof (LOGPALETTE) + 255 * sizeof (PALETTEENTRY)) ;
plp->palVersion = 0x0300 ;
plp->palNumEntries = 256 ;
for (i = 0 ; i < 256 ; i++)
{
plp->palPalEntry[i].peRed = i ;
plp->palPalEntry[i].peGreen = 0 ;
plp->palPalEntry[i].peBlue = 0 ;
plp->palPalEntry[i].peFlags = PC_EXPLICIT ;
}
hPalette = CreatePalette (plp) ;
free (plp) ;
return 0 ;
case WM_DISPLAYCHANGE:
if (!CheckDisplay (hwnd))
DestroyWindow (hwnd) ;
return 0 ;
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
SelectPalette (hdc, hPalette, FALSE) ;
RealizePalette (hdc) ;
for (y = 0 ; y < 16 ; y++)
for (x = 0 ; x < 16 ; x++)
{
hBrush = CreateSolidBrush (PALETTEINDEX (16 * y + x)) ;
SetRect (&rect, x * cxClient /16, y * cyClient / 16,
(x + 1)` * cxClient / 16,(y+1) * cyClient / 16);
FillRect (hdc, &rect, hBrush) ;
DeleteObject (hBrush) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_PALETTECHANGED:
if ((HWND) wParam != hwnd)
InvalidateRect (hwnd, NULL, FALSE) ;
return 0 ;
case WM_DESTROY:
DeleteObject (hPalette) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
SYSPAL2在WM_CREATE消息处理期间建立了逻辑调色盘。但是请注意:逻辑调色盘中所有的256个值都是从0到255的调色盘索引,并且peFlags字段是PC_EXPLICIT。该旗标是这样定义的:「逻辑调色盘项目的较低字组指定了一个硬件调色盘索引。此旗标允许应用程序显示硬件调色盘的内容。」该旗标就是专为我们要做的这件事情而设计的。
在WM_PAINT消息处理期间,SYSPAL2将该调色盘选进设备内容并显现它。这不会引起系统调色盘的任何重组,而是允许程序使用PALETTEINDEX宏来指定系统调色盘中的颜色。按此方法,SYSPAL2显示了256个矩形。另外,当您执行该程序时,注意顶行和底行的前10种和后10种颜色是20种保留颜色,如表16-1所示。当您执行使用自己逻辑调色盘的程序时,显示就改变了。
如果您既喜欢看SYSPAL2中的颜色,又喜欢RGB的值,那么请与第八章的WHATCLR程序同时执行。
SYSPAL系列中的第三版使用的技术对我来说是最近才出现的-从我开始研究Windows调色盘管理器七年多后,才出现了那些技术。
事实上,所有的GDI函数都直接或间接地指定颜色作为RGB值。在GDI内部,这将转换成与那个颜色相关的图素位。在某些显示模式中(例如,16位或24位颜色模式),这些转换是相当直接的。在其它显示模式中(4位或8位颜色),这可能涉及最接近颜色的搜索。
然而,有两个GDI函数让您直接指定图素位中的颜色。当然在这种方式中使用的这两个函数都与设备高度相关。它们太依赖设备了,以至于它们可以直接显示视讯显示卡上实际的调色盘对照表。这两个函数是BitBlt和StretchBlt。
程序16-6所示的SYSPAL3程序显示了使用StretchBlt显示系统调色盘中颜色的方法。
程序16-6 SYSPAL3
SYSPAL3.C
/*---------------------------------------------------------------------------
SYSPAL3.C -- Displays system palette
(c) Charles Petzold, 1998
----------------------------------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName [] = TEXT ("SysPal3") ;
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 ("System Palette #3"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
if (!hwnd)
return 0 ;
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)
{
static HBITMAP hBitmap ;
static int cxClient, cyClient ;
BYTE bits [256] ;
HDC hdc, hdcMem ;
int i ;
PAINTSTRUCT ps ;
switch (message)
{
case WM_CREATE:
if (! CheckDisplay (hwnd))
return -1 ;
for ( i = 0 ; i < 256 ; i++)
bits [i] = i ;
hBitmap = CreateBitmap (16, 16, 1, 8, &bits) ;
return 0 ;
case WM_DISPLAYCHANGE:
if (!CheckDisplay (hwnd))
DestroyWindow (hwnd) ;
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) ;
StretchBlt (hdc, 0, 0, cxClient, cyClient,
hdcMem, 0, 0, 16, 16, SRCCOPY) ;
DeleteDC (hdcMem) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
DeleteObject (hBitmap) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -