Prevent Form being moved

I recently had a need to dock a form to the right hand side of the screen and prevent users from dragging it away. The form can be minimised into the system tray but not resized or moved, of course I could have removed the forms control box and drawn my own but wanted it to fit with the other forms in the project.

Method 1: Override WndProc.

protected override void WndProc(ref Message msg)
{
    const int WM_SYSCOMMAND = 0x0112;
    const int SC_MOVE = 0xF010;

    switch (msg.Msg)
    {
        case WM_SYSCOMMAND:
            int cmd = msg.WParam.ToInt32() & 0xfff0;
    
            if (cmd == SC_MOVE)
                return;
        
            break;
    }

    base.WndProc(ref msg);
}

Method 2: This is the preferred method and allows the form to be dragged onto multiple monitors but will always dock to the right hand side of whichever screen it is dragged to.

private const int scrnBuffer = 5;
private Screen scrn;

private void Form1_Move(object sender, EventArgs e)
{
    SizeForms();
}

private void SizeForms()
{
    scrn = Screen.FromControl(this);

    this.Height = scrn.WorkingArea.Height - scrnBuffer * 2;
    this.Location = new Point(scrn.WorkingArea.Right - this.Width - scrnBuffer, scrn.WorkingArea.Top + scrnBuffer);
}
Advertisements

Control Arrays in .NET

Back in the day when I dabbled briefly in VB6, creating an array of controls was pretty straight forward and it was something that I found hard to adjust to when I moved across to .NET. It’s actually very easy, I’ll show you…

Start a new Winforms project and drop a button on a form, then copy and paste the following code into the button’s click event:

private void button1_Click(object sender, EventArgs e)
{
    int numBtns = 5;   //number of buttons to create.

    for (int i = 0; i < numBtns; i++)
    {
        Button btns = new Button();
        btns.Size = button1.Size;
        btns.Location = new Point(0, 0 + btns.Height * i);   //so the buttons don't overlap.
        btns.Name = "Button" + i;
        btns.Text = btns.Name;
        btns.Click +=new EventHandler(btns_Click);   //so we know when a button is clicked.
        this.Controls.Add(btns);   //add them to the form.
    }
}

public void btns_Click(object sender, EventArgs e)
{
    Button myBtn = (Button)sender;   //the clicked button is sent across as 'sender' so cast this as a Button
    MessageBox.Show("You Clicked" + myBtn.Name);    //and you can use the object as you wish!
}

BAM! Simple as that, we’ve created an array of buttons and assigned them an on_click event handler. There is a Tag property that can be set on the Button control and can also be used to identify which button was clicked.

Transparent ListView Control???

Ok so the ListView control does not support transparency, this I know because last week I spent a couple of hours, first trying to override it’s OnPaint method and finally frustratedly trawling the internet to find out why I could not!  Essentially the ListView control in VS is just a wrapper to the old Win32 control, meaning there’s no simple way of implementing transparency.

Being a newbie to .NET I did not want the complication of learning and using hooks to achieve the desired effect, so did what I tend to always do in situations such as these and cheated!  By creating a pixel array of the background (which has a nice gradient effect) directly behind the ListView box, I was able to create a new Bitmap and use this as the Background Image of the LV, thus giving the illusion of transparency!  Ok ok, yes it’s a cheat and yes, it’s not a very good one but hey it looks the part!

My code is as follows and is almost certainly the least optimal way of achieving this…next step is to look more closely at the Bitmap class for a neater and faster method:

private void MakeTransparent(Control ctrl, int x, int y)
{
    Bitmap bMap = new Bitmap(this.BackgroundImage);
    Color[,] pixelArray = new Color[ctrl.Width, ctrl.Height];

    for (int i = 0; i < ctrl.Width; i++)
    {
        for (int j = 0; j < ctrl.Height; j++)
        {
            pixelArray[i, j] = bMap.GetPixel(x + i, y + j);
        }
    }

    Bitmap bmp = new Bitmap(ctrl.Width, ctrl.Height);

    for (int i = 0; i < ctrl.Width; i++)
    {
        for (int j = 0; j < ctrl.Height; j++)
        {
            bmp.SetPixel(i, j, pixelArray[i, j]);
        }
    }

    ctrl.BackgroundImage = bmp;
    ctrl.Location = new Point(x, y);
}

And the result…