C++ MFC How to Draw Alpha transparent Rectangle - c++

in a C++ MFC application. using the dc of ( CPaintDC dc(this); )
How do i draw a rectangle ( LPRECT ) with an alpha transparency that i can adjust.?
Following is an example c# code which i need to convert into C++
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Color color = Color.FromArgb(75,Color.Red); //sets color Red with 75% alpha transparency
Rectangle rectangle = new Rectangle(100,100,400,400);
g.FillRectangle(new SolidBrush(color), rectangle); //draws the rectangle with the color set.
}

You need to look into GDI+. Its a bit of a faff but you can create a "Graphics" object as follows:
Gdiplus::Graphics g( dc.GetSafeHdc() );
Gdiplus::Color color( 192, 255, 0, 0 );
Gdiplus::Rect rectangle( 100, 100, 400, 400 );
Gdiplus::SolidBrush solidBrush( color );
g.FillRectangle( &solidBrush, rectangle );
Don't forget to do
#include <gdiplus.h>
and to call
GdiplusStartup(...);
somewhere :)
You'll notice it's pretty damned similar to your C# code ;)
Its worth noting that the 75 you put in your FromArgb code doesn't set 75% alpha it actually sets 75/255 alpha or ~29% alpha.

GDI (and thus MFC) has no decent support for drawing with an alpha. But GDI+ is available in C++ code as well. Use #include <gdiplus.h> and initialize it with GdiplusStartup(). You can use the Graphics class, create one with its Graphics(HDC) constructor from your CPaintDC. And use its FillRectangle() method. The SDK docs are here.

int StartHoriz,StartVert,BarWidth,BarHeight; // rect start, width and height
StartHoriz=0;
StartVert=100;
width = 100;
height=120;
CDC* pCDC = GetDC(); // Get CDC pointer
CRect Rect(StartHoriz,StartVert,BarWidth,BarHeight); //create rectangle dimensions
pCDC->Rectangle(Rect); //draw rectangle

Related

Underline is drawn outside of rectangle reported by DrawText with DT_CALCRECT

Symptoms
I'm having an issue with the recent version 2.0 of the Lato font in its "Regular" variant. This issue doesn't appear with Lato 1.0.
It seems that the underline is drawn 1px below the rectangle reported by DrawText() with the DT_CALCRECT flag.
In the following screenshots the calculated rectangle is indicated by the blue background. I've added 10px to the right of this rectangle so you can see the discrepancy to the position where the underline is drawn.
Lato 2.0 - underline is incorrectly drawn outside of rectangle reported by DT_CALCRECT:
Lato 1.0 - underline is correctly drawn inside of rectangle reported by DT_CALCRECT:
MCVE
can be reproduced on Win 10 and Win 7 (Win 8 not tested)
Download and install the Lato 2.0 Regular font (Lato-Regular.ttf).
Create a dialog based MFC application using the wizard and replace the OnPaint() handler of the dialog with the sample code.
Sample code for OnPaint():
CPaintDC dc{ this };
CRect rect; GetClientRect( &rect );
LOGFONTW lf{};
wcscpy_s( lf.lfFaceName, L"Lato" );
lf.lfHeight = 20 * 10; // tenths of a point
lf.lfWeight = FW_NORMAL;
lf.lfUnderline = TRUE;
CFont font;
VERIFY( font.CreatePointFontIndirect( &lf ) );
const int saved = dc.SaveDC();
dc.SelectObject( &font );
dc.SetBkMode( TRANSPARENT );
dc.SetTextColor( RGB( 0, 0, 0 ) );
const CString text = L"Hello Lato";
const DWORD dtFlags = 0;
// Calculate the size required by the text and fill this rectangle
CRect textRect = rect;
dc.DrawText( text, textRect, dtFlags | DT_CALCRECT );
textRect.right += 10;
dc.FillSolidRect( 0, 0, textRect.right, textRect.bottom, RGB( 180, 180, 255 ) );
// Actually draw the text
dc.DrawTextW( text, rect, dtFlags );
if( saved )
dc.RestoreDC( saved );
Question
Do you think this is an issue in my code, a bug in the OS or a bug in the font?
Unfortunately I can't just use Lato 1.0 as Lato 2.0 added support for many new languages my software needs to support.

QPaintedTextureImage in Qt3D (Qt 5.8)

I want to create an entity with Qt3D that has a custom image as texture. I came across the QPaintedTextureImage (link leads to Qt 5.9 version for details. Here ist doc for 5.8), which can be written with a QPainter but I don't understand how.
First, this is how I imagine the entity could look like:
[EDIT]: code is edited and works now!
planeEntity = new Qt3DCore::QEntity(rootEntity);
planeMesh = new Qt3DExtras::QPlaneMesh;
planeMesh->setWidth(2);
planeMesh->setHeight(2);
image = new TextureImage; //see below
image->setSize(QSize(100,100));
painter = new QPainter;
image->paint(painter)
planeMaterial = new Qt3DExtras::QDiffuseMapMaterial;
planeMaterial->diffuse()->addTextureImage(image);
planeEntity->addComponent(planeMesh);
planeEntity->addComponent(planeMaterial);
TextureImage is the subclassed QPaintedTextureImage with paint function:
class TextureImage : public Qt3DRender::QPaintedTextureImage
{
public:
void paint(QPainter* painter);
};
What does the QPainter, passed to paint function, need to do in the implementation of paint if I just want to draw a big circle to the planeEntity?
[Edit] Implementation:
void TextureImage::paint(QPainter* painter)
{
//hardcoded values because there was no device()->width/heigth
painter->fillRect(0, 0, 100, 100, QColor(255, 255, 255));
/* Set pen and brush to whatever you want. */
painter->setPen(QPen(QBrush(QColor(255, 0, 255)) ,10));
painter->setBrush(QColor(0, 0, 255));
/*
* Draw a circle (or an ellipse -- the outcome depends very much on
* the aspect ratio of the bounding rectangle amongst other things).
*/
painter->drawEllipse(0, 0, 100, 100);
}
The short answer is... use QPainter exactly the same way you would normally.
void TextureImage::paint (QPainter* painter)
{
int w = painter->device()->width();
int h = painter->device()->height();
/* Clear to white. */
painter->fillRect(0, 0, w, h, QColor(255, 255, 255));
/* Set pen and brush to whatever you want. */
painter->setPen(QPen(QBrush(QColor(0, 0, 0)) ,10));
painter->setBrush(QColor(0, 0, 255));
/*
* Draw a circle (or an ellipse -- the outcome depends very much on
* the aspect ratio of the bounding rectangle amongst other things).
*/
painter->drawEllipse(0, 0, w, h);
}
However, note that you really shouldn't invoke the paint method directly. Instead use update which will cause Qt to schedule a repaint, initialize a QPainter and invoke your overridden paint method with a pointer to that painter.
It might be simpler to dynamically load the image you need in QML.
I had to do it not so long ago and opened a question on SO for it:
Qt3D dynamic texture

Can someone explain me the CDC::SelectObject to me?

http://msdn.microsoft.com/en-us/library/sa8ahz7h(v=vs.80).aspx
//Border
CPen pen;
pen.CreatePen(PS_DASH, 20, RGB(0, 0, 0));
CPen* penOld = dc.SelectObject(&pen);
dc.Rectangle(rect);
dc.FillRect(rect, &brush);
How does this code work? It draws a rectangle and then a border around it. I just can't get my head around it.
When you ask the device context to draw a rectangle, it will use the current Pen.
You can set the current Pen, Brush, clipping region or whatever using the SelectObject() method. You're basically saying "use this Pen from now on".
SelectObject() also returns the item it was using before, so that it doesn't get lost and leak memory, and you can put it back later if you want. This is why penOld is being saved to a variable in your code. It will probably be selected back again later on.
CPen pen; //declare a new Pen object
pen.CreatePen(PS_DASH, 20, RGB(0, 0, 0)); //Create the GDI Pen, dashed, 20 pixels wide, black.
CPen* penOld = dc.SelectObject(&pen); //Tell the DC to use this pen from now on.
dc.Rectangle(rect); //Draw a rectangle (using the current pen)
dc.FillRect(rect, &brush); //Fill a rectangle (using the current brush)
It creates a pen, selects it into the DC, and then instructs the DC to use the pen (which is 20 pixels wide) to draw a rectangle at the specified coordinates. It then fills in the inside of that rectangle with a brush.

Black border around characters when draw Image to a transparent Bitmap

I have to draw a String on a transparent bitmap at first, then draw A to destination canvas.
However on certain case, there is black border around the characters.
Bitmap* tempImg = new Bitmap(1000, 1000, PixelFormat32bppARGB);
Graphics tempGr(tempImg);
tempGr.Clear(Color(0, 255,255,255));
Gdiplus::SolidBrush* brush = new SolidBrush(Color(255, 255, 0, 0 ));
Gdiplus::FontFamily fontFamily(L"Times New Roman");
Gdiplus::Font* font = new Gdiplus::Font(&fontFamily, 19, FontStyleRegular, UnitPixel);
RectF rec(400, 400, 1000, 10000);
tempGr.DrawString(
L"Merry Chrismas",
-1,
font,
rec,
NULL,
brush
);
Graphics desGr(hdc);
desGr.Clear(Color::Gray);
desGr.DrawImage(tempImg , 0,0, 1000, 1000);
The character draw on desGr have black board for some fontsize.
How can I avoid this problem?
Many thanks!
I think the problem here is that you are drawing the text onto a transparent background.
You could try adding this line after the call to tempGr.Clear...
tempGr.TextRenderingHint = TextRenderingHint.AntiAlias;
ps - sorry not sure the exact syntax in C++ ;)
I just solved this problem in XNA:
Clear background to the same as the foreground color. The only difference is that the background should have Alpha=0, and the foreground with Alpha >> 0
The black border comes from blending of your background and foreground of different colors. Try to clear the background to some contrasting color to fully appreciate the phenomenon.

Small example on getting Cairo graphics to work with MFC?

I have some legacy MFC apps, and I'd like to use the Cairo drawing engine to add some charts and graphs.
I'm searching for a small example of how to get that to work. Basically, once I've created a PNG or GIF file, how do I get that show up in an MFC CView window?
My google-fu is not finding any good clues.
From my demo samples,
// cairo_surface_t *surface;
// cairo_t *cr;
// surface = call_win32_surface_create_with_dib_T(CAIRO_FORMAT_ARGB32, 240, 80);
// cr = call_create_T (surface);
// call_surface_write_to_png_T (surface, "hello.png");
HDC src = call_win32_surface_get_dc_T(surface); // <--------
BitBlt(dest, 0, 0, 240, 80, src, 0,0, SRCCOPY); // <--------
Assuming that you already have a surface you can use something like the above sample.dest is the HDC handle to the window you want to render the cairo surface.
Update: CView::OnDraw()
You should implement the OnDraw() method for your CView (inherited?) class.
You can use the pDC pointer to draw the cairo surface, ie:
pDC->BitBlt(0, 0, 240, 80, src, 0,0, SRCCOPY); // "HDC src" is mentioned above