Re: WM_PAINT NON-STOP IN CUSTOM CONTROL



See below...

On Wed, 23 Aug 2006 07:06:02 -0700, Robert <Robert@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:

No, Joseph.. you didn't understand me..

I've done that finally...

The idea that I wanted (do have the solution now) to use MFC (classes)
advantages and still have the ability to create your own custom control (not
owner draw)..
*****
And this is different from what MFC supports naturally in exactly what way?
*****
Custom Control is not well automated in VC MFCDialog application mode.
*****
I can't even parse this sentence. I build custom controls all the time in MFC and haven't
had any problems doing so. What do you mean?
*****

Create a Button, ListBox - not a big deal.. but Custom Control needs some
methodology.
*****
Such as what? Derive from CWnd??? Oh yes, I did that last week. And three times last
month.
*****

That WM_PAINT non-stop - is not HOW WINDOWS WORKS (I have 10 yrs experience
of Windows programming and still don't know how Windows works ;)))..
****
If you don't do the BeginPaint, then WM_PAINT *is* nonstop, and that *is* how Windows
works. In fact, that's how it is *supposed* to work. The rules for WM_PAINT handlers are
very clear.
****

Windows send WM_PAINT when the rectangle needs to be updated..
****
Yes. And BeginPaint says that you've updated it. And you must use the DC from
BeginPaint, not create another gratuitous DC.
****

Non-stop, just because MFC controls all events of application and it is
non-compatible thing to use both own Win Proc Handling and MFC in one MFC
application.
****
This doesn't even make sense. You can create a window with its own window procedure, and
it works quite well with MFC, but you can't treat the window as an MFC class.

In fact, just to demonstrate this is possible, I did it. I spent about 15 minutes typing
it in. It's trivial, it works, and it works within MFC just fine. The window paints
without infinite loops in WM_PAINT just fine.
****

I wanted to use Win 32 programming (Win Proc Handling ) + MFC classes
advantages.. that's the point.......>>!!
****
Fine. And that requires the WM_PAINT handler does a BeginPaint, or you get an infinite
loop of WM_PAINT messages, because that's how Windows is defined to work.
****

It's possible though, and it should be done in a proper order.

Then WM_PAINT comes only once, and mouse events come for sure, and other MFC
classes are incapsulated inside Dialog (in my case) MFC application..
*****
It does seem to be a needlessly complicated way to handle a simple problem. But at no
point have you indicated why you think BeginPaint should be eliminated (this violates
fundamental rules of Windows programming), or justify something as remarkably silly as
putting a Beep(0,n) in to "make it work" (instead of using BeginPaint, which *will* make
it work)

If you wish to know how, tell me by mail and I'll send it to you..

****
How about "I already know how to do it", and here's the code, or at least the relevant
parts. The control c_Frame is a static MFC CStatic control whose sole purpose is to let
me know where I want to put the window I create.

There's nothing particularly difficult here. You can generate an ordinary dialog-based
app and add the code shown below

// WndProcTestDlg.cpp : implementation file

void CWndProcTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_FRAME, c_Frame);
****
This was actually added by ClassWizard, using "Add Variable"
****
}

#define MyWndClassName _T("My Class {6E387F55-AD22-428f-BEAD-541B146AE732}")

// CWndProcTestDlg message handlers

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{ /* msg */
case WM_LBUTTONDOWN:
{ /* change color */
COLORREF color = (COLORREF)::GetWindowLong(hWnd, GWL_USERDATA);
UINT R = GetRValue(color);
UINT G = GetGValue(color);
UINT B = GetBValue(color);
R += 16;
if(R >= 256)
G += 16;
if(G >= 256)
B += 16;
color = RGB(R, G, B);
::SetWindowLong(hWnd, GWL_USERDATA, (LONG)color);
::InvalidateRect(hWnd, NULL, FALSE);
} /* change color */
return 0;
case WM_PAINT:
{ /* paint */
PAINTSTRUCT ps;
HDC dc = ::BeginPaint(hWnd, &ps);
RECT r;
HBRUSH br;
COLORREF color = (COLORREF)::GetWindowLong(hWnd, GWL_USERDATA);
br = ::CreateSolidBrush(color);

int save = ::SaveDC(dc);
::SelectObject(dc, br);
::GetClientRect(hWnd, &r);
::PatBlt(dc, r.left, r.top, r.right, r.bottom, PATCOPY);
::RestoreDC(dc, save);
::EndPaint(hWnd, &ps);
} /* paint */
return 0;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
} /* msg */
} // WndProc


BOOL CWndProcTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();

.... usual OnInitDialog code was here...

// TODO: Add extra initialization here
WNDCLASS wc = {0};
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.hInstance = AfxGetInstanceHandle();
wc.hIcon = NULL;
wc.hCursor = ::LoadCursor(NULL, IDC_HAND);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = MyWndClassName;
VERIFY(::RegisterClass(&wc));

CRect r;
c_Frame.GetWindowRect(&r);
ScreenToClient(&r);
::CreateWindow(MyWndClassName, // class name
NULL, // window name
WS_CHILD | WS_VISIBLE, // style
r.left, r.top, // x, y
r.right - r.left, // width
r.bottom - r.top, // height
m_hWnd, // parent
NULL, // menu
AfxGetInstanceHandle(), // instance handle
NULL); // LPARAM


return TRUE; // return TRUE unless you set the focus to a control
}

So why do you claim you can't mix-and-match ordinary WndProc code and MFC code?
****
Thanks for your site, was interesting to know that you like to compose music..

All the best.
Robert
vitagoni@xxxxxxxxxxxx


"Joseph M. Newcomer" wrote:

That sounds like Windows is working in exactly the way it is designed to work. In fact,
it is following its specifications precisely. If you need to change the image, you have
to call InvalidateRect(NULL) to say that you've changed the image, otherwise there is no
reason for Windows to believe there is any need to repaint anything.

I have no idea what you mean by "sending the message func works OK", but it makes me
suspect you are doing something completely wrong.

The BeginPaint is mandatory.

WM_UPDATE does not exist. There is no such message. Surely you mean WM_PAINT.

And commenting out BeginPaint means that Windows is doing exactly what it is *supposed* to
do, which is to keep sending WM_PAINT messages until somebody redraws the window contents.
Lose the beep. You really need to understand basic Windows programming here.

See below...
On Tue, 22 Aug 2006 20:44:01 -0700, Robert <Robert@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:

Hello Fellas,

With that BeginPaint I have the constantly receiving WM_PAINT's stopped, but
instead of updating whole region when I draw an image, it updates the only
erased rectangles or doesn't update at all if there is no dirty areas, but
the background image already changed and I need it to be full updated!!..
Loading an image function sends just one message to that image win to
WM_UPDATE and the image win callback returns 0, no problem with that
function..
Sending the message func works Ok..

But without BeginPaint it was non-stop update, so I couldn't even move the
window!!

Then I placed Beep function, just to control when the image win receives
WM_UPDATE..

And then suddenly, I commented BeginPaint/End functions and just left only
Beep..

And again I began to hear that beep non-stop again (WM_UPDATE), BUT>>>!!!!!!

Image update and window moving was fine!!!!! it works now good, exactly how
it suppose to.

So, now I placed Beep (0,1) function and no sound and perfect work..

Of course I understand that's stupid and unwell, but what can I do..???

Any Idea??


/*************************************************************/
case WM_PAINT:
// PAINTSTRUCT ps;
// BeginPaint(hwnd, &ps);
*****
hdc = BeginPaint(hwnd, &ps);
****
Beep(0, 1);
****
Lose this completely. It serves no useful purpose.
****

if (hImage != NULL)
{
HDC tmpDC;
hdc = GetDC(hwnd);
****
Lose the GetDC. You already have the correct DC from BeginPaint. This code is wrong
****
tmpDC = CreateCompatibleDC(hdc); //
GetWindowRect(hwnd, &rct);
SelectObject(tmpDC, hImage);

BitBlt(hdc, 0, 0, rct.right, rct.bottom, tmpDC, 0, 0, SRCCOPY);

DeleteDC(tmpDC);
ReleaseDC(hwnd, hdc);
****
Since the GetDC is gone, lose the ReleaseDC as well
****
}

// EndPaint(hwnd, &ps);
return 0;


Joseph M. Newcomer [MVP]
email: newcomer@xxxxxxxxxxxx
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Joseph M. Newcomer [MVP]
email: newcomer@xxxxxxxxxxxx
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
.


Loading