🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.nativeapi
7 messages
7 total messages Started by JD Sat, 22 Apr 2006 10:06
WM_MOUSEMOVE
#3856
Author: JD
Date: Sat, 22 Apr 2006 10:06
132 lines
5713 bytes
I've subclassed a ListView's Header WndProc and the problem I'm
having is (I think) with WM_MOUSEMOVE. More specifically, when
moving the mouse over any of the Column's right boundry, the
cursor changes to crSizeAll and I don't get how because I'm not
passing on the message for processing.

How does it know to change the cursor and how can I change this
behavior?

Minimal sample:

#include "MyListView.h"
//--------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
    new TMyListView( this );
}
//--------------------------------------------------------------


//--------------------------------------------------------------
#ifndef MyListViewH
#define MyListViewH
//--------------------------------------------------------------
#include <Classes.hpp>
#include <ComCtrls.hpp>
//--------------------------------------------------------------
#ifdef STRICT
#define HEADERWNDPROC WNDPROC
#else
#define HEADERWNDPROC FARPROC
#endif
//--------------------------------------------------------------
class TMyListView : public TListView
{
    private:
        typedef TListView inherited;
        HWND hHeader;
        LONG HeaderWndProcPtr;
        HEADERWNDPROC OldHeaderWndProc;
        void  __fastcall HeaderWndProc( TMessage &Message );
        void  __fastcall SubclassHeaderWndProc();
        void  __fastcall HeaderMouseMove( TShiftState Shift, int X, int Y );
        MESSAGE void __fastcall CMRecreateWnd( TMessage &Message );
    public:
        BEGIN_MESSAGE_MAP
            VCL_MESSAGE_HANDLER( CM_RECREATEWND, TMessage, CMRecreateWnd )
        END_MESSAGE_MAP( inherited )
    public:
        __fastcall  TMyListView( TComponent* Owner );
        __fastcall ~TMyListView();
};
//--------------------------------------------------------------
#endif

//--------------------------------------------------------------
#pragma hdrstop
#include "MyListView.h"
#include "shlwapi.h"
#pragma package(smart_init)
//--------------------------------------------------------------
__fastcall TMyListView::TMyListView(TComponent* Owner) : TListView( Owner )
{
    Parent = dynamic_cast<TWinControl*>( Owner );
    Align = alClient;
    ShowColumnHeaders = true;
    ViewStyle = vsReport;

    TListColumn *pColumn;
    for( int x = 0; x < 3; ++x )
      {
          pColumn = Columns->Add();
          pColumn->Caption = "Column " + IntToStr(x);
          pColumn->Width   = (Width - 20) / 3;
      }

    TListItem *pItem;
    for( int x = 0; x < 3; ++x )
      {
          pItem = Items->Add();
          pItem->Caption = "Col " + IntToStr(0) + " ,Row " + IntToStr(x);
          for( int y = 0; y < Columns->Count; ++y )
            {
                pItem->SubItems->Add("Col " + IntToStr(y+1) + " ,Row " + IntToStr(x));
            }
      }

    HeaderWndProcPtr = reinterpret_cast<LONG>( MakeObjectInstance(HeaderWndProc) );
    SubclassHeaderWndProc();
}
//--------------------------------------------------------------
__fastcall TMyListView::~TMyListView()
{
    if( hHeader ) ::SetWindowLong( hHeader, GWL_WNDPROC, reinterpret_cast<LONG>(OldHeaderWndProc) );
    FreeObjectInstance( reinterpret_cast<void*>(HeaderWndProcPtr) );
}
//--------------------------------------------------------------
MESSAGE void __fastcall TMyListView::CMRecreateWnd( TMessage &Message )
{
    inherited::Dispatch( &Message );
    SubclassHeaderWndProc();
}
//--------------------------------------------------------------
void __fastcall TMyListView::SubclassHeaderWndProc()
{
    hHeader = ListView_GetHeader( Handle );
    if( hHeader ) OldHeaderWndProc = reinterpret_cast<HEADERWNDPROC>( ::SetWindowLong(hHeader, GWL_WNDPROC, HeaderWndProcPtr) );
}
//--------------------------------------------------------------
void __fastcall TMyListView::HeaderWndProc( TMessage &Message )
{
    switch( Message.Msg )
      {
          case   WM_MOUSEMOVE: HeaderMouseMove( KeysToShiftState(Message.WParam), LOWORD(Message.LParam), HIWORD(Message.LParam) );
                               Message.Result = 0;
                               return;
          case     WM_DESTROY: Message.Result = ::CallWindowProc(OldHeaderWndProc, hHeader, Message.Msg, Message.WParam, Message.LParam );
                               ::SetWindowLong( hHeader, GWL_WNDPROC, reinterpret_cast<LONG>(OldHeaderWndProc) );
                               hHeader = NULL;
                               return;
      }
    Message.Result = ::CallWindowProc( OldHeaderWndProc, hHeader, Message.Msg, Message.WParam, Message.LParam );
}
//--------------------------------------------------------------
void __fastcall TMyListView::HeaderMouseMove( TShiftState Shift, int X, int Y )
{
    //
}
//--------------------------------------------------------------

~ JD
Re: WM_MOUSEMOVE
#3857
Author: JD
Date: Sat, 22 Apr 2006 11:25
8 lines
953 bytes
"JD" <nospam@nospam.com> wrote:
>
> [...] (I think) with WM_MOUSEMOVE.

I should have been looking for is WM_SETCURSOR.

~ JD
Re: WM_MOUSEMOVE
#3792
Author: Remy Lebeau (TeamB)
Date: Mon, 24 Apr 2006 18:57
156 lines
5974 bytes
"JD" <nospam@nospam.com> wrote in message
news:444a0026$1@newsgroups.borland.com...

> Minimal sample:

Just an FYI, since you are now using a descendant class to manage the
subclassing, you can do so much more efficiently by not intercepting the
CM_RECREATEWND message at all.  Use the virtual CreateWnd() and DestroyWnd()
methods instead.  For example:


    --- Unit1.cpp ---

    #include "MyListView.h"

    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
        TMyListView *lv = new TMyListView(this);
        lv->Parent = this;
        lv->Align = alClient;

        TListColumn *pColumn;
        for(int x = 0; x < 3; ++x)
        {
            pColumn = lv->Columns->Add();
            pColumn->Caption = "Column " + IntToStr(x);
            pColumn->Width = (lv->Width - 20) / 3;
        }

        TListItem *pItem;
        for(int x = 0; x < 3; ++x)
        {
            pItem = lv->Items->Add();
            pItem->Caption = "Col " + IntToStr(0) + ", Row " + IntToStr(x);
            for(int y = 0; y < lv->Columns->Count; ++y)
                pItem->SubItems->Add("Col " + IntToStr(y+1) + ", Row " +
IntToStr(x));
        }
    }


    --- MyListView.h ---

    //--------------------------------------------------------------
    #ifndef MyListViewH
    #define MyListViewH
    //--------------------------------------------------------------
    #include <Classes.hpp>
    #include <ComCtrls.hpp>
    //--------------------------------------------------------------
    #ifdef STRICT
    #define HEADERWNDPROC WNDPROC
    #else
    #define HEADERWNDPROC FARPROC
    #endif
    //--------------------------------------------------------------
    class TMyListView : public TListView
    {
        typedef TListView inherited;
    private:
        HWND hHeader;
        LONG HeaderWndProcPtr;
        HEADERWNDPROC OldHeaderWndProc;
        void  __fastcall HeaderWndProc(TMessage &Message);
    protected:
        virtual void __fastcall CreateWnd();
        virtual void __fastcall DestroyWnd();
        virtual void  __fastcall HeaderMouseMove(TShiftState Shift, int X,
int Y);
    public:
        __fastcall  TMyListView(TComponent* Owner);
        __fastcall ~TMyListView();
    };
    //--------------------------------------------------------------
    #endif

    //--------------------------------------------------------------
    #pragma hdrstop
    #include "MyListView.h"
    #include "shlwapi.h"
    #pragma package(smart_init)
    //--------------------------------------------------------------
    __fastcall TMyListView::TMyListView(TComponent* Owner)
        : TListView(Owner)
    {
        ShowColumnHeaders = true;
        ViewStyle = vsReport;
        HeaderWndProcPtr =
reinterpret_cast<LONG>(MakeObjectInstance(HeaderWndProc));
    }
    //--------------------------------------------------------------
    __fastcall TMyListView::~TMyListView()
    {
        FreeObjectInstance(reinterpret_cast<void*>(HeaderWndProcPtr));
    }
    //--------------------------------------------------------------
    void __fastcall TMyListView::CreateWnd()
    {
        inherited::CreateWnd();
        if( HandleAllocated() )
        {
            hHeader = ListView_GetHeader(Handle);
            if( hHeader )
                OldHeaderWndProc =
reinterpret_cast<HEADERWNDPROC>(::SetWindowLong(hHeader, GWL_WNDPROC,
HeaderWndProcPtr));
        }
    }
    //--------------------------------------------------------------
    void __fastcall TMyListView::DestroyWnd()
    {
        if( hHeader )
        {
            ::SetWindowLong(hHeader, GWL_WNDPROC,
reinterpret_cast<LONG>(OldHeaderWndProc));
            hHeader = NULL;
            OldHeaderWndProc = NULL;
        }
        inherited::DestroyWnd();
    }
    //--------------------------------------------------------------
    void __fastcall TMyListView::HeaderWndProc(TMessage &Message)
    {
        switch( Message.Msg )
        {
            case WM_MOUSEMOVE:
                HeaderMouseMove(KeysToShiftState(Message.WParam),
LOWORD(Message.LParam), HIWORD(Message.LParam));
                Message.Result = 0;
                break;
            case WM_DESTROY:
                ::SetWindowLong(hHeader, GWL_WNDPROC,
reinterpret_cast<LONG>(OldHeaderWndProc));
                Message.Result = ::CallWindowProc(OldHeaderWndProc, hHeader,
Message.Msg, Message.WParam, Message.LParam);
                hHeader = NULL;
                OldHeaderWndProc = NULL;
                break;
            default:
                Message.Result = ::CallWindowProc(OldHeaderWndProc, hHeader,
Message.Msg, Message.WParam, Message.LParam);
                break;
        }
    }
    //--------------------------------------------------------------
    void __fastcall TMyListView::HeaderMouseMove(TShiftState Shift, int X,
int Y)
    {
        //
    }
    //--------------------------------------------------------------


Gambit
Re: WM_MOUSEMOVE
#3805
Author: JD
Date: Tue, 25 Apr 2006 11:31
12 lines
1232 bytes
"Remy Lebeau \(TeamB\)" <no.spam@no.spam.com> wrote:
>
> [...] since you are now using a descendant [...] Use the
> virtual CreateWnd() and DestroyWnd() methods instead.

Believe it or not, that *was* on my to-do list! Thanks for the
sample. Now it's just cut-n-paste.

OT: Are you aware of any bugs with the underlying MS ListView?

~ JD
Re: WM_MOUSEMOVE
#3809
Author: Remy Lebeau (TeamB)
Date: Tue, 25 Apr 2006 16:58
10 lines
1137 bytes
"JD" <nospam@nospam.com> wrote in message
news:444e08a0$1@newsgroups.borland.com...

> Are you aware of any bugs with the underlying MS ListView?

In what regards?


Gambit
Re: WM_MOUSEMOVE
#3823
Author: JD
Date: Thu, 27 Apr 2006 12:30
37 lines
2307 bytes
"Remy Lebeau \(TeamB\)" <no.spam@no.spam.com> wrote:
>
>> Are you aware of any bugs with the underlying MS ListView?
>
>In what regards?

Any in general but I asked because of this:

    http://tinyurl.com/zyjue

Some one was using a sample by Damon Chandler that pre-dated
XP and it exposed a problem when the ListView was themed. I
was able to determine that when theming was enabled, the OS
was sending WM_NOTIFY messages that it didn't send when
theming was not enabled.

When ever the code member of the LPNMHDR structure that
accompanies the WM_NOTIFY message was 0xFFFFFDEE, it caused
the control to generate a superfluous OnCustomDraw event.

I searched msdn to try to determine what was happening and
what 0xFFFFFDEE is intended for but came up empty so my
suggestion to the OP was that my best guess was that it
was ok to just swallow that message.

This leads me to believe that the underlying ListView has not
been brought up to date with the advent of XP or perhaps it's
a bug with the control. In this particular case, since I'm
doing all of the drawing, I can disable theming for the control
but where there's one bug, there's sure to be more and I just
don't want to run into a wall later.

I also don't want to be painting and repainting when it isn't
needed which is what the above was causing.

~ JD
Re: WM_MOUSEMOVE
#3828
Author: Remy Lebeau (TeamB)
Date: Thu, 27 Apr 2006 17:26
15 lines
1408 bytes
"JD" <nospam@nospam.com> wrote in message
news:4450b969$1@newsgroups.borland.com...

> When ever the code member of the LPNMHDR structure that
> accompanies the WM_NOTIFY message was 0xFFFFFDEE,
> it caused the control to generate a superfluous OnCustomDraw event.

0xFFFFFDEE is TTN_GETDISPINFOW:


http://msdn.microsoft.com/library/en-us/shellcc/platform/commctls/tooltip/notifications/ttn_getdispinfo.asp


Gambit
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads