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

Résolu
steph12358 Messages postés 149 Date d'inscription jeudi 22 avril 2004 Statut Membre Dernière intervention 10 décembre 2009 - 28 mars 2008 à 14:18
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 - 2 avril 2008 à 10:34
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

cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
28 mars 2008 à 14:44
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
3
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
28 mars 2008 à 15:20
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++
0
steph12358 Messages postés 149 Date d'inscription jeudi 22 avril 2004 Statut Membre Dernière intervention 10 décembre 2009 1
28 mars 2008 à 15:36
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
0
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
28 mars 2008 à 15:57
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
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
steph12358 Messages postés 149 Date d'inscription jeudi 22 avril 2004 Statut Membre Dernière intervention 10 décembre 2009 1
28 mars 2008 à 16:08
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+
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
28 mars 2008 à 16:20
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++
0
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
28 mars 2008 à 16:20
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
0
steph12358 Messages postés 149 Date d'inscription jeudi 22 avril 2004 Statut Membre Dernière intervention 10 décembre 2009 1
31 mars 2008 à 09:45
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+
0
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
2 avril 2008 à 10:34
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
0
Rejoignez-nous