Announcement

Collapse
No announcement yet.

Palette trouble..

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Palette trouble..

    In 256 color mode, sometimes necessary to use own palette. I have a custom
    control here that uses a brighter shade of %COLOR_BTNFACE. For 256 color
    mode, I create a palette and all works fine, until Netscape is started.
    Netscape does bad things to palettes, so now all colors gets screwed up.
    Slight problem with MSIE too, but not as bad and MSIE restores the palette
    properly when minimized/closed. Seems like Netscape fails to do this.

    Problem is, controls are not addressed on changes to palette, only top-level
    windows are. So in a dialog, no problem, but how to handle this in a control,
    especially a custom one that must be able to handle all things by itself?
    Have tried passing on %WM_PALETTECHANGED and %WM_QUERYNEWPALETTE, but no
    good solution for a custom control, plus it didn't work well..

    Maybe not possible to use own palettes in controls? I can see another
    potential danger - if control and dialog (or another control) has different
    palettes, so I'm beginning to think I must skip idea of using own palette
    in a custom control. In dialog, yes - in control, ?

    Tried using a patterned brush instead, but text looks a bit bad on pattern,
    even a "fine-masked" one. If anyone has any ideas on how to treat palettes
    in controls, in 256 color mode, I'm all ears (or know if it's even possible).


    ------------------

  • #2
    Found a working solution, I think. In WM_PAINT, I was using SelectPalette
    with bForceBackground parameter set to %FALSE, and then RealizePalette.
    Changed the parameter to %TRUE and all seems to works fine.

    Also, I only did the above to the memDC I was using. Added same commands to
    the ps.hDC, before creating the memDC and everything looks fine, even with
    Netscape running next to the test program - in 256 color mode.

    Will post what I've got as soon as I've cleaned up the code a bit..


    ------------------

    Comment


    • #3
      Working, but extremely bad for performance (try to move/size a dialog or to move another window over control).
      Should be more clever tactic - to test current system pallette and to use %True if necessary only.


      ------------------
      E-MAIL: [email protected]

      Comment


      • #4
        Yep, you are right, Semen. Amazing - so much trouble for a few extra colors.
        I'll do some more testing, maybe find better way to use patterned brush in
        low color mode instead. Most people use >256 color anyway, so think it doesn't
        matter too much.

        BTW, thanks a lot for all your previous work with palettes, Semen. Have learned
        plenty from it.


        ------------------

        Comment


        • #5
          Hi Borje,

          Is there any chance I can take a look at your palette code please? I'm interested to see how you handled it, as compared to my strategy.

          Thanks!!!


          ------------------
          Lance
          PowerBASIC Support
          mailto:[email protected][email protected]</A>
          Lance
          mailto:[email protected]

          Comment


          • #6
            Following is the essential palette parts. I have done kind of middle-thing and
            don't handle WM_PALETTECHANGED and WM_QUERYNEWPALETTE at all, like one should.

            Problem is, this is a custom control button/label, and individual controls are
            not given these messages, only top-level windows are. Tried to pass them on from
            parent, but no good solution, plus it didn't work well. Following does the job
            fairly well, so I decided to leave it at that. Question is always, is it worth
            90% of work for maybe 1% of users? Sometimes it is, sometimes it isn't..

            I have copied first part of WM_PAINT, plus CreateRRButtonPalette SUB, which is
            main parts in my palette "handling". Hm, maybe not that easy to follow. Tell you
            what - I have zipped up the files and uploaded to http://www.tolken99.com/pb/rrbutton.zip

            It is almost finished, a quite useful button/label control, complete with demo
            and comments. Must go through it more carefully before I make if "official",
            but think most is done. Extract from rrbutton.inc file:
            Code:
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            ' draw control
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                 CASE %WM_PAINT
                    'Individual controls do not receive WM_SYSCOLORCHANGE message
                    'from stupid Windows when/if a user for example changes the
                    'color scheme. By using a reference color, following ensures
                    'the control updates brush + palette to correct colors anyway.
                    IF GetSysColor(%COLOR_BTNFACE) <> @rr.PalClr(5) THEN
                       CreateRRButtonPalette hWnd
                    END IF
             
                    '=== Get Rect and Caption ==================================
                    CALL GetClientRect(hWnd, rc)
                    CALL GetWindowText(hWnd, zCap, %MAX_PATH)
             
                    '=== Initialize ============================================
                    BeginPaint hWnd, ps
             
                    IF @rr.PalClr(0) THEN 'if we have palette (256 color mode), then use it DC..
                       SelectPalette ps.hDC, @rr.PalClr(0), 1
                       RealizePalette ps.hDC
                    END IF
             
                    memDC = CreateCompatibleDC(ps.hDC)
             
                    IF @rr.PalClr(0) THEN 'if we have palette (256 color mode), then use it in memDC..
                       SelectPalette memDC, @rr.PalClr(0), 1
                       RealizePalette memDC
                    END IF
             
                    hbit  = CreateCompatibleBitmap(ps.hDC, rc.nRight, rc.nBottom)
                    IF hbit THEN hbit = SelectObject(memDC, hbit)
            ' etc, etc..
             
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            ' set colors and create palette for button, when needed
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            SUB CreateRRButtonPalette(BYVAL hWnd AS LONG)
              LOCAL I AS LONG, hDC AS LONG, rr AS RRBUTTONDATA PTR
              rr = GetWindowLong(hWnd, 0)
             
              IF @rr.btnColor = @rr.PalClr(5) + &H101010 THEN 'if original color, change accordingly
                 @rr.btnColor = GetSysColor(%COLOR_BTNFACE) + &H101010
              ELSEIF @rr.btnColor = @rr.PalClr(5) THEN         'common case - standard color..
                 @rr.btnColor = GetSysColor(%COLOR_BTNFACE)
              END IF
             
              @rr.PalClr(1) = @rr.btnColor
              @rr.PalClr(2) = GetSysColor(%COLOR_BTNFACE) - &H101010
              @rr.PalClr(3) = GetSysColor(%COLOR_INFOBK)    '&HE1FFFF
              @rr.PalClr(4) = GetSysColor(%COLOR_SCROLLBAR) '&HC0C0C0
              @rr.PalClr(5) = GetSysColor(%COLOR_BTNFACE)   'for reference only
             
              hDC = GetDc(hWnd)                             'need own palette if in 256 color mode
              IF GetDeviceCaps(hDC, %NUMCOLORS) > -1 AND _
              (GetDeviceCaps(hDC, %RASTERCAPS) AND %RC_PALETTE) = %RC_PALETTE THEN
                 IF @rr.PalClr(0) THEN DeleteObject @rr.PalClr(0)
                 @rr.PalClr(0) = MAKLNG(&H0300, 4)
                 @rr.PalClr(0) = CreatePalette (BYVAL VARPTR(@rr.PalClr(0)))
                 FOR I = 1 TO 4
                    @rr.PalClr(I) = @rr.PalClr(I) + &H02000000
                 NEXT
                 @rr.btnColor = @rr.PalClr(1)
              END IF
             
              ReleaseDc hWnd, hDC
             
              IF @rr.hBrush THEN DeleteObject @rr.hBrush
              @rr.hBrush = CreateSolidBrush(@rr.btnColor)
             
            END SUB

            ------------------

            Comment


            • #7
              Thanks! Yes it uses the same strategy as I have always used. I experimented with restoring the original palette too, but seems to make no or very little difference.

              In all this time, I've not been able to find a "palette guru"... more often than not I've found conflicting advise and code all over the 'net...

              Palettes can certainly be tricky, and yes, Netscape is a beast with the palette.

              Try running an older version of Graphics Workshop and Netscape and your own Palette code at the same time as overlapped windows displaying images that are stored in 32-bit color, then task switch... scary! (to be fair, I've not tried this with your RRBUTTON code though, but it does look very good!)

              ------------------
              Lance
              PowerBASIC Support
              mailto:[email protected][email protected]</A>
              Lance
              mailto:[email protected]

              Comment


              • #8
                Did some more testing and found that if one traps %WM_PALETTECHANGED
                in parent and redraws entire dialog, all controls become updated so
                colors look alright when switching between app's with different palettes.
                Not the best solution, but it works. Also found that one probably have
                to add at least the basic 16 colors to own palette.
                Following, in main dialog's message handler works pretty well:
                Code:
                     CASE %WM_PALETTECHANGED
                        IF CBWPARAM <> CBHNDL THEN
                           RedrawWindow CBHNDL, ByVal 0, ByVal 0, %RDW_INVALIDATE OR %RDW_UPDATENOW
                        END IF

                ------------------

                Comment


                • #9
                  Borje,
                  Maybe this code for an Id Palette would help??
                  James

                  Code:
                  '============================================================================
                  'dwRGB is a pointer to an array of RGBQUAD's
                  FUNCTION _
                     CreateIDPal ( _
                       BYVAL dwRGB    AS DWORD,_
                       BYVAL nColors  AS INTEGER _
                     ) AS WORD
                    DIM lpRGB         AS RGBQUAD PTR,_
                        lpPalEntry(255)  AS PALETTEENTRY,_
                        tLogPal       AS LOGPALETTE,_
                        x             AS INTEGER,_
                        nStaticColors AS INTEGER,_
                        nUsableColors AS INTEGER,_
                        hDC           AS DWORD,_
                        lpbmi         AS BITMAPINFO256 PTR
                  
                  
                    lpRGB = dwRGB
                    lpbmi = dwRGB
                    tLogPal.palVersion = &H300
                    tLogPal.palNumEntries = 256
                    hDC = GetDC(BYVAL 0)
                    nStaticColors = GetDeviceCaps(hDC,%NUMCOLORS)
                  
                    GetSystemPaletteEntries hDC,0,256,tLogPal.palPalEntry(0)
                    nStaticColors = nStaticColors/2
                    FOR x = 0 TO nStaticColors
                      tLogPal.palPalEntry(x).peFlags = 0
                    NEXT x
                    nUsableColors = nColors - nStaticColors
                    FOR x = nStaticColors+1  TO nUsableColors
                      tLogPal.palPalEntry(x).peRed = @lpbmi.bmiColors(x).rgbRed
                      tLogPal.palPalEntry(x).peGreen [email protected](x).rgbGreen
                      tLogPal.palPalEntry(x).peBlue = @lpbmi.bmiColors(x).rgbBlue
                      tLogPal.palpalEntry(x).peFlags = %PC_NOCOLLAPSE
                    NEXT x
                    FOR x = nUsableColors + 1 TO 256 - nStaticColors
                      tLogPal.palPalEntry(x).peFlags = %PC_NOCOLLAPSE
                      INCR lpRGB
                    NEXT x
                    FOR x = 255 - nStaticColors TO 255
                      tLogPal.palPalEntry(x).peFlags = 0
                    NEXT x
                  
                    ReleaseDC BYVAL 0,BYVAL hDC
                  
                    FUNCTION = CreatePalette(BYVAL VARPTR(tLogPal))
                  END FUNCTION

                  ------------------

                  Comment


                  • #10
                    Yes James, it already has. Saw it in your response to Semen a while
                    ago and tested. Funny thing with palette is, even if one uses this
                    way to grab "original" palette, colors end up looking weird when app's
                    like Netscape starts messing around with the colors.

                    Who can understand the concept? The fellows at Netscape definitely
                    has not. When I run MSIE next to Netscape in 256 color mode, buttons
                    in Netscape gets all kinds of strange colors and it does not correct
                    itself automatically when it gets focus again. MSIE handles the palette
                    change correctly, so I guess someone at MS has understood. Would like
                    to talk to that someone..

                    Think I'll leave it at current status. At least it updates on palette
                    change, even if way I do it maybe isn't 100% correct..


                    ------------------

                    Comment


                    • #11
                      Probably, it's possible to struggle with incorrect apps with assist of
                      SetSystemPaletteUse ... SYSPAL_NOSTATIC ? (didn't test)


                      ------------------
                      E-MAIL: [email protected]

                      Comment

                      Working...
                      X