Announcement

Collapse
No announcement yet.

Where have all the pixels gone?

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

  • Where have all the pixels gone?

    The following program displays a text label and draws a
    vertical bar on the screen. If you then hit the full
    screen button on the right hand side of the title bar
    it is redrawn, but some pixels at the top of the bar
    are not painted. I've tried to isolate the problem but
    just can't seem to find out why this is happending.
    The redraw code for the text lable is causing the
    problem. If I redraw the line then the text lable the
    problem goes away. But there is no overlap of the pixel
    space on the screen! (BTW my monitor is a ViewSonic 24 inch
    in 1280 x 1024 mode).

    Can anyone see what I'm doing wrong?
    -----------------------------------------------------------
    Code:
    #COMPILE EXE
    #REGISTER NONE
    $INCLUDE "WIN32API.INC"
    
    GLOBAL dWidth       AS      LONG
    GLOBAL dHeight      AS      LONG
    GLOBAL sWidth       AS      LONG
    GLOBAL sHeight      AS      LONG
    GLOBAL hDlg         AS      LONG ' Global Dialog handle
    GLOBAL Lh           AS      LONG ' Height of one line
    '**************** Font Size Control Section
    GLOBAL FontIndex    AS      LONG
    GLOBAL hFont        AS      LONG ' Global Font handle
    GLOBAL hMyFont()    AS      LONG ' Global Font Sizes Table
    '****************
    CALLBACK FUNCTION MA_Main()
    SELECT CASE CBMSG
      CASE %WM_DESTROY
        DestroyWindow hDlg
    
      CASE %WM_SIZE
        DIALOG PIXELS CBHNDL,LOWRD(CBLPARAM),HIWRD(CBLPARAM) TO UNITS sWidth,sHeight
        FontIndex=Lh*(sHeight/dHeight)
        CALL SendMessage(hFont,%WM_SETFONT,hMyFont(FontIndex),0)
        CONTROL SET LOC hDlg,100,sWidth/dWidth*0,sHeight/dHeight*20
        CONTROL SET SIZE hDlg,100,sWidth/dWidth*320,sHeight/dHeight*Lh
        CONTROL SET TEXT hDlg,100,"This is a test message"
        CONTROL SET LOC hDlg,200,sWidth/dWidth*15,sHeight/dHeight*35
        CONTROL SET SIZE hDlg,200,sWidth/dWidth*10,sHeight/dHeight*163
    
    END SELECT
    END FUNCTION
    
    FUNCTION PBMAIN() AS LONG
    
    DIM hFont          AS LONG
    DIM hMyFont(18:40) AS LONG
    FOR f&=18 TO 40
    hMyFont(f&)=_
    CreateFont(f&,0, _   'height,width(default=0)
               0,0, _    'escapement(angle),orientation
               700, _    'weight (default=0,normal=400,bold=700)
               %FALSE, _ 'Italic
               %FALSE, _ 'Underline
               %FALSE, _ 'StrikeThru
               %ANSI_CHARSET, %OUT_CHARACTER_PRECIS, _
               %CLIP_DEFAULT_PRECIS, %PROOF_QUALITY, _
               %FIXED_PITCH OR %FF_DONTCARE,"MS Sans Serif" )
    NEXT f&
    Lh=17 'Global line height
    FontIndex=Lh*(sHeight/dHeight)
    
    dWidth=320:sWidth=dWidth
    dHeight=240:sHeight=dHeight
    
    DIALOG NEW 0,"Missing Pixels in Full Screen",,,dWidth,dHeight,_
      %WS_CAPTION OR %WS_SYSMENU OR %WS_THICKFRAME OR %WS_MAXIMIZEBOX OR _
      %WS_MINIMIZEBOX OR %DS_CONTEXTHELP,0 TO hDlg
    
    CONTROL ADD LABEL,hDlg,100,"",sWidth/dWidth*0,_
           sHeight/dHeight*20,sWidth/dWidth*320,sHeight/dHeight*Lh,%SS_CENTER
    
    CONTROL HANDLE hDlg,100 TO hFont
    CALL SendMessage(hFont,%WM_SETFONT,hMyFont(FontIndex),0)
    
    CONTROL ADD LINE,hDlg,200,"",sWidth/dWidth*15,_
          sHeight/dHeight*35,sWidth/dWidth*10,_
          sHeight/dHeight*16,%SS_BLACKRECT
    
    DIALOG SHOW MODAL hDlg, CALL MA_Main
    END FUNCTION

  • #2
    Joe --
    It's necessary to be more accuracy.
    Your elements covers each other.
    Change, for example,
    CONTROL SET LOC hDlg,100,sWidth/dWidth*0,sHeight/dHeight*20 to
    CONTROL SET LOC hDlg,100,sWidth/dWidth*0,sHeight/dHeight*10
    and a problem disappears

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

    Comment


    • #3
      A quick hint for this type of problem: temporarily add the %SS_SUNKEN style to your LABEL control(s) to see their true extent on the screen. Another way to achieve the same effect (and it works for other control types) is to use the extended style %WS_EX_STATICEDGE.

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

      Comment


      • #4
        I modified the coordinates slightly to insure that they DO NOT
        OVERLAP. And added %SS_SUNKEN to the label plus MSGBOX's to
        display the cooridnates.

        The RESIZE algorithm is not really straight forward! What is
        happening is that the label text is being resized onto the
        dialog screen before the line is done. The redrawing of
        label and text changes part of the old line (before it is
        resized). Then when the line is resized and redrawen it is
        done with damaged pixels.

        It seems to me that for the general case, resizing/redrawing
        the screen requires copying from one bit map to another so
        the controls do not interfere with each other. Alternatively
        the code should repaint from left to right, top to bottom when
        decreasing the size of the screen, and right to left, bottom to
        top when increasing the size of the screen. (This depends on
        the sequence the painting algorithm -- I'm just guessing based
        on what I see on the screen. A rigorous proof would be needed
        before suggesting code to fix the problem.)

        Bottom line here is I believe this problem deserves closer
        inspection before dismissing it as a coding error. It may still
        be but please check the x, y coordinates and confirm that they
        do or do not overlap.
        -----------------------------------------------------------------
        Code:
        #COMPILE EXE
        #REGISTER NONE
        $INCLUDE "WIN32API.INC"
        
        GLOBAL dWidth       AS      LONG
        GLOBAL dHeight      AS      LONG
        GLOBAL sWidth       AS      LONG
        GLOBAL sHeight      AS      LONG
        GLOBAL hDlg         AS      LONG ' Global Dialog handle
        GLOBAL Lh           AS      LONG ' Height of one line
        '**************** Font Size Control Section
        GLOBAL FontIndex    AS      LONG
        GLOBAL hFont        AS      LONG ' Global Font handle
        GLOBAL hMyFont()    AS      LONG ' Global Font Sizes Table
        '****************
        CALLBACK FUNCTION MA_Main()
        SELECT CASE CBMSG
          CASE %WM_DESTROY
            DestroyWindow hDlg
        
          CASE %WM_SIZE
            DIALOG PIXELS CBHNDL,LOWRD(CBLPARAM),HIWRD(CBLPARAM) TO UNITS sWidth,sHeight
            FontIndex=Lh*(sHeight/dHeight)
            fw!=sWidth/dWidth:fh!=sHeight/dHeight
        MSGBOX STR$(fw!)+"|"+STR$(fh!)
            CALL SendMessage(hFont,%WM_SETFONT,hMyFont(FontIndex),0)
        x&=fw!*0:y&=fh!*20
            CONTROL SET LOC hDlg,100,x&,y&
        dx&=fw!*320:dy&=fh!*Lh
            CONTROL SET SIZE hDlg,100,dx&,dy&
        MSGBOX STR$(x&)+"|"+STR$(y&)+"|"+STR$(dx&)+"|"+STR$(dy&)
            CONTROL SET TEXT hDlg,100,"This is a test message"
        x&=fw!*15:y&=fh!*38
            CONTROL SET LOC hDlg,200,sWidth/dWidth*15,sHeight/dHeight*38
        dx&=fw!*10:dy&=fh!*163
            CONTROL SET SIZE hDlg,200,sWidth/dWidth*10,sHeight/dHeight*163
        MSGBOX STR$(x&)+"|"+STR$(y&)+"|"+STR$(dx&)+"|"+STR$(dy&)
        
        END SELECT
        END FUNCTION
        
        FUNCTION PBMAIN() AS LONG
        
        DIM hFont          AS LONG
        DIM hMyFont(18:40) AS LONG
        FOR f&=18 TO 40
        hMyFont(f&)=_
        CreateFont(f&,0, _   'height,width(default=0)
                   0,0, _    'escapement(angle),orientation
                   700, _    'weight (default=0,normal=400,bold=700)
                   %FALSE, _ 'Italic
                   %FALSE, _ 'Underline
                   %FALSE, _ 'StrikeThru
                   %ANSI_CHARSET, %OUT_CHARACTER_PRECIS, _
                   %CLIP_DEFAULT_PRECIS, %PROOF_QUALITY, _
                   %FIXED_PITCH OR %FF_DONTCARE,"MS Sans Serif" )
        NEXT f&
        Lh=17 'Global line height
        FontIndex=Lh*(sHeight/dHeight)
        
        dWidth=320:sWidth=dWidth
        dHeight=240:sHeight=dHeight
        
        DIALOG NEW 0,"Missing Pixels in Full Screen",,,dWidth,dHeight,_
          %WS_CAPTION OR %WS_SYSMENU OR %WS_THICKFRAME OR %WS_MAXIMIZEBOX OR _
          %WS_MINIMIZEBOX OR %DS_CONTEXTHELP,0 TO hDlg
        
        CONTROL ADD LABEL,hDlg,100,"",sWidth/dWidth*0,_
               sHeight/dHeight*20,sWidth/dWidth*320,sHeight/dHeight*Lh,%SS_CENTER OR %SS_SUNKEN
        
        CONTROL HANDLE hDlg,100 TO hFont
        CALL SendMessage(hFont,%WM_SETFONT,hMyFont(FontIndex),0)
        
        CONTROL ADD LINE,hDlg,200,"",sWidth/dWidth*15,_
              sHeight/dHeight*38,sWidth/dWidth*10,_
              sHeight/dHeight*16,%SS_BLACKRECT
        
        DIALOG SHOW MODAL hDlg, CALL MA_Main
        END FUNCTION
        ------------------

        Comment


        • #5
          Joe --
          Line element is based on graphic operations (I think).
          Try to stimulate refreshing in WM_SIZE by following way:
          Insert
          ShowWindow GetDlgItem(hDlg, 200), 0
          before
          Control Set Loc hDlg, 200, ...
          Control Set Size hDlg,200, ...
          and
          ShowWindow GetDlgItem(hDlg, 200), 1
          after these two statements



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

          Comment


          • #6
            Sorry Joe, but it is technically a coding error. You are resizing the controls in a manner that does not cause them to repaint.

            Semens's suggestion should work fine, as the control is forced to be redrawn when it becomes visible again.

            Anther technique is simply to use InvalidateRect() after performing the resizing so all controls are forced to be redrawn.
            If you are resizing a number of controls, then use RedrawWindow() to force all controls to be redrawn at the same time.

            My preferred technique (and one that I use in my RESIZE32 custom control) is to use BeginDeferWindowPos(), followed by DeferWindowPos() on all the controls, and finally EndDeferWindowPos() - this also has the effect of moving and redrawing all the controls.


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

            Comment


            • #7
              Another tip that has a "major" effect on the resizing your code performs, Joe:

              Add %WS_CLIPSIBLINGS style to the child controls and watch what happens. ALso, in these type of projects, it is always a good idea to add %WS_CLIPCHILDREN style to the dialog itself.


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

              Comment


              • #8
                Thanks fellows. Appreciate the information. I played with
                various solutions and used Semen's only because it fit the
                current logic best.

                I didn't try InvalidateRect(), or RedrawWindow() because I
                guessed they would cause double painting and be slower.

                I tried %WS_CLIPSIBLINGS and it worked too, but I don't
                understand what it did or how it works. Further I couldn't
                find any reference in the documentation to understand if
                this option applies to all CONTROL button types. I've been
                burned before using a style on the wrong box type. Is there
                not a complete document that shows which style can be use with
                which control type?

                %WS_CLIPCHILDREN had no effect, that I could see.

                The most interesting approach was "BeginDeferWindowPos(),
                followed by DeferWindowPos() on all the controls, and finally
                EndDeferWindowPos()"! The documentation shows this to be
                exactly what I've been doing with my own structures and I'm
                sure their's is much more efficient. But I'm too lazy to
                rewrite all the code right now. I will later!

                Thanks for the help. Resizing now works in all cases in my
                application.

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

                Comment


                • #9
                  From Win32.HLP:
                  WS_CLIPSIBLINGS Clips child windows relative to each other; that is, when a particular child window receives a WM_PAINT message, the WS_CLIPSIBLINGS style clips all other overlapping child windows out of the region of the child window to be updated. If WS_CLIPSIBLINGS is not specified and child windows overlap, it is possible, when drawing within the client area of a child window, to draw within the client area of a neighboring child window.
                  While this does not feature in the DDT documentation, it can often be used with DDT control styles quite successfully (ie, it is a child control style, not a dialog style).

                  %WS_CLIPCHILDREN is a dialog style that prevents a dialog from drawing over child controls during a %WM_PAINT event - usually this style is not necessary unless you are actually drawing on your dialog in response to %WM_PAINT.

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

                  Comment

                  Working...
                  X