]> git.saurik.com Git - wxWidgets.git/blob - src/msw/dibutils.cpp
Improved wxFileDialog behaviour wrt to remembering filenames
[wxWidgets.git] / src / msw / dibutils.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        dibutils.cpp
3 // Purpose:     Utilities for DIBs
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     04/01/98
7 // RCS-ID:      $Id$
8 // Copyright:   (c) Microsoft, Julian Smart and Markus Holzem
9 // Licence:     wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "dibutils.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/setup.h"
25 #include "wx/defs.h"
26 #include "wx/string.h"
27 #endif
28
29 #include <windows.h>
30 #include <windowsx.h>
31 #include <stdio.h>
32
33 #include "wx/msw/dibutils.h"
34
35 #ifdef __WXWINE__
36   #include <module.h>
37 #endif
38
39 #if defined(__WIN32__)
40 #if !defined(__MWERKS__) && !defined(__SALFORDC__)
41     #include <memory.h>             // for _fmemcpy()
42 #endif
43    #define _huge
44 #ifndef hmemcpy
45     #define hmemcpy memcpy
46 #endif
47 #endif
48
49 #define BFT_ICON   0x4349   /* 'IC' */
50 #define BFT_BITMAP 0x4d42   /* 'BM' */
51 #define BFT_CURSOR 0x5450   /* 'PT' */
52
53 #ifndef SEEK_CUR
54 /* flags for _lseek */
55 #define  SEEK_CUR 1
56 #define  SEEK_END 2
57 #define  SEEK_SET 0
58 #endif
59
60 /* Copied from PNGhandler for coompilation with MingW32, RR */
61
62 #ifndef GlobalAllocPtr
63 #define     GlobalPtrHandle(lp)         \
64                 ((HGLOBAL)GlobalHandle(lp))
65
66 #define     GlobalLockPtr(lp)                \
67                 ((BOOL)GlobalLock(GlobalPtrHandle(lp)))
68 #define     GlobalUnlockPtr(lp)      \
69                 GlobalUnlock(GlobalPtrHandle(lp))
70
71 #define     GlobalAllocPtr(flags, cb)        \
72                 (GlobalLock(GlobalAlloc((flags), (cb))))
73 #define     GlobalReAllocPtr(lp, cbNew, flags)       \
74                 (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
75 #define     GlobalFreePtr(lp)                \
76                 (GlobalUnlockPtr(lp), (BOOL)GlobalFree(GlobalPtrHandle(lp)))
77 #endif
78
79
80 /*
81  *  Clear the System Palette so that we can ensure an identity palette 
82  *  mapping for fast performance.
83  */
84
85 void ClearSystemPalette(void)
86 {
87   //*** A dummy palette setup
88   struct
89   {
90     WORD Version;
91     WORD NumberOfEntries;
92     PALETTEENTRY aEntries[256];
93   } Palette =
94   {
95     0x300,
96     256
97   };
98
99   HPALETTE ScreenPalette = 0;
100   HDC ScreenDC;
101   int Counter;
102   UINT nMapped = 0;
103   BOOL bOK = FALSE;
104   int  nOK = 0;
105   
106   // *** Reset everything in the system palette to black
107   for(Counter = 0; Counter < 256; Counter++)
108   {
109     Palette.aEntries[Counter].peRed = 0;
110    Palette.aEntries[Counter].peGreen = 0;
111     Palette.aEntries[Counter].peBlue = 0;
112     Palette.aEntries[Counter].peFlags = PC_NOCOLLAPSE;
113   }
114
115   // *** Create, select, realize, deselect, and delete the palette
116 #ifdef __WXWINE__
117   ScreenDC = GetDC((HWND)NULL);
118 #else
119   ScreenDC = GetDC(NULL);
120 #endif
121   ScreenPalette = CreatePalette((LOGPALETTE *)&Palette);
122
123   if (ScreenPalette)
124   {
125    ScreenPalette = SelectPalette(ScreenDC,ScreenPalette,FALSE);
126    nMapped = RealizePalette(ScreenDC);
127     ScreenPalette = SelectPalette(ScreenDC,ScreenPalette,FALSE);
128     bOK = DeleteObject(ScreenPalette);
129   }
130
131 #ifdef __WXWINE__
132   nOK = ReleaseDC((HWND)NULL, ScreenDC);
133 #else
134   nOK = ReleaseDC(NULL, ScreenDC);
135 #endif
136
137   return;
138 }
139
140
141 /*
142  *   Open a DIB file and return a MEMORY DIB, a memory handle containing..
143  *
144  *   BITMAP INFO    bi
145  *   palette data
146  *   bits....
147  */
148
149 int DibWriteFile(LPTSTR szFile, LPBITMAPINFOHEADER lpbi)
150 {
151    HFILE               fh;
152    OFSTRUCT            of;
153
154    fh = OpenFile(wxConvFile.cWX2MB(szFile), &of, OF_WRITE | OF_CREATE);
155
156   if (!fh) {
157 //   printf("la regamos0");
158    return 0;
159   }
160
161   long size = DibSize(lpbi);
162
163   // write file header
164   BITMAPFILEHEADER bmf;
165   bmf.bfType = 'BM';
166   bmf.bfSize = sizeof(bmf) + size;
167   bmf.bfReserved1 = 0;
168   bmf.bfReserved2 = 0;
169   bmf.bfOffBits = sizeof(bmf) + (char FAR*)(DibPtr(lpbi)) - (char FAR*)lpbi;
170 #if defined( __WATCOMC__) || defined(__VISUALC__) || defined(__SC__) || defined(__SALFORDC__) || defined(__MWERKS__) || defined(wxUSE_NORLANDER_HEADERS)
171   if (_hwrite(fh, (LPCSTR)(&bmf), sizeof(bmf))<0 ||
172   _hwrite(fh, (LPCSTR)lpbi, size)<0) {
173     _lclose(fh);
174 //   printf("la regamos1");
175     return 0;
176   }
177 #else
178   if (_hwrite(fh, (LPBYTE)(&bmf), sizeof(bmf))<0 ||
179   _hwrite(fh, (LPBYTE)lpbi, size)<0) {
180     _lclose(fh);
181 //   printf("la regamos1");
182     return 0;
183   }
184 #endif
185
186   _lclose(fh);
187   return 1;
188 }
189
190 PDIB DibOpenFile(LPTSTR szFile)
191 {
192    HFILE               fh;
193    DWORD               dwLen;
194    DWORD               dwBits;
195    PDIB                pdib;
196    LPVOID              p;
197    OFSTRUCT            of;
198
199 #if defined(WIN32) || defined(_WIN32)
200    #define GetCurrentInstance()    GetModuleHandle(NULL)
201 #else
202    #define GetCurrentInstance()    (HINSTANCE)SELECTOROF((LPVOID)&of)
203 #endif
204
205    fh = OpenFile(wxConvFile.cWX2MB(szFile), &of, OF_READ);
206
207    if (fh == -1)
208    {
209       HRSRC h;
210
211           // TODO: Unicode version
212 #ifdef __WIN16__
213       h = FindResource(GetCurrentInstance(), szFile, RT_BITMAP);
214 #elif wxUSE_UNICODE
215       h = FindResourceW(GetCurrentInstance(), szFile, RT_BITMAP);
216 #else
217       h = FindResourceA(GetCurrentInstance(), szFile, RT_BITMAP);
218 #endif
219
220 #if defined(__WIN32__)
221       //!!! can we call GlobalFree() on this? is it the right format.
222       //!!! can we write to this resource?
223       if (h)
224         return (PDIB)LockResource(LoadResource(GetCurrentInstance(), h));
225 #else
226       if (h)
227         fh = AccessResource(GetCurrentInstance(), h);
228 #endif
229    }
230
231    if (fh == -1)
232       return NULL;
233
234    pdib = DibReadBitmapInfo(fh);
235
236    if (!pdib)
237       return NULL;
238
239     /* How much memory do we need to hold the DIB */
240
241     dwBits = pdib->biSizeImage;
242     dwLen  = pdib->biSize + DibPaletteSize(pdib) + dwBits;
243
244     /* Can we get more memory? */
245
246    p = GlobalReAllocPtr(pdib,dwLen,0);
247
248     if (!p)
249     {
250       GlobalFreePtr(pdib);
251         pdib = NULL;
252     }
253     else
254     {
255         pdib = (PDIB)p;
256     }
257
258     if (pdib)
259     {
260       /* read in the bits */
261       _hread(fh, (LPBYTE)pdib + (UINT)pdib->biSize + DibPaletteSize(pdib), dwBits);
262     }
263
264     _lclose(fh);
265
266     return pdib;
267 }
268
269
270 /*
271  *  ReadDibBitmapInfo()
272  *
273  *  Will read a file in DIB format and return a global HANDLE to its
274  *  BITMAPINFO.  This function will work with both "old" and "new"
275  *  bitmap formats, but will always return a "new" BITMAPINFO.
276  */
277
278 PDIB DibReadBitmapInfo(HFILE fh)
279 {
280     DWORD     off;
281     int       size;
282     int       i;
283     int       nNumColors;
284
285     RGBQUAD FAR       *pRgb;
286     BITMAPINFOHEADER   bi;
287     BITMAPCOREHEADER   bc;
288     BITMAPFILEHEADER   bf;
289     PDIB               pdib;
290
291     if (fh == -1)
292         return NULL;
293
294     off = _llseek(fh,0L,SEEK_CUR);
295
296     if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
297         return FALSE;
298
299     /*
300      *  do we have a RC HEADER?
301      */
302     if (bf.bfType != BFT_BITMAP)
303     {
304         bf.bfOffBits = 0L;
305         _llseek(fh,off,SEEK_SET);
306     }
307
308     if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
309         return FALSE;
310
311     /*
312      *  what type of bitmap info is this?
313      */
314     switch (size = (int)bi.biSize)
315     {
316         default:
317         case sizeof(BITMAPINFOHEADER):
318             break;
319
320         case sizeof(BITMAPCOREHEADER):
321             bc = *(BITMAPCOREHEADER*)&bi;
322             bi.biSize               = sizeof(BITMAPINFOHEADER);
323             bi.biWidth              = (DWORD)bc.bcWidth;
324             bi.biHeight             = (DWORD)bc.bcHeight;
325             bi.biPlanes             =  (UINT)bc.bcPlanes;
326             bi.biBitCount           =  (UINT)bc.bcBitCount;
327             bi.biCompression        = BI_RGB;
328             bi.biSizeImage          = 0;
329             bi.biXPelsPerMeter      = 0;
330             bi.biYPelsPerMeter      = 0;
331             bi.biClrUsed            = 0;
332             bi.biClrImportant       = 0;
333
334             _llseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
335
336             break;
337     }
338
339     nNumColors = DibNumColors(&bi);
340
341 #if 0
342     if (bi.biSizeImage == 0)
343         bi.biSizeImage = DibSizeImage(&bi);
344
345     if (bi.biClrUsed == 0)
346         bi.biClrUsed = DibNumColors(&bi);
347 #else
348     FixBitmapInfo(&bi);
349 #endif
350
351     pdib = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE,(LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
352
353     if (!pdib)
354         return NULL;
355
356     *pdib = bi;
357
358     pRgb = DibColors(pdib);
359
360     if (nNumColors)
361     {
362         if (size == sizeof(BITMAPCOREHEADER))
363         {
364             /*
365              * convert a old color table (3 byte entries) to a new
366              * color table (4 byte entries)
367              */
368             _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBTRIPLE));
369
370             for (i=nNumColors-1; i>=0; i--)
371             {
372                 RGBQUAD rgb;
373
374                 rgb.rgbRed      = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
375                 rgb.rgbBlue     = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
376                 rgb.rgbGreen    = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
377                 rgb.rgbReserved = (BYTE)0;
378
379                 pRgb[i] = rgb;
380             }
381         }
382         else
383         {
384             _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBQUAD));
385         }
386     }
387
388     if (bf.bfOffBits != 0L)
389         _llseek(fh,off + bf.bfOffBits,SEEK_SET);
390
391     return pdib;
392 }
393
394 /*
395  *  DibSetUsage(hdib,hpal,wUsage)
396  *
397  *  Modifies the color table of the passed DIB for use with the wUsage
398  *  parameter specifed.
399  *
400  *  if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
401  *  if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
402  *      in the passed palette
403  */
404
405 BOOL DibSetUsage(PDIB pdib, HPALETTE hpal,UINT wUsage)
406 {
407     PALETTEENTRY       ape[256];
408     RGBQUAD FAR *      pRgb;
409     WORD FAR *         pw;
410     int                nColors;
411     int                n;
412
413     if (hpal == NULL)
414         hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
415
416     if (!pdib)
417         return FALSE;
418
419     nColors = DibNumColors(pdib);
420     
421     if (nColors == 3 && DibCompression(pdib) == BI_BITFIELDS)
422         nColors = 0;
423
424     if (nColors > 0)
425     {
426         pRgb = DibColors(pdib);
427
428         switch (wUsage)
429         {
430             //
431             // Set the DIB color table to palette indexes
432             //
433             case DIB_PAL_COLORS:
434                 for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
435                     *pw = n;
436                 break;
437
438             //
439             // Set the DIB color table to RGBQUADS
440             //
441             default:
442             case DIB_RGB_COLORS:
443                 nColors =  (nColors < 256) ? nColors: 256;
444
445                 GetPaletteEntries(hpal,0,nColors,ape);
446
447                 for (n=0; n<nColors; n++)
448                 {
449                     pRgb[n].rgbRed      = ape[n].peRed;
450                     pRgb[n].rgbGreen    = ape[n].peGreen;
451                     pRgb[n].rgbBlue     = ape[n].peBlue;
452                     pRgb[n].rgbReserved = 0;
453                 }
454                 break;
455         }
456     }
457     return TRUE;
458 }
459
460 /*
461  *  DibCreate(bits, dx, dy)
462  *
463  *  Creates a new packed DIB with the given dimensions and the
464  *  given number of bits per pixel
465  */
466
467 PDIB DibCreate(int bits, int dx, int dy)
468 {
469     LPBITMAPINFOHEADER lpbi ;
470     DWORD       dwSizeImage;
471     int         i;
472     DWORD FAR  *pdw;
473
474     dwSizeImage = dy*(DWORD)((dx*bits/8+3)&~3);
475
476     lpbi = (PDIB)GlobalAllocPtr(GHND,sizeof(BITMAPINFOHEADER)+dwSizeImage + 1024);
477
478     if (lpbi == NULL)
479         return NULL;
480
481     lpbi->biSize            = sizeof(BITMAPINFOHEADER) ;
482     lpbi->biWidth           = dx;
483     lpbi->biHeight          = dy;
484     lpbi->biPlanes          = 1;
485     lpbi->biBitCount        = bits ;
486     lpbi->biCompression     = BI_RGB ;
487     lpbi->biSizeImage       = dwSizeImage;
488     lpbi->biXPelsPerMeter   = 0 ;
489     lpbi->biYPelsPerMeter   = 0 ;
490     lpbi->biClrUsed         = 0 ;
491     lpbi->biClrImportant    = 0 ;
492
493     if (bits == 4)
494         lpbi->biClrUsed = 16;
495
496     else if (bits == 8)
497         lpbi->biClrUsed = 256;
498
499     pdw = (DWORD FAR *)((LPBYTE)lpbi+(int)lpbi->biSize);
500
501     for (i=0; i<(int)lpbi->biClrUsed/16; i++)
502     {
503         *pdw++ = 0x00000000;    // 0000  black
504         *pdw++ = 0x00800000;    // 0001  dark red
505         *pdw++ = 0x00008000;    // 0010  dark green
506       *pdw++ = 0x00808000;    // 0011  mustard
507         *pdw++ = 0x00000080;    // 0100  dark blue
508         *pdw++ = 0x00800080;    // 0101  purple
509         *pdw++ = 0x00008080;    // 0110  dark turquoise
510         *pdw++ = 0x00C0C0C0;    // 1000  gray
511         *pdw++ = 0x00808080;    // 0111  dark gray
512         *pdw++ = 0x00FF0000;    // 1001  red
513         *pdw++ = 0x0000FF00;    // 1010  green
514       *pdw++ = 0x00FFFF00;    // 1011  yellow
515         *pdw++ = 0x000000FF;    // 1100  blue
516         *pdw++ = 0x00FF00FF;    // 1101  pink (magenta)
517         *pdw++ = 0x0000FFFF;    // 1110  cyan
518         *pdw++ = 0x00FFFFFF;    // 1111  white
519     }
520
521     return (PDIB)lpbi;
522 }
523
524 static void xlatClut8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
525 {
526     DWORD dw;
527
528 #ifdef __cplusplus
529     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
530 #else
531     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
532 #endif
533         *pb = xlat[*pb];
534 }
535
536 static void xlatClut4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
537 {
538     DWORD dw;
539
540 #ifdef __cplusplus
541     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
542 #else
543     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
544 #endif
545         *pb = (BYTE)(xlat[*pb & 0x0F] | (xlat[(*pb >> 4) & 0x0F] << 4));
546 }
547
548 #define RLE_ESCAPE  0
549 #define RLE_EOL     0
550 #define RLE_EOF     1
551 #define RLE_JMP     2
552
553 static void xlatRle8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
554 {
555     BYTE    cnt;
556     BYTE    b;
557     BYTE _huge *prle = pb;
558
559     for(;;)
560     {
561         cnt = *prle++;
562         b   = *prle;
563
564         if (cnt == RLE_ESCAPE)
565         {
566             prle++;
567
568             switch (b)
569             {
570                 case RLE_EOF:
571                     return;
572
573                 case RLE_EOL:
574                     break;
575
576                 case RLE_JMP:
577                     prle++;     // skip dX
578                     prle++;     // skip dY
579                     break;
580
581                 default:
582                     cnt = b;
583                     for (b=0; b<cnt; b++,prle++)
584                         *prle = xlat[*prle];
585
586                     if (cnt & 1)
587                         prle++;
588
589                     break;
590             }
591         }
592         else
593         {
594             *prle++ = xlat[b];
595         }
596     }
597 }
598
599 static void xlatRle4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
600 {
601 }
602
603 static void hmemmove(BYTE _huge *d, BYTE _huge *s, LONG len)
604 {
605     d += len-1;
606     s += len-1;
607
608     while (len--)
609         *d-- = *s--;
610 }
611
612 /*
613  *  DibMapToPalette(pdib, hpal)
614  *
615  *  Map the colors of the DIB, using GetNearestPaletteIndex, to
616  *  the colors of the given palette.
617  */
618
619 BOOL DibMapToPalette(PDIB pdib, HPALETTE hpal)
620 {
621    LPBITMAPINFOHEADER  lpbi;
622    PALETTEENTRY        pe;
623    int                 n;
624    int                 nDibColors;
625    int                 nPalColors=0;
626    BYTE FAR *          lpBits;
627    RGBQUAD FAR *       lpRgb;
628    BYTE                xlat[256];
629    DWORD               SizeImage;
630
631    if (!hpal || !pdib)
632       return FALSE;
633
634    lpbi   = (LPBITMAPINFOHEADER)pdib;
635    lpRgb  = DibColors(pdib);
636
637    GetObject(hpal,sizeof(int),(LPSTR)&nPalColors);
638    nDibColors = DibNumColors(pdib);
639
640    if ((SizeImage = lpbi->biSizeImage) == 0)
641       SizeImage = DibSizeImage(lpbi);
642
643    //
644    //  build a xlat table. from the current DIB colors to the given
645    //  palette.
646    //
647    for (n=0; n<nDibColors; n++)
648       xlat[n] = (BYTE)GetNearestPaletteIndex(hpal,RGB(lpRgb[n].rgbRed,lpRgb[n].rgbGreen,lpRgb[n].rgbBlue));
649
650    lpBits = (LPBYTE)DibPtr(lpbi);
651    lpbi->biClrUsed = nPalColors;
652
653    //
654    // re-size the DIB
655    //
656    if (nPalColors > nDibColors)
657    {
658       GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
659       hmemmove((BYTE _huge *)DibPtr(lpbi), (BYTE _huge *)lpBits, SizeImage);
660       lpBits = (LPBYTE)DibPtr(lpbi);
661    }
662    else if (nPalColors < nDibColors)
663    {
664       hmemcpy(DibPtr(lpbi), lpBits, SizeImage);
665       GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
666       lpBits = (LPBYTE)DibPtr(lpbi);
667    }
668
669    //
670    // translate the DIB bits
671    //
672    switch (lpbi->biCompression)
673    {
674       case BI_RLE8:
675         xlatRle8(lpBits, SizeImage, xlat);
676         break;
677
678       case BI_RLE4:
679         xlatRle4(lpBits, SizeImage, xlat);
680         break;
681
682         case BI_RGB:
683         if (lpbi->biBitCount == 8)
684                 xlatClut8(lpBits, SizeImage, xlat);
685             else
686                 xlatClut4(lpBits, SizeImage, xlat);
687             break;
688     }
689
690     //
691     //  Now copy the RGBs in the logical palette to the dib color table
692     //
693     for (n=0; n<nPalColors; n++)
694     {
695         GetPaletteEntries(hpal,n,1,&pe);
696
697         lpRgb[n].rgbRed      = pe.peRed;
698       lpRgb[n].rgbGreen    = pe.peGreen;
699       lpRgb[n].rgbBlue     = pe.peBlue;
700       lpRgb[n].rgbReserved = (BYTE)0;
701    }
702
703    return TRUE;
704 }
705
706
707 HPALETTE MakePalette(const BITMAPINFO FAR* Info, UINT flags)
708 {
709   HPALETTE hPalette;
710   const RGBQUAD FAR* rgb = Info->bmiColors;
711
712   WORD nColors = Info->bmiHeader.biClrUsed;
713   if (nColors) {
714    LOGPALETTE* logPal = (LOGPALETTE*)
715      new BYTE[sizeof(LOGPALETTE) + (nColors-1)*sizeof(PALETTEENTRY)];
716
717    logPal->palVersion  = 0x300; // Windows 3.0 version
718    logPal->palNumEntries = nColors;
719    for (WORD n = 0; n < nColors; n++) {
720     logPal->palPalEntry[n].peRed   = rgb[n].rgbRed;
721     logPal->palPalEntry[n].peGreen = rgb[n].rgbGreen;
722     logPal->palPalEntry[n].peBlue  = rgb[n].rgbBlue;
723     logPal->palPalEntry[n].peFlags = (BYTE)flags;
724    }
725    hPalette = ::CreatePalette(logPal);
726    delete logPal;
727   } else
728    hPalette = 0;
729
730   return hPalette;
731 }
732