Click to See Complete Forum and Search --> : How to write over text cleanly with DrawText()?
Hobbieman
November 15th, 2003, 06:56 PM
Hi, I have a program which when it receives events, it writes the name of the event received to specific coordinates in the client area. BTW, it uses SetBkMode(TRANSPARENT).
So, my problem is that the first event received is displayed correctly, but every other event after that is writing over the name of the old event without erasing the text that was there previously, so the name of the new event is unreadable.
How do I fix this?
I tried fixing it by doing the following when the event is received:
1. store the name of the event received in a global char array
2. set a global boolean flag indicating that text needs to be displayed
3. call InvalidateRect(m_hWnd, &rc, true); // rc has coordinates of place where text is to be displayed.
Then, in the WndProc() for the window, I check that it is processing a WM_PAINT event, and then do:
1. DefWindowProc(hWnd, uMessage, wParam, lParam);
2. If the global boolean flag is set call GetDC(), DrawText() and clear the boolean flag.
However, this still does not work because now the text just flashes onto the screen briefly before disappearing. I also tried changing the WndProc to do the DrawText when WM_ERASEBKGND was received, but that also failed.
Could someone help me out, again? :-)
Thanks,
Hobbieman
Marc G
November 16th, 2003, 03:22 AM
Just drop the global boolean flag.
And in your wndproc, always use DrawText to draw the text in the char array.
Instead of GetDC(), you better use BeginPaint() and EndPaint() because these function automatically setup the clipping region for you.
Hobbieman
November 16th, 2003, 09:18 PM
Thanks for the response, I tried what you suggested and I still have the same problem.
I should note that the window on which I am drawing the text has a child window over it. The child window is a directshow video window. Got any ideas on how to get this to work?
Hobbieman
Caprice
November 17th, 2003, 02:23 AM
Could you write your special window to show your events?
OK, if even not, before the text drawing you can draw a rectangle behind the text.
And maybe you forgot about WM_ERASEBKGND ?
Malcolm
November 17th, 2003, 08:23 AM
Maybe I misunderstood the question but when I did something similar I stored the old event name. When a new event is received, draw the old event again, but set the text colour to the background colour first. Then draw the new event in the correct colour text. maybe overkill, but it worked (and I can't remeber any flickering / flashing etc).
Hobbieman
November 17th, 2003, 07:01 PM
Hi, I have captured the events received by my WNDPROC when I press the keys which trigger the drawing of the text:
[17h:33m:24s:370ms] Handling WM_KEYDOWN
[17h:33m:24s:370ms] Key means pause, SendPause()
[17h:33m:24s:370ms] TextToBeDrawn = "Pause"
[17h:33m:24s:370ms] InvalidateRect()
[17h:33m:24s:370ms] UpdateWindow()
[17h:33m:24s:380ms] Handling WM_CHAR
[17h:33m:24s:380ms] DefWindowProc
[17h:33m:24s:380ms] Handling EC_PAUSED
[17h:33m:24s:380ms] status = paused
[17h:33m:24s:390ms] Handling WM_PAINT
[17h:33m:24s:390ms] TextToBeDrawn = "Pause"
[17h:33m:24s:390ms] BeginPaint()
[17h:33m:24s:390ms] **Handling WM_ERASEBKGND
[17h:33m:24s:390ms] **DefWindowProc
[17h:33m:24s:390ms] DrawText()
[17h:33m:24s:390ms] EndPaint()
[17h:33m:24s:390ms] Start timer to erase the text in 1 second
[17h:33m:24s:480ms] Handling WM_KEYUP
[17h:33m:24s:480ms] DefWindowProc
[17h:33m:25s:391ms] Handling WM_TIMER CLEAR_ACTION_TEXT
[17h:33m:25s:391ms] KillTimer()
[17h:33m:25s:391ms] TextToBeDrawn = ""
[17h:33m:25s:391ms] InvalidateRect()
[17h:33m:25s:391ms] UpdateWindow()
[17h:33m:25s:391ms] Handling WM_PAINT
[17h:33m:25s:391ms] Text not drawn because it is "\0"
[17h:33m:25s:391ms] DefWindowProc
[17h:33m:25s:391ms] Handling WM_ERASEBKGND
[17h:33m:25s:391ms] DefWindowProc
[17h:33m:27s:84ms] Handling WM_KEYDOWN
[17h:33m:27s:84ms] Key means next, SendNext()
[17h:33m:27s:84ms] TextToBeDrawn = "Next"
[17h:33m:27s:84ms] InvalidateRect()
[17h:33m:27s:84ms] UpdateWindow()
[17h:33m:27s:84ms] Handling WM_PAINT
[17h:33m:27s:84ms] TextToBeDrawn = "Next"
[17h:33m:27s:84ms] BeginPaint()
[17h:33m:27s:84ms] *Handling WM_ERASEBKGND
[17h:33m:27s:84ms] *DefWindowProc
[17h:33m:27s:84ms] DrawText()
[17h:33m:27s:84ms] EndPaint()
[17h:33m:27s:84ms] Start timer to erase the text in 1 second
[17h:33m:27s:84ms] Handling EC_NEXT_STARTED
[17h:33m:27s:254ms] Handling WM_KEYUP
[17h:33m:27s:254ms] DefWindowProc
[17h:33m:28s:85ms] Handling WM_TIMER CLEAR_ACTION_TEXT
[17h:33m:28s:85ms] KillTimer()
[17h:33m:28s:85ms] TextToBeDrawn = ""
[17h:33m:28s:85ms] InvalidateRect()
[17h:33m:28s:85ms] UpdateWindow()
[17h:33m:28s:85ms] Handling WM_PAINT
[17h:33m:28s:85ms] Text not drawn because it is "\0"
[17h:33m:28s:85ms] DefWindowProc
[17h:33m:28s:85ms] Handling WM_ERASEBKGND
[17h:33m:28s:85ms] DefWindowProc
As you can see, the WM_ERASEBKGND event is sent to my window while the WM_PAINT is still being handled. I guess this is a result of me calling BeginPaint() while handling WM_PAINT and the fact that I requested the background to be erased in InvalidateRect()...
Also, as you can see above, I start a ONE second timer which erases the text. I achieve this by invalidating the same RECT where the text was drawn and just calling DefWindowProc, which erases the area. The timer seems to be working fine, it triggers ONE second after it was started. I do not think it is causing the flashing...
Though, lately, on a single run of the program, the text can be seen flash sometimes, but display properly at other times... It is so unpredictable!!! Argghhh!
Thanks for any help you may be able to provide.
Hobbieman
Hobbieman
November 17th, 2003, 07:03 PM
Malcom, I do not think I can use the method you suggested because I am using a TRANSPARENT background [ SetBkMode(TRANSPARENT) ] for the text, and the text is being drawn over a directshow video window which has video playing on it...
Marc G
November 18th, 2003, 03:39 AM
Aha, you're drawing text OVER a directvideo window! That's your problem. When a movie in directvideo is playing, it will probably refresh your image 25 times per second. So when you draw some text over it, it will disappear in 1/25 seconds, because the next video frame is being rendered.
A solution could be the following (if you'r targetting Windows 2K/XP). You can make a layered window which you put on top of you directvideo window and which you make transparent except for the text on it.
If it should also work on Windows 9x, you can try to use setwindowrgn or something. You again make a little window on top of you directvideo window. You draw your text and get the region occupied by that text. And then you use SetWindowRgn on the little window, so only the text is visible and the rest of the window is transparent.
Hobbieman
November 18th, 2003, 10:12 PM
Marc G: Yeah, that is a good idea. I might try that one of these days. However, I got it to work by putting a 50ms delay right after calling BeginPaint() and that has fixed the problem for now... I know, I know: this is a terrible hack, but for the moment it works. Thanks!
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.