Default for WM_SETTEXT is if there is no handler at all. If you add a
or DefWindowProc. In general, these are the decisions you have to make when
change that fact. I don't understand the point of bringing
takes an HWND not a WNDPROC. Doesn't that just lead directly back to your
"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message
The key problem is that it ends up calling Default(), instead of handing
it implicitly by
calling DefWindowProc with the correct parameters. The catch here is that
unlike the
windowsx.h handlers, where you can write FORWARD_WM_SETTEXT(oldwndproc,
lParam), you have
to magically "know" that the object has been subclassed, but you can't
hijack the
upper-level class, which just calls Default().
The argument given was that this was "to reduce the size of the MFC
runtime". It seems a
remarkably silly reason for making such an egregious error.
The bool member flag ("Am I sending a message to myself?") is one of the
workarounds, one
that I have used in the past. What is amazing is the number of horrendous
kludges we have
to do to work around the design flaw in MFC that reuses the incoming
parameters instead of
allowing us to supply the parameters in the superclass call (which is
certainly consistent
with the OO inheritance model)
Part of the reason that the superclass shouldn't make the call itself is
that this week it
is a subclass of CEdit, but next week I might want to split another
superclass in above
it. Finding DefWindowProc calls is not obvious in such code refactoring.
My spin control solution doesn't use set-buddy-integer, so there wouldn't
be a second
WM_SETTEXT. However, it has other problems, such as wanting to call the
correct SetText
method of the buddy. Since these are not virtual methods, it has to know
the type of the
buddy to get the right method, a real violation of modularity.
Bottom line: none of the solutions are terribly good, each have some
defect or other. Mine
solves one set of problems while introducing a different set, but the
problems it solved
were the ones I needed to solve. The correct solution would involve a
buddy notification
and/or getting rid of the design flaw in MFC that reuses the original
parameters. The
latter would be a good idea anyway.
joe
On Thu, 13 Jul 2006 02:07:11 -0500, "Jeff Partch" <jeffp@mvps.org> wrote:
"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message
news:0auab218hbltneuuf1ssd8ub9prt55m81i@4ax.com...
LRESULT CMyControl::OnSetText(WPARAM, LPARAM lParam)
{
CString s;
// format s for the desired state
return CMyParent::OnSetText(0, (LPARAM)(LPCTSTR)s);
}
This is what I should be able to write. But of course, due to terminal
brain death of
some MFC designer, this cannot possibly work. So one idea is
******
With three exceptions: COleControl, CMiniFrameWnd and CStatusBar, I
believe
that the MFC designer has otherwise all but ignored the existance of
WM_SETTEXT. Is your complaint here that there is no OnSetText? Or that if
there were it would probably end up calling Default?
******
LRESULT CMyControl::OnSetText(WPARAM, LPARAM lParam)
{
CString s;
// format s for the desired state
return SendMessage(WM_SETTEXT, 0, (LPARAM)(LPCTSTR)s);
}
of course, this generates an infinitely recrusive loop so I get a stack
overflow.
******
Yes it would, but isn't the solution only a bool member flag?
******
LRESULT CMyControl::OnSetText(WPARAM, LPARAM lParam)
{
CString s;
// format s
DefWindowProc(m_hWnd, WM_SETTEXT, 0, (LPARAM)(LPCSTR)s);
}
works, but if CMyControl is a subclass of CMyBetterEdit, which is a
subclass of
CMyCoolEdit, then DefWindowProc bypasses everything.
******
Couldn't your CMyCoolEdit make the DefWindowProc call?
LRESULT CMyCoolEdit::OnSetText(WPARAM, LPARAM lParam)
{
CString s;
// format s
DefWindowProc(WM_SETTEXT, 0, (LPARAM)(LPCSTR)s);
}
LRESULT CMyBetterEdit::OnSetText(WPARAM, LPARAM lParam)
{
CString s;
// format s
return CMyCoolEdit::OnSetText(0, (LPARAM)(LPCTSTR)s);
}
LRESULT CMyControl::OnSetText(WPARAM, LPARAM lParam)
{
CString s;
// format s
return CMyBetterEdit::OnSetText(0, (LPARAM)(LPCTSTR)s);
}
Or somesuch. We could both of us come up with a better implementation I
reckon.
******
OTOH, if I had a "buddy notification" message, I could do
void CMyControl::OnBuddySet(CSpinButtonCtrl * buddy)
{
int n = buddy->GetPos();
double f = (double)n / 100.0;
// format f as appropriate
SetWindowText(s); // update the text
}
where the default handler in the edit control would be to format the
position as an
integer and setting the text. By overriding that, I get the behavior I
want. But this
isn't how it was done.
******
I thought your original contention was that it sent its buddy no messages
at
all. I see now that your complaint was that it didn't send it the message
you want it to. Sorry.
******
(have you noticed that spin buttons can also work with list boxes and
combo boxes? And it
doesn't do a WM_SETTEXT)
******
I knew it did a test for a WC_LISTBOX buddy and sent it an LB_SETCURSEL
and
LB_GETCURSEL (as well as sending the parent an LBN_SELCHANGE) instead. I
chose to ignore it as an extraneous corner case, but see that was probably
a
mistake. I did not know it did anything special for a WC_COMBOBOX.
******
/////////////////////////////////////////////////////////////////////////////
// CScaledSpinCtrl message handlers
void CScaledSpinCtrl::OnDeltapos(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
PostMessage(UWM_UPDATE_BUDDY);
*pResult = 0;
}
/****************************************************************************
* CScaledSpinCtrl::OnUpdateBuddy
* Inputs:
* WPARAM: ignored
* LPARAM: ignored
* Result: LRESULT
* Logically void, 0, always
* Effect:
* Updates the buddy control
****************************************************************************/
LRESULT CScaledSpinCtrl::OnUpdateBuddy(WPARAM, LPARAM)
{
CFloatingEdit * buddy = (CFloatingEdit *)GetBuddy();
if(buddy == NULL)
return 0;
double d = GetPos(); //
REQ
#209
CString s;
s.Format(fmt, d);
CString old;
buddy->GetWindowText(old);
if(s != old)
buddy->SetWindowText(s);
return 0;
} // CScaledSpinCtrl::OnUpdateBuddy
******
While this is probably neither here nor there in the great scheme of
things,
I suspect that by the time this handler returns your buddy has received
two
WM_SETTEXT and two WM_GETTEXT messages. Anyway, what would you do here
when
your CBetterScaledSpinCtrl wanted to process this message and pass it on
to
its base?
******
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm