질문란에 올렸다가 좀 더 쉽게 메시지를 처리하고자 작성해본 소스입니다.
뭐 원리는 간단합니다.
각각의 컴포넌트에 해당 메시지 처리기를 등록하는 방법입니다.
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);
}
//---------------------------------------------------------------------------
|