|
|
1.1 root 1: /***************************************************************************
2: * *
3: * PROGRAM : MyPal.c *
4: * *
5: * PURPOSE : Sets up a bar representation of the current physical *
6: * palette and displays useful information regarding *
7: * pixel colors and palette indices. *
8: * *
9: * FUNCTIONS : WinMain() - calls initialization function, *
10: * processes message loop *
11: * *
12: * WndProc() - Window function for app. Processes *
13: * window messages. *
14: * *
15: * ShowColor() - Displays a little box on each side of the *
16: * caption bar displaying the pixel color at the*
17: * mouse position. *
18: ***************************************************************************/
19:
20: #include <windows.h>
21: #include "mypal.h"
22:
23: HANDLE hPal; /* Handle to the application's logical palette */
24: static INT nSizeX; /* Width of the application window */
25: static INT nSizeY; /* Height of the application window */
26: NPLOGPALETTE pLogPal; /* Pointer to program's logical palette */
27: INT nXBorder; /* Width of window border */
28: INT nXTitle; /* Width of title bar */
29: INT nYTitle; /* Height of title bar */
30: BOOL bCaptureOn; /* Indicates if mouse capture is on */
31: INT iIndex; /* Last index selected in palette */
32: CHAR szTitlebuf[90];/* Buffer for pixel and palette info. text */
33: HDC hDCGlobal; /* The Screen DC */
34: INT iNumColors; /* Number of colors supported by device */
35: INT iRasterCaps; /* Raster capabilities */
36: RECT rClientRect; /* Client rectangle coordinates */
37: DWORD dwPal[PALETTESIZE]; /* Stores palette entries for later lookup */
38: INT iGlobalXOffset;
39: INT iGlobalYOffset;
40: INT iYMiddle;
41:
42: LONG APIENTRY WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam);
43:
44: /****************************************************************************
45: * *
46: * FUNCTION : void ShowColor(HWND hWnd, HDC hDC) *
47: * *
48: * PURPOSE : Displays a little box on each side of the caption bar *
49: * displaying the pixel color at the mouse position. *
50: * *
51: ****************************************************************************/
52: VOID ShowColor (
53: HWND hWnd,
54: HDC hDC)
55: {
56: HBRUSH hBrush, hOldBrush;
57:
58: hBrush = CreateSolidBrush ( PALETTEINDEX(iIndex) );
59: hOldBrush = SelectObject (hDC,hBrush) ;
60:
61: GetWindowRect (hWnd, (LPRECT)&rClientRect);
62:
63: PatBlt ( hDC,
64: rClientRect.left + nXTitle + nXBorder + 1,
65: rClientRect.top + nXBorder,
66: nXTitle,
67: nYTitle,
68: PATCOPY);
69:
70: PatBlt(hDC,
71: rClientRect.right - ( 3 * nXTitle + nXBorder + 2),
72: rClientRect.top + nXBorder,
73: nXTitle,
74: nYTitle,
75: PATCOPY);
76: SelectObject (hDC, hOldBrush);
77: DeleteObject (hBrush) ;
78: }
79:
80: /****************************************************************************
81: * *
82: * FUNCTION : WinMain(HANDLE, HANDLE, LPSTR, int) *
83: * *
84: * PURPOSE : Creates the app. window and processes the message loop. *
85: * *
86: ****************************************************************************/
87: int APIENTRY WinMain(
88: HANDLE hInstance,
89: HANDLE hPrevInstance,
90: LPSTR lpCmdLine,
91: int nCmdShow
92: )
93: {
94: static CHAR szAppName [] = "MyPal";
95: HWND hWnd;
96: WNDCLASS wndclass;
97: MSG msg ;
98: INT xScreen;
99: INT yScreen;
100:
101: UNREFERENCED_PARAMETER( lpCmdLine );
102:
103: if (!hPrevInstance){
104: wndclass.style = CS_HREDRAW | CS_VREDRAW;
105: wndclass.lpfnWndProc = (WNDPROC) WndProc;
106: wndclass.cbClsExtra = 0;
107: wndclass.cbWndExtra = 0;
108: wndclass.hInstance = hInstance;
109: wndclass.hIcon = LoadIcon(hInstance, szAppName);
110: wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
111: wndclass.hbrBackground = GetStockObject (BLACK_BRUSH);
112: wndclass.lpszMenuName = szAppName;
113: wndclass.lpszClassName = szAppName;
114:
115: if (!RegisterClass (&wndclass))
116: return FALSE ;
117: }
118:
119: /* Do some global initializations */
120: xScreen = GetSystemMetrics (SM_CXSCREEN);
121: yScreen = GetSystemMetrics (SM_CYSCREEN);
122: nXBorder = (INT)GetSystemMetrics (SM_CXFRAME);
123: nXTitle = (INT)GetSystemMetrics (SM_CXSIZE);
124: nYTitle = (INT)GetSystemMetrics (SM_CYSIZE);
125: iIndex = 0;
126: bCaptureOn = FALSE;
127:
128: hDCGlobal = GetDC (NULL);
129: iRasterCaps = GetDeviceCaps(hDCGlobal, RASTERCAPS);
130: iRasterCaps = (iRasterCaps & RC_PALETTE) ? TRUE : FALSE;
131:
132: if (iRasterCaps)
133: iNumColors = GetDeviceCaps(hDCGlobal, SIZEPALETTE);
134: else
135: iNumColors = GetDeviceCaps( hDCGlobal, NUMCOLORS);
136: ReleaseDC (NULL,hDCGlobal);
137:
138: nSizeX = ((xScreen - 2*nXBorder) / PALETTESIZE) * PALETTESIZE;
139:
140: /* create the app. window */
141: hWnd = CreateWindow (szAppName,
142: "My Physical Palette ",
143: WS_OVERLAPPEDWINDOW,
144: (xScreen-nSizeX) / 2 - nXBorder,
145: yScreen - ( 4 * GetSystemMetrics (SM_CYCAPTION)),
146: nSizeX + 2 * nXBorder,
147: 4 * GetSystemMetrics (SM_CYCAPTION),
148: NULL,
149: NULL,
150: hInstance,
151: NULL);
152: ShowWindow (hWnd, nCmdShow);
153: UpdateWindow (hWnd);
154:
155: while (GetMessage (&msg, NULL, 0, 0)){
156: TranslateMessage (&msg) ;
157: DispatchMessage (&msg) ;
158: }
159:
160: return msg.wParam ;
161: }
162:
163: /******************************************************************************
164: * *
165: * FUNCTION: WndProc(HWND, unsigned, WORD, LONG) *
166: * *
167: * PURPOSE: Processes window messages and sets up a 256 bar representation *
168: * of the current physical palette. Specifically, in response to: *
169: * *
170: * WM_CREATE -Allocates for and sets up a LOGPALETTE *
171: * structure, creates a logical palette the same *
172: * size as the physical palette and obtains a *
173: * handle to the logical palette. *
174: * *
175: * WM_DESTROY -Destroys the logical palette and shuts down app. *
176: * *
177: * WM_PAINT -Resizes client area to hold as many vertical *
178: * color bars as there are physical palette entries.*
179: * Also realises the current logical palette and *
180: * draws one color bar corresponding to each *
181: * palette entry *
182: * *
183: * WM_RBUTTONDOWN -Captures the mouse and initiates the below *
184: * process: *
185: * *
186: * WM_MOUSEMOVE -Following a WM_RBUTTONDOWN, if the right mouse *
187: * key is depressed, displays info about the *
188: * pixel RGB value and palette index of the mouse *
189: * coordinates. *
190: * *
191: * WM_RBUTTONUP -Release mouse capture and terminates the above *
192: * process *
193: * *
194: * WM_LBUTTONDOWN -Determines and displays the palette index and *
195: * RGB value of the bar under the mouse. *
196: * *
197: * WM_KEYDOWN -Allows use of the arrow keys in stepping thro' *
198: * palette entries. *
199: * *
200: *****************************************************************************/
201: LONG APIENTRY WndProc (
202: HWND hWnd,
203: UINT iMessage,
204: UINT wParam,
205: LONG lParam)
206: {
207: HDC hDC;
208: PAINTSTRUCT ps;
209: INT iLoop;
210: INT nStart;
211: HBRUSH hBrush;
212: HBRUSH hOldBrush;
213:
214: MPOINT pt;
215: static INT nIncr;
216: static DWORD dwColor;
217: static DWORD dwLastColor;
218: static INT i, x;
219:
220: switch (iMessage) {
221: case WM_DESTROY:
222: /* delete the handle to the logical palette if it has any
223: * color entries and quit.
224: */
225: if (pLogPal->palNumEntries)
226: DeleteObject (hPal);
227: PostQuitMessage (0) ;
228: break ;
229:
230: case WM_CREATE:
231: /* Allocate enough memory for a logical palette with
232: * PALETTESIZE entries and set the size and version fields
233: * of the logical palette structure.
234: */
235: pLogPal = (NPLOGPALETTE) LocalAlloc (LMEM_FIXED,
236: (sizeof (LOGPALETTE) +
237: (sizeof (PALETTEENTRY) * (PALETTESIZE))));
238:
239: if(!pLogPal){
240: MessageBox(hWnd, "<WM_CREATE> Not enough memory for palette.", NULL, MB_OK | MB_ICONHAND);
241: PostQuitMessage (0) ;
242: break;
243: }
244:
245: pLogPal->palVersion = 0x300;
246: pLogPal->palNumEntries = PALETTESIZE;
247:
248: /* fill in intensities for all palette entry colors */
249: for (iLoop = 0; iLoop < PALETTESIZE; iLoop++) {
250: *((WORD *) (&pLogPal->palPalEntry[iLoop].peRed)) = (WORD)iLoop;
251: pLogPal->palPalEntry[iLoop].peBlue = 0;
252: pLogPal->palPalEntry[iLoop].peFlags = PC_EXPLICIT;
253: }
254:
255: /* create a logical color palette according the information
256: * in the LOGPALETTE structure.
257: */
258: hPal = CreatePalette ((LPLOGPALETTE) pLogPal) ;
259: break;
260:
261: case WM_GETMINMAXINFO:
262:
263: ((LPRGPT)lParam)->iInfo[6] = nXBorder * 2 + PALETTESIZE;
264: ((LPRGPT)lParam)->iInfo[7] = nXBorder * 2 + nYTitle*3;
265:
266: return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
267: break;
268:
269: case WM_PAINT:
270:
271: /* Divide client width into equal-sized parts, one per palette
272: * entry, and re-calculate client width so that it will display
273: * exactly as many vertical bars as there are palette entries.
274: */
275: GetClientRect(hWnd,(LPRECT) &rClientRect);
276: nSizeX = (rClientRect.right - rClientRect.left);
277: nSizeX = (nSizeX/iNumColors) * iNumColors;
278:
279: nSizeY = rClientRect.bottom - rClientRect.top;
280: GetWindowRect(hWnd,(LPRECT) &rClientRect);
281:
282: /* Adjust window width so that it can display exactly
283: * as many vertical bars( of equal width) as there are palette
284: * colors.
285: */
286:
287: SetWindowPos( hWnd,
288: (HWND)NULL,
289: 0,
290: 0,
291: nSizeX + 2*nXBorder,
292: rClientRect.bottom - rClientRect.top,
293: SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
294:
295: hDC = BeginPaint(hWnd, &ps);
296:
297: /* Select the palette into the window device context and
298: * make the Palette Manager map the logical palette to the
299: * system palette (realize it).
300: */
301: SelectPalette (hDC, hPal, 1);
302: RealizePalette (hDC);
303:
304: /* Calculate width of each color bar to be displayed */
305: nIncr = nSizeX / iNumColors;
306:
307: /* Paint the individual bars separately on the app. window */
308: for (nStart = iLoop = 0; iLoop < iNumColors; iLoop++){
309:
310: /* Since this app. uses a logical palette, use the
311: * PALETTEINDEX macro to specify the palette entry
312: * index instead of using an explicit RGB value.
313: */
314: hBrush = CreateSolidBrush (PALETTEINDEX (iLoop));
315: dwPal[iLoop] = GetNearestColor (hDC, PALETTEINDEX (iLoop) );
316: hOldBrush = SelectObject (hDC,hBrush) ;
317: PatBlt (hDC, nStart, 0, nIncr, nSizeY, PATCOPY);
318: nStart += nIncr;
319: SelectObject (hDC, hOldBrush);
320: DeleteObject (hBrush) ;
321: }
322: wsprintf (szTitlebuf, "MyPal Colors= %d", iNumColors);
323: SetWindowText (hWnd, (LPSTR)szTitlebuf);
324:
325: EndPaint(hWnd,&ps);
326:
327: break ;
328:
329: case WM_MOUSEMOVE:
330:
331: if (wParam & MK_RBUTTON) {
332:
333: POINT pt;
334:
335: #ifdef WIN16
336: /* Convert mouse position to screen coordinates */
337: pt.x = LOWORD(lParam);
338: pt.y = HIWORD(lParam);
339: #else
340: LONG2POINT(lParam, pt);
341: #endif
342: ClientToScreen(hWnd, &pt);
343:
344: /* Get RGB value (color) of pixel under mouse coordinate */
345: dwColor = GetPixel(hDCGlobal, pt.x, pt.y);
346:
347: /* If color value already exists in palette lookup table,
348: * obtain it's index.
349: */
350: for (i=0 ; i < iNumColors ; i++)
351: if ( dwColor == dwPal[i] )
352: break;
353: iIndex = i;
354:
355: /* If previous color value was not identical to current one,
356: * display color boxes on either side of title bar,
357: * the R, G, B values and palette index of current color.
358: */
359: if (dwColor != dwLastColor) {
360: wsprintf ( szTitlebuf,
361: "MyPal Colors=%d Index=%d R=%3u G=%3u B=%3u",
362: iNumColors,
363: iIndex,
364: (WORD)(BYTE) GetRValue (dwColor),
365: (WORD)(BYTE) GetGValue (dwColor),
366: (WORD)(BYTE) GetBValue (dwColor));
367: SetWindowText (hWnd, (LPSTR)szTitlebuf);
368: ShowColor (hWnd, hDCGlobal);
369: dwLastColor = dwColor;
370: }
371: }
372: break;
373:
374: case WM_RBUTTONDOWN:
375:
376: /* Determine number of color bar under mouse, thus the index
377: * of color in palette.
378: */
379: x = LOWORD(lParam);
380: iIndex = (x / nIncr );
381:
382: wsprintf ( szTitlebuf,
383: "MyPal Colors=%d Index=%d PalSize=%d RasterCaps:%d",
384: iNumColors,
385: iIndex,
386: iNumColors,
387: iRasterCaps );
388:
389: SetWindowText (hWnd, (LPSTR)szTitlebuf);
390:
391: /* Set mouse capture so that subsequent WM_MOUSEMOVEs
392: * (with right mouse button depressed) will allow MyPal
393: * to display RGB info anywhere on the screen without losing
394: * the focus.
395: */
396: SetCapture (hWnd);
397: bCaptureOn = TRUE;
398: hDCGlobal = GetDC(NULL);
399: if (hPal) {
400: SelectPalette (hDCGlobal, hPal, FALSE);
401: RealizePalette (hDCGlobal);
402: }
403: break;
404:
405: case WM_RBUTTONUP:
406: /* Stops displaying RGB and palette info and releases mouse
407: * capture
408: */
409: ReleaseDC (NULL, hDCGlobal);
410: bCaptureOn = FALSE;
411: ReleaseCapture ();
412: break;
413:
414: case WM_MOVE:
415: /* If you have a wide column, this adds 1/2 so X is centered */
416: iGlobalXOffset = LOWORD (lParam);
417: iGlobalYOffset = HIWORD (lParam) + nXBorder;
418: break;
419:
420: case WM_SIZE:
421: iYMiddle = (HIWORD (lParam)/2);
422: break;
423:
424: case WM_LBUTTONDOWN:
425: case WM_KEYDOWN:
426:
427: if (iMessage == WM_LBUTTONDOWN){
428: /* determine which column was hit by the mouse */
429: x = LOWORD(lParam);
430: iIndex = (x / nIncr );
431: }
432: else{
433: /* Use arrow keys to step thro' the palette entries */
434: switch (wParam) {
435: case VK_RIGHT:
436: case VK_UP:
437: /* go to next (higher) palette entry */
438: iIndex++;
439: break;
440: case VK_LEFT:
441: case VK_DOWN:
442: /* go to previous (lower) palette entry */
443: iIndex--;
444: break;
445: case VK_NEXT:
446: iIndex += 10;
447: break;
448: case VK_PRIOR:
449: iIndex -= 10;
450: break;
451: case VK_HOME:
452: /* go to first palette entry */
453: iIndex = 0;
454: break;
455: case VK_END:
456: /* go to last palette entry */
457: iIndex = iNumColors-1;
458: break;
459: default:
460: return 0L;
461: break;
462: }
463: /* Make sure the palette index is within range else
464: * set it to the limiting values and give a warning beep.
465: */
466: if (iIndex < 0) {
467: iIndex = 0;
468: MessageBeep(1);
469: }
470: else{
471: if (iIndex > iNumColors-1) {
472: iIndex = iNumColors-1;
473: MessageBeep(1);
474: }
475: }
476:
477: pt.x = (SHORT)((iIndex * nIncr) +
478: iGlobalXOffset +
479: ((nIncr > 1) ? (nIncr / 2) : 1));
480: pt.y = (SHORT)(iYMiddle + iGlobalYOffset);
481:
482: SetCursorPos (pt.x, pt.y);
483: }
484:
485: if (TRUE == bCaptureOn) {
486: MessageBeep(1);
487: break;
488: }
489:
490: /* Select & realize the palette or the colors > 0x7
491: * will not match up.
492: */
493: hDC = GetDC(NULL);
494: SelectPalette (hDC, hPal, 1);
495: RealizePalette (hDC) ;
496:
497: dwColor = GetNearestColor (hDC, PALETTEINDEX (iIndex));
498:
499: wsprintf ( szTitlebuf,
500: "MyPal Colors=%d Index=%d R=%3u G=%3u B=%3u",
501: iNumColors,
502: iIndex,
503: (WORD)(BYTE)GetRValue (dwColor),
504: (WORD)(BYTE)GetGValue (dwColor),
505: (WORD)(BYTE)GetBValue (dwColor)
506: );
507:
508: SetWindowText (hWnd, (LPSTR)szTitlebuf);
509: ShowColor (hWnd,hDC);
510: ReleaseDC(NULL, hDC);
511: break;
512:
513: default:
514: return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
515:
516: }
517: return 0L ;
518: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.