Форум: "WinAPI";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];
ВнизПрозрачная область на форме Найти похожие ветки
← →
Леший (2005-04-23 16:30) [0]Подскажите, как можно на форме сделать прозрачную область/области, или хотя бы "дыру" в форме, но чтобы она ловила события мыши?
← →
Ученик (2005-04-23 16:44) [1]
type
TForm1 = class(TForm)
procedure FormShow(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
FRgn: HRgn;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormShow(Sender: TObject);
var
Rgn1, Rgn2: HRgn;
begin
Rgn1 := CreateRectRgn(0, 0, Width, Height);
try
Rgn2 := CreateRectRgn(100, 100, 200, 200);
try
FRgn := CreateRectRgn(0, 0, 0, 0);
CombineRgn(FRgn, Rgn1, Rgn2, RGN_DIFF);
SetWindowRgn(Handle, FRgn, False)
finally
DeleteObject(Rgn2)
end
finally
DeleteObject(Rgn1)
end
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
DeleteObject(FRgn)
end;
← →
Юрий Зотов © (2005-04-24 20:58) [2]> Ученик (23.04.05 16:44) [1]
DeleteObject(FRgn) - это лишнее. Если посмотреть результат, он будет равен нулю - то есть, функция отработала с ошибкой и ничего не освободила.
Объясняется это тем, что после вызова SetWindowRgn владельцем региона FRgn становится не наша программа, а система и освободить его может только она сама.
← →
Ученик (2005-04-24 21:28) [3]>Юрий Зотов © (24.04.05 20:58) [2]
Да, действительно так
After a successful call to SetWindowRgn, the system owns the region specified by the region handle hRgn. The system does not make a copy of the region. Thus, you should not make any further function calls with this region handle. In particular, do not delete this region handle. The system deletes the region handle when it no longer needed.
← →
Piter © (2005-04-24 22:01) [4]Леший (23.04.05 16:30)
но чтобы она ловила события мыши?
а зачем ей ловить события мыщи, если там дырка?
← →
Леший (2005-04-25 01:55) [5]Ловить события мыши очень надо - я тягаю форму за "тело", да и некоторые другие события не мешало бы обработать.
С комбинацией регионов я работать уже пробовал, но при этом мышь через дыры падает на нижнее окно, а как с этим бороться я не знаю. (С хуками я не дружу.) Поэтому и написал в форум. Так что если у кого-то есть какие-либо конструктивные соображения/предложения - восприму с благодарностью.
← →
alpet © (2005-04-25 11:44) [6]Накрой получившуюся дыру другим окном (формой) с установленной прозрачностью (opacity), и синхронизируй его позицию относительно основного окна. В Win98 есстно это работать не будет.
← →
Deka © (2005-04-25 12:03) [7]Может быть сделать форму полностью прозрачной, а на нее поместить TImage c включенной прозрачностью и картинкой в виде прямоугольника (по размерам форму) с кругом посередине. Круг соотвественно тоже должен быть прозрачным. В результате рабочий стол ты по идее увидишь но мышка будет всегда оставаться над твоим окном. Может так? Сам не пробовал, чисто теоретическое предположение.
← →
Чапаев © (2005-04-25 13:10) [8]SetCapture()?
← →
alpet © (2005-04-25 13:17) [9]2 Deka
Все что помещается на прозрачное окно как дочерний элемент управления - наследует его прозрачность.
← →
Deka © (2005-04-25 14:06) [10]Мда...
Наверное придется как в [6]...
← →
Piter © (2005-04-25 17:15) [11]Deka © (25.04.05 14:06) [10]
Наверное придется как в [6]...
наверное, придется передумать. Ибо что это за юзабельность - я тыкаю в пустое место, а получается, что я хватаю за форму. Что за бред? Ты где-нибудь такое видел?
← →
Леший (2005-04-25 21:54) [12]Вторая форма - это не серьезно. Есть следующее соображение: после установки новой области (см. пример) сохранять битмап дырки, устанавливать SetWindowRgn(Handle, Rgn1, True), и кидать на него сохраненный битмап. Пробую реализовать.
2 Чапаев:
Мысль интересная, но SetCapture посылает весь ввод в указанное окно. А для того чтобы передавать ввод в др. окна придется отслеживать координаты мыши и при выходе ее из области моего окна выполнять ReleaseCapture. Я правильно ловлю мысль?
И вопрос ко всем: я когда сотворял аналог примера самостоятельно использовал что-то вроде CombineRgn(Rgn1, Rgn1, Rgn2, RGN_DIFF); при этом все работало также, но при незакрепленной панели задач она отказывалась всплывать. Если сделать как в примере, то этого не наблюдается. Есть этому логическое объяснение, или это просто глюк системы?
← →
Чапаев © (2005-04-26 09:55) [13]> Я правильно ловлю мысль?
Ахха. WM_MOUSEMOVE перехватывай.
← →
Чапаев © (2005-04-26 09:55) [14]> Я правильно ловлю мысль?
Ахха. WM_MOUSEMOVE перехватывай.
← →
Deka © (2005-04-26 11:31) [15]А для чего нужна работа со всеми этими регионами?
Ученик, у тебя во время работы с окном рабочий стол меняется? Ну в смысле ты другие программы запускаешь? Если нет, то можно при старте скопировать рабочий стол в Bitmap, потом показать обычную прямоугольную форму на которой в TImage отрисовывать круг вырезанный из сохраненного в Bitmap рабочего стола. При перемещении из Bitmap вырезается и помещается в TImage круг с другими координатами. Получится "прозрачность". Будет видно рабочий стол, регионы будут не нужны и форма всегда получит события от мышки. Правда если открыть другое приложение (или другим способом изменить картинку на экране), то его в дырке видно не будет, пока не пересохранишь рабочий стол.
Вот такой вот вариант.
← →
Леший (2005-04-28 02:36) [16]2 Чапаев
Думаю целесообразнее при WM_NCMOUSEMOVE возвращать ввод системе. Однако, столкнудся с тем, что не могу захватить ввод, даже при прописывании SetCapture( ) в OnCreate. Видимо выходит что при комбинации регионов форма образуется их пересечением, т.е. дырка все равно не есть форма. Но тогда не ясно почему то что осталось формой не хочет ловить весь ввод.
← →
Чапаев © (2005-04-28 12:10) [17]> [16]
Ну, про wm_NCmousemove я ничего не говорил...
> дырка все равно не есть форма
Да.
← →
Леший (2005-04-28 20:28) [18]Да-то да, а как проблему решить?
← →
Ученик (2005-04-29 22:36) [19]>Deka © (26.04.05 11:31) [15]
??????????
← →
Deka © (2005-04-30 10:21) [20]2 Леший
Так чего? Как я написал попробовать не хочешь?
← →
Леший (2005-04-30 15:32) [21]Отчего же, хочу. Высылай.
← →
Deka © (2005-04-30 18:04) [22]Да текста то нет. Тебе придется самому все накропать. А идея в [15]. Буду вопросы - спрашивай.
← →
Deka © (2005-04-30 18:05) [23]Щас попробую сделать простенький пример с квадратной дыркой... ;)
← →
Deka © (2005-04-30 18:52) [24]Готово. Есть форма с прозрачной квадратной областью посередине, которая может реагировать на любые стандартные для TImage события. Работает. Есть шероховатости, но это не главное. А главное в том, что никаких регионов!
← →
Deka © (2005-05-03 13:41) [25]Немножко модифицировал - теперь стало получше.
← →
Леший (2005-05-03 17:57) [26]Немного отсутствовал - праздники-с, с чем всех и поздравляю.
2 Deka
Все-то ничего, но не выходит у меня перерисовывать форму при перемещении, да и при восстановлении из панели задач после перетасовки окон фигня выходит, но об этом уже говорилось.
← →
Deka © (2005-05-04 12:27) [27]У меня пока не получилось отлавливать изменение экрана, но и особо этим не занимался. Думаю что надо просто отлавливать событие активации формы. Сейчас попробую. А так все работает. Все красиво и в динамике ;)
← →
Леший (2005-05-05 01:10) [28]В смысле "в динамике"?
← →
Deka © (2005-05-05 11:50) [29]При перемещении. Даже быстром ;)
← →
Леший (2005-05-05 15:35) [30]У меня не выходит.
← →
GrayFace © (2005-05-05 16:47) [31]Леший (03.05.05 17:57) [26]
Пример полупрозрачного окна: http://www.grayface.chat.ru/trans.rar
← →
Deka © (2005-05-06 09:56) [32]Ok, Леший, вот мой код...
Сперва сделай в дельфи новый проект, потом брось на форму TIMage, ну а дальше думаю разберешься...
procedure TForm1.FormCreate(Sender: TObject);
var
ScreenDC: HDC;
begin
TmpBmp:= TBitmap.Create;
ScreenDC:= GetDC(0);
try
TmpBmp.Width:= GetSystemMetrics(SM_CXSCREEN);
TmpBmp.Height:= GetSystemMetrics(SM_CYSCREEN);
BitBlt(TmpBmp.Canvas.Handle, 0, 0, TmpBmp.Width, TmpBmp.Height, ScreenDC, 0, 0, SRCCOPY);
finally
ReleaseDC(0, ScreenDC);
end;
Image1.Picture.Bitmap.Width:= Image1.Width;
Image1.Picture.Bitmap.Height:= Image1.Height;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
TmpBmp.Free;
end;
// Второй способ
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
const
SC_DRAGMOVE: Longint = $F012;
begin
if Button <> mbRight then
begin
ReleaseCapture;
SendMessage(Handle, WM_SYSCOMMAND, SC_DRAGMOVE, 0);
end;
end;
type
PRect = ^TRect;
procedure TForm1.WMMoving(var M: TMessage);
begin
Caption:= IntToStr(Form1.Left) + " / " + IntToStr(Form1.Top);
// Теперь скопируем картинку
BitBlt(Image1.Picture.Bitmap.Canvas.Handle, 0, 0, Image1.Width, Image1.Height,
TmpBmp.Canvas.Handle,
PRect(M.LParam)^.Left + GetSystemMetrics(SM_CXBORDER) + Image1.Left + 2,
PRect(M.LParam)^.Top + 20 + Image1.Top + 1,
SRCCOPY);
Image1.Refresh;
end;
procedure TForm1.Image1Click(Sender: TObject);
begin
ShowMessage("Это дырка обрабатывающая события...");
end;
P.S. Осталось пару проблем, но главное сделано ;)
← →
Deka © (2005-05-06 09:59) [33]Да! Совсем забыл сказать, что BorderStyle у Form1 надо поставить в bsToolWindow. Иначе придется подкорректировать смещения в процедуре копирования.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.036 c