C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[66] 폼에 속한 컴포넌트들의 메시지 처리하기
pulyip [] 8368 읽음    2000-08-07 00:00
질문란에 올렸다가 좀 더 쉽게 메시지를 처리하고자 작성해본 소스입니다.

뭐 원리는 간단합니다.

각각의 컴포넌트에 해당 메시지 처리기를 등록하는 방법입니다.

TListView --| (등록)
            |
            v
        HandlerSet

구현은 Q&A란에서 임프님이 답변하신 방법대로 GetWindowLong, SetWindowLong으로 기본

메시지 핸들러를 바꿔서 처리하는 방식입니다.(--; 넘 간단하죠... 원래 원리야 뭐...헤헤)

등록한 컴포넌트로부터 WM_xxx 메시지 발생. --> HandlerSet::WndProc(HWND hWnd, ....) -->

--> 해당 HandlerSet을 찾은후 --> (해당 메시지핸들러가 등록돼 있으면: 해당 핸들러실행)
                             --> ( 미 등록시: 원래의 처리함수(WndProc)실행)


근데 좀 불편한게 ... Class Explorer를 사용해서 메시지 핸들러를 삽입하면... 자동으로

해당 메시지에 핸들러가 불리지만... 이 경우는 본인이 직접 메시지핸들러(함수)를

컴포넌트 핸들러에 등록해 줘야 합니다. 어떤 스크립트 기능이 있음 좋은텐데요.. ^^;

뭘 잘 몰라서... 그것 까진...

암튼 C++Builder가
     BEGIN_MESSAGE_MAP
         VCL_MESSAGE_HANDLER(WM_DROPFILES, TMessage, WMDropFiles)
     END_MESSAGE_MAP(TListView)

자동 삽입하는 대신에... 본인이 직접
    aHandlerSet.RegisterMessage(WM_DROPFILE, WMDropFiles)
를 해 줘야 합니다..

아래는 코드입니다.
/*
Message Handler prototype :
    typedef void __fastcall (__closure *FnEventHandler)
        (System::TObject* Sender, TMessage &msg);

    RegisterHandlerSet( HandlerSet *); 새로운 메시지 핸들러에 연결.
    UnRegisterHandlerSet( HandlerSet *pHS); 기본 메시지 핸들러에 연결.

    HandlerSet(TWinControl *widget); 메시지처리 대상위젯으로 생성.
    SetWidget(TWinControl *widget);

    RegisterMessage(Cardinal msgID, FnEventHandler handler);
        msgID: 윈도우 메시지.
        handler: 핸들러 메소드.
    UnRegisterMessage(Cardinal msgID);
    void UnRegisterMessageAll(Cardinal msgID);


*/

HandlerSet.h
//---------------------------------------------------------------------------
#ifndef HandlerSetH
#define HandlerSetH
#include <vcl.h>
#include <map>

typedef void __fastcall (__closure *FnEventHandler)
    (System::TObject* Sender, TMessage &msg);

class HandlerSet
{
public:
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    static void __fastcall RegisterHandlerSet  ( HandlerSet *pHS);
    static void __fastcall UnRegisterHandlerSet( HandlerSet *pHS);

public:
    HandlerSet(TWinControl *widget);
    virtual ~HandlerSet();

    void RegisterMessage(Cardinal msgID, FnEventHandler handler);
    void UnRegisterMessage(Cardinal msgID);
    void UnRegisterMessageAll(Cardinal msgID);

    void SetWidget(TWinControl *widget);
    TWinControl * GetWidget() { return FWidget;}

protected:
typedef    std::map<Cardinal, FnEventHandler>     WndProcMap;
    TWinControl  *FWidget;
    WNDPROC FOrgWndProc;
    WndProcMap     _WndProcMap;

protected:
typedef std::map<HWND, HandlerSet*>            HandlerSetMap;
    static HandlerSetMap    _HandlerSetMap;
};
//---------------------------------------------------------------------------
#endif

HandlerSet.cpp
#include <vcl.h>
#pragma hdrstop

#include "HandlerSet.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

std::map<HWND, HandlerSet*>        HandlerSet::_HandlerSetMap;

//////////////////////////////////////////////////////////////////////
// Widget WndProc Method
LRESULT CALLBACK HandlerSet::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HandlerSet *pSet = _HandlerSetMap[hWnd];
    if( !pSet )
    {
        AnsiString msg("NULL HandlerSet of ");
        msg.sprintf("%p", hWnd);
        throw Exception( msg );
    }

    WndProcMap::iterator pos = pSet->_WndProcMap.find(uMsg);
    if( pos != pSet->_WndProcMap.end() ) {
        FnEventHandler Handler = pos->second;
        TMessage msg = { uMsg, };
        msg.WParam = wParam;
        msg.LParam = lParam;
        Handler(pSet->FWidget, msg);
        return 0L;
    }

    return pSet->FOrgWndProc(hWnd, uMsg, wParam, lParam);
}

//////////////////////////////////////////////////////////////////////
// [Un]Register HandlerSet
void __fastcall HandlerSet::RegisterHandlerSet( HandlerSet *pHS)
{
    if( !pHS) return ;
    HandlerSetMap::iterator pos = _HandlerSetMap.find(pHS->FWidget->Handle);
    if( pos != _HandlerSetMap.end() )
    {
        return ; //already registered..
    }
    _HandlerSetMap[pHS->FWidget->Handle] = pHS;
    pHS->FOrgWndProc = (WNDPROC)::GetWindowLong(pHS->FWidget->Handle, GWL_WNDPROC);
    ::SetWindowLong(pHS->FWidget->Handle, GWL_WNDPROC, (LONG)WndProc);
}
void __fastcall HandlerSet::UnRegisterHandlerSet( HandlerSet *pHS)
{
    if( !pHS ) return ;
    HandlerSetMap::iterator pos = _HandlerSetMap.find(pHS->FWidget->Handle);
    if( pos == _HandlerSetMap.end() )
    {
        return ; //already unregistered..
    }
    ::SetWindowLong(pHS->FWidget->Handle, GWL_WNDPROC, (LONG)pHS->FOrgWndProc);
    _HandlerSetMap.erase(pos);
    pHS->FOrgWndProc = NULL;
}

//////////////////////////////////////////////////////////////////////
// Con/Destructor
HandlerSet::HandlerSet(TWinControl *widget)
{
    SetWidget(widget);
    FOrgWndProc = NULL;
}

HandlerSet::~HandlerSet()
{
    if( !FOrgWndProc ) return ;
   ::SetWindowLong(FWidget->Handle, GWL_WNDPROC, (LONG)FOrgWndProc);
}

//////////////////////////////////////////////////////////////////////
// [Un]Register Message
void HandlerSet::RegisterMessage(Cardinal msgID, FnEventHandler handler)
{
    _WndProcMap[msgID] = handler;//Duplicated...
}

void HandlerSet::UnRegisterMessage(Cardinal msgID)
{
    WndProcMap::iterator pos = _WndProcMap.find(msgID);
    if( pos != _WndProcMap.end() ) _WndProcMap.erase(msgID);
}
void HandlerSet::UnRegisterMessageAll(Cardinal msgID)
{
    _WndProcMap.clear();
}

//////////////////////////////////////////////////////////////////////
// Interface
void HandlerSet::SetWidget(TWinControl *widget)
{
    FWidget = widget;
}




HandlerSet *pPanelHandler = NULL;
HandlerSet *pEditHandler = NULL;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    if( !pPanelHandler ) pPanelHandler = new HandlerSet(Panel1);
    if( !pEditHandler ) pEditHandler = new HandlerSet(Edit1);
    pPanelHandler->RegisterMessage(WM_DROPFILES, OnDropFiles);
    pEditHandler->RegisterMessage(WM_SETFOCUS, OnSetFocus);
    pEditHandler->RegisterMessage(WM_KILLFOCUS, OnKillFocus);

    HandlerSet::RegisterHandlerSet(pPanelHandler);
    HandlerSet::RegisterHandlerSet(pEditHandler);
    Button1->Visible = false;
    Button2->Visible = true;
}
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    HandlerSet::UnRegisterHandlerSet(pPanelHandler);
    HandlerSet::UnRegisterHandlerSet(pEditHandler);
    delete pPanelHandler;    pPanelHandler = NULL;
    delete pEditHandler;    pEditHandler = NULL;
    Button1->Visible = true;
    Button2->Visible = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnDropFiles(TObject * Sender, TMessage & msg)
{
    TPanel *Pnl = (TPanel*)Sender;

    char szFile[MAX_PATH+1];
    ::DragQueryFile( (HDROP)msg.WParam, 0, szFile, MAX_PATH);

    AnsiString sFile(szFile);
    int iPos = sFile.LastDelimiter( AnsiString("\\") );

    Pnl->Caption = "Dropped File: "
        + sFile.SubString(iPos+1, sFile.Length()-iPos);
}

void __fastcall TForm1::OnSetFocus(TObject * Sender, TMessage & msg)
{
    TEdit *pEdt = (TEdit*)Sender;
    pEdt->Text = "WM_SETFOCUS";
}

void __fastcall TForm1::OnKillFocus(TObject * Sender, TMessage & msg)
{
    TEdit *pEdt = (TEdit*)Sender;
    pEdt->Text = "WM_KILLFOCUS";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    ::DragAcceptFiles( Panel1->Handle, true);
}
//---------------------------------------------------------------------------

+ -

관련 글 리스트
66 폼에 속한 컴포넌트들의 메시지 처리하기 pulyip 8368 2000/08/07
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.