Графический интерфейс GDI в Microsoft Windows

         

Приложение 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


Содержание раздела