Hardware overlay

Signaler
Messages postés
10
Date d'inscription
vendredi 29 juillet 2005
Statut
Membre
Dernière intervention
26 avril 2009
-
Messages postés
10
Date d'inscription
vendredi 29 juillet 2005
Statut
Membre
Dernière intervention
26 avril 2009
-
Bonjour,

Je cherche des infos sur la hardware overlay. Il s'agit d'un système des cartes vidéos qui permet la gestion 2D pour créer des interfaces utilisateur. Le buffer du hardware overlay étant affiché par dessus ce qui est calculé par la carte vidéo il permet de créer des UI fonctionnant à la fois en mode fenêtré et en plein écran par dessus toute application ayant le focus. C'est un autre canal que le canal 3D habituel.
Toutes les infos que j'ai pu trouver parlent de directshow et directdraw qui sont passés à la trappe avec directx9.

Merci.

10 réponses

Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
14
Bonjour,

Tu peux faire de la 2D en Direct3D si c'est la question. Qui peut le plus peu le moins, même si directshow et directdraw était au moins encore il y a peu beaucoup utilisé.
Messages postés
10
Date d'inscription
vendredi 29 juillet 2005
Statut
Membre
Dernière intervention
26 avril 2009

Oui, je sais qu'on peut faire de la 2D avec directx, mais le problème ici est de pouvoir afficher la 2D hors de tout contexte, que ce soit sur le bureau ou par dessus une application fenêtrée ou plein écran.
Je vais regardé ton lien, mais on m'a parlé des Swap Chains.
Affaire à suivre...
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
14
Tu veux faire quelque chose comme ça ?



A priori ça n'a rien à voir avec DirectX que ce soit show, draw ou 3D. C'est juste quelques flags bien positionnés. Je crois me souvenir avoir fait des essais là dessus. Je peux donner plus d'info si ça t'intéresse.
Messages postés
10
Date d'inscription
vendredi 29 juillet 2005
Statut
Membre
Dernière intervention
26 avril 2009

Si ça marche aussi en mode fenêtré comme une fenêtre standard windows c'est exactement ce qu'il me faut !
Toutes les infos sont les bienvenue.
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
14
WS_EX_TOPMOST



Et la fenêtre reste devant même quand on active une autre fenêtre.
<hr size="2" width="100%" />#ifdef UNICODE
#define _UNICODE
#endif /* UNICODE */

#include <windows.h>
#include <tchar.h>

HINSTANCE _hThisInstance;              /* Handle du module                    */
HWND _hWnd;                            /* Handle de la fenêtre                */
LPTSTR _lpAppName = _T("StayOnTop");   /* Nom de l'appli                      */

/**
 * Affiche un message d'erreur correspondant à la dernière erreur Win32
 */
DWORD __stdcall ShowLastError()
{
  DWORD nLastError;           /* Numéro de l'erreur                           */
  LPTSTR lpMessageBuffer;     /* Récupération du message                      */

  nLastError = GetLastError();

  /* Formatage du message */
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                NULL, nLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                (void*)&lpMessageBuffer, 0, NULL);

  /* Affichage du message */
  MessageBox(NULL, lpMessageBuffer, _T("ERROR"), MB_OK | MB_ICONERROR);

  LocalFree(lpMessageBuffer);
  return nLastError;
}

/**
 * Traitement des messages
 */
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
  int bHandled;               /* Pour savoir si le message est traité          */
  long nResult;

  nResult = 0;
  bHandled = 0;
  switch (nMessage)
  {
    case WM_DESTROY:
      /* On signale que le thread va s'arrêter */
      PostQuitMessage(0);
      bHandled = 1;
      break;
  }
  if (! bHandled)
    nResult = DefWindowProc(hWnd, nMessage, wParam, lParam);
  return nResult;
}

/**
 * Initialise la fenêtre principale de l'appli.
 */
int __stdcall CreateMyWindow()
{
  WNDCLASSEX wincl;       /* Classe de la fenêtre utilisée                    */
  int nResult;

  nResult = 0;

  /* Création de la classe de fenêtre */
  wincl.cbSize = sizeof(WNDCLASSEX);
  wincl.style = 0;
  wincl.lpfnWndProc = WindowProcedure;
  wincl.cbClsExtra = 0;
  wincl.cbWndExtra = 0;
  wincl.hInstance = _hThisInstance;
  wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
  wincl.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  wincl.lpszMenuName = 0;
  wincl.lpszClassName = _lpAppName;
  wincl.hIconSm = NULL;

  /* Enregistrement de la classe */
  if (! RegisterClassEx(&wincl)) goto the_end;

  /* Création de la fenêtre */
  _hWnd = CreateWindowEx(WS_EX_TOPMOST,
                         _lpAppName, _lpAppName,
                         WS_OVERLAPPEDWINDOW,
                         CW_USEDEFAULT, CW_USEDEFAULT, 500, 300,
                         HWND_DESKTOP, NULL, _hThisInstance, NULL);
  if (! _hWnd) goto the_end;

  /* Affichage de la fenêtre */
  ShowWindow (_hWnd, SW_SHOW);

  nResult = 1;
the_end:
  return nResult;
}

/**
 * Main
 */
int __cdecl WinMainCRTStartup()
{
  MSG messages;                       /* Messages envoyés à l'application     */
  int nResult;

  /* Récupération du handle du module */
  _hThisInstance = GetModuleHandle(NULL);

  if (! CreateMyWindow())
  {
    nResult = ShowLastError();
    goto the_end;
  }

  /* Boucle de traitement des messages */
  while (GetMessage(&messages, NULL, 0, 0))
  {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
  }
  nResult = messages.wParam;

the_end:
  /* ExitProcess nécessaire car sinon c'est un ExitThread */
  ExitProcess(nResult);

  /* Pour esquiver le warning */
  return 0;
}
Messages postés
10
Date d'inscription
vendredi 29 juillet 2005
Statut
Membre
Dernière intervention
26 avril 2009

J'avais déjà essayé en managed et j'ai réessayé avec le code standard comme celui que tu as donné.
Ça ne marche ni sur Quake 3 ni sur Left4Dead.
WS_EX_TOPMOST ne place la fenêtre que devant toute fenêtre non WS_EX_TOPMOST. Il y'a donc de nombreux cas dans lesquels ça ne marche pas. A mois qu'il ne suffise pas de mettre WS_EX_TOPMOST et que quelque chose d'autre m'a échappé.
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
14
Visiblement, les gens s'orientent plutôt vers un hook des fonction de rendu de manière à dessiner depuis l'application en question... Mais ce n'est très probablement pas la technique employée pour "game overlay" de mon lien plus haut. Ce logiciel fonctionne-t-il sur Quake 3 ?

A tout hasard, je vais essayer de faire un bout de code qui s'arrange pour que seule la fenêtre courante soit WS_EX_TOPMOST.
Messages postés
10
Date d'inscription
vendredi 29 juillet 2005
Statut
Membre
Dernière intervention
26 avril 2009

J'ai regardé pas mal de trucs sur le hook et l'injection de d3d.dll, mais le problème ici est que ça ne marche qu'a l'intérieur de l'application, pas sur le bureau ni à cheval sur une application fenêtrée et le bureau.
Pourtant c'est possible http://www.playxpert.com/web/guest/product/in-game

> A tout hasard, je vais essayer de faire un bout de code qui s'arrange pour que seule la fenêtre courante soit WS_EX_TOPMOST.

Je ne vois pas comment. Si c'était possible on pourrait se retrouver avec des fenêtres qui bataillent pour être topmost et bloquer le pc. Du genre "si je ne suis plus devant, me mettre devant" qui déclanche le "si je ne suis plus devant, me mettre devant" de l'autre et ainsi de suite.

Je pense qu'il faut dessiner directement dans la carte vidéo juste avant qu'elle n'envoi les infos à l'écran, ce qui marcherait quelque soit ce qui est affiché à l'écran.
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
14
"Si c'était possible on pourrait se retrouver
avec des fenêtres qui bataillent pour être topmost et bloquer le pc. Du
genre "si je ne suis plus devant, me mettre devant" qui déclanche le
"si je ne suis plus devant, me mettre devant" de l'autre et ainsi de
suite."

Bah vi ça peut rentrer en conflit avec une application existante... Mais bon, n'est ce pas ce que tu veux au final, que ce soit ton application qui soit au premier plan quitte à batailler avec le reste du monde ?

Cette application s'arrange pour être la seule topmost. C'est mal codé (timer...) mais c'est suffisant pour faire des essais. Globalement, cela supprime le caractère top most de toutes les fenêtres sauf de la fenêtre courante. Cela fonctionne sur des applications classique. Je n'ai pas essayé avec un jeu.
<hr size="2" width="100%" />#ifdef UNICODE
#define _UNICODE
#endif /* UNICODE */

#include <windows.h>
#include <tchar.h>

#define TIMER_ID 1
#define BUFFER_SIZE 1024

HINSTANCE _hThisInstance;              /* Handle du module                    */
HWND _hWnd;                            /* Handle de la fenêtre                */
LPTSTR _lpAppName = _T("StayOnTop");   /* Nom de l'appli                      */
HDESK _hDesk;                          /* Handle sur le desktop               */

/**
 * Affiche un message d'erreur correspondant à la dernière erreur Win32
 */
DWORD __stdcall ShowLastError()
{
  DWORD nLastError;           /* Numéro de l'erreur                           */
  LPTSTR lpMessageBuffer;     /* Récupération du message                      */

  nLastError = GetLastError();

  /* Formatage du message */
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                NULL, nLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                (void*)&lpMessageBuffer, 0, NULL);

  /* Affichage du message */
  MessageBox(NULL, lpMessageBuffer, _T("ERROR"), MB_OK | MB_ICONERROR);

  LocalFree(lpMessageBuffer);
  return nLastError;
}

/**
 * Call back appelée pour toutes les fenêtres
 */
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
  if (IsWindowVisible(hwnd) && (hwnd != _hWnd))
    SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
                 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  return TRUE;
}

/**
 * Traitement des messages
 */
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
  int bHandled;               /* Pour savoir si le message est traité          */
  long nResult;

  nResult = 0;
  bHandled = 0;
  switch (nMessage)
  {
    case WM_TIMER:
      EnumDesktopWindows(_hDesk, EnumWindowsProc, 0);
      bHandled = 1;
      break;
    case WM_DESTROY:
      /* On signale que le thread va s'arrêter */
      PostQuitMessage(0);
      bHandled = 1;
      break;
  }
  if (! bHandled)
    nResult = DefWindowProc(hWnd, nMessage, wParam, lParam);
  return nResult;
}

/**
 * Initialise la fenêtre principale de l'appli.
 */
int __stdcall CreateMyWindow()
{
  WNDCLASSEX wincl;       /* Classe de la fenêtre utilisée                    */
  int nResult;

  nResult = 0;

  /* Création de la classe de fenêtre */
  wincl.cbSize = sizeof(WNDCLASSEX);
  wincl.style = 0;
  wincl.lpfnWndProc = WindowProcedure;
  wincl.cbClsExtra = 0;
  wincl.cbWndExtra = 0;
  wincl.hInstance = _hThisInstance;
  wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
  wincl.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  wincl.lpszMenuName = 0;
  wincl.lpszClassName = _lpAppName;
  wincl.hIconSm = NULL;

  /* Enregistrement de la classe */
  if (! RegisterClassEx(&wincl)) goto the_end;

  /* Création de la fenêtre */
  _hWnd = CreateWindowEx(WS_EX_TOPMOST,
                         _lpAppName, _lpAppName,
                         WS_OVERLAPPEDWINDOW,
                         CW_USEDEFAULT, CW_USEDEFAULT, 500, 300,
                         HWND_DESKTOP, NULL, _hThisInstance, NULL);
  if (! _hWnd) goto the_end;

  /* Affichage de la fenêtre */
  ShowWindow (_hWnd, SW_SHOW);

  nResult = 1;
the_end:
  return nResult;
}

/**
 * Main
 */
int __cdecl WinMainCRTStartup()
{
  MSG messages;                       /* Messages envoyés à l'application     */
  int nResult;

  /* Récupération du handle du module */
  _hThisInstance = GetModuleHandle(NULL);

  /* Récupération d'un handle sur le desktop (CloseDesktop pas nécessaire) */
  _hDesk = GetThreadDesktop(GetCurrentThreadId());
  if (! CreateMyWindow())
  {
    nResult = ShowLastError();
    goto the_end;
  }

  /* Création du timer */
  if (! SetTimer(_hWnd, TIMER_ID, 100, NULL))
  {
    nResult = ShowLastError();
    goto the_end;
  }

  /* Boucle de traitement des messages */
  while (GetMessage(&messages, NULL, 0, 0))
  {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
  }
  nResult = messages.wParam;

the_end:
  /* ExitProcess nécessaire car sinon c'est un ExitThread */
  ExitProcess(nResult);

  /* Pour esquiver le warning */
  return 0;
}
Messages postés
10
Date d'inscription
vendredi 29 juillet 2005
Statut
Membre
Dernière intervention
26 avril 2009

j'ai trouvé ça qui fonctionne sur le bureau et sur certains jeux (mais pas tous) :
http://www.codeproject.com/KB/directx/Overlay_Tools.aspx
Deux problèmes :
c'est du directdraw7 qui est la dernière version et n'existe plus, même s'il est toujours supporté (deprecated)
ça ne marche pas sur tous les jeux, il y'a donc des trucs a changer, mais je vais voir ce que je peux faire.

Ça règle le problème de topmost qui, en plus, risque d'iconifier les application en fullscreen.