When placing text in memory and then coping it to the interface i cant seem to get the colors corrent. What happens is the font is the right color and the background right behind the text is correct however the background of the entire area is not right. The area without the text show up black. I was wondering if there is a way to fix this? the code i am using is as follows.
invoke BeginPaint, hWnd, ADDR ps
invoke CreateCompatibleDC, ps.hdc
mov memDC, eax
invoke CreateCompatibleBitmap, ps.hdc, 150, 90
mov hBmp, eax
invoke SelectObject, memDC, hBmp
RGB 235,235,230
invoke SetTextColor,memDC,eax
RGB 57,88,41
invoke SetBkColor,memDC,eax
mov rect.top, 20
mov rect.bottom, 40
mov rect.left, 0
mov rect.right, 185
invoke DrawText, memDC ,ADDR GameName,-1, ADDR rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER
invoke BitBlt, ps.hdc, 0, 0, 150, 90, memDC, 0, 0, SRCCOPY
invoke DeleteObject, hBmp
invoke DeleteDC, memDC
invoke EndPaint, hWnd, ADDR ps
[]
here is my hbrBackground
RGB 57,88,41
Invoke CreateSolidBrush, eax
mov wc.hbrBackground, eax
Its only black where the source rectangle is copied to the destination area except for behind the text. Its like it does not fill the rectangle.
ok i figured it out but still if there is a better way then pls let me now.. Anyway here is what i did that fixed it.
mov rect.top, 0
mov rect.bottom, 250
mov rect.left, 0
mov rect.right, 187
RGB 57,88,41
Invoke CreateSolidBrush, eax
Invoke FillRect, memDC, addr rect, eax
[]
Even easier, BitBlt the area of your main window to the memDC before you put the text and BitBlt back to the main window.
In your case, since you are deleting that memDC immediately after you use it, you shouldn't even bother with it. Simply put the text directly on the main DC. By setting the background to transparent for the text, you could then have clean text on any part of the main window, regardless of its current background.
Raymond
by doing that my text is unreadable when it updates since the text behind the new text is still showing. Also with writing to memory it seems to reduce or get rid of the flicker. I have run into another problem however. After a period of time i loose all my colors still. They go back to default colors and stay that way. (black on grey) Does anyone happen to know why this is and how to fix it? I know i have asked this a long time back but no one ever was able to answer it.
Jackal,here is what I propose to you:
------> IF you think and you want and you need a back DC
- after you INVOKE CreateWindow(Ex) and before your message loop create the compatible DC like this:
INVOKE GetDC,hWndMain
mov hDCMain, eax
INVOKE CreateCompatibleDC, hDCMain
mov hDCBack, eax
INVOKE SaveDC, hDCBack
mov hSaveDCBack, eax
INVOKE CreateCompatibleBitmap, hDCMain,20,150
mov hBTMBack, eax
INVOKE ReleaseDC,hWndMain, hDCMain
INVOKE SelectObject,hDCBack, hBTMBack
INVOKE GetStockObject,NULL_PEN
INVOKE SelectObject,hDCBack,eax
INVOKE CreateSolidBrush,00FF66CCh
mov hBrsBack, eax
INVOKE SelectObject, eax
INVOKE Rectangle, hDCBack,0,0,20,150
- in your WinProc, when WM_DESTROY arrives, don't forget to:
INVOKE RestoreDC,hDCBack,hSaveDCBack
INVOKE DeleteDC,hDCBack
INVOKE DeleteObject,hBTMBack
INVOKE DeleteObject, hBrsBack
- in your WinProc, when WM_PAINT arrives, you should:
LOCAL PS:PAINTSTRUCT
INVOKE BeginPaint, hWndMain,addr PS
INVOKE BitBlt,PS.hDC,0,0,20,150,hDCBack,0,0
INVOKE EndPaint,hWndMain,addr PS
now that we know this things, you should also know that DrawText is much better, even if TextOut is a bit faster. I use DrawText, so I will use it in this example:
- this must be done just once, after you had created the DC if you don't plan to change this mode, or before any call to text functions if you do.
INVOKE SetBkMode,hDCBack,TRANSPARENT
- this must be done just once, after you had created the DC if you don't plan to change this color, or before any call to text functions if you do.
INVOKE SetTextColor,hDCBack,0033FF77h
- this must be done just when you want to set/ change the text
mov Rect1.left, 0
mov Rect1.right, 20
mov Rect1.top, 0
mov Rect1.bottom, 150
INVOKE Rectangle, hDCBack, Rect1.left, Rect1.top, Rect1.right, Rect1.bottom
INVOKE DrawText,hDCBack, addr SomeString,-1,addr Drept1,DT_CENTER or DT_SINGLELINE or DT_VCENTER
INVOKE InvalidateRect,hWndMain,addr Rect1,TRUE
----> IF you don't need, ..., a back DC
-when your WM_PAINT arrives
LOCAL TmpBrs:DWORD
LOCAL PS:PAINTSTRUCT
LOCAL Rect1:RECT
INVOKE BeginPaint, hWndMain,addr PS
INVOKE CreateSolidBrush,00FF66CCh
INVOKE SelectObject, eax
mov TmpBrs, eax
INVOKE SetTextColor,PS.hDC,0033FF77h
INVOKE SetBkMode,PS.hDC,TRANSPARENT
mov Rect1.left, 0
mov Rect1.right, 20
mov Rect1.top, 0
mov Rect1.bottom, 150
INVOKE Rectangle, PS.hDC, Rect1.left, Rect1.top, Rect1.right, Rect1.bottom
INVOKE DrawText, PS.hDC, addr SomeString,-1,addr Drept1,DT_CENTER or DT_SINGLELINE or DT_VCENTER
INVOKE SelectObject, TmpBrs
INVOKE DeleteObject, eax
INVOKE EndPaint,hWndMain,addr PS
This pices of code are not commented. This is because I don't have enough time. If you have questions or you think there is something wrong with this code, make a new post and tell us.
QuoteI know i have asked this a long time back but no one ever was able to answer it.
We were able, be shure of that. We didn't want to, that's all. :lol
there was a few things wrong there but i got it working and i wrote a test application for it which is working perfect so now i get to put it in my app. Thanks for the help and i see what you did different that i have not tried. :cheekygreen:
My pleasure! There may be mistakes, I really writed it in a big hurry. :8)
ok now the only question i have left on this topic is how can i make it so my listview is either placed in this dc or how can i make it so that my listview does not flash? I tried to bitblt my window to the dc and back but that did not work and i put the memory dc in my createwindowex for the listview but this also did not solve the problem. Got any ideas?
If possible, don't use CS_VREDRAW and CS_HREDRAW in the style member of the WNDCLASS structure, assuming thet your listview flashes when you resize the window. If not, consider using a sizing rectangle for your window (it will flash only once).
Maybe I didn't understand the question well, and this is not the answer?
Nick
you see the window flash when the app redraws i belive it is. This is caused by using Invoke InvalidateRect, hWnd, 0, 0 which is needed to force the window to update.
I thing that if you strip the code and you post it, it would be much easier for us.
Hi, all. It was quite interesting to read once again about implementation of double buffering. Some questions appeared. When we make compatible DC & Bitmap we have memDC that have exactly the same attributes that are selected in the original one, right? And we have the memBitmap that's have the dimensions of the original DC and filled with some trash, i.e. completely uninitialized, right?
Why to SaveDC and RestoreDC? It's unneeded i think...
SaveDC and RestoreDC appeared here because of a topic here about a statement from Win32.hlp. There it is stated, at the SelectObject function, that:
Quote
This function returns the previously selected object of the specified type. An application should always replace a new object with the original, default object after it has finished drawing with the new object.
jojo sugested the use of SaveDC and RestoreDC to avoid selecting the old object back in thet DC. I considered this a good sugestion and I used this method ever sience.
Well, this is the story of SaveDC and RestoreDC as I know it ::) ....
Nick
IMHO, there's no necessary in using Save/Restore because Memory Context is used and deleted by you only and when you need it only. System doesnt share so no need even to save cuz finally U delete it, as i said, by your own hands. It's only useful to select back the resource if the deletion sequence is strict: e.g. Created Brush->mem DC. the first of all you delete Brush then mem DC. But what if you use ony Stock objects->you dont have to delete them only delete mem DC->not need to Save/Restore. Just my opinion on what microsoft recommends...
Ok i stripped out most the code of my app and left what makes my apps design as in the gui. I also turned up the timer to make it more visible of my problem. If i dont expand the DC accross the listview i dont get the green but the items will still blink. I tried to put the listview on the DC in memory but could not get it working when i tried to do that. Any help would be appreciated..
[attachment deleted by admin]
Your problem is caused by the fact that every time you call InvalidateRect, it causes the entire window to be cleared and then its components are redrawn. For the listview this means its entire area is erased to window background and then redrawn over that - since these two colours are different, you see the flicker as the listview redraws itself.
Simple solution - don't erase the entire window, just the parts that will change and need updating.
Assuming this is just the info boxes (the listview redraws itself), modify your code like so:
(in WndProc)..
cmp uMsg, WM_TIMER
jne @F
mov rect.top, 20
mov rect.bottom, 40
mov rect.left, 6
mov rect.right, 185
;**these rectangles don't need to be drawn again - nothing to do with your problem, but still ;)
; Invoke Rectangle, hDCBack, rect.left, rect.top, rect.right, rect.bottom
;** invalidate just the info box area
;** this could be reduced to just the text line - since that's what actually changes
;** erase-background is false here
:** if you draw a long string and then a short one, you will still see the tail of the long one
;** making it TRUE will fix that, but can also cause a flicker
invoke InvalidateRect, hWnd, ADDR rect, FALSE
Invoke DrawText,hDCBack, addr AppName,-1,ADDR rect,DT_CENTER or DT_SINGLELINE or DT_VCENTER
mov rect.top, 120
mov rect.bottom, 140
mov rect.left, 6
mov rect.right, 185
; Invoke Rectangle, hDCBack, rect.left, rect.top, rect.right, rect.bottom
invoke InvalidateRect, hWnd, ADDR rect, FALSE
Invoke DrawText,hDCBack, addr FB,-1,ADDR rect,DT_CENTER or DT_SINGLELINE or DT_VCENTER
mov rect.top, 70
mov rect.bottom, 90
mov rect.left, 6
mov rect.right, 185
; Invoke Rectangle, hDCBack, rect.left, rect.top, rect.right, rect.bottom
invoke InvalidateRect, hWnd, ADDR rect, FALSE
Invoke DrawText,hDCBack, addr nTime,-1,ADDR rect,DT_CENTER or DT_SINGLELINE or DT_VCENTER
mov rect.top, 170
mov rect.bottom, 192
mov rect.left, 6
mov rect.right, 185
; Invoke Rectangle, hDCBack, rect.left, rect.top, rect.right, rect.bottom
invoke InvalidateRect, hWnd, ADDR rect, FALSE
Invoke DrawText,hDCBack, addr mNone,-1,ADDR rect,DT_CENTER or DT_SINGLELINE or DT_VCENTER
mov rect.top, 220
mov rect.bottom, 240
mov rect.left, 6
mov rect.right, 185
; Invoke Rectangle, hDCBack, rect.left, rect.top, rect.right, rect.bottom
invoke InvalidateRect, hWnd, ADDR rect, FALSE
Invoke DrawText,hDCBack, addr mChange,-1,ADDR rect,DT_CENTER or DT_SINGLELINE or DT_VCENTER
;** don't need to redraw the WHOLE window anymore - yay
; invoke InvalidateRect, hWnd, 0, FALSE
jmp Return
ok i see now. Ill play with it and see if i can get it working like i want. Thank you for the help.. I knew there had to be a way to do just parts but i couldnt figure it out and maybe i misunderstood msdn. again thx to everyone who helped :bg
ok its working perfectly now :bg I still have the rectangle api in there to redraw over any strings that may be longer than the the new one. Also instead of using the invalidaterect api i just did the entire left side at the end of the timer.