Control resizing mathematics - c#

Ok... So I've got this pretty killer Screenshot system I've been using for a while... It pretty much involves creating a somewhat transparent Form that auto-sizes to fit all monitors... Which gives the screen(s) a "dark-out" effect... I then have a hidden "button" control whos position is set upon mouse-down... Then, until mouse-up, the button will resize in real-time to create a sort of "selection" area... The Button is granted full transparency to implement this effect.
Source Example: http://db.tt/LWxfDB6 [Also posted below]
I'm having two issues that are directly related, I believe.
1.) The coordinates are off for multimonitors, it properly returns the coordinates that are clicked upon (highlighted), but the highlight box (effect) is often on the wrong monitor.
2.) You can only select from top-left ---> bottom-right and not universal.
Sorry if I didn't explain it well, the source should explain better.
Thanks, in advance, for any and all help received. :)
:MarkRect.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.IO;
namespace TW_Media_Chat_
{
public partial class MarkRect : Form
{
Point Point1;
Point Point2;
public MarkRect()
{
InitializeComponent();
// Programatically maximize to all monitors
Screen[] Screens = Screen.AllScreens;
int AllWidth = 0;
int AllHeight = 0;
for (int index = 0; index < Screens.Length; index++)
{
AllWidth += Screens[index].Bounds.Width;
AllHeight += Screens[index].Bounds.Height;
}
this.Width = AllWidth;
this.Height = AllHeight;
}
private void Transparency_MouseDown(object sender, MouseEventArgs e)
{
button1.Visible = true;
button1.Location = Cursor.Position;
Point1 = Cursor.Position;
}
private void Transparency_MouseUp(object sender, MouseEventArgs e)
{
this.Visible = false;
Point2 = Cursor.Position;
AjaxChatBridge.AjaxVars.Point1 = Point1;
AjaxChatBridge.AjaxVars.Point2 = Point2;
this.Close();
}
private void MarkRect_MouseMove(object sender, MouseEventArgs e)
{
this.button1.Width = Cursor.Position.X - this.button1.Left;
this.button1.Height = Cursor.Position.Y - this.button1.Top;
}
}
}
:MarkRect.Designer.cs:
namespace TW_Media_Chat_
{
partial class MarkRect
{
///
/// Required designer variable.
///
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.BackColor = System.Drawing.Color.Lime;
this.button1.ForeColor = System.Drawing.Color.Lime;
this.button1.Location = new System.Drawing.Point(220, 172);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(19, 18);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = false;
this.button1.Visible = false;
//
// MarkRect
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Black;
this.ClientSize = new System.Drawing.Size(490, 406);
this.Controls.Add(this.button1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Name = "MarkRect";
this.Opacity = 0.5D;
this.Text = "Transparency";
this.TopMost = true;
this.TransparencyKey = System.Drawing.Color.Lime;
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Transparency_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MarkRect_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Transparency_MouseUp);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
}
}

You should implement control resizing logic easier:
void MarkRect_MouseMove(...)
{
var mouseX = Cursor.Position.X;
var originalMouseX = Point1.X;
button1.Left = Math.Min(mouseX, originalMouseX);
button1.Width = Math.Abs(mouseX - originalMouseX);
// the same for Y
}
You should post that code here. We are to lazy to go to your dropbox to see the code. There are easier questions to answer here.

Related

Why aren't the generated buttons showing in the FlowLayoutPanel?

So, I'm trying to create an accordion with dynamically loaded buttons. In the future, the title of the buttons will change depending on the details I've retrieved from somewhere. For now, what I'm trying to do is to load buttons to look like these:
I've tried doing the following below:
// Forms1.cs
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
int buttonCount = 3;
var buttons = new FontAwesome.Sharp.IconButton[buttonCount];
for (int i = 0; i < buttonCount; i++)
{
var btn = new FontAwesome.Sharp.IconButton
{
Text = "Button " + i,
TextAlign = ContentAlignment.MiddleLeft,
IconChar = FontAwesome.Sharp.IconChar.Book,
IconColor = ColorTranslator.FromHtml("#6A6A73"),
IconSize = 20,
IconFont = FontAwesome.Sharp.IconFont.Auto,
TextImageRelation = TextImageRelation.ImageBeforeText,
FlatStyle = FlatStyle.Flat
};
btn.FlatAppearance.BorderSize = 0;
btn.ForeColor = ColorTranslator.FromHtml("#6A6A73");
btn.BackColor = ColorTranslator.FromHtml("#FDFEFF");
btn.Dock = DockStyle.Top;
buttons[i] = btn;
}
flowLayoutPanel1.Controls.AddRange(buttons);
}
}
}
// Forms1.Designer.cs
namespace WindowsFormsApp1
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.SuspendLayout();
//
// flowLayoutPanel1
//
this.flowLayoutPanel1.BackColor = System.Drawing.SystemColors.ControlLight;
this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Left;
this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
this.flowLayoutPanel1.Size = new System.Drawing.Size(200, 450);
this.flowLayoutPanel1.TabIndex = 0;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.flowLayoutPanel1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
}
}
Here's what it looks like after building and running the application:
What am I doing wrong?
Form1_Load method is not subscribed to Load event of your form. Body of InitializeComponent is missing following line of code.
this.Load += new System.EventHandler(this.Form1_Load);
Insert this line before this.ResumeLayout(false);. You can fix it in designer as well.

how to disable part ToolStripSplitButton

I would like to disable the button part of a ToolStripSplitButton in a c# winforms app. As far as I see it is not possible and I would like to avoid a complex solution (rewriting entire toolstripsplitbutton) so I'm trying to disable visually at least, ie. draw a grayed icon when button part disabled.
First I browsed referencesource and found that ToolStripRenderer and ToolStripProfessionalRenderer uses some 'internal' properties and methods in OnRenderItemImage(ToolStripItemImageRenderEventArgs e) so I cannot mimic (copy-and-modify-a-bit) the behaviour of OnRenderItemImage.
Next I tried the following code.
Basically it works, the toolStripSplitButton1 is grayed out when the Tag is boolean false.
But this solution kills all my System.Windows.Forms.Timer somehow! Try this code, when toolStripSplitButton1.Tag == false then the toolstrip-independent timer1 does not tick anymore. And the toolStripSplitButton1 tooltip does not show up (guess because it uses Timer as well).
(button1 and button1_Click is just for toggle toolStripSplitButton1.Tag)
My first question is why OnRenderItemImage kills all System.Windows.Forms.Timer?
Second question is how to achieve the original aim to gray out button icon at least visually independently of the button itself?
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
toolStrip1.Renderer = new MyToolStripProfessionalRenderer();
toolStripSplitButton1.Tag = false; // this is for disabling button part
toolStripSplitButton1.ToolTipText = "toolStripSplitButton1 ToolTip";
System.Windows.Forms.Timer timer1 = new Timer();
timer1.Interval = 1000;
timer1.Tick += T_Tick;
timer1.Start();
}
int ticks = 0;
private void T_Tick(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine(ticks++);
}
private void button1_Click(object sender, EventArgs e)
{
toolStripSplitButton1.Tag = !((bool)toolStripSplitButton1.Tag);
}
}
class MyToolStripProfessionalRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderItemImage(ToolStripItemImageRenderEventArgs e)
{
try
{
if (e.Item.Enabled &&
e.Item.Tag?.GetType() == typeof(bool) &&
!(bool)e.Item.Tag)
{
e.Item.Enabled = false;
base.OnRenderItemImage(e);
e.Item.Enabled = true;
}
else
base.OnRenderItemImage(e);
}
catch (Exception ex)
{
// this never reached, there's no exceptions
System.Diagnostics.Debug.WriteLine(ex);
}
}
}
}
Designer.cs:
namespace WindowsFormsApplication
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.toolStripSplitButton1 = new System.Windows.Forms.ToolStripSplitButton();
this.button1 = new System.Windows.Forms.Button();
this.toolStrip1.SuspendLayout();
this.SuspendLayout();
//
// toolStrip1
//
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripSplitButton1});
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(352, 25);
this.toolStrip1.TabIndex = 0;
this.toolStrip1.Text = "toolStrip1";
//
// toolStripSplitButton1
//
this.toolStripSplitButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.toolStripSplitButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripSplitButton1.Image")));
this.toolStripSplitButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
this.toolStripSplitButton1.Name = "toolStripSplitButton1";
this.toolStripSplitButton1.Size = new System.Drawing.Size(32, 22);
this.toolStripSplitButton1.Text = "toolStripSplitButton1";
//
// button1
//
this.button1.Location = new System.Drawing.Point(13, 64);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 1;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(352, 265);
this.Controls.Add(this.button1);
this.Controls.Add(this.toolStrip1);
this.Name = "Form1";
this.Text = "Form1";
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ToolStrip toolStrip1;
private System.Windows.Forms.ToolStripSplitButton toolStripSplitButton1;
private System.Windows.Forms.Button button1;
}
}
I don't think that using a timer for tracking the change is a good idea. What I suggest is create a changeOccurred event and do the operations inside the event.

Foreach stops finding dynamically created controls after some amount of time. Resizing window makes it work again. Why? How can I fix it?

I'm a fairly new c# programmer currently in class and I've been doing this side project that (kind of) accurately represents bouncing balls. I also want it to be able to handle balls that are created on mouse click. I've done all of this and it works, for a few seconds. The original ball always works and always bounces/rolls. Dynamically created balls that are created on mouse click will hop and roll for a little but then they all freeze(not all at the same time) as the foreach statement I use stops recognizing that they are there. Weirdly enough when the window is resized using the bottom they start to work again. Am I missing something or is this a bug I can't fix? Here's the form code and the designer code. If you need anything else let me know.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace testBouncingBallMulti
{
public partial class Form1 : Form
{
const int INITY = 0;
const int INITX = 3;
const int GRAVITY = 1;
public Form1()
{
InitializeComponent();
this.ball0.Tag = new Point(INITX, INITY);
}
byte counter = 1;
private void createBall(object sender, MouseEventArgs e)
{
Label l = new Label();
l.BackColor = System.Drawing.Color.Black;
l.Location = new Point(MousePosition.X - this.Left, MousePosition.Y - this.Top);
this.Controls.Add(l);
l.Size = new System.Drawing.Size(15, 15);
l.Tag = new Point(INITX, INITY);
l.Name = "ball" + Convert.ToString(counter);
counter++;
}
private void physicsLoop1(object sender, EventArgs e)
{
foreach (var ball in this.Controls.OfType<Label>())
{
moveBall(ball);
bounce(ball);
Point? init = ball.Tag as Point?;
Point velocities = init.GetValueOrDefault(new Point(0, 0));
if (velocities.Y == 0 && ball.Location.Y >= ClientSize.Height - 15)
{
return;
}
velocities.Y = velocities.Y + GRAVITY;
ball.Tag = new Point(velocities.X, velocities.Y);
}
}
private void moveBall(Control ball)
{
Point? init = ball.Tag as Point?;
Point velocities = init.GetValueOrDefault(new Point(0,0));
ball.Location = new Point(ball.Location.X + velocities.X, ball.Location.Y + velocities.Y);
}
private void bounce(Control ball)
{
Point? init = ball.Tag as Point?;
Point velocities = init.GetValueOrDefault(new Point(0,0));
if (ball.Location.Y >= ClientSize.Height - 15)
{
if (velocities.Y == 0 && ball.Location.Y >= ClientSize.Height - 15)
{
}
else if (ball.Location.Y > ClientSize.Height - 15)
{
ball.Location = new Point(ball.Location.X, ClientSize.Height - 15);
velocities.Y = -(velocities.Y - 2);
}
}
if (ball.Location.X >= ClientSize.Width - 15)
{
velocities.X = -(velocities.X);
}
if (ball.Location.X <= 0)
{
ball.Location = new Point(0, ball.Location.Y);
velocities.X = -(velocities.X);
}
ball.Tag = new Point(velocities.X, velocities.Y);
}
private void physicsLoop2(object sender, EventArgs e)
{
}
private void physicsLoop3(object sender, EventArgs e)
{
}
}
}
and the designer code:
namespace testBouncingBallMulti
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.ball0 = new System.Windows.Forms.Label();
this.timer2 = new System.Windows.Forms.Timer(this.components);
this.timer3 = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Interval = 20;
this.timer1.Tick += new System.EventHandler(this.physicsLoop1);
//
// ball0
//
this.ball0.BackColor = System.Drawing.Color.Black;
this.ball0.Location = new System.Drawing.Point(12, 24);
this.ball0.Name = "ball0";
this.ball0.Size = new System.Drawing.Size(15, 15);
this.ball0.TabIndex = 0;
//
// timer2
//
this.timer2.Tick += new System.EventHandler(this.physicsLoop2);
//
// timer3
//
this.timer3.Tick += new System.EventHandler(this.physicsLoop3);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(504, 396);
this.Controls.Add(this.ball0);
this.Name = "Form1";
this.Text = "Form1";
this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.createBall);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Label ball0;
private System.Windows.Forms.Timer timer2;
private System.Windows.Forms.Timer timer3;
}
}
Replace return with continue in
if (velocities.Y == 0 && ball.Location.Y >= ClientSize.Height - 15)
{
return;
}
You need to give some breathing room in your label move procedure to repaint the form. Either use best practice and place your painting into a thread or at least process a windows message or two in your timer loop.

InvalidateRec with User32.dll , trying to delete all other frames except last frame created

Im actually trying to paint an elipse around my cursor when i moove it, I dont want it to leave a trail like it does actually.
Can someone help with this, I believe it has something to do with the invalidaterec option
Any example son using invalidate rec?
Here is my code, besides the trail it has to work the same way it does now.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace MouseTest
{
public partial class Form1 : Form
{
[DllImport("user32.dll", EntryPoint = "GetDC")]
private static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll", EntryPoint = "ReleaseDC")]
private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[System.Runtime.InteropServices.DllImport("Shell32.dll")]
private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
System.Timers.Timer t1 = new System.Timers.Timer(100);
public Form1()
{
t1.Elapsed += new System.Timers.ElapsedEventHandler(t1_Elapsed);
t1.Start();
// System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
//Mouse.OverrideCursor = System.Windows.Input.Cursors.Hand;
InitializeComponent();
}
void t1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
t1.Stop();
//SolidBrush b = new SolidBrush(Color.Red);
IntPtr desktopDC = GetDC(IntPtr.Zero);
Graphics g = Graphics.FromHdc(desktopDC);
g.FillEllipse(new SolidBrush(Color.BlueViolet), Cursor.Position.X, Cursor.Position.Y, 25, 25);
g.Dispose();
ReleaseDC(IntPtr.Zero, desktopDC);
t1.Start();
}
}
}
Yes, keeping the previous coordinate and calling InvalidateRect on the previous enclosing rectangle before drawing the new new ellipse would probably work. I don't have any code lying around that calls InvalidateRect, but if this is exactly your goal:" to paint an elipse around my cursor when i moove it, I dont want it to leave a trail like it does actually." there are other, more straight forward ways.
One way is to draw the ellipse on a transparent form and then move that form around based on the cursor's movement:
Here, first is the form definition:
namespace MouseForm
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.shapeContainer1 = new Microsoft.VisualBasic.PowerPacks.ShapeContainer();
this.ovalShape1 = new Microsoft.VisualBasic.PowerPacks.OvalShape();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// shapeContainer1
//
this.shapeContainer1.Location = new System.Drawing.Point(0, 0);
this.shapeContainer1.Margin = new System.Windows.Forms.Padding(0);
this.shapeContainer1.Name = "shapeContainer1";
this.shapeContainer1.Shapes.AddRange(new Microsoft.VisualBasic.PowerPacks.Shape[] {
this.ovalShape1});
this.shapeContainer1.Size = new System.Drawing.Size(74, 74);
this.shapeContainer1.TabIndex = 0;
this.shapeContainer1.TabStop = false;
//
// ovalShape1
//
this.ovalShape1.BorderColor = System.Drawing.Color.Red;
this.ovalShape1.BorderWidth = 3;
this.ovalShape1.FillColor = System.Drawing.SystemColors.Control;
this.ovalShape1.FillStyle = Microsoft.VisualBasic.PowerPacks.FillStyle.Solid;
this.ovalShape1.Location = new System.Drawing.Point(2, 2);
this.ovalShape1.Name = "ovalShape1";
this.ovalShape1.Size = new System.Drawing.Size(70, 70);
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(74, 74);
this.ControlBox = false;
this.Controls.Add(this.shapeContainer1);
this.Enabled = false;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Name = "Form1";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.Text = "Form1";
this.TopMost = true;
this.TransparencyKey = System.Drawing.SystemColors.Control;
this.ResumeLayout(false);
}
#endregion
private Microsoft.VisualBasic.PowerPacks.ShapeContainer shapeContainer1;
private Microsoft.VisualBasic.PowerPacks.OvalShape ovalShape1;
private System.Windows.Forms.Timer timer1;
}
}
And here is the code:
using System;
using System.Windows.Forms;
namespace MouseForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
this.Left = Cursor.Position.X - this.Width / 2;
this.Top = Cursor.Position.Y - this.Height / 2;
}
}
}
I'll leave it as an exercise to the reader to implement a way to close the transparent form :)

What's the correct way to use controls in Owner drawn list box?

I am experimenting with owner drawn list box. I am adding a text box to a specific item within list box. However, when I start scrolling, the text box does not display in the right location. What is the right way to do this?
Here's the code I am using.
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace ListBoxControlScrollIssue
{
public partial class Form1 : Form
{
private const Int32 cellHeight = 40;
private ListBox listBox1;
private Font displayFont = new Font(FontFamily.GenericSerif, 8, FontStyle.Regular);
private Brush displayBrush = Brushes.Black;
private Pen displayPen = Pens.Black;
private Button separateDebug;
private TextBox item3Text;
public Form1()
{
SetupListBox();
}
private void SetupListBox()
{
this.listBox1 = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// listBox1
//
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point(40, 40);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(300, 100);
this.listBox1.TabIndex = 0;
this.listBox1.DrawMode = DrawMode.OwnerDrawVariable;
this.listBox1.MeasureItem += new MeasureItemEventHandler(listBox1_MeasureItem);
this.listBox1.DrawItem += new DrawItemEventHandler(listBox1_DrawItem);
//
// Add items to list box.
//
this.listBox1.Items.Add("Item0");
this.listBox1.Items.Add("Item1");
this.listBox1.Items.Add("Item2");
this.listBox1.Items.Add("Item3");
this.listBox1.Items.Add("Item4");
//
// Add button.
//
separateDebug = new Button();
separateDebug.Name = "SeperateDebug";
separateDebug.Text = "Seperator";
separateDebug.Location = new Point(400, 100);
separateDebug.Click += new EventHandler(separateDebug_Click);
//
// Create the text box. However, don't add it to anything.
//
item3Text = new TextBox();
item3Text.Name = "item3Text";
item3Text.Multiline = false;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(525, 421);
this.Controls.Add(this.listBox1);
this.Controls.Add(this.separateDebug);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
void separateDebug_Click(object sender, EventArgs e)
{
Debug.Print("\n=========================\n");
}
void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
PointF displayLocation = new PointF(20, e.Index * cellHeight + 3);
//
// Display text names of the items here.
//
//
Debug.Print("DrawItem:: Index = {0}, location = {1}", e.Index, displayLocation);
e.Graphics.DrawString(this.listBox1.Items[e.Index].ToString(), displayFont, displayBrush, e.Bounds);
//
// Draw rectangle around the border to show boundary of cell.
//
e.Graphics.DrawRectangle(displayPen, e.Bounds);
}
void listBox1_MeasureItem(object sender, MeasureItemEventArgs e)
{
e.ItemHeight = cellHeight;
e.ItemWidth = this.listBox1.Width;
if (e.Index == 3)
{
//
// Set the location of item3Text to the location of bounds.
//
item3Text.Location = new Point(21, e.Index * cellHeight + 21);
listBox1.Controls.Add(item3Text);
}
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace ListBoxControlScrollIssue
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Form.Designer.cs
namespace ListBoxControlScrollIssue
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
}
#endregion
}
}
Edit I re-wrote my answer in order to be clearer.
The ListBox below displays a TextBox with along its SelectedItem.
GetItemRectangle(int index)
is used to retrieve an item's current location in the ListBox. It seems to be the key method you're looking for.
public class ListBoxEx : ListBox
{
public ListBoxEx()
{
TextBox.Visible = false;
Controls.Add(TextBox);
}
private readonly Size TextBoxOffset = new Size(16, 16);
private const Int32 CellHeight = 40;
private readonly TextBox TextBox = new TextBox();
protected override void OnSelectedIndexChanged(EventArgs e)
{
base.OnSelectedIndexChanged(e);
TextBox.Visible = SelectedIndex != -1;
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);
// Somehow necessary
e.Graphics.FillRectangle(new SolidBrush(BackColor), e.Bounds);
// Drawing the item's text
e.Graphics.DrawString(Items[e.Index].ToString(), Font, new SolidBrush(ForeColor), e.Bounds);
// Drawing the item's borders
e.Graphics.DrawRectangle(new Pen(ForeColor), e.Bounds);
// Drawing updating the TextBox location
if (SelectedIndex != -1)
TextBox.Location = Point.Add(GetItemRectangle(SelectedIndex).Location, TextBoxOffset);
// Because clicking the scrollbar sometimes cause the ListBox to hide the TextBox
TextBox.BringToFront();
// Making sure the TextBox is redrawn ASAP
TextBox.Invalidate();
}
protected override void OnMeasureItem(MeasureItemEventArgs e)
{
base.OnMeasureItem(e);
e.ItemHeight = CellHeight;
}
}

Categories