2011년 3월 15일 화요일

폼에 마우스 이벤트 통과시키기

알송을 보면 폼 위에서 클릭을 해도 마우스 이벤트가 통과하여 그 뒤에 있는 창이 클릭된다.
이 기능을 하는 함수이다.
윈도우 핸들을 받아서 마우스 이벤트를 통과시킨다.

SetTransparent(핸들, True or False); 처럼 사용하면 됨. True 는 통과시키기, False 는 통과시키지 않기.


procedure SetTransparent(aHWND: HWND; Transparent: Boolean);
var
orgStyle: Integer;
Style: Integer;
begin
orgStyle:=GetWindowLong(aHWND, GWL_EXSTYLE);

// 이벤트 통과 시키기
if Transparent then Style:=orgStyle or WS_EX_LAYERED or WS_EX_TRANSPARENT
// 이벤트 통과 안되게 복구하기 else Style:=orgStyle and (not WS_EX_TRANSPARENT) and (not WS_EX_LAYERED);

SetWindowLong(aHWND, GWL_EXSTYLE, Style);
end;




키포인트는 WS_EX_TRANSPARENT 였다.
하지만 여기서 약간의 문제가 있으니 WS_EX_LAYERED 가 문제다.
원래부터 WS_EX_LAYERED 가 없었던 윈도우라면 저 함수로 아무 문제가 없으나,
델파이 TForm 의 property 에서 AlphaBlend 를 True 로 하고 반투명 창으로 쓴다면,
이벤트 통과 시키기를 하고 난 후 통과시키지 않게 복구하는데 and (not WS_EX_LAYERED) 가 적용되어 반투명 효과가 사라져버린다.
static 같은게 있었으면 어떻게 쓰겠는데 그냥 클래스로 하나 만들어 버렸다.

생성자에서 원래부터 WS_EX_LAYERED 가 있었는지 여부를 Boolean 변수로 받아서,
복구시킬 때 WS_EX_LAYERED 를 뺄지 말지 결정한다.


{ interface }
type
TTransparent=class
private
FAlphaBlend: Boolean;
public
constructor Create(AlphaBlend: Boolean); reintroduce;
procedure SetTransparent(aHWND: HWND; Transparent: Boolean);
end;


{ implementation }
constructor TTransparent.Create(AlphaBlend: Boolean);
begin
FAlphaBlend:=AlphaBlend;
end;

procedure TTransparent.SetTransparent(aHWND: HWND; Transparent: Boolean);
var
orgStyle: Integer;
Style: Integer;
begin
orgStyle:=GetWindowLong(aHWND, GWL_EXSTYLE);

if Transparent then
Style:=orgStyle or WS_EX_LAYERED or WS_EX_TRANSPARENT
else begin Style:=orgStyle and (not WS_EX_TRANSPARENT);
if not FAlphaBlend then Style:=Style and (orgStyle and (not WS_EX_LAYERED));
end;

SetWindowLong(aHWND, GWL_EXSTYLE, Style);
end;







... ...
var
TP: TTransparent;

원래부터 반투명창이었다면,
TP:=TTransparent.Create(True); 로 생성해서 아래처럼 사용하면 되고,
TP.SetTransparent(Form2.Handle, True); // 통과시키기
TP.SetTransparent(Form2.Handle, False); // 통과시키지 않기


반투명이 아니었다면,
생성할 때만 TP:=TTransparent.Create(False); 로 생성해서 똑같이 사용하면 된다.

댓글 없음:

댓글 쓰기