• Advertisement
Sign in to follow this  

draw outside WM_PAINT

This topic is 4401 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Is it possible to draw text or line outside WM_PAINT message ? I try and it dosen't work, any suggestion ?

Share this post


Link to post
Share on other sites
Advertisement
Do you use GDI or GDI+?

atm I use GDI+ and can draw from any part of code, i must only supply windows handle, so it must work even with GDI

edit: Check your code, cause WM_PAINT redraws window client when its been moved, resized etc. , so when you draw from other place than its possible, that it is immediately overdrawn

Share this post


Link to post
Share on other sites
This is my code, is there anything wrong ?
why it won't show anything


#include <windows.h>

HDC hDC;
PAINTSTRUCT ps;
int x=0, y=0;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
SetTimer(hwnd, 10, 50, NULL);
break;

case WM_PAINT:
break;

case WM_TIMER:
x++;
y++;

hDC = BeginPaint(hwnd, &ps);
TextOut(hDC, x, y, "Hello", 5);
EndPaint(hwnd, &ps);
break;

case WM_DESTROY:
PostQuitMessage(WM_QUIT);
break;

default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}

return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{

WNDCLASSEX wc;
HWND hwnd;
MSG msg;

wc.cbSize = sizeof(WNDCLASSEX);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Example";
wc.hInstance = hInstance;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wc.lpszMenuName = NULL;

RegisterClassEx(&wc);

hwnd = CreateWindow("Example", "Window Example", WS_OVERLAPPEDWINDOW ,
CW_USEDEFAULT, CW_USEDEFAULT,
300, 300, NULL, NULL, hInstance, NULL);

ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return (int)msg.wParam;

}

Share this post


Link to post
Share on other sites
Never use BeginPaint() outside of WM_PAINT unless you really know what you're doing. The problem is that you're retrieving a handle to an empty region. BeginPaint will only return a handle to a paintable region when it's called under WM_PAINT. Either insert InvalidateRect(hwnd, NULL, _TRUE_OR_FALSE); before the call to BeginPaint (not recommended but it should work), or retrieve a handle to the entire client area (region) to paint by calling GetDC(hwnd); or GetDCEx(hwnd); if you want to set the initial clipping region. instead. - edit -[don't forget to call ReleaseDC(hwnd, hdc);
before leaving WM_TIMER]


xeddiex

Share this post


Link to post
Share on other sites
Quote:
Original post by invisal
Is it possible to draw text or line outside WM_PAINT message ? I try and it dosen't work, any suggestion ?


It would work if you have a way to redraw the the line , cause the window doesn't save the graphical data unless you save it yourself , thats why in games the render sub is called every frame , WM_PAINT happens every time the window moves,resizes when ever they need to redraw any part of the non-client area , so it draws your line too , a good way is to save every pixel in memory and redraw them every time the window recives WM_PAINT , some people would save every line coord but that can be a lot of over heads when lines are erased and others are drawn and if you try to draw circles and save thier coords too you would be working with vector graphics , so see what best suits you and work with that .

Share this post


Link to post
Share on other sites
here it is working



#include &lt;windows.h&gt;

HDC hDC;
PAINTSTRUCT ps;
int x=0, y=0;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
SetTimer(hwnd, 10, 50, NULL);
break;

case WM_PAINT:
hDC = BeginPaint(hwnd,&ps);


ValidateRect(hwnd,NULL);
EndPaint(hwnd,&ps);

break;

case WM_TIMER:
x++;
y++;


hDC = GetWindowDC(hwnd);
TextOut(hDC, x, y, "Hello", 5);


break;

case WM_DESTROY:
PostQuitMessage(WM_QUIT);
break;

default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}

return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{

WNDCLASSEX wc;
HWND hwnd;
MSG msg;

wc.cbSize = sizeof(WNDCLASSEX);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Example";
wc.hInstance = hInstance;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hbrBackground = (HBRUSH)(BLACK_BRUSH);
wc.lpszMenuName = NULL;

RegisterClassEx(&wc);

hwnd = CreateWindow("Example", "Window Example", WS_OVERLAPPEDWINDOW ,
CW_USEDEFAULT, CW_USEDEFAULT,
300, 300, NULL, NULL, hInstance, NULL);

ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

while (1)
{
if (GetMessage(&msg, NULL, 0, 0) != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);

}
else
{
return 0;
}

}


return (int)msg.wParam;

}









i tuned up some procedures for you hope you like it .

Share this post


Link to post
Share on other sites
Quote:
Original post by Code Fusion
here it is working

*** Source Snippet Removed ***


i tuned up some procedures for you hope you like it .


GetWindowDC is going to give him unwanted effects. He doesn't need a handle to the entire window if all he wants to do is paint in the client area and outside of WM_PAINT. Also, calling ValidateRect right before EndPaint is unnecessary since EndPaint does it for you.

xeddiex.

Share this post


Link to post
Share on other sites
GetWindowDC Get the handle to the Client+Non-Client area but i guess you would need both in a game and in case he wants to get only the client area he could use GetSystemMetrics to get the size of the two borders and add them to the obsloute value of the x,y this way he has the two options , and yes its not necessary to use ValidateRect cause BeginPaint does it automaticly but some Documention says its faster (no idea why).

Share this post


Link to post
Share on other sites
Here, I fixed up CodeFusions code so it doesn't leave memory allocated (ReleaseDC added) and changed it to GetDC() (you can look up GetDCEx() if you like.


#include <windows.h>

HDC hDC;
PAINTSTRUCT ps;
int x=0, y=0;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
SetTimer(hwnd, 10, 50, NULL);
break;

case WM_PAINT:
hDC = BeginPaint(hwnd,&ps);
// other draw code here.
EndPaint(hwnd,&ps);

break;

case WM_TIMER:
x++;
y++;

hDC = GetDC(hwnd);
TextOut(hDC, x, y, "Hello", 5);
ReleaseDC(hDC);

break;

case WM_DESTROY:
PostQuitMessage(WM_QUIT);
break;

default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}

return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{

WNDCLASSEX wc;
HWND hwnd;
MSG msg;

wc.cbSize = sizeof(WNDCLASSEX);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Example";
wc.hInstance = hInstance;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hbrBackground = (HBRUSH)(BLACK_BRUSH);
wc.lpszMenuName = NULL;

RegisterClassEx(&wc);

hwnd = CreateWindow("Example", "Window Example", WS_OVERLAPPEDWINDOW ,
CW_USEDEFAULT, CW_USEDEFAULT,
300, 300, NULL, NULL, hInstance, NULL);

ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

while (1)
{
if (GetMessage(&msg, NULL, 0, 0) != 0)
{
TranslateMessage(&msg); //Note: You only need this if you handle WM_CHAR or WM_SYSCHAR
DispatchMessage(&msg);

}
else
{
return 0;
}

}


return (int)msg.wParam;

}




Hope that helps (and fixes the issue).

Edit:
GetWindowDC() -- Allows you to draw over the entire window.
GetDC() -- Only allows you to draw over the client area. Which in 90% of cases is what most people want to update. Not many people want to draw pixels over the title bar.
GetDCEx() -- Allows the same as GetDC except you can specify regions and set some flags.

For what you seem to be doing, I highly recommend GetDC(), it will make your life a lot easier, no worrying about offsets and stuff.

Share this post


Link to post
Share on other sites
now I get it, I should leave hDC = BeginPaint(hwnd, &ps); and EndPaint(hwnd,&ps); in WM_PAINT even you draw something outside WM_PAINT right.

Share this post


Link to post
Share on other sites
that would work for most of the things you wanna do , but in some special cases you might wanna change when the WM_Paint occur but thats something else, you must find a way to redraw the Grahpics every time the windwo is resized , Painted , moved etc.. when ever WM_Paint occurs .
hope that helped .

Share this post


Link to post
Share on other sites
Thanks you all for your spend your time to help me :D, I really appropriate that, and HAPPY NEW YEAR

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement