Announcement

Collapse
No announcement yet.

BeginPaint vs GetDC (in WM_PAINT)

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

  • Peter Scheutz
    replied
    If you create your offscreen Dib in the WM_RESIZE event, you can get a 1:1 relation between screen/offscreen coords.


    Edited to correct the following wrong information. Sorry!
    On systems with more than one monitor, upper left corner is not always (0,0)
    That is correct for window coords, not GetClientRect upper left.
    Those are always at (0,0,)...I think, maybee...almost sure...


    --
    Best Regards
    Peter Scheutz
    ------------------




    [This message has been edited by Peter Scheutz (edited March 23, 2001).]

    Leave a comment:


  • Dominic Mitchell
    replied
    Semen,
    I have to agree with Lance and Edwin, your code shows poor use of the
    WM_PAINT message. If you are going to forcefully invalidate the entire
    client area in WM_PAINT then do your painting in WM_ERASEBKGND.

    Anyway, I cannot test your code because I do not use DDT but the following
    may help to explain your problem.

    First, using the rectangle returned by GetClientRect in WM_PAINT will only
    work if you use the DC returned by GetDC or if you forcefully invalidate the
    entire client area and use tps.hdc. This is because the tps.hdc context is
    clipped so any drawing you do outside of the invalid area(tps.rcPaint) will
    not be seen.
    Second, mapping and clipping.
    For example,

    1. Given a bitmap located at (x,y) in the client area of a window
    2. Given the invalid area from BeginPaint, tps.rcPaint = (x1,y1,x2,y2)
    3. The memory dc for this area would be(0, 0, x2 - x1 + 1, y2 - y1 + 1)
    The upper left corner of the bitmap in the memory dc would be (x - x1, y - y1).
    However, when the entire client area is invalid,
    rcClient = tps.rcPaint = rcMemDC and the bitmap would be located at (x,y) in
    the memory dc since x1 = y1 = 0.
    rcClient = bounding rectangle of client area
    rcMemDC = bounding rectangle of memory dc


    ------------------
    Dominic Mitchell

    Leave a comment:


  • Semen Matusovski
    replied
    Lance --
    I added InvalidateRect CbHndl, ByVal 0, 0 exactly before BeginPaint and don't see double WM_PAINT under Win2000.
    Is known that BeginPaint (unlike GetDC) repaints invalidated areas only.

    If DefWindowProc for EraseBkgnd includes InvalidateRect, all is clear.
    If not, I understand nothing.

    Edwin --
    With what exactly are you disagree ?

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

    Leave a comment:


  • Lance Edmonds
    replied
    Interesting...

    I tried Semen's first code example above, added FUNCTION = 1 to the WM_PAINT event and it works perfectly...

    Anyone else try this "simple" solution without the need to GetDC, InvalidateRect, etc?

    Later: Hmmm... it's almost perfect... I did not drag a window across the text counter.

    When adding InvalidateRect() it certainly fixes the problem at the cost of doubling the WM_PAINT events: You are just forcibly changing the update region to the entire dialog, this seems like a crazy approach to solve the problem.

    I'll experiment with this later (when I have some time), but moving the background painting to WM_ERASEBKGND and retaining the foreground painting in WM_PAINT is likely the best avenue for experimentation here, and the closest to how an app is "supposed" to work.

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

    Leave a comment:


  • Edwin Knoppert
    replied
    I disagree, invalidaterect forces WM_PAINT but option set to 1 will erasebackground.
    How can you use invalidaterect FROM WM_PAINT, it looks recursive behaviour to me.
    I'm not gonna maintain a static, it's simply bad.

    Did i miss the point?


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

    Leave a comment:


  • Semen Matusovski
    replied
    Guys --
    Thanx for replies.
    I see two simple ways, which works -
    single InvalidateRect CbHndl, BYVAL %NULL, 0 in WM_ERASEBKGND + BeginPaint
    or GetDC instead of BeginPaint in WM_PAINT

    Interesting, is InvalidateRect a part of DefWindowProc in WM_ERASEBKGND ?

    [This message has been edited by Semen Matusovski (edited March 18, 2001).]

    Leave a comment:


  • Patrice Terrier
    replied
    Semen

    I am aware of this problem and to avoid it I use InvalidateRect
    just before BeginPaint.

    Code:
        CASE %WM_PAINT
    
             ARRAY SCAN hWinShadow&(), = hWnd&, TO Item&
             IF Item& > 1 THEN
                DECR Item& 
    
                CALL GetWindowRect (hWnd&, rc) 
    
                XShadow& = rc.nRight - rc.nLeft: YShadow& = rc.nBottom - rc.nTop
    
                CALL InvalidateRect(hWnd&, BYVAL %NULL, 0) ' <-- SEMEN
    
                hDC& = BeginPaint(hWnd&, ps)
    ------------------
    Patrice Terrier
    mailto[email protected][email protected]</A>

    Leave a comment:


  • Chris Boss
    replied
    Semen;

    I noticed you were using the same variable to receive the return value
    from BeginPaint as you are using as a parameter to BeginPaint (in BeginPaint it is
    the UDT ps, but the return value is put into a member of that same UDT).

    I would suggest using a different value to store the return value !

    By using a member to return a value that is a part of a UDT passed as
    a member, maybe some confusion can occur. Using GetDC, no UDT is being
    passed to conflict with the return variable.

    Even if it does work it is not a good habit.



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

    Leave a comment:


  • Borje Hagsten
    replied
    Yes, it clips, so in this case, it is "normal" behaviour. Either
    use GetDc, or add InvalidateRect to %WM_ERASEBKGND, like:
    Code:
             CASE %WM_ERASEBKGND
                InvalidateRect CBHNDL, BYVAL %NULL, 0 '<- last one must be zero, otherwise endless problem..
                UpdateWindow CBHNDL
                FUNCTION = 1

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

    Leave a comment:


  • Peter Scheutz
    replied
    I think the painting that you do not see is supposed to happen in the WM_ERASEBKGND event.

    From MSDN:
    The BeginPaint function automatically sets the clipping region of the device context to exclude any area outside the update region.

    Try copying the GetDC version of your code to the WM_ERASEBKGND event.
    Use the BeginPaint version in WM_PAINT
    To know wich one is executing change one of them to:

    hBrush = CreateSolidBrush (GetNearestColor(myhDC, %Red))

    --
    Best Regards
    Peter Scheutz


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

    Leave a comment:


  • Semen Matusovski
    replied
    Guys --
    try to move any second window over this.
    With BeginPaint visible problems.
    Funny, but counter is updated.
    I tried to add Function = 1 to WM_PAINT. Doesn't help. More than strange.

    Code:
       #Compile Exe
       #Dim All
       #Register None
       #Include "WIN32API.INC"
       CallBack Function DlgProc
          Select Case CbMsg
             Case %WM_PAINT
                Dim hBrush As Long, hFont As Long, rc As RECT, ps As PAINTSTRUCT, hMemDC As Long, hMemBmp As Long
                Dim zText As Asciiz * 255, i As Long, j As Long, sz As SIZEL
                Dim dx As Long, dy As Long, dw As Long, dh As Long, ddx As Long, n As Long
                ps.hDC = BeginPaint (CbHndl, ps) ' <----------   ps.hDC = GetDC(CbHndl)
                GetClientRect CbHndl, rc
                hMemDC = CreateCompatibleDC(ps.hDC)
                hMemBmp = CreateCompatibleBitMap (ps.hDC, rc.nRight, rc.nBottom)
                SelectObject hMemDC, hMemBmp
                hBrush = CreateSolidBrush (GetNearestColor(ps.hDC, %Blue)) ' Rgb(0, 128, 192)))
                hFont = CreateFont(rc.nBottom / 6, 0, 0, 0, %FW_NORMAL, _
                   0, 0, 0, %RUSSIAN_CHARSET, 0, 0, 0, 0, "Times New Roman")
                FillRect hMemDC, rc, hBrush
                SelectObject hMemDC, hFont
                SetBkMode hMemDC, %TRANSPARENT
                Static h As Long
                Incr h
                zText = Str$(h) ' $Text
                dx = 10: dy = 10 ' Initial x, y
                ddx = 5 ' distance between letters
                dw = 10: dh = 5 ' size of shadow
                n = Max(dw, dh)
                For i = 1 To Len(zText)
                   For j = 0 To n
                      SetTextColor hMemDC, Rgb(j * 255 / n, j * 255 / n, 0)
                      TextOut hMemDC, dx + (n - j) * dw / n, dy + (n - j) * dh / n, Mid$(zText, i, 1), 1
                   Next
                   GetTextExtentPoint32 hMemDC, Mid$(zText, i, 1), 1, sz
                   dx = dx + sz.cx + ddx
                Next
                BitBlt ps.hDC, rc.nLeft, rc.nTop, rc.nRight, rc.nBottom, hMemDC, 0, 0, %SRCCOPY
                EndPaint CbHndl, ps ' <---- ReleaseDc CbHndl, ps.hDc
                DeleteDC hMemDC
                DeleteObject hMemBmp
                DeleteObject hBrush
                DeleteObject hFont
             Case %WM_ERASEBKGND
                Function = 1: Exit Function
          End Select
       End Function
       
       Function PbMain () As Long
          Local hDlg As Long
          Dialog New 0, "Polus", ,, 0, 0, %WS_MAXIMIZE  Or %WS_SYSMENU  To hDlg
          Dialog Show Modal hDlg Call DlgProc
      End Function
    [This message has been edited by Semen Matusovski (edited March 17, 2001).]

    Leave a comment:


  • Borje Hagsten
    replied
    Do you use the hDC returned by BeginPaint, or the one in its PAINTSTRUCT
    member? Should be same, but maybe Win2000 thinks differently, so using
    the returned hDC is safer there?


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

    Leave a comment:


  • Edwin Knoppert
    replied
    If your window has invalidated parts it should redraw when Windows is idle.
    You can force it with updatewindow of course.
    I saw an example that returned 1 instead of 0 in SDK window
    It's 0 for SDK, 1 for Dialogboxes !

    Ever considered using the WM_ERASBKGROUND instead?





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

    Leave a comment:


  • Semen Matusovski
    started a topic BeginPaint vs GetDC (in WM_PAINT)

    BeginPaint vs GetDC (in WM_PAINT)

    Guys --
    In WM_PAINT (Win2000) I create memory DC and then copy it (BitBlt) to window's hDC.
    Somebody can explain, why I have troubles with BeginPaint/EndPaint (not always updates), unlike GetDC/ReleaseDC works fine ?

    ------------------
    E-MAIL: [email protected]
Working...
X