BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Subclassing WndProc and CM_RECREATEWND

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (VCL Components Usage)
View previous topic :: View next topic  
Author Message
JD
Guest





PostPosted: Fri Apr 14, 2006 11:03 pm    Post subject: Subclassing WndProc and CM_RECREATEWND Reply with quote



I'm subclassing the WndProc for a TListView's Header:

HWND hHandle;
FARPROC NewHeaderWndProc;
FARPROC OldHeaderWndProc;
void __fastcall HeaderWndProc( TMessage &Message );

hHandle = reinterpret_cast<HWND>( ::SendMessage(ListView1->Handle, LVM_GETHEADER, 0, 0) );
NewHeaderWndProc = reinterpret_cast<FARPROC>( MakeObjectInstance(HeaderWndProc) );
OldHeaderWndProc = reinterpret_cast<FARPROC>( ::SetWindowLong(hHandle, GWL_WNDPROC, reinterpret_cast<LONG>(NewHeaderWndProc)) );

My questions are about how to handle if and when the HWND is
ever recreated.

Do I simply just make another call to SetWindowLong as I did
above?

Will the Header be sent CM_RECREATEWND as well as the ListView?

~ JD
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Sat Apr 15, 2006 12:03 am    Post subject: Re: Subclassing WndProc and CM_RECREATEWND Reply with quote



"JD" <nospam (AT) nospam (DOT) com> wrote in message
news:44402056$1 (AT) newsgroups (DOT) borland.com...

Quote:
Will the Header be sent CM_RECREATEWND as well as the ListView?

No, because the header is not mananged by the VCL at all. It is managed
only by the Win32 API directly, as an internal child of the ListView window.
If the ListView HWND is created, it will automatically free the header
window as well. You have to catch the CM_RECREATEWND message by subclassing
the TListView itself instead.


Gambit
Back to top
JD
Guest





PostPosted: Sat Apr 15, 2006 3:03 am    Post subject: Re: Subclassing WndProc and CM_RECREATEWND Reply with quote



"Remy Lebeau \(TeamB\)" <no.spam (AT) no (DOT) spam.com> wrote:
Quote:

[...] If the ListView HWND is created, it will automatically
free the header window as well. You have to catch the
CM_RECREATEWND message by subclassing the TListView itself
instead.

I can't get the logic down. At what point do I need to restore
the Header's WndProc and then when can I subclass it again?

~ JD
Back to top
JD
Guest





PostPosted: Sat Apr 15, 2006 9:03 am    Post subject: Re: Subclassing WndProc and CM_RECREATEWND Reply with quote

"JD" <nospam (AT) nospam (DOT) com> wrote:
Quote:

I can't get the logic down. [...]

This is what I did. Are there any problems with it?

//-------------------------------------------------------------
void __fastcall TForm1::HeaderWndProc( TMessage &Message )
{
if( Message.Msg == WM_DESTROY )
{
::SetWindowLong( hHeader, GWL_WNDPROC, reinterpret_cast<LONG>(OldHeaderWndProc) );
FreeObjectInstance( NewHeaderWndProc );
}
Message.Result = ::CallWindowProc( OldHeaderWndProc, hHeader, Message.Msg, Message.WParam, Message.LParam );
}
//-------------------------------------------------------------
void __fastcall TForm1::NewListViewWndProc( TMessage &Message )
{
if( Message.Msg == WM_DESTROY )
{
Destroying = true;
ListView1->WindowProc = OldListViewWndProc;
}
else if( Message.Msg == CM_RECREATEWND )
{
hHeader = reinterpret_cast<HWND>( ::SendMessage(ListView1->Handle, LVM_GETHEADER, 0, 0) );
NewHeaderWndProc = reinterpret_cast<FARPROC>( MakeObjectInstance(HeaderWndProc) );
OldHeaderWndProc = reinterpret_cast<FARPROC>( ::SetWindowLong(hHeader, GWL_WNDPROC, reinterpret_cast<LONG>(NewHeaderWndProc)) );
}
OldListViewWndProc( Message );
}
//-------------------------------------------------------------

~ JD
Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Mon Apr 17, 2006 7:03 pm    Post subject: Re: Subclassing WndProc and CM_RECREATEWND Reply with quote

"JD" <nospam (AT) nospam (DOT) com> wrote in message
news:4440aed4$1 (AT) newsgroups (DOT) borland.com...

Quote:
This is what I did. Are there any problems with it?

Yes. Your handling of the CM_RECREATEWND message is wrong. You need to
pass the CM_RECREATEWND message to the default handler *before* you can
subclass the new header HWND. It is during TListView's default handling of
that message that the current HWNDs get destroyed and reallocated. You are
calling the default handler *after* subclassing the header HWND, so you are
going to subclass the HWND that you already subclassed (and thus lose your
pointer to the original window procedure) and ignore the new HWND
completely.

Try this instead:

#ifdef STRICT
#define MYWNDPROC WNDPROC
#else
#define MYWNDPROC FARPROC
#endif

class TForm1 : public TForm
{
private:
HWND hHeader;
LONG HeaderWndProcPtr;
MYWNDPROC OldHeaderWndProc;
TWndMethod OldListViewWndProc;
void __fastcall HeaderWndProc(TMessage &Message);
void __fastcall ListViewWndProc(TMessage &Message);
//...
};

__fastcall TForm1::TForm1(TComponent *Owner)
: TForm(Owner)
{
HeaderWndProcPtr =
reinterpret_cast<LONG>(MakeObjectInstance(HeaderWndProc));
OldListViewWndProc = ListView1->WindowProc;
ListView1->WindowProc = ListViewWndProc;
}

__fastcall TForm1::~TForm1()
{
if( hHeader )
{
::SetWindowLong(hHeader, GWL_WNDPROC,
reinterpret_cast<LONG>(OldHeaderWndProc));
hHeader = NULL;
}
ListView1->WindowProc = OldListViewWndProc;
FreeObjectInstance(reinterpret_cast<void*>(HeaderWndProcPtr));
}

void __fastcall TForm1::HeaderWndProc(TMessage &Message)
{
Message.Result = ::CallWindowProc(OldHeaderWndProc, hHeader,
Message.Msg, Message.WParam, Message.LParam);
if( Message.Msg == WM_DESTROY )
{
::SetWindowLong(hHeader, GWL_WNDPROC,
reinterpret_cast<LONG>(OldHeaderWndProc));
hHeader = NULL;
}
}

void __fastcall TForm1::ListViewWndProc(TMessage &Message)
{
OldListViewWndProc(Message);

if( Message.Msg == CM_RECREATEWND )
{
hHeader = ListView_GetHeader(ListView1->Handle);
if( hHeader )
OldHeaderWndProc =
reinterpret_cast<MYWNDPROC>(::SetWindowLong(hHeader, GWL_WNDPROC,
HeaderWndProcPtr));
}
}


Gambit
Back to top
JD
Guest





PostPosted: Tue Apr 18, 2006 5:03 am    Post subject: Re: Subclassing WndProc and CM_RECREATEWND Reply with quote

"Remy Lebeau \(TeamB\)" <no.spam (AT) no (DOT) spam.com> wrote:
Quote:

Your handling of the CM_RECREATEWND message is wrong.
You need to pass the CM_RECREATEWND message to the default
handler *before* you can subclass the new header HWND. [...]

Makes perfect sense now! Thanks.

~ JD
Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (VCL Components Usage) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.