Draw and erase line - mfc

I have a mfc mdi application.
I have a black color line.
On clicking draw button I have to draw red color line over the back color line.
On clicking delete button I have to erase the red color line but the black color line should be visible.
I am able to draw red color line but I dont know how to erase red color line?
I am using below code. On erasing the line, I am getting kind of green color line and black color line also got erased.
void CScrRulerView::DrawLine(CDC* pDC, CRect rulerRect, bool bDraw)
{
int nPrevMode;
CPen pen(PS_SOLID,1,RGB(255,0,0));
CPen* pPenOld = pDC->SelectObject (&pen);
if(bDraw)
nPrevMode = pDC->SetROP2(R2_COPYPEN);
else
nPrevMode = pDC->SetROP2(R2_NOT);
pDC->MoveTo(rulerRect.left,rulerRect.top);
pDC->LineTo(rulerRect.right,rulerRect.bottom);
pDC->SelectObject(pPenOld);
pDC->SetROP2(nPrevMode);
}
I am using SetROP2(R2_NOT); for erasing whether I have to use some other option?

Related

How to change the color of window border and title bar background programmatically when using DWM in win32?

I want to customize the window frame using DWM in win32 to get an appearance like VS2022 (draw menu on title bar) or Chrome (draw tabs on title bar), so I use the function DwmExtendFrameIntoClientArea with margin {0, 0, caption height, 0}. Unfortunately, it shows a white window border with 1-pixel width and white title bar area. I use the function DwmDefWindowProc to handle the system messages and show the system control buttons (min, max, close button). But I have no idea how to change the color of the window border and title bar background. If I paint in WM_PAINT, it may cover the system control buttons and looks weird. If I paint in WM_NCPAINT, the window shadow with WS_THICKFRAME style may disappear and need to draw which I feel is difficult to do.
Additionally, the 1-pixel width border may come from the following code:
if (message == WM_NCCALCSIZE) {
auto client_area_needs_calculating = static_cast<bool>(wparam);
if (client_area_needs_calculating) {
auto parameters = reinterpret_cast<NCCALCSIZE_PARAMS*>(lparam);
auto& requested_client_area = parameters->rgrc[0];
requested_client_area.right -= GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
requested_client_area.left += GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
requested_client_area.bottom -= GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
return 0;
}
}

How to set the text color in winapi properly

I wrapped the handles in a widget class so the foreground color, background color, and cursor go along for the ride.
I am having a lot of trouble figuring out how to set the foreground (text) color of a static control. I can get the foreground color to change, but then the background color doesn't match the Window color, or the Window color is correct but the text color is not.
Here is what I have, where the control is question is a static control, but there are edit controls on the window also:
case WM_CTLCOLOREDIT:
case WM_CTLCOLORSTATIC:
widget = Widget::find((HWND)lParam); // find a widget from handle
if (widget)
{
COLORREF color = widget->color();
HBRUSH bg = widget->background(); // may be nullptr if none set (use default window bg)
SetBkMode((HDC)wParam, TRANSPARENT);
SetTextColor((HDC)wParam, color);
// try 1: always return the background, even if nullptr
// result: correct foreground color, incorrect background color (white)
return (INT_PTR)bg;
// try 2: only return the background if set, else default to DefWindowProcW(...)
// result: incorrect foreground color (black), correct background color
if (bg) return (INT_PTR)bg;
break;
// try 3: if no background, ask for parent's background
// result: both foreground and background are correct,
// however, every control has the same background color (the main window's),
// but some controls I want to have their default
// (i.e. edit controls have a white background by default)
while (!bg && widget)
{
widget = widget->parent();
if (widget) bg = widget->background();
}
return (INT_PTR)bg;
}
Can the foreground (text) color be set without setting the background? I don't always know what the background color is (when background() returns nullptr), and want to use the control's default.
Or, am I taking the complete wrong approach to this?
I am new to the Win32 API and GUI programming.

How to fill the color outside of source in pixmap

I had tried to fill the color outside of the actual image but fails to do so. I get the pixmap as the input.
QRect target = AlignRect(aRect, iPixmap.size(), Alignment());
aPainter.drawPixmap(target, iPixmap);
QPainter painter(&iPixmap);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.setBrush(QColor::fromRgb(43, 174, 255));
painter.setPen(QColor::fromRgb(43, 174, 255));
painter.drawRect(target);
I get the below image as the pixmap.
I want to fill the color outside the white icon like
Can someone give the pointer for the same?
This can be done easily because your iPixmap has a transparent background...
You can draw a rect at 0,0 with a WIDTH and HEIGH of the widgets size and then after that place the X on top of that.
example:
painter.drawRect(0,0,w,h);

Draw over Dialog Margins in an MFC Dialog

I want a dialog to be borderless and yet have a dialog shadow. I came across this solution Borderless Window Using Areo Snap, Shadow, Minimize Animation, and Shake which uses a workaround by making the Dialog having a Margin of 1 px and extending the Client Area to it.
MARGINS borderless = { 1, 1, 1, 1 };
DwmExtendFrameInfoClientArea(this->GetSafeHwnd(), &borderless);
The post mentioned that the Client Area is literally being extended and Transparent drawing makes the Dialog edges of 1px each visible again.
Now this is exactly what happened, when I tried to paint a Solid Rectangle onto the whole dialog:
// getting the client area
CRect clientRect;
GetClientRect(&clientRect);
// expanding it to the new margins
clientRect.left -= 1;
clientRect.top -= 1;
clientRect.right += 2;
clientRect.bottom += 2;
// set the Device Context to draw non transparent and with a black background
pDC->SetBkMode(OPAQUE);
pDC->SetBkColor(RGB(0, 0, 0));
// finally draw a rectangle to it
CBrush brush_back_ground(RGB(0, 0, 0));
pDC->FillRect(clientRect, &brush_back_ground);
But the dialog is still drawn with its margins:
How would it be possible to draw something stretched on the margins? Later I'm going to use pictures as dialog Background which should be drawn on the margins aswell.
Thanks to Hans Passant for his comment. The solution is to use GDI+ drawing instead of GDI drawing
// making a Gdi+ graphics object from my CDC*
Graphics g(*pDC);
// getting the client area
CRect clientRect;
GetClientRect(&clientRect);
// making a Gdi+ rect
Rect bkRect(0,0,clientRect.Width(), clientRect.Height());
// making a pen for the Rect Drawing
Pen bkPen(Color(255,0,0,0));
// draw the rectangle over the full dialog
g.DrawRectangle(&bkPen, bkRect);

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.