 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
JD Guest
|
Posted: Fri Apr 14, 2006 11:03 pm Post subject: Subclassing WndProc and CM_RECREATEWND |
|
|
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
|
Posted: Sat Apr 15, 2006 12:03 am Post subject: Re: Subclassing WndProc and CM_RECREATEWND |
|
|
"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
|
Posted: Sat Apr 15, 2006 3:03 am Post subject: Re: Subclassing WndProc and CM_RECREATEWND |
|
|
"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
|
Posted: Sat Apr 15, 2006 9:03 am Post subject: Re: Subclassing WndProc and CM_RECREATEWND |
|
|
"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
|
Posted: Mon Apr 17, 2006 7:03 pm Post subject: Re: Subclassing WndProc and CM_RECREATEWND |
|
|
"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
|
Posted: Tue Apr 18, 2006 5:03 am Post subject: Re: Subclassing WndProc and CM_RECREATEWND |
|
|
"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 |
|
 |
|
|
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
|
|