Osadzenie okna zewnętrznego programu wewnątrz okna własnego i usunięcie jego obramowania

0

W tym poście pokazałem sposób na osadzenie programu wewnątrz okna własnej aplikacji. Jest to hack, raczej nieprzenośny, ale do własnych zastosowań się nadaje (jeśli wiemy co robimy). Całość działa poprawnie, póki się za bardzo nie kombinuje z oknem osadzonego programu. :d

W swoim programie zwanym Richtris skorzystałem z tego bajeru i osadziłem okno emulatora wewnątrz okna mojego narzędzia. Dodatkowo, aby całość wyglądała ładnie, za pomocą funkcji systemowych usunąłem obramowanie okna emulatora. Teraz odpaliłem mój program na Win10 i o ile osadzanie nadal działa, tak usunięcie obramowania już nie – emulator ma standardową ramkę okna, wyglądającą jak z Win7.

Czy wie ktoś w jaki sposób usunąć obramowanie okna programu, który został osadzony? W podlinkowanym poście są źródła projektu, które można użyć jako bazę. Dodam, że Notepad w tamtym programie uruchamia się poprawnie, ale Paint wariuje (choć pod WinXP wszystko działało poprawnie).

Nie żeby mi na tym jakoś szczególnie zależało, ale dobrze by było naprawić moje narzędzie i jednak obramowanie emulatora usunąć. :]

4

Nie wiem w jaki sposób usuwałeś obramowanie ale u mnie na Windows 10 w notatniku bazując na źródłach tamtego Twojego projektu działa takie coś:

  Windows.SetParent(EnumData.WindowHandle, CWorkspacePanel.Handle);

  Style:= Windows.GetWindowLong(EnumData.WindowHandle, GWL_STYLE);
  Style:= Style and (not WS_OVERLAPPEDWINDOW);
  Windows.SetWindowLong(EnumData.WindowHandle, GWL_STYLE, Style);

  Windows.MoveWindow(EnumData.WindowHandle, 0, 0, CWorkspacePanel.ClientWidth, CWorkspacePanel.ClientHeight, False);

  Windows.ShowWindow(EnumData.WindowHandle, SW_SHOW); 
0
kAzek napisał(a):

Nie wiem w jaki sposób usuwałeś obramowanie […]

Wykluczałem kupkę flag dotyczących obramowania, menu i systemowych przycisków, w tym stylu:

WindowStyle := WindowStyle and not (WS_CAPTION or WS_THICKFRAME or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU);

Potem leciał SetWindowPos, dalej MoveWindow. Na XP to śmigało, ale na Win10 w ogóle – okno ani się nie osadzało poprawnie, ani też nie pozbywało się obramowania. Problem też miałem taki, że w swoim kodzie najpiew zmieniałem styl okna, a na koniec rodzica, a tutaj konieczne jest odwrócenie kolejności.

Twoja propozycja działa z notatnikiem, jednak nie działa z oknem emulatora FCEUX – okno albo zostaje osadzone i posiada obramowanie (w sumie to ze dwa razy mi się zdarzyło), albo po usunięciu obramowania przestaje być osadzone (w większości przypadków). Co ciekawe i co mnie cieszy, okno emulatora Nestopia osadza się poprawnie i obramowanie zostaje prawidłowo usunięte, ale MoveWindow musi w ostatnim parametrze przyjmować True – w przeciwnym razie ramka będzie widoczna i zniknie dopiero przy jakimś inpucie (np. wciśnięciu klawisza Alt, co wymusza odmalowanie okna). Cieszy mnie to dlatego, że FCEUX w trybie okienkowym działa tragicznie na Win10, a Nestopia radzi sobie dobrze (choć też nie idealnie).

No nic, tego typu kombinacje będą sprawiać problemy i zdawałem sobie z tego sprawę, ale mimo wszystko jest szansa naprawić mój projekt. Choć problemów mam z nim sporo, bo enumeracja okien nie działa, nie znajduje okna emulatora, a więc nie da się z niego czytać pikseli. I teraz nie wiem w co ręce włożyć, aby postawić Richtrisa na nogi. :/

Ale dzięki wielkie za pomoc – Twoja propozycja działa super. Problem rozwiązany.

2

Nie wiem, czy to zadziała konkretnie w Twoim wypadku.
Ale ogólnie rzecz biorąc to w Windows XP nie było trybu Aero.
Kiedy system dostarcza Aero, to cały proces rysowania okien i ich obudowy może przebiegać dwiema drogami.
Kiedy efekty przeźroczystości są wyłączone, to wszystko działa jak w XP. Okna są rysowane wprost na ekranie.
Kiedy efekty przeźroczystości są włączone, to okna i ich ramki są rysowane na wewnętrznych bufora i wyświetlany jest dopiero wynik operacji. I to może powodować, że tego typu zabiegi jak zmiana stylu mogą działać nieprzewidywalnie.
Możesz wyłączyć programowo różne efekty renderowania obszaru NC dla Twojego okna i być może wtedy zadziała.

To jest funkcja, która włącza i wyłącza różne efekty z tym związane:
https://docs.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetwindowattribute

Spróbuj ustawić dwAttribute na DWMWA_NCRENDERING_POLICY, a zawartość pvAttribute na DWMNCRP_DISABLED.
Może pomoże.

0

Dziękuję @Stefan_3N za wskazówki. Na razie nie wiem czy jest jeszcze sens poświęcać czas na ten program, dlatego że podjąłem decyzję o zakupie oryginalnej konsoli NES, ze względu na treningi do turniejów. Niestety żaden emulator nie odwzorowuje idealnie pracy konsoli i kineskopu, a na poziomie jaki obecnie prezentuję (nie żebym się chwalił – po prostu tak to wygląda), każda milisekunda się liczy (co na ekranie LCD 60Hz jest nieosiągalne dla Tetrisa w wersji PAL).

Ale to nie oznacza, że kończę z softwarem dla Tetrisa – być może, gdy znajdę czas, przerobię Richtrisa i przystosuję go do czytania danych z obrazu przechwyconego przez grabber USB prosto z konsoli. Wiele przeróbek nie będzie, ale mimo wszystko odczytywanie danych z rozmazanych klatek do łatwych należeć nie będzie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1