 |
|
 |
Works Perfect. 5 from me.
I want to show my form moving when i drag it but when i drag it only shows border of the form. how do i do it?
|
|
|
|
 |
|
 |
Hi
first of all nice code,
is there any way to snap to other window form or instance of the same form ?? can any one have done this?? help will really appreciated!
thank you!
|
|
|
|
 |
|
 |
based on MikeOA's c# translation posted here, and integrating Richard Rathmann's VB fix (also posted here) for multiple monitor support (I have not tested this on multiple monitors, myself),
just ask ... here.
I don't feel I've "added enough value" by what I've done to publish a new article.
in my "version" a boolean Form level variable "KeepFormOnScreen" is used to control whether or not the Form is allowed to have any "bits" off-screen.
best, Bill
p.s. the c# version I'm using has nothing that depends on VS 2010 in a way that it wouldn't compile on VS2008 or any other IDE, imho.
"Many : not conversant with mathematical studies, imagine that because it [the Analytical Engine] is to give results in numerical notation, its processes must consequently be arithmetical, numerical, rather than algebraical and analytical. This is an error. The engine can arrange and combine numerical quantities as if they were letters or any other general symbols; and it fact it might bring out its results in algebraical notation, were provisions made accordingly." Ada, Countess Lovelace, 1844
|
|
|
|
 |
|
 |
Public Class Form1 Private Const SnapOffset As Integer = 20 Private Const WM_WINDOWPOSCHANGING As Integer = &H46 Public Structure WINDOWPOS Public hwnd As IntPtr Public hwndInsertAfter As IntPtr Public x As Integer Public y As Integer Public cx As Integer Public cy As Integer Public flags As SWP End Structure <Flags()> Public Enum SWP Normal = 0 NoSize = &H1 NoMove = &H2 NoZOrder = &H4 NoRedraw = &H8 NoActivate = &H10 FrameChanged = &H20 ShowWindow = &H40 HideWindow = &H80 NoCopyBits = &H100 NoOwnerZOrder = &H200 NoSendChanging = &H400 DrawFrame = FrameChanged NoReposition = NoOwnerZOrder DeferErase = &H2000 AsyncWindowPos = &H4000 End Enum Protected Overrides Sub WndProc(ByRef m As Message) ' Listen for operating system messages Select Case m.Msg Case WM_WINDOWPOSCHANGING SnapToDesktopBorder(m.LParam) End Select MyBase.WndProc(m) End Sub Private Sub SnapToDesktopBorder(ByVal LParam As IntPtr) ' Snap client to the top, left, bottom or right desktop border ' as the form is moved near that border. ' Marshal the LPARAM value which is a WINDOWPOS struct Dim WPNewPosition As WINDOWPOS = DirectCast(Runtime.InteropServices.Marshal.PtrToStructure(LParam, GetType(WINDOWPOS)), WINDOWPOS) If (WPNewPosition.Flags And SWP.NoSize) = 0 OrElse (WPNewPosition.Flags And SWP.NoMove) = 0 Then Dim RWorking As Rectangle = Screen.FromControl(Me).WorkingArea Dim Changed As Boolean If Math.Abs(WPNewPosition.x - RWorking.X) <= SnapOffset Then WPNewPosition.x = RWorking.X Changed = True ElseIf Math.Abs(WPNewPosition.x + WPNewPosition.cx - RWorking.Right) <= SnapOffset Then WPNewPosition.x = RWorking.Right - WPNewPosition.cx Changed = True End If If Math.Abs(WPNewPosition.y - RWorking.Y) <= SnapOffset Then WPNewPosition.y = RWorking.Y Changed = True ElseIf Math.Abs(WPNewPosition.y + WPNewPosition.cy - RWorking.Bottom) <= SnapOffset Then WPNewPosition.y = RWorking.Bottom - WPNewPosition.cy Changed = True End If ' Marshal it back If Changed Then Runtime.InteropServices.Marshal.StructureToPtr(WPNewPosition, LParam, True) End If End Sub End Class
|
|
|
|
 |
|
 |
I thank ur code, but i've written it in an easier way. It's for a form with no border and control box *formborderstyle = none* (moving the form is done in mousemove event) , but it can be placed in locationchanged event to act when u move form normally.
Here's the code:
Public Class Form1
Dim X1 As Integer, Y1 As Integer
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
X1 = e.X
Y1 = e.Y
End Sub
Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
If Not e.Button = Windows.Forms.MouseButtons.Left Then Exit Sub
Dim WR As Rectangle = Screen.GetWorkingArea(Me)
Dim NewX As Integer = Me.Left + (e.X - X1)
Dim NewY As Integer = Me.Top + (e.Y - Y1)
Dim W As Integer = Me.Width
Dim H As Integer = Me.Height
If NewY >= WR.Top - 15 And NewY <= WR.Top + 15 Then
Me.Top = WR.Top
ElseIf NewY + H > WR.Bottom - 15 And NewY + H < WR.Bottom + 15 Then
Me.Top = WR.Bottom - H
Else
Me.Top = NewY
End If
If NewX >= WR.Left - 15 And NewX <= WR.Left + 15 Then
Me.Left = WR.Left
ElseIf NewX + W > WR.Right - 15 And NewX + W < WR.Right + 15 Then
Me.Left = WR.Right - W
Else
Me.Left = NewX
End If
End Sub
End Class
|
|
|
|
 |
|
 |
I'm sure it's not as difficult as I am making it out to be to modify the msnapoffset value during runtime?
|
|
|
|
 |
|
 |
Nevermind
|
|
|
|
 |
|
 |
Just what I was looking for. Excellent work.
|
|
|
|
 |
|
 |
I have been reading from many sources on form to form docking, and perhaps because of the enviroment i am in(autocad extension) none of it works. Looking at it, it seems this should be retoolable to do edge to edge docking of two forms, since i don't care if the form is pushed off the edge by the user it seems a simple Idea.
If i am wrong, I hope to get input before I try to hard.
Previously i was trying to control form position witht the left and top values of the two frames with the the width and height used to determine remaining position. for some reason it is obvious something else is ruling over the position of the form, so maybe I could engage this code at some tale end event time and get them to link up anyway?
|
|
|
|
 |
|
 |
It works like a charm, thank you for this great piece of code!
|
|
|
|
 |
|
 |
Love it, bro.
I copied it over to C#. If it'll save anyone the same trouble (not much trouble really), I'll be glad to post it.
Mike
|
|
|
|
 |
|
 |
Would love if you would. I was just looking @ the function thinking, I wonder if I could port that successfully.
|
|
|
|
 |
|
 |
Obviously, this is all Perry's code, just in C#. It's his article and a very good one.
private confiltered= 30;
private const int WM_WINDOWPOSCHANGING = 70;
[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPOS
{
public IntPtr hwnd;
public IntPtr hwndInsertAfter;
public int x;
public int y;
public int cx;
public int cy;
public int flags;
}
protected override void WndProc(ref Message m)
{
switch(m.Msg)
{
case WM_WINDOWPOSCHANGING:
SnapToDesktopBorder(this, m.LParam, 0);
break;
}
base.WndProc(ref m);
}
public void SnapToDesktopBorder(Form clientForm, IntPtr LParam, int widthAdjustment)
{
if (clientForm == null)
throw new ArgumentNullException();
// Snap client to the top, left, bottom or right desktop border
// as the form is moved near that border.
try
{
// Marshal the LPARAM value which is a WINDOWPOS struct
WINDOWPOS newPosition = new WINDOWPOS();
newPosition = (WINDOWPOS)System.Runtime.InteropServices.Marshal.PtrToStructure(LParam, newPosition.GetType());
if (newPosition.y == 0 || newPosition.x == 0)
return;
// Adjust the client size for borders and caption bar
Rectangle clientRect = clientForm.RectangleToScreen(clientForm.ClientRectangle);
clientRect.Width += SystemInformation.FrameBorderSize.Width - widthAdjustment;
clientRect.Height += SystemInformation.FrameBorderSize.Height + SystemInformation.CaptionHeight;
// Now get the screen working area (without taskbar)
Rectangle workingRect = Screen.GetWorkingArea(clientForm.ClientRectangle);
// Left border
if (newPosition.x >= workingRect.X - mSnapOffset &&
newPosition.x <= workingRect.X + mSnapOffset)
newPosition.x = workingRect.X;
// Get screen bounds and taskbar height (when taskbar is horizontal)
Rectangle screenRect = Screen.GetBounds(Screen.PrimaryScreen.Bounds);
int taskbarHeight = screenRect.Height = workingRect.Height;
// Top border (check if taskbar is on top or bottom via WorkingRect.Y)
if (newPosition.y >= -mSnapOffset &&
(workingRect.Y > 0 && newPosition.y <= (taskbarHeight + mSnapOffset)) ||
(workingRect.Y <= 0 && newPosition.y <= mSnapOffset))
{
if (taskbarHeight > 0)
newPosition.y = workingRect.Y; // Horizontal Taskbar
else
newPosition.y = 0; // Vertical Taskbar
}
// Right border
if (newPosition.x + clientRect.Width <= workingRect.Right + mSnapOffset &&
newPosition.x + clientRect.Width >= workingRect.Right - mSnapOffset)
newPosition.x = workingRect.Right - (clientRect.Width + SystemInformation.FrameBorderSize.Width);
// Bottom border
if (newPosition.y + clientRect.Height <= workingRect.Bottom + mSnapOffset &&
newPosition.y + clientRect.Height >= workingRect.Bottom - mSnapOffset)
newPosition.y = workingRect.Bottom - (clientRect.Height + SystemInformation.FrameBorderSize.Height);
// Marshal it back
Marshal.StructureToPtr(newPosition, LParam, true);
}
catch (ArgumentException)
{
}
}
|
|
|
|
 |
|
|
 |
|
 |
I just noticed that the first line where the offset is declared is screwed up. Apparently my pasting abilities need some work. It should be:
private const int mSnapOffset = 30;
|
|
|
|
 |
|
 |
This works like a charm, thanks to both the author of the article and you!
|
|
|
|
 |
|
 |
Prety strait forward and very usefull. Thanks
Pablo
Sometimes I think there's no reason to get out of bed . . . then I feel wet, and I realize there is.
|
|
|
|
 |
|
 |
Hi!
When you have more than 1 monitor on your computer, the snapping only works for your primary screen.
On the secondary screen, the window snaps to the top and the bottom (in my case, where the task bar only resides on screen 1, the snapping is off by the taskbar height), but the left and right borders don't have any effect.
Perhaps you can fix this? This would make the solution even better...
Regards,
mav
--
Black holes are the places where god divided by 0...
|
|
|
|
 |
|
 |
It only takes a few minor updates to Perry's original SnapToDesktopBorder subroutine to make it work on multiple desktop systems. All you need to do is change the following two lines in the code:
...
Dim WorkingRect As Rectangle = Screen.GetWorkingArea(clientForm.ClientRectangle)
...
Dim ScreenRect As Rectangle = Screen.GetBounds(Screen.PrimaryScreen.Bounds)
...
to these two, respectively:
...
Dim WorkingRect As Rectangle = Screen.FromControl(clientForm).WorkingArea
...
Dim ScreenRect As Rectangle = Screen.FromControl(clientForm).Bounds
...
-- modified at 18:48 Tuesday 29th August, 2006
|
|
|
|
 |
|
 |
Great little saying ya got there! I would just like to suggest capitalizing the name of God.
--------
Seven days without Jesus makes one weak.
|
|
|
|
 |
|
 |
I haven't tried it out, but it's fantastic stuff to have here. Cheers.
-- modified at 18:49 Thursday 24th August, 2006
|
|
|
|
 |
|
 |
Always wondered how Winamp and others did that. Thanks!
|
|
|
|
 |