|
|
1.1 root 1: /*******************************************************************************
2: * *
3: * PROGRAM : ShowDIB.c *
4: * *
5: * PURPOSE : Application to illustrate the use of the GDI *
6: * DIB (Device Independent Bitmap) and Palette manager *
7: * functions. *
8: * *
9: * FUNCTIONS : WinMain () - Creates the app. window and enters *
10: * the message loop. *
11: * *
12: * WndProc() - Processes app. window messages. *
13: * *
14: * MenuCommand() - Processes menu commands. *
15: * *
16: * FreeDIB() - Frees currently active objects. *
17: * *
18: * InitDIB() - Reads DIB from a file and loads it.*
19: * *
20: *******************************************************************************/
21:
22: #include <windows.h>
23: #include <io.h>
24: #include <stdio.h>
25: #include "showdib.h"
26: #include <commdlg.h>
27:
28: DIBPARAMS DIBParams; /* params for the SETSCALING escape */
29: CHAR achFileName[128] = "";
30: DWORD dwOffset;
31: NPLOGPALETTE pLogPal;
32: HPALETTE hpalSave = NULL;
33: HANDLE hInst ;
34: RECT rcClip;
35: static HCURSOR hcurSave;
36:
37: BOOL fPalColors = FALSE; /* TRUE if the current DIB's color table */
38: /* contains palette indexes not rgb values */
39: UINT nAnimating = 0; /* Palette animation count */
40: WORD UpdateCount = 0;
41:
42: BOOL bUpdateColors = TRUE; /* Directly update screen colors */
43: BOOL bDIBToDevice = FALSE; /* Use SetDIBitsToDevice() to BLT data. */
44: BOOL bNoUgly = FALSE; /* Make window black on a WM_PALETTEISCHANGING */
45: BOOL bLegitDraw = FALSE; /* We have a valid bitmap to draw */
46:
47: CHAR szBitmapExt[] = "*.BMP; *.DIB; *.RLE"; /* possible file extensions */
48: WORD wTransparent = TRANSPARENT; /* Mode of DC */
49: CHAR szAppName[] = "ShowDIB" ; /* App. name */
50:
51: HPALETTE hpalCurrent = NULL; /* Handle to current palette */
52: HANDLE hdibCurrent = NULL; /* Handle to current memory DIB */
53: HBITMAP hbmCurrent = NULL; /* Handle to current memory BITMAP */
54: HANDLE hbiCurrent = NULL; /* Handle to current bitmap info struct */
55: HWND hWndApp; /* Handle to app. window */
56:
57: /* Styles of app. window */
58: DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
59: WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME;
60:
61: VOID PrintDIB (HWND hWnd, HDC hDC, INT x, INT y, INT dx, INT dy);
62: /****************************************************************************
63: * *
64: * FUNCTION : WinMain(HANDLE, HANDLE, LPSTR, int) *
65: * *
66: * PURPOSE : Creates the app. window and enters the message loop. *
67: * *
68: ****************************************************************************/
69: int APIENTRY WinMain(
70: HANDLE hInstance,
71: HANDLE hPrevInstance,
72: LPSTR lpCmdLine,
73: int nCmdShow
74: )
75: {
76: HWND hWnd ;
77: WNDCLASS wndclass ;
78: MSG msg ;
79: int xScreen, yScreen ;
80: CHAR ach[40];
81:
82: hInst = hInstance ;
83:
84: /* Initialize clip rectangle */
85: SetRectEmpty(&rcClip);
86:
87: if (!hPrevInstance) {
88: wndclass.style = CS_DBLCLKS;
89: wndclass.lpfnWndProc = (WNDPROC) WndProc ;
90: wndclass.cbClsExtra = 0 ;
91: wndclass.cbWndExtra = 0 ;
92: wndclass.hInstance = hInstance ;
93: wndclass.hIcon = LoadIcon(hInst, "SHOWICON");
94: wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
95: wndclass.hbrBackground = GetStockObject (BLACK_BRUSH) ;
96: wndclass.lpszMenuName = szAppName ;
97: wndclass.lpszClassName = szAppName ;
98:
99: if (!RegisterClass (&wndclass))
100: return FALSE ;
101: }
102:
103: if (!GetProfileString("extensions", "bmp", "", ach, sizeof(ach)))
104: WriteProfileString("extensions", "bmp", "showdib.exe ^.bmp");
105: if (!GetProfileString("extensions", "dib", "", ach, sizeof(ach)))
106: WriteProfileString("extensions", "dib", "showdib.exe ^.dib");
107:
108: /* Save the pointer to the command line */
109: lstrcpy(achFileName, lpCmdLine);
110:
111: xScreen = GetSystemMetrics (SM_CXSCREEN) ;
112: yScreen = GetSystemMetrics (SM_CYSCREEN) ;
113:
114: /* Create the app. window */
115: hWnd = CreateWindow( szAppName,
116: szAppName,
117: dwStyle,
118: CW_USEDEFAULT,
119: 0,
120: xScreen / 2,
121: yScreen / 2,
122: NULL,
123: NULL,
124: hInstance,
125: NULL) ;
126:
127: ShowWindow (hWndApp = hWnd, nCmdShow) ;
128:
129: /* Enter message loop */
130: while (GetMessage (&msg, NULL, 0, 0)) {
131: TranslateMessage (&msg) ;
132: DispatchMessage (&msg) ;
133: }
134:
135: return msg.wParam ;
136: }
137:
138: /****************************************************************************
139: * *
140: * FUNCTION : WndProc (hWnd, iMessage, wParam, lParam) *
141: * *
142: * PURPOSE : Processes window messages. *
143: * *
144: ****************************************************************************/
145: LONG APIENTRY WndProc (
146: HWND hWnd ,
147: UINT iMessage ,
148: UINT wParam ,
149: LONG lParam )
150:
151: {
152: PAINTSTRUCT ps;
153: HDC hDC;
154: HANDLE h;
155: INT i;
156: INT iMax;
157: INT iMin;
158: INT iPos;
159: INT dn;
160: RECT rc,Rect;
161: HPALETTE hOldPal;
162: HMENU hMenu;
163:
164: switch (iMessage) {
165: case WM_DESTROY:
166: /* Clean up and quit */
167: FreeDib();
168: PostQuitMessage(0);
169: break ;
170:
171: case WM_CREATE:
172: /* Allocate space for our logical palette */
173: pLogPal = (NPLOGPALETTE) LocalAlloc( LMEM_FIXED,
174: (sizeof(LOGPALETTE) +
175: (sizeof(PALETTEENTRY)*(MAXPALETTE))));
176: if(!pLogPal){
177: MessageBox(hWnd, "<WM_CREATE> Not enough memory for palette.", NULL, MB_OK | MB_ICONHAND);
178: PostQuitMessage (0) ;
179: break;
180: }
181:
182: // Temporary workaround. lpCmdLine points to exe name, not first parameter
183: /* If DIB initialization fails, quit */
184: // if (achFileName[0] && !InitDIB(hWnd))
185: // PostQuitMessage (3) ;
186:
187: /* fall through */
188:
189: case WM_WININICHANGE:
190:
191: hMenu = GetMenu(hWnd);
192:
193: /* If printer initialization succeeds, enable appropriate
194: * menu item and clean up.
195: */
196: if ( hDC = GetPrinterDC() ) {
197: EnableMenuItem( hMenu,
198: IDM_PRINT,
199: (RC_DIBTODEV &
200: GetDeviceCaps(hDC, RASTERCAPS)) ?
201: MF_ENABLED :
202: MF_GRAYED | MF_DISABLED);
203: DeleteDC(hDC);
204: }
205: break;
206:
207: case WM_PALETTEISCHANGING:
208: /* if SHOWDIB was not responsible for palette change and if
209: * ok to hide changes, paint app. window black.
210: */
211: if (wParam != (UINT)(hWnd && bNoUgly)) {
212: GetClientRect(hWnd, &Rect);
213:
214: hDC = GetDC(hWnd);
215: FillRect( hDC, (LPRECT) &Rect, GetStockObject(BLACK_BRUSH));
216: ReleaseDC(hWnd, hDC);
217: }
218: break;
219:
220: case WM_ACTIVATE:
221: if (!GET_WM_ACTIVATE_STATE(wParam, lParam)) /* app. is being de-activated */
222: break;
223: /* If the app. is moving to the foreground, fall through and
224: * redraw full client area with the newly realized palette,
225: * if the palette has changed.
226: */
227:
228: case WM_QUERYNEWPALETTE:
229: /* If palette realization causes a palette change,
230: * we need to do a full redraw.
231: */
232: if (bLegitDraw) {
233: hDC = GetDC (hWnd);
234: hOldPal = SelectPalette (hDC, hpalCurrent, 0);
235:
236: i = RealizePalette(hDC);
237:
238: SelectPalette (hDC, hOldPal, 0);
239: ReleaseDC (hWnd, hDC);
240:
241: if (i) {
242: InvalidateRect (hWnd, (LPRECT) (NULL), 1);
243: UpdateCount = 0;
244: return 1;
245: } else
246: return FALSE;
247: }
248: else
249: return FALSE;
250: break;
251:
252: case WM_PALETTECHANGED:
253: /* if SHOWDIB was not responsible for palette change and if
254: * palette realization causes a palette change, do a redraw.
255: */
256: if ((HWND)wParam != hWnd){
257: if (bLegitDraw){
258: hDC = GetDC (hWnd);
259: hOldPal = SelectPalette (hDC, hpalCurrent, 0);
260:
261: i = RealizePalette (hDC);
262:
263: if (i){
264: if (bUpdateColors){
265: UpdateColors (hDC);
266: UpdateCount++;
267: }
268: else
269: InvalidateRect (hWnd, (LPRECT) (NULL), 1);
270: }
271:
272: SelectPalette (hDC, hOldPal, 0);
273: ReleaseDC (hWnd, hDC);
274: }
275: }
276: break;
277:
278: case WM_RENDERALLFORMATS:
279: /* Ensure that clipboard data can be rendered even tho'
280: * app. is being destroyed.
281: */
282: SendMessage(hWnd,WM_RENDERFORMAT,CF_DIB,0L);
283: SendMessage(hWnd,WM_RENDERFORMAT,CF_BITMAP,0L);
284: SendMessage(hWnd,WM_RENDERFORMAT,CF_PALETTE,0L);
285: break;
286:
287: case WM_RENDERFORMAT:
288: /* Format data in manner specified and pass the data
289: * handle to clipboard.
290: */
291: if (h = RenderFormat(wParam))
292: SetClipboardData((WORD)wParam,h);
293: break;
294:
295: case WM_COMMAND:
296: /* Process menu commands */
297: return MenuCommand(hWnd, LOWORD(wParam));
298: break;
299:
300: case WM_TIMER:
301: /* Signal for palette animation */
302: hDC = GetDC(hWnd);
303: hOldPal = SelectPalette(hDC, hpalCurrent, 0);
304: {
305: PALETTEENTRY peTemp;
306:
307: /* Shift all palette entries left by one position and wrap
308: * around the first entry
309: */
310: peTemp = pLogPal->palPalEntry[0];
311: for (i = 0; i < (pLogPal->palNumEntries - 1); i++)
312: pLogPal->palPalEntry[i] = pLogPal->palPalEntry[i+1];
313: pLogPal->palPalEntry[i] = peTemp;
314: }
315: /* Replace entries in logical palette with new entries*/
316: AnimatePalette(hpalCurrent, 0, pLogPal->palNumEntries, pLogPal->palPalEntry);
317:
318: SelectPalette(hDC, hOldPal, 0);
319: ReleaseDC(hWnd, hDC);
320:
321: /* Decrement animation count and terminate animation
322: * if it reaches zero
323: */
324: if (!(--nAnimating))
325: PostMessage(hWnd,WM_COMMAND,IDM_ANIMATE0,0L);
326: break;
327:
328: case WM_PAINT:
329: /* If we have updated more than once, the rest of our
330: * window is not in some level of degradation worse than
331: * our redraw... we need to redraw the whole area
332: */
333: if (UpdateCount > 1) {
334: BeginPaint(hWnd, &ps);
335: EndPaint(hWnd, &ps);
336: UpdateCount = 0;
337: InvalidateRect(hWnd, (LPRECT) (NULL), 1);
338: break;
339: }
340:
341: hDC = BeginPaint(hWnd, &ps);
342: AppPaint(hWnd,
343: hDC,
344: GetScrollPos(hWnd,SB_HORZ),
345: GetScrollPos(hWnd,SB_VERT) );
346: EndPaint(hWnd, &ps);
347: break ;
348:
349: case WM_SIZE:
350: SetScrollRanges(hWnd);
351: break;
352:
353: case WM_KEYDOWN:
354: /* Translate keyboard messages to scroll commands */
355: switch (wParam) {
356: case VK_UP:
357: PostMessage (hWnd, WM_VSCROLL, SB_LINEUP, 0L);
358: break;
359:
360: case VK_DOWN:
361: PostMessage (hWnd, WM_VSCROLL, SB_LINEDOWN, 0L);
362: break;
363:
364: case VK_PRIOR:
365: PostMessage (hWnd, WM_VSCROLL, SB_PAGEUP, 0L);
366: break;
367:
368: case VK_NEXT:
369: PostMessage (hWnd, WM_VSCROLL, SB_PAGEDOWN, 0L);
370: break;
371:
372: case VK_HOME:
373: PostMessage (hWnd, WM_HSCROLL, SB_PAGEUP, 0L);
374: break;
375:
376: case VK_END:
377: PostMessage (hWnd, WM_HSCROLL, SB_PAGEDOWN, 0L);
378: break;
379:
380: case VK_LEFT:
381: PostMessage (hWnd, WM_HSCROLL, SB_LINEUP, 0L);
382: break;
383:
384: case VK_RIGHT:
385: PostMessage (hWnd, WM_HSCROLL, SB_LINEDOWN, 0L);
386: break;
387: }
388: break;
389:
390: case WM_KEYUP:
391: switch (wParam) {
392: case VK_UP:
393: case VK_DOWN:
394: case VK_PRIOR:
395: case VK_NEXT:
396: PostMessage (hWnd, WM_VSCROLL, SB_ENDSCROLL, 0L);
397: break;
398:
399: case VK_HOME:
400: case VK_END:
401: case VK_LEFT:
402: case VK_RIGHT:
403: PostMessage (hWnd, WM_HSCROLL, SB_ENDSCROLL, 0L);
404: break;
405: }
406: break;
407:
408: case WM_VSCROLL:
409: /* Calculate new vertical scroll position */
410: GetScrollRange (hWnd, SB_VERT, &iMin, &iMax);
411: iPos = GetScrollPos (hWnd, SB_VERT);
412: GetClientRect (hWnd, &rc);
413:
414: switch (GET_WM_VSCROLL_CODE(wParam, lParam)) {
415: case SB_LINEDOWN:
416: dn = rc.bottom / 16 + 1;
417: break;
418:
419: case SB_LINEUP:
420: dn = -rc.bottom / 16 + 1;
421: break;
422:
423: case SB_PAGEDOWN:
424: dn = rc.bottom / 2 + 1;
425: break;
426:
427: case SB_PAGEUP:
428: dn = -rc.bottom / 2 + 1;
429: break;
430:
431: case SB_THUMBTRACK:
432: case SB_THUMBPOSITION:
433: dn = GET_WM_VSCROLL_POS(wParam, lParam)-iPos;
434: break;
435:
436: default:
437: dn = 0;
438: break;
439: }
440: /* Limit scrolling to current scroll range */
441: if (dn = BOUND (iPos + dn, iMin, iMax) - iPos) {
442: ScrollWindow (hWnd, 0, -dn, NULL, NULL);
443: SetScrollPos (hWnd, SB_VERT, iPos + dn, TRUE);
444: }
445: break;
446:
447: case WM_HSCROLL:
448: /* Calculate new horizontal scroll position */
449: GetScrollRange (hWnd, SB_HORZ, &iMin, &iMax);
450: iPos = GetScrollPos (hWnd, SB_HORZ);
451: GetClientRect (hWnd, &rc);
452:
453: switch (GET_WM_HSCROLL_CODE(wParam, lParam)) {
454: case SB_LINEDOWN:
455: dn = rc.right / 16 + 1;
456: break;
457:
458: case SB_LINEUP:
459: dn = -rc.right / 16 + 1;
460: break;
461:
462: case SB_PAGEDOWN:
463: dn = rc.right / 2 + 1;
464: break;
465:
466: case SB_PAGEUP:
467: dn = -rc.right / 2 + 1;
468: break;
469:
470: case SB_THUMBTRACK:
471: case SB_THUMBPOSITION:
472: dn = GET_WM_HSCROLL_POS(wParam, lParam)-iPos;
473: break;
474:
475: default:
476: dn = 0;
477: break;
478: }
479: /* Limit scrolling to current scroll range */
480: if (dn = BOUND (iPos + dn, iMin, iMax) - iPos) {
481: ScrollWindow (hWnd, -dn, 0, NULL, NULL);
482: SetScrollPos (hWnd, SB_HORZ, iPos + dn, TRUE);
483: }
484: break;
485:
486: case WM_LBUTTONDOWN:
487: /* Start rubberbanding a rect. and track it's dimensions.
488: * set the clip rectangle to it's dimensions.
489: */
490: TrackMouse (hWnd, MAKEMPOINT(lParam));
491: break;
492:
493: case WM_LBUTTONDBLCLK:
494: break;
495:
496: case WM_INITMENU:
497: /* check/uncheck menu items depending on state of related
498: * flags
499: */
500: CheckMenuItem((HMENU)wParam, IDM_UPDATECOL,
501: (bUpdateColors ? MF_CHECKED : MF_UNCHECKED));
502: CheckMenuItem((HMENU)wParam, IDM_TRANSPARENT,
503: (wTransparent == TRANSPARENT ? MF_CHECKED : MF_UNCHECKED));
504: CheckMenuItem((HMENU)wParam, IDM_DIBSCREEN,
505: (bDIBToDevice ? MF_CHECKED : MF_UNCHECKED));
506: CheckMenuItem((HMENU)wParam, IDM_NOUGLY,
507: (bNoUgly ? MF_CHECKED : MF_UNCHECKED));
508: CheckMenuItem((HMENU)wParam, IDM_MEMORYDIB, MF_CHECKED);
509: EnableMenuItem((HMENU)wParam, IDM_PASTEDIB,
510: IsClipboardFormatAvailable(CF_DIB)?MF_ENABLED:MF_GRAYED);
511: EnableMenuItem((HMENU)wParam, IDM_PASTEDDB,
512: IsClipboardFormatAvailable(CF_BITMAP)?MF_ENABLED:MF_GRAYED);
513: EnableMenuItem((HMENU)wParam, IDM_PASTEPAL,
514: IsClipboardFormatAvailable(CF_PALETTE)?MF_ENABLED:MF_GRAYED);
515: EnableMenuItem((HMENU)wParam, IDM_PRINT,
516: bLegitDraw ? MF_ENABLED : MF_GRAYED);
517: EnableMenuItem((HMENU)wParam, IDM_SAVE,
518: bLegitDraw ? MF_ENABLED : MF_GRAYED);
519: EnableMenuItem((HMENU)wParam, IDM_COPY,
520: bLegitDraw ? MF_ENABLED : MF_GRAYED);
521:
522: EnableMenuItem((HMENU)wParam, IDM_ANIMATE0,
523: bLegitDraw ? MF_ENABLED : MF_GRAYED);
524: EnableMenuItem((HMENU)wParam, IDM_ANIMATE5,
525: bLegitDraw ? MF_ENABLED : MF_GRAYED);
526: EnableMenuItem((HMENU)wParam, IDM_ANIMATE50,
527: bLegitDraw ? MF_ENABLED : MF_GRAYED);
528: EnableMenuItem((HMENU)wParam, IDM_ANIMATE100,
529: bLegitDraw ? MF_ENABLED : MF_GRAYED);
530: EnableMenuItem((HMENU)wParam, IDM_ANIMATE200,
531: bLegitDraw ? MF_ENABLED : MF_GRAYED);
532: EnableMenuItem((HMENU)wParam, IDM_ANIMATE201,
533: bLegitDraw ? MF_ENABLED : MF_GRAYED);
534: EnableMenuItem((HMENU)wParam, IDM_STEALCOL,
535: bLegitDraw ? MF_ENABLED : MF_GRAYED);
536: break;
537:
538: default:
539: return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
540:
541: }
542: return 0L ;
543:
544: }
545: /****************************************************************************
546: * *
547: * FUNCTION : MenuCommand ( HWND hWnd, WPARAM wParam) *
548: * *
549: * PURPOSE : Processes menu commands. *
550: * *
551: * RETURNS : TRUE - if command could be processed. *
552: * FALSE - otherwise *
553: * *
554: ****************************************************************************/
555: BOOL MenuCommand (
556: HWND hWnd,
557: UINT id)
558:
559: {
560: BITMAPINFOHEADER bi;
561: HDC hDC;
562: HANDLE h;
563: HBITMAP hbm;
564: HPALETTE hpal;
565: WORD i;
566: CHAR Name[40];
567: BOOL bSave;
568: INT xSize, ySize, xRes, yRes, dx, dy;
569: RECT Rect;
570: HFILE fh;
571: WORD fFileOptions;
572:
573: switch (id) {
574: case IDM_ABOUT:
575: /* Show About .. box */
576: fDialog ((INT)ABOUTBOX, hWnd,(FARPROC)AppAbout);
577: break;
578:
579: case IDM_COPY:
580: if (!bLegitDraw)
581: return 0L;
582:
583: /* Clean clipboard of contents */
584: if (OpenClipboard(hWnd)) {
585: EmptyClipboard ();
586: SetClipboardData (CF_DIB ,NULL);
587: SetClipboardData (CF_BITMAP ,NULL);
588: SetClipboardData (CF_PALETTE ,NULL);
589: CloseClipboard ();
590: }
591: break;
592:
593: case IDM_PASTEPAL:
594: if (OpenClipboard (hWnd)) {
595: if (h = GetClipboardData (CF_PALETTE)) {
596: /* Delete current palette and get the CF_PALETTE data
597: * from the clipboard
598: */
599: if (hpalCurrent)
600: DeleteObject (hpalCurrent);
601:
602: hpalCurrent = CopyPalette (h);
603:
604: /*
605: * If we have a bitmap realized against the old palette
606: * delete the bitmap and rebuild it using the new palette.
607: */
608: if (hbmCurrent){
609: DeleteObject (hbmCurrent);
610: hbmCurrent = NULL;
611:
612: if (hdibCurrent)
613: hbmCurrent = BitmapFromDib (hdibCurrent, hpalCurrent);
614: }
615: }
616: CloseClipboard();
617: }
618: break;
619:
620: case IDM_PASTEDIB:
621: if (OpenClipboard (hWnd)) {
622: if (h = GetClipboardData (CF_DIB)) {
623: /* Delete current DIB and get CF_DIB and
624: * CF_PALETTE format data from the clipboard
625: */
626: hpal = GetClipboardData (CF_PALETTE);
627:
628: FreeDib();
629: hdibCurrent = CopyHandle (h);
630: if (hdibCurrent) {
631: bLegitDraw = TRUE;
632: lstrcpy(achFileName,"<Clipboard>");
633: hbiCurrent = hdibCurrent;
634:
635: /* If there is a CF_PALETTE object in the
636: * clipboard, this is the palette to assume
637: * the DIB should be realized against, otherwise
638: * create a palette for it.
639: */
640: if (hpal)
641: hpalCurrent = CopyPalette (hpal);
642: else
643: hpalCurrent = CreateDibPalette (hdibCurrent);
644:
645: SizeWindow(hWnd);
646: }
647: else {
648: bLegitDraw = FALSE;
649: ErrMsg("No Memory Available!");
650: }
651: }
652: CloseClipboard();
653: }
654: break;
655:
656: case IDM_PASTEDDB:
657: if (OpenClipboard (hWnd)) {
658: if (hbm = GetClipboardData(CF_BITMAP)) {
659: hpal = GetClipboardData(CF_PALETTE);
660: FreeDib();
661:
662: /*
663: * If there is a CF_PALETTE object in the
664: * clipboard, this is the palette to assume
665: * the bitmap is realized against.
666: */
667: if (hpal)
668: hpalCurrent = CopyPalette(hpal);
669: else
670: hpalCurrent = GetStockObject(DEFAULT_PALETTE);
671:
672: hdibCurrent = DibFromBitmap(hbm,BI_RGB,0,hpalCurrent);
673:
674: if (hdibCurrent) {
675: bLegitDraw = TRUE;
676: lstrcpy(achFileName,"<Clipboard>");
677: hbiCurrent = hdibCurrent;
678:
679: hbmCurrent = BitmapFromDib(hdibCurrent,hpalCurrent);
680:
681: SizeWindow(hWnd);
682: }
683: else {
684: bLegitDraw = FALSE;
685: ErrMsg("No Memory Available!");
686: }
687: }
688: CloseClipboard ();
689: }
690: break;
691:
692: case IDM_PRINT:
693: GetWindowText(hWnd, Name, sizeof(Name));
694:
695: DibInfo(hbiCurrent, &bi);
696:
697: if (!IsRectEmpty(&rcClip))
698: {
699: bi.biWidth = rcClip.right - rcClip.left;
700: bi.biHeight = rcClip.bottom - rcClip.top;
701: }
702:
703: /* Initialise printer stuff */
704: if (!(hDC = GetPrinterDC()))
705: break;
706:
707: xSize = GetDeviceCaps(hDC, HORZRES);
708: ySize = GetDeviceCaps(hDC, VERTRES);
709: xRes = GetDeviceCaps(hDC, LOGPIXELSX);
710: yRes = GetDeviceCaps(hDC, LOGPIXELSY);
711:
712: /* Use half inch margins on left and right
713: * and one inch on top. Maintain the same aspect ratio.
714: */
715:
716: dx = xSize - xRes;
717: dy = (INT)((LONG)dx * bi.biHeight/bi.biWidth);
718:
719: /* Fix bounding rectangle for the picture .. */
720: Rect.top = yRes;
721: Rect.left = xRes / 2;
722: Rect.bottom = yRes + dy;
723: Rect.right = xRes / 2 + dx;
724:
725: /* ... and inform the driver */
726: Escape(hDC, SET_BOUNDS, sizeof(RECT), (LPSTR)&Rect, NULL);
727:
728: bSave = TRUE;
729:
730: if (InitPrinting(hDC, hWnd, hInst, Name)) {
731:
732: PrintDIB(hWnd, hDC, xRes/2, yRes, dx, dy);
733:
734: /* Signal to the driver to begin translating the drawing
735: * commands to printer output...
736: */
737: Escape (hDC, NEWFRAME, NULL, NULL, NULL);
738:
739: TermPrinting(hDC);
740: }
741:
742: DeleteDC(hDC);
743: break;
744:
745: case IDM_OPEN:
746: {
747:
748: /* Bring up File/Open ... dialog */
749: fh = DlgOpenFile (hWnd,
750: "Select a DIB to display",
751: (LONG)OF_EXIST | OF_MUSTEXIST | OF_NOOPTIONS,
752: szBitmapExt,
753: achFileName,
754: NULL
755: );
756: /* Load up the DIB if the user did not press cancel */
757: if (fh > 0) {
758: StartWait();
759: if (InitDIB (hWnd))
760: InvalidateRect (hWnd, NULL, FALSE);
761: else
762: bLegitDraw = FALSE;
763: EndWait();
764: }
765: break;
766: }
767: case IDM_SAVE:
768: DibInfo(hbiCurrent,&bi);
769: fFileOptions = 0;
770:
771: /* Depending on compression type for current DIB,
772: * set the appropriate bit in the fFileOptions flag
773: */
774: if (bi.biCompression == BI_RGB)
775: fFileOptions |= F_RGB;
776: else if (bi.biCompression == BI_RLE4)
777: fFileOptions |= F_RLE4;
778: else if (bi.biCompression == BI_RLE8)
779: fFileOptions |= F_RLE8;
780:
781: /* Depending on bits/pixel type for current DIB,
782: * set the appropriate bit in the fFileOptions flag
783: */
784: switch (bi.biBitCount){
785: case 1:
786: fFileOptions |= F_1BPP;
787: break;
788:
789: case 4:
790: fFileOptions |= F_4BPP;
791: break;
792:
793: case 8:
794: fFileOptions |= F_8BPP;
795: break;
796:
797: case 24:
798: fFileOptions |= F_24BPP;
799: }
800:
801: /* Bring up File/Save... dialog and get info. about filename,
802: * compression, and bits/pix. of DIB to be written.
803: */
804: fh = DlgOpenFile (hWnd,
805: "Select File to save DIB to",
806: (LONG)OF_EXIST | OF_SAVE | OF_NOSHOWSPEC,
807: szBitmapExt,
808: achFileName,
809: &fFileOptions);
810:
811: /* Extract DIB specs. if the user did not press cancel */
812: if (fh != 0){
813: if (fFileOptions & F_RGB)
814: bi.biCompression = BI_RGB;
815:
816: if (fFileOptions & F_RLE4)
817: bi.biCompression = BI_RLE4;
818:
819: if (fFileOptions & F_RLE8)
820: bi.biCompression = BI_RLE8;
821:
822: if (fFileOptions & F_1BPP)
823: bi.biBitCount = 1;
824:
825: if (fFileOptions & F_4BPP)
826: bi.biBitCount = 4;
827:
828: if (fFileOptions & F_8BPP)
829: bi.biBitCount = 8;
830:
831: if (fFileOptions & F_24BPP)
832: bi.biBitCount = 24;
833:
834: /* Realize a DIB in the specified format and obtain a
835: * handle to it.
836: */
837: hdibCurrent = RealizeDibFormat(bi.biCompression,bi.biBitCount);
838: if (!hdibCurrent){
839: ErrMsg("Unable to save the specified file");
840: return 0L;
841: }
842:
843: /* Write the DIB */
844: StartWait();
845: if (!WriteDIB(achFileName,hdibCurrent))
846: ErrMsg("Unable to save the specified file");
847: EndWait();
848: }
849: break;
850:
851: case IDM_EXIT:
852: PostMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
853: break;
854:
855: case IDM_UPDATECOL:
856: /* Toggle state of "update screen colors" flag. If it is
857: * off, clear the "hide changes" flag
858: */
859: bUpdateColors = !bUpdateColors;
860: if (bUpdateColors)
861: bNoUgly = 0;
862: break;
863:
864: case IDM_DIBSCREEN:
865: bDIBToDevice = !bDIBToDevice;
866: InvalidateRect(hWnd, (LPRECT) (NULL), 1);
867: break;
868:
869: case IDM_MEMORYDIB:
870: break;
871:
872: case IDM_NOUGLY:
873: /* Toggle state of "hide changes" flag. If it is off, clear
874: * the "update screen colors" flag. This will tell SHOWDIB
875: * to paint itself black while the palette is changing.
876: */
877: bNoUgly = !bNoUgly;
878: if (bNoUgly)
879: bUpdateColors = 0;
880: break;
881:
882: case IDM_TRANSPARENT:
883: /* Toggle DC mode */
884: wTransparent = (WORD) (wTransparent == TRANSPARENT ?
885: OPAQUE : TRANSPARENT);
886: break;
887:
888: case IDM_ANIMATE0:
889: if (!hpalSave)
890: break;
891:
892: /* Reset animation count and stop timer */
893: KillTimer(hWnd, 1);
894: nAnimating = 0;
895:
896: /* Restore palette which existed before animation started */
897: DeleteObject(hpalCurrent);
898: hpalCurrent = hpalSave;
899:
900: /* Rebuild bitmap based on newly realized information */
901: hDC = GetDC (hWnd);
902: SelectPalette (hDC, hpalCurrent, 0);
903: RealizePalette (hDC);
904: ReleaseDC (hWnd, hDC);
905:
906: if (hbmCurrent){
907: DeleteObject (hbmCurrent);
908: hbmCurrent = NULL;
909:
910: if (hdibCurrent)
911: hbmCurrent = BitmapFromDib (hdibCurrent, hpalCurrent);
912: }
913: hpalSave = NULL;
914:
915: /* Force redraw with new palette for everyone */
916: InvalidateRect(hWnd, NULL, TRUE);
917: break;
918:
919: case IDM_STEALCOL:
920: case IDM_ANIMATE5:
921: case IDM_ANIMATE20:
922: case IDM_ANIMATE50:
923: case IDM_ANIMATE100:
924: case IDM_ANIMATE200:
925: case IDM_ANIMATE201:
926: /* Set animation count i.e number of times animation is to
927: * take place.
928: */
929: nAnimating = id;
930: if (id == IDM_STEALCOL)
931: nAnimating = 0;
932:
933: /* Save current palette */
934: hpalSave = CopyPalette(hpalCurrent);
935:
936: GetObject(hpalCurrent, sizeof(INT), (LPSTR)&pLogPal->palNumEntries);
937: GetPaletteEntries(hpalCurrent, 0, pLogPal->palNumEntries, pLogPal->palPalEntry);
938:
939: /* Reserve all entries in the palette otherwise AnimatePalette()
940: * will not modify them
941: */
942: for (i = 0; i < pLogPal->palNumEntries; i++) {
943: pLogPal->palPalEntry[i].peFlags = (BYTE)PC_RESERVED;
944: }
945:
946: SetPaletteEntries(hpalCurrent, 0, pLogPal->palNumEntries, pLogPal->palPalEntry);
947:
948: /* Rebuild bitmap based on newly realized information */
949: if (hbmCurrent){
950: DeleteObject (hbmCurrent);
951: hbmCurrent = NULL;
952:
953: if (hdibCurrent)
954: hbmCurrent = BitmapFromDib (hdibCurrent, hpalCurrent);
955: }
956:
957: /* Force redraw with new palette for everyone */
958: InvalidateRect(hWnd, NULL, TRUE);
959:
960: /* Initiate the timer so that palette can be animated in
961: * response to a WM_TIMER message
962: */
963: if (nAnimating && !SetTimer(hWnd, 1, 250, (WNDPROC)(LPSTR) NULL))
964: nAnimating = 0;
965:
966: default:
967: break;
968: }
969:
970: return TRUE;
971: }
972:
973: /****************************************************************************
974: * *
975: * FUNCTION : InitDIB(hWnd) *
976: * *
977: * PURPOSE : Reads a DIB from a file, obtains a handle to it's *
978: * BITMAPINFO struct., sets up the palette and loads the DIB. *
979: * *
980: * RETURNS : TRUE - DIB loads ok *
981: * FALSE - otherwise *
982: * *
983: ****************************************************************************/
984: INT InitDIB(HWND hWnd)
985: {
986: HFILE fh;
987: LPBITMAPINFOHEADER lpbi;
988: WORD FAR * pw;
989: INT i;
990: BITMAPINFOHEADER bi;
991: OFSTRUCT of;
992:
993: FreeDib();
994:
995: /* Open the file and get a handle to it's BITMAPINFO */
996:
997: fh = OpenFile(achFileName, (LPOFSTRUCT)&of, (UINT)OF_READ);
998: if (fh == -1) {
999: ErrMsg("Can't open file '%ls'", (LPSTR)achFileName);
1000: return FALSE;
1001: }
1002: hbiCurrent = ReadDibBitmapInfo(fh);
1003:
1004: dwOffset = _llseek(fh, 0L, (UINT)SEEK_CUR);
1005: _lclose(fh);
1006:
1007: if (hbiCurrent == NULL) {
1008: ErrMsg("%ls is not a Legitimate DIB File!", (LPSTR)achFileName);
1009: return FALSE;
1010: }
1011: DibInfo(hbiCurrent,&bi);
1012:
1013: /* Set up the palette */
1014: hpalCurrent = CreateDibPalette(hbiCurrent);
1015: if (hpalCurrent == NULL) {
1016: ErrMsg("CreatePalette() Failed");
1017: return FALSE;
1018: }
1019:
1020: /* Convert the DIB color table to palette relative indexes, so
1021: * SetDIBits() and SetDIBitsToDevice() can avoid color matching.
1022: * We can do this because the palette we realize is identical
1023: * to the color table of the bitmap, ie the indexes match 1 to 1
1024: *
1025: * Now that the DIB color table is palette indexes not RGB values
1026: * we must use DIB_PAL_COLORS as the wUsage parameter to SetDIBits()
1027: */
1028: lpbi = (VOID FAR *)GlobalLock(hbiCurrent);
1029: if (lpbi->biBitCount != 24) {
1030: fPalColors = TRUE;
1031:
1032: pw = (WORD FAR *)((LPSTR)lpbi + lpbi->biSize);
1033:
1034: for (i=0; i<(INT)lpbi->biClrUsed; i++)
1035: *pw++ = (WORD)i;
1036: }
1037: GlobalUnlock(hbiCurrent);
1038: bLegitDraw = TRUE;
1039:
1040: /* If the input bitmap is not in RGB FORMAT the banding code will
1041: * not work! we need to load the DIB bits into memory.
1042: * if memory DIB, load it all NOW! This will avoid calling the
1043: * banding code.
1044: */
1045: hdibCurrent = OpenDIB(achFileName);
1046:
1047: /* If the RLE could not be loaded all at once, exit gracefully NOW,
1048: * to avoid calling the banding code
1049: */
1050: if ((bi.biCompression != BI_RGB) && !hdibCurrent){
1051: ErrMsg ("Could not load RLE!");
1052: FreeDib();
1053: return FALSE;
1054: }
1055:
1056: if (hdibCurrent && !bDIBToDevice){
1057: hbmCurrent = BitmapFromDib(hdibCurrent,hpalCurrent);
1058: if (!hbmCurrent){
1059: ErrMsg ("Could not create bitmap!");
1060: FreeDib();
1061: return FALSE;
1062: }
1063: }
1064:
1065: SizeWindow(hWnd);
1066:
1067: return TRUE;
1068: }
1069: /****************************************************************************
1070: * *
1071: * FUNCTION : FreeDib(void) *
1072: * *
1073: * PURPOSE : Frees all currently active bitmap, DIB and palette objects *
1074: * and initializes their handles. *
1075: * *
1076: ****************************************************************************/
1077: VOID FreeDib()
1078: {
1079: if (hpalCurrent)
1080: DeleteObject(hpalCurrent);
1081:
1082: if (hbmCurrent)
1083: DeleteObject(hbmCurrent);
1084:
1085: if (hdibCurrent)
1086: GlobalFree(hdibCurrent);
1087:
1088: if (hbiCurrent && hbiCurrent != hdibCurrent)
1089: GlobalFree(hbiCurrent);
1090:
1091: fPalColors = FALSE;
1092: bLegitDraw = FALSE;
1093: hpalCurrent = NULL;
1094: hdibCurrent = NULL;
1095: hbmCurrent = NULL;
1096: hbiCurrent = NULL;
1097: SetRectEmpty (&rcClip);
1098: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.