Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Tutorial - Snap to screen edges

Status
Not open for further replies.

imagenetics

Programmer
Dec 8, 2003
66
PL
This example is based on the various sample applications I've found on the Internet. The following code makes your application's form, when dragged, snap to screen edges.

Green lines is what you have to write. Red are already in the code.

In "Unit1.h" add this:
Code:
[COLOR=red]public:
__fastcall TForm1(TComponent* Owner);[/color]
[COLOR=green]BEGIN_MESSAGE_MAP
 MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, TWMWindowPosChanging, WMWindowPosChanging);
END_MESSAGE_MAP(TForm);[/color]
Now in "Unit1.cpp" add:
Code:
[COLOR=green]void __fastcall TForm1::WMWindowPosChanging(TWMWindowPosChanging &msg)
{
RECT workArea;
SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);

if(abs(msg.WindowPos->x) <= (workArea.left + 15)){
 msg.WindowPos->x = workArea.left;
}else if((msg.WindowPos->x + msg.WindowPos->cx) >= (workArea.right - 15) && (msg.WindowPos->x + msg.WindowPos->cx) <= (workArea.right + 15)){
 msg.WindowPos->x = workArea.right - msg.WindowPos->cx;
}

if(abs(msg.WindowPos->y) <= (workArea.top + 15)){
 msg.WindowPos->y = workArea.top;
}else if((msg.WindowPos->y + msg.WindowPos->cy) >= (workArea.bottom - 15) && (msg.WindowPos->y + msg.WindowPos->cy) <= (workArea.bottom + 15)){
 msg.WindowPos->y = workArea.bottom - msg.WindowPos->cy;
}
}[/color]
In the precending code the snap value is 15 (measured in pixels - form is snapped when its rectangle is 15 pixels or less from the edge of the screen, which I think is optimal. You can, ofcourse, change it, or assign it to an integer variable if you want to allow user to adjust this value.

Note I:
This works only for the form which it's applied to. If your program consists of more than one form and you want all of then to snap, rewrite the code for all forms.

Note II:
The code reads the dimensions of working area - desktop excluding the taskbar - the bottom edge is taskbar's top border.

Note III:
While compiling, you might get a warning "[C++ Warning] Unit1.h(60): W8027 Functions containing switch are not expanded inline". This IS NOT critical and everything will work.
If you want to get rid of this warning, go to compiler options (Project->Options[Shit+Ctrl+F11]->Compiler tab), click Warnings button, in the warnings list find "W8027 Functions containing..." and uncheck it.

I hope that is helpful.
 
Very nice!
One quick additional question for you though... How could I implement this code to do something like: if I've got Form2, and I want it to snap to the bottom of Form1?

Cyprus
 
Never tried this, but I think you should get main form's rectangle instead of reading work area rectangle. I'll experiment on this. If I come up something, I'll let you know.
 
OK, here you go. This isn't exactly what you've been asking for, beacuse Form2 snaps to all borders of Form1, not only to the bottom one.

Note:
To specify to which window the snapable (snapable?) window should snap, you have to include its class name in HWND winToSnapTo = FindWindow([className], NULL);. If winToSnapTo is a part of your application, class name is what you type as a form name ("Form1" by default).

Now the code. As above, green is what you have to write, red are already there. Comments are blue.

In "Unit2.h" (notice that we work only in Form2's source):
Code:
[COLOR=red]private:[/color][COLOR=green]
 HWND winToSnapTo;
 RECT workArea;
 void __fastcall WMWindowPosChanging(TWMWindowPosChanging &msg);[/color]
[COLOR=red]public:
 __fastcall TForm2(TComponent* Owner);[/color]
 [COLOR=green]BEGIN_MESSAGE_MAP
  MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, TWMWindowPosChanging, WMWindowPosChanging);
 END_MESSAGE_MAP(TForm);[/color]

In "Unit2.cpp":
Code:
[COLOR=green]void __fastcall TForm2::WMWindowPosChanging(TWMWindowPosChanging &msg)
{
RECT snapRect;
winToSnapTo = FindWindow("TForm1", NULL); [COLOR=blue]// Parent window's class[/color]

[COLOR=blue]// Snap to window borders[/color]
if(winToSnapTo && IsWindowVisible(winToSnapTo)){
 if(GetWindowRect(winToSnapTo, &snapRect)){
  if((msg.WindowPos->x <= (snapRect.right + 15)) &&  (msg.WindowPos->x >= (snapRect.right - 15))){
   if((msg.WindowPos->y > snapRect.top) && (msg.WindowPos->y < snapRect.bottom)){
    msg.WindowPos->x = snapRect.right;
   }
  }else if((msg.WindowPos->x + msg.WindowPos->cx) >= (snapRect.left - 15) && (msg.WindowPos->x + msg.WindowPos->cx) <= (snapRect.left + 15)){
   if((msg.WindowPos->y > snapRect.top) && (msg.WindowPos->y < snapRect.bottom)){
    msg.WindowPos->x = snapRect.left - msg.WindowPos->cx;
   }
  }
  if((msg.WindowPos->y <= (snapRect.bottom + 15)) && (msg.WindowPos->y >= (snapRect.bottom - 15))){
   if((msg.WindowPos->x > snapRect.left) && (msg.WindowPos->x < snapRect.right)){
    msg.WindowPos->y = snapRect.bottom;
   }
  }else if((msg.WindowPos->y + msg.WindowPos->cy) <= (snapRect.top + 15) && (msg.WindowPos->y + msg.WindowPos->cy) >= (snapRect.top - 15)){
   if((msg.WindowPos->x > snapRect.left) && (msg.WindowPos->x < snapRect.right)){
    msg.WindowPos->y = snapRect.top - msg.WindowPos->cy;
   }
  }
 }
}

[COLOR=blue]// Snap to screen edges[/color]
snapRect = workArea;
SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);

if(abs(msg.WindowPos->x) <= (snapRect.left + 15)){
 msg.WindowPos->x = snapRect.left;
}else if((msg.WindowPos->x + msg.WindowPos->cx) >= (snapRect.right - 15) && (msg.WindowPos->x + msg.WindowPos->cx) <= (snapRect.right + 15)){
 msg.WindowPos->x = snapRect.right-msg.WindowPos->cx;
}

if(abs(msg.WindowPos->y) <= (snapRect.top + 15)){
 msg.WindowPos->y = snapRect.top;
}else if((msg.WindowPos->y + msg.WindowPos->cy) >= (snapRect.bottom - 15) && (msg.WindowPos->y + msg.WindowPos->cy) <= (snapRect.bottom + 15)){
 msg.WindowPos->y = snapRect.bottom - msg.WindowPos->cy;
}
}
[/color]
End of transmission.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top