Имя: Пароль:
1C
 
Win API. Как сделать прозрачное окно?
,
0 Супер король
 
23.03.15
08:11
Пишу прогу на MS Visual Studio под Win32, не консольную.
Создается простое окно.
Нужно чтобы оно было прозрачным, с видимой нарисованной сеткой. Чтобы можно было это окно наложить поверх другой программы.

И еще нужно чтобы окно не было активным и не перехватывало события мыши. Чтобы кликалась другая программа.

Как такое сделать? Или это нельзя сделать?
1 Супер король
 
23.03.15
08:14
Вот так создается:
CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
2 Супер король
 
23.03.15
08:15
Если сделаю все окно невидимым, то сетка тоже станет невидимой. Как победить?
3 Кирпич
 
23.03.15
08:42
Ищи про это:

CreateRectRgn
CombineRgn
SetWindowRgn
4 shpioleg
 
23.03.15
08:46
Попробуй тут в разделе ассемблер посмотреть. http://www.manhunter.ru/assembler/page_21/
5 PiVa123
 
23.03.15
09:01
6 Кирпич
 
23.03.15
09:39
вот накалякал пример
http://www.imageup.ru/img216/2081257/sc1.jpg.html

окно с дырками для мыши
http://www.imageup.ru/img216/2081257/sc1.jpg.html

код на паскаля (извиняйте)

procedure TForm1.SetRgn;
var
  rg, rg2: HRGN;
  Wnd: HWND;
  x, y, i, z: integer;

const
  Step = 50; //ширина ячейки сетки
  WW = 20;  //отступ от левого края окна
  HH = 50;  //отступ сверху
  S = 2; //толщина линии сетки
begin
  Wnd := Self.Handle;

  GetWindowRgn(Wnd, rg);
  DeleteObject(rg);

  rg := CreateRectRgn(1, 1, Self.Width + WW, Self.Height + HH);

  x := Step;
  for i := 1 to (Self.Width - Step * 2) div Step do
  begin
    y := Step;
    for z := 1 to (Self.Height - Step * 2) div Step do
    begin
      rg2 := CreateRectRgn(x, y, x + Step, y + Step);
      CombineRgn(rg, rg, rg2, RGN_DIFF);
      Inc(y, Step + S);
      DeleteObject(rg2);
    end;
    Inc(x, Step + S);
  end;

  SetWindowRgn(Wnd, rg, True);

end;
7 Rebelx
 
23.03.15
10:03
(0) - прозрачность можно регулировать альфа-каналом
8 Гёдза
 
23.03.15
10:06
Тебе нужно не прозрачное окно, а окно состоящее из сетки.
Те в пустых квадратах сетки нет окна.
Поэтому см (3)
9 Супер король
 
23.03.15
11:37
(6) Круто, спасибо!

А если я попаду мышью в сетку, то событие получит это окно? А надо чтобы оно не получало ничего, как будто сетки нет.
10 бомболюк
 
23.03.15
11:44
чтоб мышь не перехватывалась надо на WMNCHITTEST возвращать HTTRASPARENT
11 Супер король
 
23.03.15
11:45
(10) ок, погуглю про это.
12 Супер король
 
23.03.15
11:45
(6)   Кирпич, куда денег слать?
13 H A D G E H O G s
 
23.03.15
12:24
(4) Спасибо тебе, добрый человек за эту ссылку.
Большое.
Ежовское.
Спасибо.
14 Сергей Д
 
23.03.15
12:47
http://www.delphikingdom.ru - сюда вам
15 Бертыш
 
23.03.15
13:17
Неплохие ссылки
16 Кирпич
 
23.03.15
13:33
(12) пожертвуй в приют для животных
17 Супер король
 
23.03.15
13:39
(16) Ок. Куплю коту Вискас.

Кирпич, если использовать то что в (10) посоветовали, то вырезать квадратики из окна не нужно будет? Можно сделать окно прозрачным, нарисовать в окне то что нужно не прозрачным цветом, и прикрутить (10)? Или это сложнее чем с регионами делать?
18 Супер король
 
23.03.15
13:41
(10) правильно так:
WM_NCHITTEST
HTTRANSPARENT
19 Кирпич
 
23.03.15
13:42
(17) в (10) про мышку написано. делай (6) плюс (10)
20 Супер король
 
23.03.15
13:44
Ок. Всем спасибо.
21 Кирпич
 
23.03.15
13:44
+(19) хотя попробуй как в (17). будет работать, я думаю.
22 Кирпич
 
23.03.15
13:47
я просто не знаю как ты будешь рисовать в прозрачном окне непрозрачным цветом.
23 H A D G E H O G s
 
23.03.15
14:08
Непроканает.
Обе формы должны выполняться в одном потоке.
24 H A D G E H O G s
 
23.03.15
14:10
HTTRANSPARENT
-1

In a window currently covered by another window in the same thread (the message will be sent to underlying windows in the same thread until one of them returns a code that is not HTTRANSPARENT).


Я проверил.
Работает для 2-х форм одного процесса, не работает для 2-х форм различных процессов.
25 H A D G E H O G s
 
23.03.15
14:16
Можна конечно поиграться с
AttachThreadInput()
но тут у нас гемморойчик - надо узнать PID потока (ну пусть будет дескриптор окна) - подложки - а это перебор Z- ордера top level окон, поиск в нем нашего покрывающего окна и полученение предыдущего окна - подложки.

Нахер-нахер.
26 Torquader
 
24.03.15
00:39
А чего - полупрозрачные окна не решают проблему ?
Окно с дыркой выглядит как-то не очень.

Если нужно просто изображение другого окна в своём как-то отслеживать, то можно не прозрачное окно сделать, а прозрачный фон - тогда мышь будет ездить по нашему окну, а видеть мы будем то, что было до появления нашего окна.
27 Супер король
 
24.03.15
06:26
(25) Можно найти окно по названию программы или по заголовку окна. Я только не знаю как.
28 Андрюха
 
24.03.15
07:57
(0) В сях у окна нету свойства OPACITY ?
29 Андрюха
 
24.03.15
08:03
(28)+ В Delphi за это дело отвечает AlphaBlend
http://imghost.in/img/2015-03/24/29kn679spaiw878z2y2s6zmoj.jpg
30 Кирпич
 
24.03.15
09:38
(0) не морочь людям голову. в гугле всё есть.

  SetWindowLong(Self.WindowHandle, GWL_EXSTYLE,
    GetWindowLong(Self.WindowHandle, GWL_EXSTYLE) or WS_EX_TRANSPARENT or
    WS_EX_TOPMOST or WS_EX_LAYERED);

WS_EX_TRANSPARENT - форма прозрачна для мышки

  SetLayeredWindowAttributes(Self.WindowHandle, RGB(0, 0, 0), 0, LWA_COLORKEY); //делает прозрачным черный цвет
31 Кирпич
 
24.03.15
10:11
(0) вот еще пример http://ipic.su/img/img7/fs/test2.1427180867.png

procedure TForm1.FormPaint(Sender: TObject);
var
  p1, p2: TPoint;
  i, x, y: integer;
const
  Step = 50;
begin

  //рисуем сетку

  Canvas.Pen.Color := clLtGray;
  Canvas.Pen.Width := 1;
  x := 0;
  y := 0;
  p1.y := 0;
  p2.y := Self.Height;
  for i := 1 to (Self.Width div Step) do
  begin
    p1.x := x;
    p2.x := x;
    Canvas.Line(p1, p2);
    Inc(x, Step);
  end;

  x := 0;
  y := 0;
  p1.x := 0;
  p2.x := Self.Width;
  for i := 1 to (Self.Height div Step) do
  begin
    p1.y := y;
    p2.y := y;
    Canvas.Line(p1, p2);
    Inc(y, Step);
  end;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  Self.Color := clBlack;
  Self.BorderStyle := bsNone;
  Self.WindowState := wsMaximized;
  Self.FormStyle := fsSystemStayOnTop;

  SetWindowLong(Self.WindowHandle, GWL_EXSTYLE,
    GetWindowLong(Self.WindowHandle, GWL_EXSTYLE) or WS_EX_TRANSPARENT or
    WS_EX_TOPMOST or WS_EX_LAYERED);
  SetLayeredWindowAttributes(Self.WindowHandle, RGB(0, 0, 0), 0, LWA_COLORKEY);
end;
32 Супер король
 
24.03.15
11:11
Блин, так окно получается без заголовка, перетаскивать не получается.
33 H A D G E H O G s
 
24.03.15
11:20
(32) Перетаскивайбез заголовка
34 Супер король
 
24.03.15
11:20
Блин, не могу нагуглить чему равны эти константы: GWL_EXSTYLE
35 necro
 
24.03.15
11:21
(32) Ничего не мешает перемещать окно при захвате мышью за любое место
36 H A D G E H O G s
 
24.03.15
11:21
(34) msdn в помощь. А вообще они законстантированны в нормальных ЯП, like a Delphi
37 H A D G E H O G s
 
24.03.15
11:21
(35) Окно, прозрачное для мыши , хехехе
38 H A D G E H O G s
 
24.03.15
11:21
39 Супер король
 
24.03.15
11:22
(36) я бросил VS, стал на JS делать, мне так проще. А тут нет таких констант.

Нагуглил, -20
40 Супер король
 
24.03.15
11:22
(38) да, именно там
41 necro
 
24.03.15
11:23
(39) А как на JS WinAPI вызывается?
42 Кирпич
 
24.03.15
11:30
(32) у тебя же в (0) написано "Нужно чтобы оно было прозрачным, с видимой нарисованной сеткой. И еще нужно чтобы окно не было активным и не перехватывало события мыши. Чтобы кликалась другая программа."

я сделал один в один как написано и не угодил. :)
43 necro
 
24.03.15
11:32
(42) Но при этом нужно чтобы мышь таки перехватывалась
44 Супер король
 
24.03.15
11:33
делаю так:

WS_OVERLAPPEDWINDOW = 0xCF0000
WS_VISIBLE = 0x10000000
WndStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE
var ret = WinAPI.SetWindowLong (hWnd, -20, WndStyle | 32 | 8 | 524288)

Окно появляется, но при нажатии на него мышкой оно прячется на задний план.
45 Супер король
 
24.03.15
11:34
(42) Извини, я не написал что нужно чтобы можно было окно перетаскивать, чтобы правильно наложить сетку
46 H A D G E H O G s
 
24.03.15
11:34
(44) Сначало получи текущий стиль окна, к нему добавь нужные тебе.
47 Супер король
 
24.03.15
11:35
(41)
WinAPI = new ActiveXObject("DynamicWrapperX.2");
WinAPI.Register ("user32", "SetWindowLong", "i=hll", "r=l");
48 Супер король
 
24.03.15
11:41
(46) а сразу при создании окна нельзя чтоли указать стиль?
49 Супер король
 
24.03.15
11:41
Я так создал: hWnd = WinAPI.CreateWindowExW(0, "Button", "test", WndStyle, 20, 20, 400, 300, 0, 0, hModule, 0)
50 necro
 
24.03.15
11:48
(47) Извиняюсь за оффтоп, а как сообщения доставляются (WindowProc)?
51 Кирпич
 
24.03.15
12:02
(50) а мне интересно, нафиг это всё нужно вообще?
52 Гёдза
 
24.03.15
12:07
(51) Интерактивная линейка?
53 H A D G E H O G s
 
24.03.15
12:15
54 necro
 
24.03.15
12:17
(51) Всегда мечтал скриптовое окно создать. Но, к сожалению, что-то не заводится у меня эта библиотечка без админских прав...
55 Супер король
 
25.03.15
05:54
(50) Например так:

var pWndProc = WinAPI.RegisterCallback(WndProc, "i=hull", "r=l");
var ret = WinAPI.SetWindowLong (hWnd, -4, pWndProc);

function WndProc(hWnd, uMsg, wParam, lParam){
    if (uMsg == WM_CLOSE){
        Close = 1;
    }
    return WinAPI.DefWindowProcW(hWnd, uMsg, wParam, lParam);
    }
56 Супер король
 
25.03.15
05:57
(51) Для программы анализа химического состава вещества. Там в окне нужно мышкой выбирать какое место образца анализировать, а сетка нужна для удобства.
Пробовали распечатывать сетку на прозрачной пленке и накладывать на монитор, но из-за толстого стекла получается не точно и не удобно.
57 Супер король
 
25.03.15
06:00
(54) заведи ее с админскими правами.
58 Супер король
 
25.03.15
08:00
(53) Оно, только нужно чтобы было всегда поверх всех окон, чтобы было поле ввода для изменения размера ячеек, чтобы можно было растягивать окно.
59 Супер король
 
25.03.15
08:01
Чтобы было поверх всех окон, я делаю так при создании окна:
dwExStyle = WS_EX_TOPMOST | WS_EX_TRANSPARENT;
        
hWnd = WinAPI.CreateWindowExW(dwExStyle, "Button", "test", WndStyle, 20, 20, 400, 300, 0, 0, hModule, 0)
60 Супер король
 
25.03.15
08:09
(6) Кирпич, зачем у тебя так написано:
61 Супер король
 
25.03.15
08:09
GetWindowRgn(Wnd, rg);
  DeleteObject(rg);
62 Супер король
 
25.03.15
08:10
Там получаешь регион, и тут же его удаляешь.

Еще не понятно, зачем используется два объекта rg и rg2, одним обойтись нельзя?
63 Кирпич
 
25.03.15
08:37
(61) ну наверное чтобы регионы не плодить.
(62) ну там как бы два региона объединяются, поэтому их и два
64 Кирпич
 
25.03.15
08:41
Начни утро с прозрачного окна!
65 Супер король
 
25.03.15
08:59
(63) зачем тогда его получать, если он нигде не используется и удаляется на следующей строке?

Регионы объединяются между собой, потом объединяются с регионом окна.
Можно же сразу один регион объединять с регионом окна?
66 Кирпич
 
25.03.15
09:09
(65) "зачем тогда его получать, если он нигде не используется и удаляется на следующей строке? "

затем, что ты каждый раз создаешь новый регион, а старый остается. вот старый и удаляется, чтобы не плодить регионы. понятно?

"Можно же сразу один регион объединять с регионом окна?"

ну так объединяй и гляди чего получится.
67 Супер король
 
25.03.15
09:30
(66) Ты не понял вопрос. Я думаю что его не нужно создавать, раз он не используется.
68 Супер король
 
25.03.15
09:32
Вот так сделал:

hWnd = WinAPI.CreateWindowExW(dwExStyle, "Button", "test", WndStyle, 20, 20, 400, 300, 0, 0, hModule, 0)
RGN_DIFF = 4;
Fstorona = 2000;
hRgnWindow = WinAPI.CreateRectRgn(0, 0, Fstorona, Fwidth);
storona = 20;
for (i=0; i < Fstorona; i = i + storona + 1){
    for (j=30; j < Fstorona; j = j + storona + 1){
        hRgnWindow2 = WinAPI.CreateRectRgn(i, j, i + storona, j + storona);
        retval = WinAPI.CombineRgn(hRgnWindow, hRgnWindow, hRgnWindow2, RGN_DIFF);
        retval = WinAPI.DeleteObject(hRgnWindow2);
    }
}
retval = WinAPI.SetWindowRgn(hWnd, hRgnWindow, true);
retval = WinAPI.DeleteObject(hRgnWindow);
69 Кирпич
 
25.03.15
09:32
(67) "создавать" и "получать" это разные понятия
70 Супер король
 
25.03.15
09:33
(69) Вообще мне кажется у тебя там лишние строчки.
У меня без GetWindowRgn работает.
Для чего она у тебя?
71 Кирпич
 
25.03.15
09:38
(70) я тебе три раза объяснил зачем оно там. ну работает, пускай работает. если на компе 8 гигов памяти, то работать будет долго.
72 Кирпич
 
25.03.15
09:44
хотя да. лишнее. справку поглядел.
73 Кирпич
 
25.03.15
09:45
я думал GetWindowRgn дескриптор региона окна возвращает, а она копию региона делает.
74 Супер король
 
25.03.15
10:12
(73) один фиг ты его в следующей строке удалял.

Щас вроде как надо работает, но цвет окна как задать? Мне нужно зеленое чтобы было.
И как создать пустое окно попроще? Я могу указать класс окна, но там дается на выбор всякие кнопки, поля ввода и т.п.
А создавать сложную структуру, заполнять ее через адреса в памяти - сложно на JS

Мне бы задать цвет этой "кнопки" которую я создал.
75 Кирпич
 
25.03.15
10:29
(74) "один фиг ты его в следующей строке удалял."
Я думал, что удалял регион окна, а на самом деле удалял его копию. Но это уже не важно.

про окна на JS ничего не знаю и знать не хочу.
76 Супер король
 
25.03.15
11:06
(75) А как на С++ или на паскале задать цвет окна? Я на JS сам переведу.
77 H A D G E H O G s
 
25.03.15
11:14
(76) Создавай не кнопку, а свое окно.
78 H A D G E H O G s
 
25.03.15
11:15
RegisterClassEx()
http://www.vsokovikov.narod.ru/New_MSDN_API/Win_class/fn_registerclassex.htm
Структура WNDCLASSEX
http://www.vsokovikov.narod.ru/New_MSDN_API/Win_class/str_wndclassex.htm
HBRUSH  hbrBackground;

Дескриптор Кисти фона окна.
79 Супер король
 
25.03.15
11:48
(78) я бы рад, но у меня RegisterClassEx() выдает ошибку постоянно, не могу победить.
80 Супер король
 
25.03.15
11:48
Причем GetLastError() возвращает 0
81 Супер король
 
25.03.15
11:49
хотя наверное эта функция врет