Introduction
Les thumbnail de vista sont, les miniatures qui représente les application en train de fonctionner sur le systéme d'exploitation. Un exemple de thumbnail est le Flip 3D, qui affiche les application en 3D et les fait defiler. Jusque maintenant pour récupérer les thumbnail dans nos applications, on avait que la possibilité de le faire en 2D, j'ai d'ailleur écrit un article dessus.
http://netfxfactory.org/blogs/articles/archive/2007/03/30/dwm-api-et-milcore.aspx
Jeremiah Morril a reussi a trouver comment récupérer les Live thumbnail pour en faire des texture Directx. Voici comment il a procédé.
Dans Windows Visa, chaque fenêtre est un objet 3D qui est géré par DirectX. Le bureau est entiérement gérer par DwmApi qui est une api de plus haut niveau que l'api MilCore (Api qui gére d'ailleur le WPF).
Les méthodes cachées
Les méthodes cachées qui permettent de récupérer les textures, sont des méthodes cachées et non documenté de DWMAPI: DwmpDxGetWindowSharedSurface et DwmpDxUpdateWindowSharedSurface.
Leur signature est la suivante.
typedef
int (__stdcall *PFNDWM_DXGETWINDOWSHAREDSURFACE)(HWND hWnd, LUID adapterLuid, DWORD one, DWORD two, DWORD *pD3DFormat, HANDLE *pSharedHandle, unsigned __int64 *arg7);
typedef
int (__stdcall *PFNDWM_DwmpDxUpdateWindowSharedSurface)(HWND hWnd, int, int, int, HMONITOR hMonitor, void* test);
Chargement des fonctions
Bien entendu comme les fonctions ne sont pas documentées, on ne peut pas les récupérer à partir d'un simple fichier H à inclure, voici donc comment on les chargera:
HMODULE hDwmApi = LoadLibrary(L"dwmapi.dll");
pDwmpDxGetWindowSharedSurface = (PFNDWM_DXGETWINDOWSHAREDSURFACE)GetProcAddress(hDwmApi, (LPCSTR)100);
pDwmpDxUpdateWindowSharedSurface = (PFNDWM_DwmpDxUpdateWindowSharedSurface)GetProcAddress(hDwmApi, (LPCSTR)101);
Récupérer les SharedTexture
Maintenant qu'on a les fonction on peut les utiliser pour récupérer les "textures" des fenêtres:
hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
monitorInfo.cbSize =sizeof(monitorInfo);
GetMonitorInfo(hMonitor, &monitorInfo);
memcpy(&openDev.DeviceName, monitorInfo.szDevice, 32);
HRESULT hr;
hr = pOpenAdapterFromGdiDisplayName(&openDev);
adapterLuid = openDev.AdapterLuid;
closeDev.hAdapter = openDev.hAdapter;
hr = pCloseAdapter(&closeDev);
hr = pDwmpDxGetWindowSharedSurface(hWnd, adapterLuid, 0, 0, d3dFormat, sharedHandle, &unknown);
Dans ce code on utilise pDwmpDxGetWindowSharedSurface auquel on passe le Handle de fenêtre dont on veut récupérer la texture, cette fonction retournera un pointeur sur la texture a utiliser
Mettre la Shared Texture dans une texture DirectX 3D
voici le bout de code qui permet de le récupérer:
HANDLE texHandle = NULL;
DWORD fmt = 0;
RECT winRect;
HWND h;
h = FindWindow(NULL, L"directx or wpf application");
GetWindowRect(h, &winRect);
HRESULT res;
SIZE sWin = { winRect.right - winRect.left, winRect.bottom - winRect.top };
GetWindowSharedSurfaceHandle(h, &texHandle, &fmt); //
IDirect3DTexture9 *texture;
hr = g_pd3dDevice->CreateTexture(sWin.cx, sWin.cy, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)fmt, D3DPOOL_DEFAULT, &g_pTexture, &sharedHandle);
pDwmpDxUpdateWindowSharedSurface(h, 0, 0, 0, 0, 0);
En piéce jointe il y a le code de textures.cpp, ce code prendra la place de Textures.cpp qui est le tutorial 5 du SDK DirectX. C'est ce même code qui est utilisé pour la vidéo présente sur le site de Jeremiah:
http://jmorrill.hjtcentral.com/Portals/21/Blog/Files/14/111/dwmhack.zip
il suffit de modifier la ligne 380 avec le titre de la fenêtre que vous voulez monitorer. Pour l'instant seul les fenêtre utilisant Directx ou WPF peuvent être utiliser en tant que texture mais tres vite les fenêtre GDI en feront partie aussi
Merci beaucoup a jeremiah pour avoir partager l'information et m'avoir permis d'en parler si librement.