Solved

A tiny issue with ".NET Snap To Screen Form"

Posted on 2007-12-05
5
671 Views
Last Modified: 2013-12-16
Hi,

The code here is working very good when the ForBorderStyle is NOT set to "None":

http://www.codeproject.com/KB/vb/SnapForm.aspx

In my application, it's set to None... And I move the form by holding down the right mouse button and moving it. The code still partially work, but when I approach the taskbar from the clock side it's not completely sticked to the corners.

I tried to figure out what wrong with code but no luck (and no experience).

The complete code is attached. Just create a new project and paste it.

Your help would be greatly appreciated.
using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices;
 

namespace WindowsFormsApplication11

{

    public partial class Form1 : Form

    {

        public const int WM_NCLBUTTONDOWN = 0xA1;

        public const int HT_CAPTION = 0x2;
 

        [DllImportAttribute("user32.dll")]

        public static extern int SendMessage(IntPtr hWnd,

                         int Msg, int wParam, int lParam);

        [DllImportAttribute("user32.dll")]

        public static extern bool ReleaseCapture();
 

        public Form1()

        {

            InitializeComponent();

        }
 

        private void Form1_Load(object sender, EventArgs e)

        {
 

        }
 

        # region SnapToDesktopBorder
 

        private const int mSnapOffset = 35;

        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)

        {

            // Listen for operating system messages

            switch (m.Msg)

            {

                case WM_WINDOWPOSCHANGING:

                    {

                        SnapToDesktopBorder(this, m.LParam, 0);

                    }

                    break;

            }
 

            base.WndProc(ref m);

        }
 

        public static void SnapToDesktopBorder(Form clientForm, IntPtr LParam, int widthAdjustment)

        {

            if (clientForm == null)

            {

                // Satisfies rule: Validate parameters

                throw new ArgumentNullException("clientForm");

            }
 

            // 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, typeof(WINDOWPOS));
 

                if (NewPosition.y == 0 || NewPosition.x == 0)

                {

                    return;

                    // Nothing to do!

                }
 

                // 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

                System.Runtime.InteropServices.Marshal.StructureToPtr(NewPosition, LParam, true);

            }

            catch (ArgumentException ex)

            {

            }

        }
 
 

        # endregion
 

        private void Form1_MouseMove(object sender, MouseEventArgs e)

        {

            if (e.Button == MouseButtons.Left)

            {

                ReleaseCapture();

                SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);

            }

        }

    }

}

Open in new window

0
Comment
Question by:EEssam
  • 3
  • 2
5 Comments
 
LVL 29

Expert Comment

by:anarki_jimbel
ID: 20417110
OK, I spend hal an hour playing with your application and coud not find any wrong.
It sticks well from what I see (didn't use glasses however so could miss something).
Eventually if you have some extra gap/overlapping  -  just add/subtract couple of pixels.
0
 

Author Comment

by:EEssam
ID: 20417301
I'm using Windows XP SP2, not Vista. The problem is happening only when:

1. FormBorderStyle is set to "None":
2. The form is moved to the corner of Windows clock.
0
 
LVL 29

Expert Comment

by:anarki_jimbel
ID: 20422729
I'm using XP.
Did you wrote any code to move your form? Can you show it?
0
 

Author Comment

by:EEssam
ID: 20423078
The code to move the form is:

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                ReleaseCapture();
                SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
            }
        }
0
 
LVL 29

Accepted Solution

by:
anarki_jimbel earned 500 total points
ID: 20424934
Try this code. For me it works fine.

It's pretty hard to explain why I use '-=" bordersize. However form with borders has
width = "form width without borders" plus
"border width" multiplied by 2. If in the firs case (your original code) we add
border width just once to get width (height) then "borderless" form should be
that minus "border width" multiplied by 2. It was just some logical conclusion.
                // Adjust the client size for borders and caption bar

                Rectangle ClientRect = clientForm.RectangleToScreen(clientForm.ClientRectangle);

                if (clientForm.FormBorderStyle != FormBorderStyle.None)

                {

                    ClientRect.Width += SystemInformation.FrameBorderSize.Width - widthAdjustment;

                    ClientRect.Height += (SystemInformation.FrameBorderSize.Height + SystemInformation.CaptionHeight);
 

                }

                else

                {

                    ClientRect.Width -= SystemInformation.FrameBorderSize.Width - widthAdjustment;

                    ClientRect.Height -= (SystemInformation.FrameBorderSize.Height);
 

                }

Open in new window

0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
This is used to tweak the memory usage for your computer, it is used for servers more so than workstations but just be careful editing registry settings as it may cause irreversible results. I hold no responsibility for anything you do to the regist…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now