Skins : form "polygonale" sans titre mais déplaçable quand même ?

[Résolu]
Signaler
Messages postés
149
Date d'inscription
jeudi 22 avril 2004
Statut
Membre
Dernière intervention
10 décembre 2009
-
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009
-
Salut à tous

Je sais déjà faire une fenêtre polygonale.
Histoire de ne plus voir un bout de la barre de titre qui dépasse j'ai
supprimé la bordure (de toutes façons ma fenêtre ne doit pas être
retaillable).

Mais maintenant je ne peux plus la déplacer, évidemment...
Pas de bras, pas de chocolat !

Voilà un exemple de code pour une fenêtre triangulaire en c++ builder ça donne :

(...)
//déclarations
HRGN maRegion;
TPoint contours[10];
(...)
//création du formulaire : on créée le masque et on l'applique à la forme
void __fastcall TForm1::FormCreate(TObject *Sender)
{
   contours[0] = Point(0,0);
   contours[1] = Point(320,0);
   contours[2] = Point(160,200);

   //pas de bordure
   BorderStyle = bsNone;
   try
   {
      maRegion = CreatePolygonRgn(contours, 3, WINDING);
      assert(maRegion!=0);
      SetWindowRgn(Handle, maRegion, true);
   }
   catch (Exception * ev)
   {
      Application->MessageBox("Lézard !","Erreur", MB_OK);
   }
}
(...)
//Destruction : on supprime le masque
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
   DeleteObject(maRegion);
}

Quelqu'un a une idée ?

9 réponses

Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009
1
Bonjour,

J'ai rencontré une fois ce problème avec une fenêtre sans barre de titre donc non déplaçable en cliquant dessus. Voilà ce que j'ai écrit et qui fonctionne en cliquant sur le corps de la fenêtre pour la déplacer. Il s'agit de traiter certains messages Windows dans la procédure de traitement des messages de la fenêtre :

LRESULT CALLBACK WinMainProc
(
    HWND   hWnd   // E:handle sur la fenêtre
   ,UINT   uiMsg  // E:message à traiter
   ,WPARAM wParam // E:paramètre WPARAM
   ,LPARAM lParam // E:paramètre LPARAM
)                 // S:code retour
{
   static bool    bIsLeftMouseButtonDown = false;
   static RECT    WindowSizeDown;
   static POINT   CursorPosDown;
   static HCURSOR hCursorPrev = NULL;



   switch(uiMsg)
   {
      ...



      // -----------------------------------------------------
      // Déplacement de la fenêtre sur l'écran
      // (impossible à faire en cliquant sur la barre de titre
      // puisqu'il n'y en a pas !)
      // -----------------------------------------------------




      // --- Appui sur le bouton gauche de la souris
      case WM_LBUTTONDOWN :
      {
         bIsLeftMouseButtonDown = true;



         // --- Curseur de déplacement
         HCURSOR hCursor = LoadCursor(NULL,IDC_SIZEALL);
         if (hCursor) hCursorPrev = SetCursor(hCursor);



         // --- Dimension de la fenêtre
         GetWindowRect(hWnd,&WindowSizeDown);



         // --- Position de la souris
         GetCursorPos(&CursorPosDown);
         ScreenToClient(hWnd,&CursorPosDown);
      }
      return 0;






      // --- Relâche du bouton gauche de la souris
      case WM_LBUTTONUP :
      {
         bIsLeftMouseButtonDown = false;



         // --- Retour au curseur initial
         if (hCursorPrev) SetCursor(hCursorPrev);
      }
      return 0;






      // --- Déplacement de la souris
      case WM_MOUSEMOVE :
      {
         // --- Pas de déplacement si pas d'appui sur le bouton gauche
         if (! bIsLeftMouseButtonDown) return 0;



         // --- Curseur de déplacement
         HCURSOR hCursor = LoadCursor(NULL,IDC_SIZEALL);
         if (hCursor) hCursorPrev = SetCursor(hCursor);



         // --- Coordonnées de la souris
         POINT CursorPos;
         GetCursorPos(&CursorPos);



         // --- Déplacer la fenêtre de la valeur du déplacement de la souris
         int iX      = CursorPos.x - CursorPosDown.x;
         int iY      = CursorPos.y - CursorPosDown.y;
         int iWidth  = WindowSizeDown.right  - WindowSizeDown.left;
         int iHeight = WindowSizeDown.bottom - WindowSizeDown.top;
         MoveWindow(hWnd,iX,iY,iWidth,iHeight,TRUE);
      }
      return 0;





      case ...
   }
   ...
}








Jean-François
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
Suffit de cela:
    case WM_MOUSEMOVE: // lParam client area
      if(wParam & MK_LBUTTON) SendMessage(hdlg, WM_NCLBUTTONDOWN, HTCAPTION, 0);
      return 0;

ciao...
BruNews, MVP VC++
Messages postés
149
Date d'inscription
jeudi 22 avril 2004
Statut
Membre
Dernière intervention
10 décembre 2009

Merci Jean-François

Je ne maîtrise pas encore les callback
Du coup en attendant de me dégrossir j'ai utilisé les événements de ma form
FormMouseDown, Move et Up et me suis inspiré de ton code
J'ai juste une erreur de compil sur la ligne ScreenToClient que j'ai du mettre entre commentaire ce qui n'est peut être pas étranger au fait que lorsque je clique sur la fenêtre... elle saute d'un côté et le curseur de l'autre...
Après quoi le déplacement se passe trés bien

J'y suis presque !

//---------------------------------------------------------------------------

void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
   if (Button != mbLeft)
      return;

   GetWindowRect(Handle,&WindowSizeDown);

   // --- Position de la souris
   GetCursorPos(&CursorPosDown);
   //ScreenToClient(Handle, &CursorPosDown);

   bIsLeftMouseButtonDown = true;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
   if (! bIsLeftMouseButtonDown)
      return;
   // --- Coordonnées de la souris
   POINT CursorPos;
   GetCursorPos(&CursorPos);

   // --- Déplacer la fenêtre de la valeur du déplacement de la souris
   int iX      = CursorPos.x - CursorPosDown.x;
   int iY      = CursorPos.y - CursorPosDown.y;
   int iWidth  = WindowSizeDown.right  - WindowSizeDown.left;
   int iHeight = WindowSizeDown.bottom - WindowSizeDown.top;

   MoveWindow(Handle, iX,iY,iWidth,iHeight,TRUE);
}

Merci encore pour ton aide
et bon Week-end
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009
1
Merci Steph et bon WE aussi !

Merci aussi à BruNews car sa solution est beaucoup plus simple (si on ne veut pas changer le curseur de la souris, mais c'est un détail).

Jean-François
Messages postés
149
Date d'inscription
jeudi 22 avril 2004
Statut
Membre
Dernière intervention
10 décembre 2009

Salut BruNews

bizarre ! j'ai voulu essayer aussi ta soluce
Dans l'événement MouseMove j'ai mis :

void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
   if (! bIsLeftMouseButtonDown)
      return;

   ReleaseCapture;
   SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}

En debug c'est bien exécuté mais ça ne déplace pas la fenêtre. Pourtant j'ai retrouvé cette syntaxe dans plusieurs forums depuis...j'ai du louper qque chose

A+
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
if (! bIsLeftMouseButtonDown)  return;
ReleaseCapture;

C'est quoi ces 2 lignes ?

Sur du direct API, ça fonctionne nickel sans risque de perfre le mouvement du curseur.

ciao...
BruNews, MVP VC++
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009
1
Il faut peut-être éviter de mélanger les 2 solutions (if (! bIsLeftMouseButtonDown) return;) ?
J'ai testé la solution de BruNews sur un programme et ça marche très bien.

Jean-François
Messages postés
149
Date d'inscription
jeudi 22 avril 2004
Statut
Membre
Dernière intervention
10 décembre 2009

Salut

Bon ben ... pour la soluce de brunews je verrai plus tard
En attendant pour ceux que ça peut intéresser :

En adaptant le code de jfrancois pour utiliser les événements d'une form ça donne :

dans le .cpp :
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
   bIsLeftMouseButtonDown = false;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
   DeleteObject(mRegion);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
   bIsLeftMouseButtonDown = false;

   contours[0] = Point(0,0);
   contours[1] = Point(320,0);
   contours[2] = Point(160,200);
   BorderStyle = bsNone;
   try
   {
      mRegion = CreatePolygonRgn(contours, 3, WINDING);
      assert(mRegion!=0);
      SetWindowRgn(Handle, mRegion, true);
   }
   catch (Exception * ev)
   {
      Application->MessageBox("Lézard !","Erreur", MB_OK);
   }
   HCURSOR hCursorPrev = NULL;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
   if (Button != mbLeft)
      return;
   GetWindowRect(Handle,&WindowSizeDown);
   // --- Position de la souris au clic initial
   GetCursorPos(&CursorPosDown);
   // --- Changement de repère
   CursorPosDown = ScreenToClient(CursorPosDown);
   bIsLeftMouseButtonDown = true;

}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
   if (! bIsLeftMouseButtonDown)
      return;
   POINT CursorPos;
   GetCursorPos(&CursorPos);
   // --- Déplacer la fenêtre de la valeur du déplacement de la souris
   int iX;
   int iY;
   int iWidth;
   int iHeight;
   iX  = CursorPos.x - CursorPosDown.x;
   iY  = CursorPos.y - CursorPosDown.y;
   iWidth = WindowSizeDown.right  - WindowSizeDown.left;
   iHeight = WindowSizeDown.bottom - WindowSizeDown.top;
   MoveWindow(Handle, iX,iY, iWidth, iHeight, TRUE);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
   bIsLeftMouseButtonDown = false;
}
//---------------------------------------------------------------------------

et dans le .h :

   bool    bIsLeftMouseButtonDown;
   RECT    WindowSizeDown;
   POINT   CursorPosDown;
   HCURSOR hCursorPrev;

C'est plus long à taper, certes, mais ça marche trés bien alors...
Merci encore pour votre aide à tous les deux.

Bonne semaine
A+
Messages postés
482
Date d'inscription
vendredi 26 août 2005
Statut
Membre
Dernière intervention
5 décembre 2009
1
Petite relance !!!

Je viens de constater qu'il y a encore plus simple pour déplacer une fenêtre en cliquant dans la zone client (et à condition de ne pas vouloir changer le curseur de la souris) :

      case WM_NCHITTEST :
      return HTCAPTION;



Jean-François