Winapi: The proper way to clear DrawText() - winapi

Hi I want to clear out the DrawText() and I don't know how to do it properly. I could simply SetTextColor to the color of my background but this is not elegant way to do it I think. I dont know maybe I could do something with a rectangle rc that holds my text.
I draw by case WM_PAINT and in it:
hdc=BeginPaint(hwnd, &paint);
.... //some other code here
DrawText(hdc, TEXT("some text"), -1, &rc, DT_SINGLELINE);
....//some other code here
EndPaint(hwnd, &paint);
and one more thing. I don't have DeleteDC(hdc); or ReleaseDC(hdc); in my WM_PAINT is that ok, or I should have them after or before EndPaint(hwnd, &paint);?

There's no way to "clear" text that you've drawn other than to draw something else over the top. If your background is a solid color then just draw a rectangle of that color (you can work out how big it needs to be by using the DT_CALCRECT flag with DrawText). If your background is an image then you need to blit the appropriate area of the image.
Note that drawing the text over the top of itself using the background color (as you suggest) may not work because of ClearType/anti-aliasing.
To answer your second question, no - the DC returned by BeginPaint is effectively deleted by the call to EndPaint and so you don't need to (and mustn't) delete it separately.

Related

Draw inside a win32 HRGN object

I am implementing a border control in win32, and I have implemented various styles for that border. I am using simple MoveTo() and LineTo() commands for drawing the border.
My problem is, when i select some new style for my border, it starts painting over the currently drawn border. I understand i need to refresh/repaint my window inorder to have a fresh canvas. I am using InvalidateRect() for now to achieve this purpose. But I am concerned, If i have other windows associated with my border control window (as child windows), how will this effect the child windows?i will need to repaint everything on this window, correct?
Secondly, Is there anyway I can draw lines inside a GDI Region (HRGN)? So far, all i have come across is how to fill up that HRGN with some fill color. Is there anyway i can retrieve HDC associated with that particular HRGN object??
This is not a concern, anything you draw is automatically clipped by the child window rectangles. No extra code is required. The underlying window style flag is WS_CLIPCHILDREN.
You cannot draw lines in a region nor are they associated with a device context. Other than by drawing the region and then drawing the lines in your paint message handler. You are probably interested in paths. The MSDN docs start here.

Clearing a window contents in a blur behind window(DWM)

I have a window on which I call DwmExtendFrameIntoClientArea(),
the window hosts other child windows, I use Direct2D to paint on one of the child windows,
When a bitmap is loaded which has a black region on it, that region becomes blurred.
I wish to clear everything in the child window and paint it again on WM_PAINT, however I cannot seem to clear the contents.
I have tried to clear it using
m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black))
This makes the child window region black, it erases all previous drawing, but no transparency.
I have tried to draw a bitmap which is just a black bar over the client area
m_pRenderTarget->DrawBitmap(m_pBkgrnd,D2D1::Rect<float> (0.f,0.f,GetWidth(),GetHeight()))
This makes whatever that had appeared before it, in black.
Tried the old GDI way of painting a black region over the entire child window,
RECT rc;
GetClientRect(m_hwnd, &rc);
HBRUSH brush = CreateSolidBrush(RGB(0,0,0));
HDC hc=GetDC(m_hwnd);
FillRect(hc, &rc, brush);
ReleaseDC(m_hwnd,hc);
DeleteObject(brush);
Doesn't work.
However if I don't do any of this and I try to resize the main window, it works right i.e. the previous painting dissappears.
Is there any API call or any way to clear the window manually before I draw it again?
How are you initializing your render target? Make sure you specify Premultipled Alpha, and not Straight or Ignore. Then, to clear everything to transparent, use ID2D1RenderTarget::Clear(D2D1::ColorF(0, 0, 0, 0)). You cannot use something like FillRectangle to draw with a transparent color, as that will blend the transparent color into what's already there and that is a no-op.

Cocoa Different text color in the same letter

What i need is a bit difficult to explain. Let's try...
I need to write a text in my app, and that text will gradually change color from left to right.
I think i could say it's a similar effect to what you see in a karaoke screen.
For instance. I draw a text line, in blue color, and gradually, using a timer, the color from left to right changes to red. But i don't want it to change letter by letter, but gradually. That would require that at some moment, the same letter can have a part in red and a part in blue.
I've been reading about core drawing, and maybe it's the solution, but i really don't know how to start. I was thinking about using a background layer and in top of it draw a transparent text (only with border), but i am not very sure how to do it.
any ideas would be appreciated.
You can probably do the job with a CGLayer.
Best of all you should be able to use your existing code to draw the characters (or anything else) in to the CGLayer.
Here's some rough code:
// first, make a CGLayer...
CGLayerRef yourDrawingPad =
CGLayerCreateWithContext(UIGraphicsGetCurrentContext(),etc..
CGContextRef yourRef = CGLayerGetContext(yourDrawingPad);
// now, draw to yourRef .. draw your various typography (or anything)
// use your current drawing code.
// all done drawing, now make an image mask...
UIGraphicsBeginImageContext(CGLayerGetSize(yourDrawingPad));
CGContextRef temp = UIGraphicsGetCurrentContext();
CGContextDrawLayerAtPoint(temp, CGPointZero, yourDrawingPad);
CGImageRef anAlphaMask = CGBitmapContextCreateImage(temp);
UIGraphicsEndImageContext();
You now have a nice mask you can use:
CGContextSaveGState(UIGraphicsGetCurrentContext()) ...
CGContextClipToMask(UIGraphicsGetCurrentContext(), self.frame, anAlphaMask);
So just mask it in to an image of a gradient, or whatever works.
(Conceivably: perhaps you will have to construct a bitmap image offscreen, and then use that as the mask?)
Footnote: Don't forget it is very likely you will have to paint upside down! Fortunately that is simple to deal with. Where it says "now, draw to yourRef" before drawing save your state and add the two lines of code:
CGContextTranslateCTM(refForMask, 0, self.frame.size.height);
CGContextScaleCTM(refForMask, 1.0, -1.0);
Hope it helps
I have an idea of how this could be done, but it is kind of complex. You could create an NSBezierPath and add the glyphs for each character. Then, set that as the clip and draw a NSGradient. Then you would just have to change the offset of the colors in the NSGradient to move the color along.

Can I create a device context that is just a portion of another device context?

I have subclassed a graphics control that takes a device context handle, HDC, as an input and uses that for drawing. My new control is just the original control centered on top of a larger image. I would like to be able to call the original control's Draw() method for code re-use, but I'm unsure how to proceed.
Here's the idea:
void CCheckBox::DrawCtrl( HDC hdc, HDC hdcTmp, LPSIZE pCtlSize, BYTE alpha ) {
// original method draws a checkbox
}
void CBorderedCheckBox::DrawCtrl( HDC hdc, HDC hdcTmp, LPSIZE pCtlSize, BYTE alpha ) {
// Draw my image here
// Create new hdc2 and hdcTemp2 which are just some portion of hdc and hdcTemp
// For example, hdc2 may just be a rectangle inside of hdc that is 20 pixels
// indented on all sides.
// Call CCheckBox::DrawCtrl() with hdc2 and hdcTemp2
}
I think you may be confused of what a device context is. A device context is a place in memory that you can draw to, be it the screen buffer or a bitmap or something else. Since I imagine you only want to draw on the screen, you only need one DC. To accomplish what you want, I would recommend passing a rectangle to the function that tells it where to draw. Optionally, and with poorer performance, you could create a new Bitmap for the smaller area, and give the function the Bitmap's DC to draw on. Now that I think about it, that might have been what you meant in the first place :P Good luck!
While not foolproof, you can fake a DC as a subsection of a DC by using a combination of SetViewportOrgEx and SelectObject with a region clipped to the sub area in question.
The problem with this approach is if drawing code already uses these APIs it needs to rewritten to be aware that it needs to combine its masking and offsetting with the existing offsets and clipping regions.

in gdi, how to clear the background color of DC. so, the drawed text will show no background color

when i draw text use DC, it always show an backgournd color which is diffrent from window's background.
SetBkMode(hdc, TRANSPARENT);
This will prevent the text-drawing functions (and some others) from drawing a background. SetBkMode(hdc, OPAQUE) will switch back to opaque mode.

Resources