Using Win7 x64 c++ with MSVC2010 pro.
I have noticed a really strange bug when using the Win32 DrawText to draw some text for a custom control. Its a pretty standard thing to do I'm sure. I did see a post about something similar and the solution was to use one the TextOut calls, but that doesn't resolve my issue.
I've subclass the "Static" control using the SetWindowSubClass and I'm hanlding the wm_paint message as:
case WM_PAINT:
{
RECT rect;
PAINTSTRUCT ps;
HDC hdc = BeginPain(hWnd,&ps);
// Create a back buffer to draw to
HDC hdcBack = CreateCompatibleDC(hdc);
GetClientRect(hWnd,&rect);
HBITMAP hbmBackbuffer= CreateCompatibleBitmap(hdc,rect.right,rect.bottom);
size_t iLength = 0;
StringCchLength(LCDText,240,&Length);
SelectObject(hdcBack,hbmBackbuffer);
// Draw a black background to clear previous text
SelectObject(hdcBack,GetSysColour(1)); // Black
Rectangle(hdcBack,rect.left,rect.top,rect.right,rect.bottom);
// Set the font, tranparency and text colour
SelectObject(hdcBack,LCDFont);
SetBkMode(hdcBack,TRANSPARENT);
SetTextColor(hdcBack,0x0000ff00);
DrawText(hdcBack,LCDText,(int)iLength,&rect,DT_LEFT);
// display
BitBlt(hdc,0,0,rect.right,rect.bottom,hdcBack,0,0,SRCCOPY);
// cleanup
DeleteObject(hbmBackbuffer);
DeleteDC(hdcBack);
EndPaint(hWnd,&ps);
break;
}
This actually works very well. The problem is that the the 'label' can display 3 lines of 40 chararcters, and after the 27 character of each line the next chars to the end of that line are 1 or 2 pixels higher up the screen. It's not immediately apparent but once you notice it then it kindof draws your attention.
Does anyone have any ideas or experience with this?
ps - I typed the code in manually into the forum so there may be some silly typos but the real code does work properly apart the alignment issue.
Regards
Dave.
Related
I'm currently experiencing an error with my program.
My program has two rectangles, each of them surrounded by a groupbox.
Currently I'm trying two place text in each of them.
I've already got text in the first rectangle - fine (with DrawText()).
If I'm trying to display text in the second rectangle (also with DrawText()), the text is not displaying.
Here's the code I'm using:
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, font);
DrawText(hdc, lpcwstr, wcslen(lpcwstr), &rect, DT_LEFT);
DrawText(hdc, lpcwstr, wcslen(lpcwstr), &rect_2, DT_LEFT);
EndPaint(FindWindow(NULL, L"Statistik (seit dem 01.01.2015)"), &ps);
Unfortunately I have no idea why the text is not displaying as expected.
Does anybody of you have a suggestion why this doesn't work?
[SOLUTION]
I was able to figure out what the problem was.
Not visible in the snippet, I posted initially, but the coordinates I set for the rectangles, were wrong.
Sadly I were not aware that all values are coordinates.
The only difference between the two calls is the RECT that you pass. The obvious conclusion is that you initialised one of the rectangles incorrectly.
You should restore the original font before calling EndPaint. And the call to FindWindow should be removed. Pass hwnd. Finally, your code performs no error checking at all. That's always imprudent.
i have the following code ...
case WM_PAINT:
{
hdc = BeginPaint(hwnd,&paintSt);
temphdc = hdc;
GetClientRect(hwnd,&aRect);
if(hBitmap!=NULL)
{
HDC memDC = CreateCompatibleDC(hdc);
if(memDC!=NULL)
{
BITMAP bmp;
GetObject(hBitmap,sizeof(bmp),&bmp);
SelectObject(memDC,hBitmap);
SetStretchBltMode(hdc,HALFTONE);
StretchBlt(hdc,0,0,aRect.right,aRect.bottom,
memDC,0,0,bmp.bmWidth,bmp.bmHeight,
SRCCOPY);
DeleteObject(&bmp);
ReleaseDC(hwnd,memDC);
}
}
// the code for painting
EndPaint(hwnd,&paintSt);
}
break;
hBitmap is a global variable which is assigned at some place in the code.... Image is displayed but disappears whenever I minimize the window....
can anyone explain this ?
thanks in advance,
Your cleanup code is all wrong, you are leaking handles badly. Should be readily visible in TaskMgr.exe, Processes tab. View + Select Columns and tick GDI Objects. This code stops working when the GDI object handle count reaches 10,000. Yes, likely to happen when you resize the window since there will be a flurry of paint requests.
Don't delete the BITMAP, it is just as struct. Restore the old bitmap handle you got back from SelectObject() before you delete the memDC. Don't use ReleaseDC, DeleteDC is required. Pay attention to the return value of these functions, they tell you when you messed up but that can't work if you never check with an assert.
GDI programming is painful with these explicit cleanup rules. Consider a class library to take care of this kind of drudgery, they never get it wrong.
I guess somehow hBitmap is changing to null while minimize.
Posting the code where you are assigning and referring hBitmap will help to identify the issue I think.
I am using the windows API (in C++) to create a windows application.
Now, I have a progress bar which I want to show like a meter. A meter is blue and has no animation. I cannot figure out how to implement this, and if I have to, I will just settle for the usual green progress bar.
Please help.
EDIT: At least, is it possible to disable the animation (highlight the slides across the filled section of the bar)?
EDIT2:
Here is the C++ solution if anyone else is having this problem:
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hwnd,&ps);
RECT r;
HTHEME theme = OpenThemeData(hwnd,L"PROGRESS");
SetRect(&r,10,10,100,25);
DrawThemeBackground(theme,hDC,11,2,&r,NULL);
SetRect(&r,10,10,50,25);
DrawThemeBackground(theme,hDC,5,4,&r,NULL);
CloseThemeData(theme);
EndPaint(hwnd,&ps);
You can draw this style of progress bar with DrawThemeBackground(). You'll find the theme name, part and state numbers in my answer in this thread.
The built in control cannot do this... however, it's not like ProgressBar is a complicated control. If you want nothing but a blue rectangle, use DrawRect and draw a blue rectangle.
Whats the most simple way (without much fancy stuff and no big setup overhead) to create a c++ project with visual studio where i can create some graphical debug output? (mainly drawing some lines, circles and triangles in a window. doesn't have to be performant or look pretty)
thanks!
The quickest way: create a new project, find or create the paint message handler (in Win32 it'll be in WndProc under "case WM_PAINT:", and in a WinForms (.net) project you'll override OnPaint), and add code to draw some stuff.
Well, for this I'll assume you would want to just use Gdi.
In a windows app, process the WM_PAINT message.
Here is an example that draws a rectangle:
case WM_PAINT:
{
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hwnd,&ps);
Rectangle(hDC,10,10,30,30);
EndPaint(hwnd,&ps);
}
I'm sort of new to c++ and i'm trying to create a game.
I have a 2d array RECT_GRID of rectangles.
I have a 2d array GRID of unsigned short.
I fill the rectangle array during WM_CREATE
The WM_PAINT event paints rectangles for all the elements in the array. The color of the rectangle is based on the value of GRID[x][y]
I made it so when the down key is pressed, It changes the color of one of the rectangles by setting GRID[1][XMOVE] = to a different color
then it invalidates the client rectangle
Basically what happens is, it works well for a while, but eventually it just stops drawing stuff. I checked my XMOVE variable during debug, I checked by grid values and stuff and everything is fine. When I remove the for loop from the paint event and focus on 1 specific rectangle, it never fails, but if I try to redraw all of them at once, after about 20 times, it stops painting things. What could cause this? I'm new to c++ and I bet I'm not painting properly and causing an overflow or something.
If anyone could explain what's going wrong, or a proper way to do this, I'd really appreciate it. I could not find anything like this example on Google.
Thanks
EDIT:
I'm using 3 global brushes
HBRUSH A;
HBRUSH B;
HBRUSH C;
and when I modify them, I always say A = MakeBrush(NUM);
ami I using brushes properly?
My first guess, if you're a total GDI/C++ newbie, is that you are probably creating a lot of Pens and Brushes. These are constrained resources in Windows. You can only create so many of them before you start to tax your resources. So either make your Brushes and Pens and Windows, etc all at once and re-use them, or dispose of them properly when you're done. I recommend getting a copy of "the Bible" (http://www.amazon.com/Programming-Windows%C2%AE-Fifth-Microsoft/dp/157231995X/ref=sr_1_1?ie=UTF8&s=books&qid=1252788457&sr=8-1) and reading the chapters in there about drawing.
EDIT: It doesn't sound like you're modifying your brushes properly, but since I can't see the code for MakeBrush, I don't know. You're probably creating a lot of brushes behind the scenes and you don't even know it. Seriously, get a copy of Petzold's book and spend an hour or two. You'll end up with more hair on your head later! ;-)
You'll notice in all GDI examples, a 'CreatePen' or 'CreateSolidBrush' will be followed by a delete object. This is because they are limited resources in windows, and you can run out of them if you don't delete them when you're finished.
PAINTSTRUCT Ps;
HDC hDC = BeginPaint(hWnd, &Ps);
HBRUSH NewBrush = CreateSolidBrush(RGB(250, 25, 5));
SelectObject(hDC, NewBrush);
Rectangle(hDC, 20, 20, 250, 125);
DeleteObject(NewBrush);
EndPaint(hWnd, &Ps);
If you forget to include the 'DeleteObject' call, then you will have problems after you use up all the brushes available. It's actually fun to try =)