Графический интерфейс GDI в Microsoft Windows© Александр Фролов, Григорий ФроловТом 14, М.: Диалог-МИФИ, 1993, 288 стр. 3.6. Приложение 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 |