/*************************************************************************** * * * PROGRAM : MyPal.c * * * * PURPOSE : Sets up a bar representation of the current physical * * palette and displays useful information regarding * * pixel colors and palette indices. * * * * FUNCTIONS : WinMain() - calls initialization function, * * processes message loop * * * * WndProc() - Window function for app. Processes * * window messages. * * * * ShowColor() - Displays a little box on each side of the * * caption bar displaying the pixel color at the* * mouse position. * ***************************************************************************/ #include #include "mypal.h" HANDLE hPal; /* Handle to the application's logical palette */ HANDLE hPal2; /* Handle to the application's logical palette */ static INT nSizeX; /* Width of the application window */ static INT nSizeY; /* Height of the application window */ NPLOGPALETTE pLogPal; /* Pointer to program's logical palette */ NPLOGPALETTE pLogPal2; /* Pointer to program's logical palette */ INT nXBorder; /* Width of window border */ INT nXTitle; /* Width of title bar */ INT nYTitle; /* Height of title bar */ BOOL bCaptureOn; /* Indicates if mouse capture is on */ INT iIndex; /* Last index selected in palette */ CHAR szTitlebuf[90];/* Buffer for pixel and palette info. text */ HDC hDCGlobal; /* The Screen DC */ INT iNumColors; /* Number of colors supported by device */ INT iRasterCaps; /* Raster capabilities */ RECT rClientRect; /* Client rectangle coordinates */ DWORD dwPal[PALETTESIZE]; /* Stores palette entries for later lookup */ INT iGlobalXOffset; INT iGlobalYOffset; INT iYMiddle; LONG APIENTRY WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam); /**************************************************************************** * * * FUNCTION : void ShowColor(HWND hWnd, HDC hDC) * * * * PURPOSE : Displays a little box on each side of the caption bar * * displaying the pixel color at the mouse position. * * * ****************************************************************************/ VOID ShowColor ( HWND hWnd, HDC hDC) { HBRUSH hBrush, hOldBrush; hBrush = CreateSolidBrush ( PALETTEINDEX(iIndex) ); hOldBrush = SelectObject (hDC,hBrush) ; GetWindowRect (hWnd, (LPRECT)&rClientRect); PatBlt ( hDC, rClientRect.left + nXTitle + nXBorder + 1, rClientRect.top + nXBorder, nXTitle, nYTitle, PATCOPY); PatBlt(hDC, rClientRect.right - ( 3 * nXTitle + nXBorder + 2), rClientRect.top + nXBorder, nXTitle, nYTitle, PATCOPY); SelectObject (hDC, hOldBrush); DeleteObject (hBrush) ; } /**************************************************************************** * * * FUNCTION : WinMain(HANDLE, HANDLE, LPSTR, int) * * * * PURPOSE : Creates the app. window and processes the message loop. * * * ****************************************************************************/ int APIENTRY WinMain( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { static CHAR szAppName [] = "MyPal"; HWND hWnd; WNDCLASS wndclass; MSG msg ; INT xScreen; INT yScreen; UNREFERENCED_PARAMETER( lpCmdLine ); if (!hPrevInstance){ wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = (WNDPROC) WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, szAppName); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = GetStockObject (BLACK_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName; if (!RegisterClass (&wndclass)) return FALSE ; } /* Do some global initializations */ xScreen = GetSystemMetrics (SM_CXSCREEN); yScreen = GetSystemMetrics (SM_CYSCREEN); nXBorder = (INT)GetSystemMetrics (SM_CXFRAME); nXTitle = (INT)GetSystemMetrics (SM_CXSIZE); nYTitle = (INT)GetSystemMetrics (SM_CYSIZE); iIndex = 0; bCaptureOn = FALSE; hDCGlobal = GetDC (NULL); iRasterCaps = GetDeviceCaps(hDCGlobal, RASTERCAPS); iRasterCaps = (iRasterCaps & RC_PALETTE) ? TRUE : FALSE; if (iRasterCaps) iNumColors = GetDeviceCaps(hDCGlobal, SIZEPALETTE); else iNumColors = GetDeviceCaps( hDCGlobal, NUMCOLORS); ReleaseDC (NULL,hDCGlobal); nSizeX = ((xScreen - 2*nXBorder) / PALETTESIZE) * PALETTESIZE; /* create the app. window */ hWnd = CreateWindow (szAppName, "My Physical Palette ", WS_OVERLAPPEDWINDOW, (xScreen-nSizeX) / 2 - nXBorder, yScreen - ( 4 * GetSystemMetrics (SM_CYCAPTION)), nSizeX + 2 * nXBorder, 4 * GetSystemMetrics (SM_CYCAPTION), NULL, NULL, hInstance, NULL); ShowWindow (hWnd, nCmdShow); UpdateWindow (hWnd); while (GetMessage (&msg, NULL, 0, 0)){ TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } /****************************************************************************** * * * FUNCTION: WndProc(HWND, unsigned, WORD, LONG) * * * * PURPOSE: Processes window messages and sets up a 256 bar representation * * of the current physical palette. Specifically, in response to: * * * * WM_CREATE -Allocates for and sets up a LOGPALETTE * * structure, creates a logical palette the same * * size as the physical palette and obtains a * * handle to the logical palette. * * * * WM_DESTROY -Destroys the logical palette and shuts down app. * * * * WM_PAINT -Resizes client area to hold as many vertical * * color bars as there are physical palette entries.* * Also realises the current logical palette and * * draws one color bar corresponding to each * * palette entry * * * * WM_RBUTTONDOWN -Captures the mouse and initiates the below * * process: * * * * WM_MOUSEMOVE -Following a WM_RBUTTONDOWN, if the right mouse * * key is depressed, displays info about the * * pixel RGB value and palette index of the mouse * * coordinates. * * * * WM_RBUTTONUP -Release mouse capture and terminates the above * * process * * * * WM_LBUTTONDOWN -Determines and displays the palette index and * * RGB value of the bar under the mouse. * * * * WM_KEYDOWN -Allows use of the arrow keys in stepping thro' * * palette entries. * * * *****************************************************************************/ LONG APIENTRY WndProc ( HWND hWnd, UINT iMessage, UINT wParam, LONG lParam) { HDC hDC; PAINTSTRUCT ps; INT iLoop; INT nStart; HBRUSH hBrush; HBRUSH hOldBrush; MPOINT pt; static INT nIncr; static DWORD dwColor; static DWORD dwLastColor; static INT i, x; switch (iMessage) { case WM_DESTROY: /* delete the handle to the logical palette if it has any * color entries and quit. */ if (pLogPal->palNumEntries) { DeleteObject (hPal); DeleteObject (hPal2); } PostQuitMessage (0) ; break ; case WM_CREATE: /* Allocate enough memory for a logical palette with * PALETTESIZE entries and set the size and version fields * of the logical palette structure. */ pLogPal = (NPLOGPALETTE) LocalAlloc (LMEM_FIXED, (sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * (PALETTESIZE)))); if(!pLogPal){ MessageBox(hWnd, " Not enough memory for palette.", NULL, MB_OK | MB_ICONHAND); PostQuitMessage (0) ; break; } pLogPal2 = (NPLOGPALETTE) LocalAlloc (LMEM_FIXED, (sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * (PALETTESIZE)))); if(!pLogPal2){ MessageBox(hWnd, " Not enough memory for palette.", NULL, MB_OK | MB_ICONHAND); PostQuitMessage (0) ; break; } pLogPal->palVersion = 0x300; pLogPal->palNumEntries = PALETTESIZE; /* fill in intensities for all palette entry colors */ for (iLoop = 0; iLoop < PALETTESIZE; iLoop++) { *((WORD *) (&pLogPal->palPalEntry[iLoop].peBlue)) = (WORD)iLoop; pLogPal->palPalEntry[iLoop].peGreen = 0; pLogPal->palPalEntry[iLoop].peRed = 0; pLogPal->palPalEntry[iLoop].peFlags = PC_NOCOLLAPSE; } pLogPal2->palVersion = 0x300; pLogPal2->palNumEntries = PALETTESIZE; /* fill in intensities for all palette entry colors */ for (iLoop = 0; iLoop < 127; iLoop++) { *((WORD *) (&pLogPal2->palPalEntry[iLoop].peBlue)) = (WORD)iLoop; pLogPal2->palPalEntry[iLoop].peGreen = 0; pLogPal2->palPalEntry[iLoop].peRed = 0; pLogPal2->palPalEntry[iLoop].peFlags = PC_RESERVED; } for (iLoop = 128; iLoop < PALETTESIZE; iLoop++) { *((WORD *) (&pLogPal2->palPalEntry[iLoop].peRed)) = (WORD)(PALETTESIZE-iLoop); *((WORD *) (&pLogPal2->palPalEntry[iLoop].peGreen)) = (WORD)(PALETTESIZE-iLoop); pLogPal2->palPalEntry[iLoop].peBlue = 0; pLogPal2->palPalEntry[iLoop].peFlags = PC_RESERVED; } /* create a logical color palette according the information * in the LOGPALETTE structure. */ hPal = CreatePalette ((LPLOGPALETTE) pLogPal) ; hPal2 = CreatePalette ((LPLOGPALETTE) pLogPal2) ; break; case WM_GETMINMAXINFO: ((LPRGPT)lParam)->iInfo[6] = nXBorder * 2 + PALETTESIZE; ((LPRGPT)lParam)->iInfo[7] = nXBorder * 2 + nYTitle*3; return DefWindowProc (hWnd, iMessage, wParam, lParam) ; break; case WM_PAINT: { static BOOL bToggle=TRUE; /* Divide client width into equal-sized parts, one per palette * entry, and re-calculate client width so that it will display * exactly as many vertical bars as there are palette entries. */ GetClientRect(hWnd,(LPRECT) &rClientRect); nSizeX = (rClientRect.right - rClientRect.left); nSizeX = (nSizeX/iNumColors) * iNumColors; nSizeY = rClientRect.bottom - rClientRect.top; GetWindowRect(hWnd,(LPRECT) &rClientRect); /* Adjust window width so that it can display exactly * as many vertical bars( of equal width) as there are palette * colors. */ SetWindowPos( hWnd, (HWND)NULL, 0, 0, nSizeX + 2*nXBorder, rClientRect.bottom - rClientRect.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); hDC = BeginPaint(hWnd, &ps); /* Select the palette into the window device context and * make the Palette Manager map the logical palette to the * system palette (realize it). */ //SetSystemPaletteUse(hDC, SYSPAL_NOSTATIC); SelectPalette (hDC, (bToggle ? hPal : hPal2), FALSE); RealizePalette (hDC); /* Calculate width of each color bar to be displayed */ nIncr = nSizeX / iNumColors; /* Paint the individual bars separately on the app. window */ for (nStart = iLoop = 0; iLoop < iNumColors; iLoop++){ /* Since this app. uses a logical palette, use the * PALETTEINDEX macro to specify the palette entry * index instead of using an explicit RGB value. */ hBrush = CreateSolidBrush (PALETTEINDEX (iLoop)); dwPal[iLoop] = GetNearestColor (hDC, PALETTEINDEX (iLoop) ); hOldBrush = SelectObject (hDC,hBrush) ; PatBlt (hDC, nStart, 0, nIncr, nSizeY, PATCOPY); nStart += nIncr; SelectObject (hDC, hOldBrush); DeleteObject (hBrush) ; } wsprintf (szTitlebuf, "MyPal Colors= %d", iNumColors); SetWindowText (hWnd, (LPSTR)szTitlebuf); EndPaint(hWnd,&ps); bToggle = (bToggle ? FALSE : TRUE); break ; } case WM_MOUSEMOVE: if (wParam & MK_RBUTTON) { POINT pt; #ifdef WIN16 /* Convert mouse position to screen coordinates */ pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); #else LONG2POINT(lParam, pt); #endif ClientToScreen(hWnd, &pt); /* Get RGB value (color) of pixel under mouse coordinate */ dwColor = GetPixel(hDCGlobal, pt.x, pt.y); /* If color value already exists in palette lookup table, * obtain it's index. */ for (i=0 ; i < iNumColors ; i++) if ( dwColor == dwPal[i] ) break; iIndex = i; /* If previous color value was not identical to current one, * display color boxes on either side of title bar, * the R, G, B values and palette index of current color. */ if (dwColor != dwLastColor) { wsprintf ( szTitlebuf, "MyPal Colors=%d Index=%d R=%3u G=%3u B=%3u", iNumColors, iIndex, (WORD)(BYTE) GetRValue (dwColor), (WORD)(BYTE) GetGValue (dwColor), (WORD)(BYTE) GetBValue (dwColor)); SetWindowText (hWnd, (LPSTR)szTitlebuf); ShowColor (hWnd, hDCGlobal); dwLastColor = dwColor; } } break; case WM_RBUTTONDOWN: /* Determine number of color bar under mouse, thus the index * of color in palette. */ x = LOWORD(lParam); iIndex = (x / nIncr ); wsprintf ( szTitlebuf, "MyPal Colors=%d Index=%d PalSize=%d RasterCaps:%d", iNumColors, iIndex, iNumColors, iRasterCaps ); SetWindowText (hWnd, (LPSTR)szTitlebuf); /* Set mouse capture so that subsequent WM_MOUSEMOVEs * (with right mouse button depressed) will allow MyPal * to display RGB info anywhere on the screen without losing * the focus. */ SetCapture (hWnd); bCaptureOn = TRUE; hDCGlobal = GetDC(NULL); if (hPal) { SelectPalette (hDCGlobal, hPal, FALSE); RealizePalette (hDCGlobal); } break; case WM_RBUTTONUP: /* Stops displaying RGB and palette info and releases mouse * capture */ ReleaseDC (NULL, hDCGlobal); bCaptureOn = FALSE; ReleaseCapture (); break; case WM_MOVE: /* If you have a wide column, this adds 1/2 so X is centered */ iGlobalXOffset = LOWORD (lParam); iGlobalYOffset = HIWORD (lParam) + nXBorder; break; case WM_SIZE: iYMiddle = (HIWORD (lParam)/2); break; case WM_LBUTTONDOWN: case WM_KEYDOWN: if (iMessage == WM_LBUTTONDOWN){ /* determine which column was hit by the mouse */ x = LOWORD(lParam); iIndex = (x / nIncr ); } else{ /* Use arrow keys to step thro' the palette entries */ switch (wParam) { case VK_RIGHT: case VK_UP: /* go to next (higher) palette entry */ iIndex++; break; case VK_LEFT: case VK_DOWN: /* go to previous (lower) palette entry */ iIndex--; break; case VK_NEXT: iIndex += 10; break; case VK_PRIOR: iIndex -= 10; break; case VK_HOME: /* go to first palette entry */ iIndex = 0; break; case VK_END: /* go to last palette entry */ iIndex = iNumColors-1; break; default: return 0L; break; } /* Make sure the palette index is within range else * set it to the limiting values and give a warning beep. */ if (iIndex < 0) { iIndex = 0; MessageBeep(1); } else{ if (iIndex > iNumColors-1) { iIndex = iNumColors-1; MessageBeep(1); } } pt.x = (SHORT)((iIndex * nIncr) + iGlobalXOffset + ((nIncr > 1) ? (nIncr / 2) : 1)); pt.y = (SHORT)(iYMiddle + iGlobalYOffset); SetCursorPos (pt.x, pt.y); } if (TRUE == bCaptureOn) { MessageBeep(1); break; } /* Select & realize the palette or the colors > 0x7 * will not match up. */ hDC = GetDC(NULL); SelectPalette (hDC, hPal, 1); RealizePalette (hDC) ; dwColor = GetNearestColor (hDC, PALETTEINDEX (iIndex)); wsprintf ( szTitlebuf, "MyPal Colors=%d Index=%d R=%3u G=%3u B=%3u", iNumColors, iIndex, (WORD)(BYTE)GetRValue (dwColor), (WORD)(BYTE)GetGValue (dwColor), (WORD)(BYTE)GetBValue (dwColor) ); SetWindowText (hWnd, (LPSTR)szTitlebuf); ShowColor (hWnd,hDC); ReleaseDC(NULL, hDC); break; default: return DefWindowProc (hWnd, iMessage, wParam, lParam) ; } return 0L ; }