Приложение SYSPAL
В завершение третьей главы приведем исходные тексты приложения SYSPAL, предназначенного для просмотра системной палитры. Оно работает только тогда, когда драйвер видеоадаптера использует цветовые палитры, поэтому вы не сможете запустить его в режимах с низким или высоким цветовым разрешением.
С помощью приложения SYSPAL вы сможете визуально проследить за изменениями системной палитры, например, при загрузке bmp-файлов в приложение Paint Brush, при запуске приложения PALETTE или других приложений, изменяющих системную палитру.
Это приложение во многом напоминает предыдущее, поэтому для экономии места мы сократили количество комментариев в его исходном тексте (листинг 3.5).
Листинг 3.5. Файл syspalet/syspal.cpp
// ---------------------------------------- // Приложение SYSPAL // Просмотр системной цветовой палитры // ----------------------------------------
#define STRICT #include <windows.h> #include <windowsx.h> #include <mem.h>
#define PALETTESIZE 256
BOOL InitApp(HINSTANCE); LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM); BOOL PaletteInfo(void);
char const szClassName[] = "SysPalClass"; char const szWindowTitle[] = "System Palette";
short cxClient, cyClient; HPALETTE hPal, hOldPalette; NPLOGPALETTE pLogPal;
// ===================================== // Функция WinMain // ===================================== #pragma argsused
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; // структура для работы с сообщениями HWND hwnd; // идентификатор главного окна приложения
if(!hPrevInstance) if(!InitApp(hInstance)) return FALSE;
if(!PaletteInfo()) return FALSE;
hwnd = CreateWindow( szClassName, // имя класса окна szWindowTitle, // заголовок окна WS_OVERLAPPEDWINDOW, // стиль окна CW_USEDEFAULT, // задаем размеры и расположение CW_USEDEFAULT, // окна, принятые по умолчанию CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, NULL);
if(!hwnd) return FALSE;
ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd);
while(GetMessage(&msg, 0, 0, 0)) { DispatchMessage(&msg); } return msg.wParam; }
// ===================================== // Функция InitApp // Выполняет регистрацию класса окна // =====================================
BOOL InitApp(HINSTANCE hInstance) { ATOM aWndClass; // атом для кода возврата WNDCLASS wc; // структура для регистрации // класса окна // Записываем во все поля структуры нулевые значения memset(&wc, 0, sizeof(wc));
wc.lpszMenuName = NULL; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszClassName = (LPSTR)szClassName;
// Регистрация класса aWndClass = RegisterClass(&wc);
return (aWndClass != 0); }
// ===================================== // Функция WndProc // =====================================
LRESULT CALLBACK _export WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps;
switch (msg) { case WM_CREATE: { int i;
// Получаем память для палитры pLogPal = (NPLOGPALETTE) LocalAlloc(LMEM_FIXED, (sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * (PALETTESIZE))));
// Заполняем заголовок палитры pLogPal->palVersion = 0x300; pLogPal->palNumEntries = PALETTESIZE;
// Младшее слово структуры PALETTEENTRY содержит поля // peRed и peGreen, а старшее - peBlue и peFlags. // Отмечаем все элементы палитры флагом PC_EXPLICIT for (i = 0; i < PALETTESIZE; i++) { pLogPal->palPalEntry[i].peBlue = 0; *((PWORD)(&pLogPal->palPalEntry[i].peRed)) = i; pLogPal->palPalEntry[i].peFlags = PC_EXPLICIT; }
// Создаем логическую палитру hPal = CreatePalette((LPLOGPALETTE) pLogPal); return 0; }
// При изменении размеров окна сохраняем // новые значения для ширины и высоты case WM_SIZE: { cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; }
// Рисование в окне case WM_PAINT: { RECT rc; int i, nWidth; HBRUSH hBrush;
hdc = BeginPaint(hwnd, &ps); hOldPalette = SelectPalette(hdc, hPal, FALSE); RealizePalette(hdc);
nWidth = 2; rc.left = rc.top = 0; rc.right = nWidth; rc.bottom = cyClient;
for (i=0; i < 256; i++) { hBrush = CreateSolidBrush (PALETTEINDEX (i)); FillRect (hdc, &rc, hBrush); rc.left = rc.right; rc.right += nWidth; DeleteBrush(hBrush); }
SelectPalette(hdc, hOldPalette, TRUE); EndPaint(hwnd, &ps); return 0; }
case WM_PALETTECHANGED: { if (hwnd == (HWND) wParam) break; }
case WM_QUERYNEWPALETTE: { HDC hdc; HPALETTE hOldPal; int nChanged;
hdc = GetDC(hwnd);
hOldPal = SelectPalette(hdc, hPal, (msg == WM_QUERYNEWPALETTE) ? FALSE : TRUE);
nChanged = RealizePalette(hdc); SelectPalette(hdc, hOldPal, TRUE);
ReleaseDC(hwnd, hdc);
if(nChanged) InvalidateRect(hwnd, NULL, TRUE);
return nChanged; }
case WM_DESTROY: { DeletePalette(hPal); LocalFree(pLogPal);
PostQuitMessage(0); return 0; }
default: break; } return DefWindowProc(hwnd, msg, wParam, lParam); }
// -------------------------------------------------------- // Функция PaletteInfo // Проверка возможности работы с палитрами // --------------------------------------------------------
BOOL PaletteInfo(void) { HDC hdc; int iRasterCaps;
hdc = GetDC(NULL); iRasterCaps = GetDeviceCaps(hdc, RASTERCAPS); ReleaseDC(NULL, hdc);
// Проверяем, используется ли механизм палитр if(iRasterCaps & RC_PALETTE) return TRUE; else return FALSE; }
Так же, как и приложение PALETTE, приложение SYSPAL создает логическую палитру для 256 цветов. Однако палитра заполняется по другому:
for (i = 0; i < PALETTESIZE; i++) { pLogPal->palPalEntry[i].peBlue = 0; *((PWORD)(&pLogPal->palPalEntry[i].peRed)) = i; pLogPal->palPalEntry[i].peFlags = PC_EXPLICIT; } hPal = CreatePalette((LPLOGPALETTE) pLogPal);
Все элементы палитры отмечаются флагом PC_EXPLICIT. Это означает, что палитра содержит не цвета, а индексы цветов системной палитры. Точнее, младшее слово каждого элемента палитры содержит индекс цвета системной палитры.
Структура PALETTEENTRY описана в файле windows.h следующим образом:
typedef struct tagPALETTEENTRY { BYTE peRed; BYTE peGreen; BYTE peBlue; BYTE peFlags; } PALETTEENTRY;
При этом младшее слово структуры PALETTEENTRY содержит поля peRed и peGreen, а старшее - peBlue и peFlags. Мы пользуемся этим обстоятельством, записывая в младшее слово значения от 0 до 255 (индекс в системной табице цветов), в поле peBlue - нулевое значение, а в поле peFlags - значение PC_EXPLICIT.
Созданная таким образом палитра используется также, как и в приложении PALETTE.
Файл определения модуля приложения SYSPAL приведен в листинге 3.6.
Листинг 3.6. Файл syspalet/syspal.def
; ============================= ; Файл определения модуля ; ============================= NAME SYSPAL DESCRIPTION 'Приложение SYSPAL, (C) 1994, Frolov A.V.' EXETYPE windows STUB 'winstub.exe' STACKSIZE 8120 HEAPSIZE 1024 CODE preload moveable discardable DATA preload moveable multiple