Solved

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

Posted on 2007-12-05
5
670 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
Comment Utility
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
Comment Utility
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
Comment Utility
I'm using XP.
Did you wrote any code to move your form? Can you show it?
0
 

Author Comment

by:EEssam
Comment Utility
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
Comment Utility
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

In my previous article (http://www.experts-exchange.com/Programming/Languages/.NET/.NET_Framework_3.x/A_4362-Serialization-in-NET-1.html) we saw the basics of serialization and how types/objects can be serialized to Binary format. In this blog we wi…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

744 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

17 Experts available now in Live!

Get 1:1 Help Now