Create or remove GDI shapes on command - c++

I'm creating a win32 application. on the main window there are 5 buttons. in front of each button there is a small circle drawn. (using GDI tools. in case WM_PAINT). now when I press on a button the circle in front of it should colour in red colour. how can I do this.
If we create a edit box any time we can change the text on it using SendMessege to it. like that is it possible to change the colour on shapes drawn earlier.
Please can someone give me an advice.
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC;
HBRUSH brusha;
hDC=BeginPaint(hWnd,&ps);
brusha=CreateSolidBrush(RGB(0,255,0));
SelectObject(hDC,brusha);
Ellipse(hDC, 20, 20, 50, 50);
DeleteObject(brusha);
EndPaint(hWnd, &ps);
}
case WM_COMMAND:
switch(LOWORD(wParam))
{
case BUTTON:
{
//here I need to change the above drawn corcle to be red.
}
}

You can't change the color of an already drawn image, but you can redraw it. Use the Windows function InvalidateRect to tell the control that it needs to be redrawn, and you will get another call to your WM_PAINT handler. In the handler select the desired color before you draw your circle.

Related

Draw text on screen C++

I want to draw text on the screen above all the windows.
I found out about HDC and start working with it. I had 2 problems: the text was flashing and there was background. I found out the function:
SetBkMode(hdc, TRANSPARENT);
but all it done is cancel the flashing. I still got background. My final code now is:
RECT rect = { 20, 20, 200, 200 };
SetTextColor(hdc,RGB(255,0,0));
SetBkMode(hdc, TRANSPARENT);
SetBkColor(hdc,RGBA(0,255,0,0));
DrawText(hdc, L"My text",-1,&rect,DT_LEFT);
I put this code in while(true) statement and sleep for 1 millisec.
Before the while i got the hdc init:
HDC hdc = GetDC(0);
So at this point i got non flashing text but with background (not transparent).
The background is half transparent so i can see what below it but it doesn't update. When i put a new window below it i can see the "background" of the old one.
I tried using wndproc like in this question:
How to draw text with transparent background using c++/WinAPI?
But it does nothing at all (i cant even see the text)
I tried using the textout example from msdn site:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd145133(v=vs.85).aspx
But it does nothing too.
How can i draw text on the screen without background at all?
Thank you guys

How can I paint a rectangle around a window without overriding the title bar in win32

I want to draw a rectangle around my window but I don't want to override the title bar.
what I wrote so far in the window callback function is:
case WM_NCPAINT:
{
HDC hdc;
RECT rect;
HPEN pen;
hdc=GetDCEx(hWnd,(HRGN)wParam,DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_LOCKWINDOWUPDATE);
GetWindowRect(hWnd,&rect);
pen=CreatePen(PS_SOLID, 10, RGB(255, 0, 0));//red pen 10 pixels in size
SelectObject(hdc,pen);
Rectangle(hdc,0,0,(rect.right-rect.left),(rect.bottom-rect.top));
DeleteObject(pen);
ReleaseDC(hWnd,hdc);
}
break;
However, this draws over the window title bar with white brush.
How can I make it not to paint over the title bar? I'm loosing the title bar text and the menu...
I have tried using HOLLOW_BRUSH before creating the pen as follows:
HBRUSH b=CreateSolidBrush(HOLLOW_BRUSH);
SelectObject(hdc,b);
But that only caused the title bar to not be drawn at all (being black).
By handling the WM_NCPAINT message, you are telling the window manager that you are taking responsibility for painting the entire non-client area, and so the window manager will not draw any of it for you.
If you want the original title bar to be drawn then you need to call DefWindowProc() first, then do your own drawing "on top" of what it draws.
You may also need to use ExcludeClipRect() to prevent the client area from being drawn over if you wish to draw the entire non-client area at once with a single rectangle.

Win32 Edit Controls of WS_EX_LAYERED parent dont receive mouse/click events when their background is transparent

I want to put some edit fields ontop of a splash screen which is rendered in another top level window (transparent PNG similar to this http://code.logos.com/blog/2008/09/displaying_a_splash_screen_with_c_part_ii.html) .
I made a secondary window which is always on top of my splash screen, and made it also transparent with WS_EX_LAYERED.
Now i set the background color of the edit fields in the wndproc by catching WM_CTLCOLOREDIT.
This works fine, my input controls are transparent (e.g. invisible) and only the entered text is visible on the splash screen.
Now the issue comes that the mouse cursor which indicates here is a text box does not work, neither can i click in that box to have it focus. The problem all disappears if i do NOT make the background of the edit control transparent. There is also no WM_NCHITTEST when its transparent. The only time im getting a mousecursor is if there is (visible)text already entered in the box
g_HWNControlsParent = CreateWindowEx( WS_EX_LAYERED,.....);
hwLoginField = CreateWindowEx(NULL,"EDIT", "-User-", WS_CHILD|WS_VISIBLE|WS_TABSTOP, ....g_HWNControlsParent);
SetLayeredWindowAttributes(g_HWNControlsParent,RGB(0, 0, 0), 0, LWA_COLORKEY) ;
in HWNControlsParent wndproc
case WM_CTLCOLOREDIT: { // BG Color of Input Fields
HDC hdc = (HDC)wParam;
SetTextColor(hdc, RGB(230,230,230));
SetBkColor(hdc, RGB(0,0,0)); // Color of Background where Text is entered
SetDCBrushColor(hdc, RGB(0,0,0)); // Color of Background where no Text is
return (LRESULT) GetStockObject(DC_BRUSH); // return a DC brush.
}
If you use an alpha of 1 instead of 0 for the transparent regions, they will still be transparent but will respond to mouse clicks.

c++ win32: how to set back color of a window?

I can set the back color when i am registering the class, e.g.:
wincl.hbrBackground = CreateSolidBrush(RGB(202, 238, 255));
RegisterClassEx(&wincl);
But how would i do it to any window i have created with the CreateWindow function?
like a button on my main window, i have visual styles enabled, and i can notice the windows default gray back color behind the button.
Don't tell me i have to SetWindowLong for the window procedure on allllllll my controls and intercept the WM_PAINT :(
All the windows controls send a message to their parent to get the brush to use to fill their background.
Assuming you save a copy of the brush handle somewhere, you can do the following in your WindowProc, or DialogProc, to ensure everything draws with the correct background brush.
case WM_CTLCOLORSTATIC:
case WM_CTLCOLORBTN:
HDC hdc;
HWND hwndCtl;
POINT pt;
hdc = (HDC)wParam;
hwndCtl = (HWND)lParam;
pt.x = 0;
pt.y = 0;
MapWindowPoints(hwndCtl,_hwnd,&pt,1);
x = -pt.x;
y = -pt.y;
SetBrushOrgEx(hdc,x,y,NULL);
return (INT_PTR)_skinBrush;
If you want a customized window you can create your own window class to draw that type of window. Implement a handler for wm_paint and draw whatever you want for the window. There are a lot of tutorials available.

GDI+ not clearing my window on repaint for vista

on WM_PAINT i do the following:
//RectF mNameRect;
//WCHAR* mName;
//HWND mWin; // this is the window handle
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(mWin, &ps);
Graphics g(hdc);
g.Clear(Color::White);
StringFormat stringForm;
stringForm.SetLineAlignment(StringAlignmentCenter);
stringForm.SetAlignment(StringAlignmentCenter);
// set the rectangle to the size of the whole window
mNameRect.Width = static_cast<float>(size.cx);
mNameRect.Height = static_cast<float>(size.cy);
g.DrawString(mName, -1, &mNameFont, mNameRect, &stringForm, &mNameBrush);
EndPaint(mWin, &ps);
}
In XP this works fine, the mName is displayed in the middle of the window. However on Vista the text doesn't move, it stays in its location no matter how I resize the window. the g.Clear(Color::White) doesn't seem to do any difference. The text doesn't even change position when the window is hidden behind another window and on focus needs to be repainted again.
How do I make mName change position in Vista?
Edit:
The paint code gets called via WM_PAINT and via WM_SIZE in the following manner:
// WndProc function
switch (msg){
case WM_SIZE:
// intentionally call paint when WM_SIZE is triggered
case WM_PAINT:
paint();
break;
You are explicitly calling your paint() function when the window is resized. However, your window is not invalidated, so it could be that the system is restricting your painting efforts to the region marked "dirty".
Instead of calling paint() directly, it is better to use InvalidateRgn to trigger a repaint. This will cause a WM_PAINT to be sent which will be handled by your application in the normal way. As a bonus, you can also tell InvalidateRgn to erase the background for you
InvalidateRgn(hWnd, NULL, TRUE);