Create an instance of app for each screen - c#

I want my WinForms application to create an instance of itself for each screen and display on that screen.
I have the following code:
Main form:
class MainForm
{
public MainForm()
{
string[] args = Environment.GetCommandLineArgs();
foreach (string arg in args)
{
if (arg == "TakeOverAllScreens") { TakeOverAllScreens(); }
if (arg.StartsWith("Screen|"))
{
string[] s;
s = arg.Split('|');
int xPos , yPos, screenNum ;
int.TryParse(s[1], out xPos);
int.TryParse(s[2], out yPos);
int.TryParse(s[3], out screenNum);
Screen[] sc;
sc = Screen.AllScreens;
this.Left = sc[screenNum].Bounds.Width;
this.Top = sc[screenNum].Bounds.Height;
this.StartPosition = FormStartPosition.Manual;
}
}
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
}
}
TakeOverAllScreens form:
private void TakeOverAllScreens()
{
int i = 0;
foreach (Screen s in Screen.AllScreens)
{
if (s != Screen.PrimaryScreen)
{
i++;
Process.Start(Application.ExecutablePath, "Screen|" + s.Bounds.X + "|" + s.Bounds.Y+"|" + i);
}
}
}
My application does create a new instance for every screen, however it only displays on my main screen and does not display on the other screens.

This looks suspect:
int.TryParse(s[1], out xPos);
int.TryParse(s[2], out yPos);
int.TryParse(s[3], out screenNum);
Screen[] sc;
sc = Screen.AllScreens;
this.Left = sc[screenNum].Bounds.Width;
this.Top = sc[screenNum].Bounds.Height;
You pass x and y values across on the command line, and then ignore them and use the width and height of the screen to set your x/y values. If all of the screens are the same resolution, and arranged horizontally or vertically, it's likely that all of these windows are positioned below (or to the right of) any visible portions of the screen.
I also can't find any guarantee that Screen.AllScreens will always return the screens in the same order, so the screenNum value may be referencing a different screen.
I'd also prefer to see this code appearing after the call to InitializeComponents rather than before, so you know that any designer set properties will be overridden by your code, rather than vice versa.
So, my code is:
public MainForm()
{
InitializeComponent();
string[] args = Environment.GetCommandLineArgs();
foreach (string arg in args)
{
if (arg == "TakeOverAllScreens") { TakeOverAllScreens(); }
if (arg.StartsWith("Screen|"))
{
string[] s;
s = arg.Split('|');
int xPos, yPos, screenNum;
int.TryParse(s[1], out xPos);
int.TryParse(s[2], out yPos);
this.Left = xPos;
this.Top = yPos;
this.StartPosition = FormStartPosition.Manual;
}
}
}
And:
private void TakeOverAllScreens()
{
foreach (Screen s in Screen.AllScreens)
{
if (s != Screen.PrimaryScreen)
{
Process.Start(Application.ExecutablePath, "Screen|" + s.Bounds.X + "|" + s.Bounds.Y);
}
}
}
Of course, the TryParse calls are pointless and can be replaced by Parse, if you're just going to ignore the return value.

Related

c# windows forms application Pinning start location when button clicked

I have made a new windows forms application, and I'm trying to use a button to allow the user to save the application startup location when the button is clicked. I have tried to look the problem up, but I can't find anything about using a button to do it.
Here is what I have found so far which saves the location on the screen when the form is closed, I just don't know how to make it only save the location when a button is clicked:
public static void GeometryFromString(string thisWindowGeometry, Form formIn)
{
if (string.IsNullOrEmpty(thisWindowGeometry) == true)
{
return;
}
string[] numbers = thisWindowGeometry.Split('|');
string windowString = numbers[4];
if (windowString == "Normal")
{
Point windowPoint = new Point(int.Parse(numbers[0]),
int.Parse(numbers[1]));
Size windowSize = new Size(int.Parse(numbers[2]),
int.Parse(numbers[3]));
bool locOkay = GeometryIsBizarreLocation(windowPoint, windowSize);
bool sizeOkay = GeometryIsBizarreSize(windowSize);
if (locOkay == true && sizeOkay == true)
{
formIn.Location = windowPoint;
formIn.Size = windowSize;
formIn.StartPosition = FormStartPosition.Manual;
formIn.WindowState = FormWindowState.Normal;
}
else if (sizeOkay == true)
{
formIn.Size = windowSize;
}
}
else if (windowString == "Maximized")
{
formIn.Location = new Point(100, 100);
formIn.StartPosition = FormStartPosition.Manual;
formIn.WindowState = FormWindowState.Maximized;
}
}
private static bool GeometryIsBizarreLocation(Point loc, Size size)
{
bool locOkay;
if (loc.X < 0 || loc.Y < 0)
{
locOkay = false;
}
else if (loc.X + size.Width > Screen.PrimaryScreen.WorkingArea.Width)
{
locOkay = false;
}
else if (loc.Y + size.Height > Screen.PrimaryScreen.WorkingArea.Height)
{
locOkay = false;
}
else
{
locOkay = true;
}
return locOkay;
}
private static bool GeometryIsBizarreSize(Size size)
{
return (size.Height <= Screen.PrimaryScreen.WorkingArea.Height &&
size.Width <= Screen.PrimaryScreen.WorkingArea.Width);
}
public static string GeometryToString(Form mainForm)
{
return mainForm.Location.X.ToString() + "|" +
mainForm.Location.Y.ToString() + "|" +
mainForm.Size.Width.ToString() + "|" +
mainForm.Size.Height.ToString() + "|" +
mainForm.WindowState.ToString();
}
Here's one of many ways to implement a button to save the Location (and optionally Size).
First, Create a Settings resource if one doesn't already exist. Right-click on the Project and select Properties.
Choose the Settings tab and click the link to create the resource.
Make entries for Size and Location:
Add a Click handler for your Save button:
public MainForm()
{
InitializeComponent();
buttonSaveSizeAndPosition.Click += saveSizeAndPosition;
}
private async void saveSizeAndPosition(object sender, EventArgs e)
{
Properties.Settings.Default.Location = Location;
Properties.Settings.Default.Size = Size;
Properties.Settings.Default.Save();
var textB4 = Text;
Text = $"Location = {Location} Size = {Size}";
await Task.Delay(1000);
Text = textB4;
}
Then, when you load the main form check to see whether the Size has moved off of the default value before reloading these properties:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!Properties.Settings.Default.Size.Equals(new Size()))
{
Location = Properties.Settings.Default.Location;
Size = Properties.Settings.Default.Size;
}
}

Moving picture box fast causes flickering C# [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm trying to move a picture box fast as it is representing a bullet. However, there is a flickering effect and it obscures the image and it is very hard to see the bullet move. I have tried to use double buffering and Invalidating the picture box before its moved but to no avail. Any suggestions? Maybe im using double buffering wrong? (I have it set to be enabled when the form is loaded.)
Code
On the Form:
public void Shoot(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
PictureBox bulletImage = new PictureBox();
DoubleBuffered = true;
StandardBullet bullet = new StandardBullet(PB_CHARA.Location.X, PB_CHARA.Location.Y, FRM_GAME.MousePosition.X, FRM_GAME.MousePosition.Y, this.ClientRectangle, bulletImage);
Controls.Add(bulletImage);
}
}
Within the Standard Bullet class:
public class StandardBullet
{
public string ImageName = "DataBaseMod.Properties.Resources.StandardBullet_3x";
public int sizeX = 15;
public int sizeY = 19;
public int x = 0;
public int y = 0;
int charaPostitionX;
int charaPostitionY;
PictureBox bulletPoint;
public int[] vector = new int[2];
private System.Timers.Timer bulletTimer;
private System.Timers.Timer RemoveTimer;
System.Drawing.Rectangle FRMBounds;
//public delegate void UpdateControlsDelegate();
public StandardBullet(int charaPostiX, int charaPostiY, int MousePostiX, int MousePostiY, System.Drawing.Rectangle FRMboundaries, PictureBox bulletImage)
{
FRMBounds = FRMboundaries;
bulletPoint = bulletImage;
bulletPoint.Name = ImageName;
string filename = ImageName;
bulletPoint.BackgroundImage = DataBaseMod.Properties.Resources.StandardBullet_3x;
var size = new System.Drawing.Size(sizeX, sizeY);
bulletPoint.Size = size;
bulletPoint.BackgroundImageLayout = ImageLayout.Stretch;
charaPostitionX = charaPostiX;
charaPostitionY = charaPostiY;
x = charaPostiX;
y = charaPostiY;
vector[0] = charaPostiX - MousePostiX;
vector[1] = charaPostiY - MousePostiY;
vectorCalc();
bulletTimer = new System.Timers.Timer(10);
RemoveTimer = new System.Timers.Timer(100);
bulletTimer.Elapsed += TickHandler;
bulletTimer.AutoReset = true;
bulletTimer.Enabled = true;
RemoveTimer.Elapsed += removeTickHandler;
RemoveTimer.Enabled = true;
RemoveTimer.AutoReset = true;
}
public void TickHandler(object sender, ElapsedEventArgs e)
{
x = x + vector[0];
y = y + vector[1];
moveBullet();
}
public void removeTickHandler(object sender, ElapsedEventArgs e)
{
RemoveBullet();
}
public void moveBullet()
{
bulletPoint.BeginInvoke(new MethodInvoker(() => { bulletPoint.Location = new System.Drawing.Point(x, y); }));
}
public void vectorCalc()
{
if (vector[0] >= 1)
{
vector[0] = -10;
}
else if (vector[0] <= -1)
{
vector[0] = 10;
}
if (vector[1] >= 1)
{
vector[1] = -10;
}
else if (vector[1] <= -1)
{
vector[1] = 10;
}
}
public void RemoveBullet()
{
if (
(FRMBounds.Left >= bulletPoint.Bounds.Left) ||
( FRMBounds.Right <= bulletPoint.Bounds.Right) ||
(FRMBounds.Top >= bulletPoint.Bounds.Top) ||
(FRMBounds.Bottom <= bulletPoint.Bounds.Bottom)
)
{
Death();
return;
}
}
public void Death()
{
try
{
bulletTimer.Enabled = false;
bulletPoint.Invoke(new MethodInvoker(() => { FRM_GAME.KillBullet(bulletPoint); }));
RemoveTimer.Enabled = false;
}
catch(Exception e)
{
}
}
}
Thanks!
EDIT: I am going to remove this as i think the error may have been casued by my computer. I had two other games running whilst this one and i think this may have caused the poor rendering. Ran my code this morning and everything is fine. Sorry for this.
Using WinForms for dynamic graphics purposes is not a good idea. Instead of controls, try using Graphics and draw desired object on form (or panel or anywhere you want to).

C# - show child control (Listbox) on top of parent control(textbox) in winform

Created a custom intellisense textbox (textbox with listbox a child).
As shown in below image, the listbox pops up when i enter a char which all works fine and good but when i am at the end of textbox the listbox is partially visible, is there anyway i can show the whole listbox content?
Tried this "Show control inside user control outside the boundaries of its parent
But when the popup window opens the text box looses focus and i cannot type anything further, my intellisense textbox keeps giving better results based on what they type but in this situation i am not able to type anymore.
FYI tried to add pParentControl.Focus() into show method defined in other article as shown below, missing something?
public void Show(Control pParentControl)
{
if (pParentControl == null) return;
// position the popup window
var loc = pParentControl.PointToScreen(new Point(0, pParentControl.Height));
pParentControl.Focus();
m_tsdd.Show(loc);
}
Here is the complete code
class TextBox_AutoComplete : TextBox
{
#region Class Members
List<string> dictionary;
ListBox listbox = new ListBox();
#endregion
private PopupHelper m_popup;
#region Extern functions
[DllImport("user32")]
private extern static int GetCaretPos(out Point p);
#endregion
#region Constructors
public TextBox_AutoComplete() : base()
{
this.Margin = new Padding(0, 0, 0, 0);
this.Multiline = true;
this.Dock = DockStyle.Fill;
this.KeyDown += Textbox_KeyDown;
this.KeyUp += Textbox_KeyUp;
listbox.Parent = this;
listbox.KeyUp += List_OnKeyUp;
listbox.Visible = false;
this.dictionary = new List<string>();
}
#endregion
#region Properties
public List<string> Dictionary
{
get { return this.dictionary; }
set { this.dictionary = value; }
}
#endregion
#region Methods
private static string GetLastString(string s)
{
Regex rgx = new Regex("[^a-zA-Z0-9_.\\[\\]]");
s = rgx.Replace(s, " ");
string[] strArray = s.Split(' ');
return strArray[strArray.Length - 1];
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
Point cp;
GetCaretPos(out cp);
List<string> lstTemp = new List<string>();
List<string> TempFilteredList = new List<string>();
string LastString = GetLastString(this.Text.Substring(0, SelectionStart));
//MessageBox.Show(LastString);
/*seperated them so that column name matches are found first*/
TempFilteredList.AddRange(dictionary.Where(n => n.Replace("[", "").ToUpper().Substring(n.IndexOf(".") > 0 ? n.IndexOf(".") : 0).StartsWith(LastString.ToUpper())
).Select(r => r)
.ToList());
TempFilteredList.AddRange(dictionary.Where(n => n.Replace("[", "").ToUpper().StartsWith(LastString.ToUpper())
|| n.ToUpper().StartsWith(LastString.ToUpper()))
.Select(r => r)
.ToList());
lstTemp = TempFilteredList.Distinct().Select(r => r).ToList();
/*Getting max width*/
int maxWidth = 0, temp = 0;
foreach (var obj in lstTemp)
{
temp = TextRenderer.MeasureText(obj.ToString(), new Font("Arial", 10, FontStyle.Regular)).Width;
if (temp > maxWidth)
{
maxWidth = temp;
}
}
listbox.SetBounds(cp.X + 20, cp.Y + 20, maxWidth, 60);
if (lstTemp.Count != 0 && LastString != "")
{
listbox.DataSource = lstTemp;
// listbox.Show();
if (m_popup == null)
m_popup = new PopupHelper(listbox);
m_popup.Show(this);
}
else if (m_popup != null)
{
//listbox.Hide();
m_popup.Hide();
}
}
protected void Textbox_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Down)
{
if (listbox.Visible == true)
{
listbox.Focus();
}
e.Handled = true;
}
else if (e.KeyCode == Keys.Escape)
{
listbox.Visible = false;
e.Handled = true;
}
}
protected void Textbox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space && listbox.Visible == true)
{
listbox.Focus();
List_OnKeyUp(listbox, new KeyEventArgs(Keys.Space));
e.Handled = true;
}
if (e.KeyCode == Keys.Down && listbox.Visible == true)
{
listbox.Focus();
e.Handled = true;
}
}
private void List_OnKeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space || e.KeyCode == Keys.Enter)
{
int Selection_Start = this.SelectionStart;
string StrLS = GetLastString(this.Text.Substring(0, Selection_Start));
this.Select(Selection_Start - StrLS.Length, StrLS.Length);
// MessageBox.Show(this.Selection_Start.ToString() + " Last string" + StrLS);
this.SelectedText=((ListBox)sender).SelectedItem.ToString();
listbox.Hide();
this.Focus();
}
}
#endregion
}
public sealed class PopupHelper : IDisposable
{
private readonly Control m_control;
private readonly ToolStripDropDown m_tsdd;
private readonly Panel m_hostPanel; // workarround - some controls don't display correctly if they are hosted directly in ToolStripControlHost
public PopupHelper(Control pControl)
{
m_hostPanel = new Panel();
m_hostPanel.Padding = Padding.Empty;
m_hostPanel.Margin = Padding.Empty;
m_hostPanel.TabStop = false;
m_hostPanel.BorderStyle = BorderStyle.None;
m_hostPanel.BackColor = Color.Transparent;
m_tsdd = new ToolStripDropDown();
m_tsdd.CausesValidation = false;
m_tsdd.Padding = Padding.Empty;
m_tsdd.Margin = Padding.Empty;
m_tsdd.Opacity = 0.9;
m_control = pControl;
m_control.CausesValidation = false;
m_control.Resize += MControlResize;
//m_hostPanel.Controls.Add(m_control);
m_tsdd.Padding = Padding.Empty;
m_tsdd.Margin = Padding.Empty;
m_tsdd.MinimumSize = m_tsdd.MaximumSize = m_tsdd.Size = pControl.Size;
m_tsdd.Items.Add(new ToolStripControlHost(m_control));
}
private void ResizeWindow()
{
m_tsdd.MinimumSize = m_tsdd.MaximumSize = m_tsdd.Size = m_control.Size;
m_hostPanel.MinimumSize = m_hostPanel.MaximumSize = m_hostPanel.Size = m_control.Size;
}
private void MControlResize(object sender, EventArgs e)
{
ResizeWindow();
}
/// <summary>
/// Display the popup and keep the focus
/// </summary>
/// <param name="pParentControl"></param>
public void Show(Control pParentControl)
{
if (pParentControl == null) return;
// position the popup window
var loc = pParentControl.PointToScreen(new Point(0, pParentControl.Height));
pParentControl.Focus();
m_tsdd.Show(loc);
}
public void Hide()
{
m_tsdd.Hide();
}
public void Close()
{
m_tsdd.Close();
}
public void Dispose()
{
m_control.Resize -= MControlResize;
m_tsdd.Dispose();
m_hostPanel.Dispose();
}
}
Firstly, I personally don't see any benefit in having a control inside another. Yes, the child control is locked inside its parent's boundaries automatically for you, but this benefit is negated by the issue that you're facing, and solving that issue requires the same work as when the two controls have no relation. In both cases, you'll have to do the calculations manually to keep the child visible inside its parent. In the second case the parent is the app's window.
Secondly, I don't recommend using hacks like the one mentioned in the comments to show the child outside its parent's boundaries. The hack creates more issues than it solves, as you found out. And what's the point of that hack anyway? If you want to show the child outside the parent, then don't make it a child control in the first place, and you don't need any hack.
The best solution is the one that you find in any well designed app, and in Windows itself. Open any app, let's say Notepad, and right-click near the upper-left corner. You'll see the context menu pulling to lower-right direction. Now right-click near the other three corners and you'll see the context menu pulling in different direction each time, so it will always be visible inside the app. Now if you resize the app window too small and right-click, the context menu will choose the best direction but some of it will be outside the app because the window is too small. That's why you need your list not to be a child, but it's up to you, and it's only about these edge cases. The solution will be similar in both cases.
You're displaying the list in this line:
listbox.SetBounds(cp.X + 20, cp.Y + 20, maxWidth, 60);
The key is cp.X and cp.Y. This is what decides where the list will appear. You need to make this point dynamic and responsive to the boundaries of the parent. You fixed the width to maxWidth and height to 60, so I will use those values in the calculation.
To make sure the list will not go beyond the bottom:
var y = this.Height < cp.Y + 60 ? this.Height - 60 : cp.Y;
To make sure the list will not go beyond the right:
var x = this.Width < cp.X + maxWidth ? this.Width - maxWidth : cp.X;
Now you can show your list at the calculated point:
listbox.SetBounds(x, y, maxWidth, 60);
Notes:
I didn't include the 20 gap that you used. I think it looks better without the gap and I haven't seen any app that has a gap. If you prefer the gap, add it to the calculation of x and y. Don't add it in the SetBounds() or that will screw up the calculation.
The calculation above doesn't take into account when the parent size is too small to show the child inside. If you want to support that edge case, you need to make the child a separate control and add some checks to the calculation.

Microsoft VSrollBar behavior or bug with touch screen - windows forms

I found a strange behavior with VScrollBar (vertical scrollbar available in Visual Studio tool box). The problem is "if I swipe down on the scrollbar, it moves up. If I swipe up, it moves down".
Steps to replicate Bug or behavior - 1
1) Add VScrollBar as a child to any user control.
2) Swipe up or down on the user control (not on scrollbar). Vertical scrollbar moves in opposite direction even if there isn't any programmatical connection between content and VScrollBar
Steps to replicate Bug or behavior - 2
1) Add VScrollBar as a child to any user control.
2) Swipe on scrollbar, it will move up during swipe up and down during swipe down (correct behavior)
3) Swipe up or down on the user control. Vertical scrollbar moves in opposite direction
4) Now swipe up or down on the vertical scrollbar. Vertical scrollbar starts moving in opposite direction (Buggy behavior, happens only after bug no: 1)
Simple control with vertical scrollbar to replicate this behavior
public class QuickViewer : Control
{
public QuickViewer()
{
// Designer generated code
// Copy pasted for illustration alone
this.vScrollBar1 = new System.Windows.Forms.VScrollBar();
this.SuspendLayout();
//
// vScrollBar1
//
this.vScrollBar1.Location = new System.Drawing.Point(420, 4);
this.vScrollBar1.Name = "vScrollBar1";
this.vScrollBar1.Size = new Size(this.vScrollBar1.Width, 292);
//
// QuickViewer
//
this.Controls.Add(this.vScrollBar1);
this.Name = "QuickViewer";
this.Size = new System.Drawing.Size(441, 296);
this.vScrollBar1.Value = 5;
this.ResumeLayout(false);
}
protected override void OnPaint(PaintEventArgs e)
{
//My actual control is different. I prepared a simple control to replicate the buggy behavior of VScrollBar
//Control border
Pen borderPen = new Pen(Color.LawnGreen, 5);
e.Graphics.DrawRectangle(borderPen, ClientRectangle);
borderPen.Dispose();
//View area
Rectangle rect = new Rectangle(ClientRectangle.Location, ClientRectangle.Size);
rect.Inflate(-25, -10);
e.Graphics.FillRectangle(Brushes.White, rect);
e.Graphics.DrawRectangle(Pens.Black, rect);
this.Font = new System.Drawing.Font("Segoe UI", 12, FontStyle.Bold);
StringFormat format = new StringFormat() { Alignment = StringAlignment.Center };
e.Graphics.DrawString("Quick viewer", this.Font, Brushes.Black, rect, format);
string content = "This is a control created to illustrate the bug in VScrollBar." +
"\n Control area refers to the area with white background" +
"\n Control and Vertical Scrollbar are not programatically connected with each other."
+ "But still VScrollBar moves if you swipe on control area";
Font font = new System.Drawing.Font("Segoe UI", 12, FontStyle.Italic);
rect.Y += 20;
e.Graphics.DrawString(content, font, Brushes.Black, rect, format);
font.Dispose();
format.Dispose();
base.OnPaint(e);
}
/// <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);
}
private System.Windows.Forms.VScrollBar vScrollBar1;
}
Question:
Is there any way to overcome this behavior or bug ? I want the scrollbar to move down while swiping down and move up while swiping up. There should not be any scrolling when swiping over the content
I want the scrollbar to move down while swiping down and move up while swiping up.
As per Hans Passants comment its just a system setting (in the form of a registry key):
The answer is actually over at SuperUser:
https://superuser.com/questions/310681/inverting-direction-of-mouse-scroll-wheel
In C# as you wanted:
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 Microsoft.Win32;
using System.Diagnostics;
using System.Security.Principal;
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private Flippable[] flippable;
private void Form1_Load(object sender, EventArgs e) {
WindowsPrincipal pricipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
bool hasAdministrativeRight = pricipal.IsInRole(WindowsBuiltInRole.Administrator);
if (!hasAdministrativeRight) {
RunElevated(Application.ExecutablePath);
this.Close();
Application.Exit();
}
//probably only want to flip mice.
flippable = getFlippable("hid.mousedevice");
dgv_flippable.DataSource = flippable;
foreach (var col in dgv_flippable.Columns.OfType<DataGridViewCheckBoxColumn>()) {
col.TrueValue = true;
col.FalseValue = false;
col.IndeterminateValue = null;
}
}
private static bool RunElevated(string fileName)
{
//MessageBox.Show("Run: " + fileName);
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.UseShellExecute = true;
processInfo.Verb = "runas";
processInfo.FileName = fileName;
try
{
Process.Start(processInfo);
return true;
}
catch (Win32Exception)
{
//Do nothing. Probably the user canceled the UAC window
}
return false;
}
private Flippable[] getFlippable(string filter) {
List<Flippable> flips = new List<Flippable>();
using (RegistryKey hid = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Enum\HID\",false)) {
foreach (string devicekn in hid.GetSubKeyNames()) {
using (RegistryKey device = hid.OpenSubKey(devicekn,false)) {
foreach (string devicekn2 in device.GetSubKeyNames()) {
using (RegistryKey device2 = device.OpenSubKey(devicekn2,false)) {
using (RegistryKey devparam = device2.OpenSubKey("Device Parameters",true)) {
if (devparam != null) {
flips.Add(new Flippable(new string[] { devicekn, devicekn2 }, device2, devparam, tmr_popup));
}
}
}
}
}
}
}
if (filter != null) {
return flips.Where(f=>f.name.Contains(filter)).ToArray();
}
return flips.ToArray();
}
private void dgv_flippable_MouseUp(object sender, MouseEventArgs e) {
dgv_flippable.EndEdit();
}
private void button1_Click(object sender, EventArgs e) {
flippable = getFlippable(null);
dgv_flippable.DataSource = flippable;
}
private void btn_flip_Click(object sender, EventArgs e) {
foreach (var f in flippable) {
f.vertical = true;
f.horizontal = true;
}
dgv_flippable.DataSource = null;
dgv_flippable.DataSource = flippable;
}
private void btn_normal_Click(object sender, EventArgs e) {
foreach (var f in flippable) {
f.vertical = false;
f.horizontal = false;
}
dgv_flippable.DataSource = null;
dgv_flippable.DataSource = flippable;
}
private void tmr_popup_Tick(object sender, EventArgs e) {
tmr_popup.Enabled = false;
notifyIcon1.ShowBalloonTip(99999999);
}
}
public class Flippable {
public Flippable(string[] keyPath, RegistryKey deviceKey, RegistryKey devparam, Timer timer) {
this._keyPath = keyPath;
IEnumerable<bool?> flipValues = Flippable.valueNames
.Select(v => onlyIntBool(devparam.GetValue(v, null)));
this.name = (string)deviceKey.GetValue("DeviceDesc");
this._vertical = flipValues.ElementAt(0);
this._horizontal = flipValues.ElementAt(1);
this._timer = timer;
}
private bool? onlyIntBool(object value) {
try {
return value == null ? null : (bool?)(((int)value) != 0);
} catch {
return null;
}
}
public static string[] valueNames = new string[] { "FlipFlopWheel", "FlipFlopHScroll" };
public string name { get; private set; }
private string[] _keyPath;
private bool? _vertical;
private bool? _horizontal;
Timer _timer;
public bool? vertical { set { flip(Flippable.valueNames[0], value); _vertical = value; } get { return _vertical; } }
public bool? horizontal { set { flip(Flippable.valueNames[1], value); _horizontal = value; } get { return _horizontal; } }
public void flip(string valueName, bool? value) {
using (RegistryKey hid = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Enum\HID\", false)) {
using (RegistryKey device = hid.OpenSubKey(_keyPath[0], false)) {
using (RegistryKey device2 = device.OpenSubKey(_keyPath[1], false)) {
using (RegistryKey devparam = device2.OpenSubKey("Device Parameters", true)) {
if (value == null) {
devparam.DeleteValue(valueName);
} else {
devparam.SetValue(valueName, value == true ? 1 : 0);
_timer.Enabled = true;
}
}
}
}
}
}
}
}
REF: https://github.com/jamie-pate/flipflop-windows-wheel/blob/master/Form1.cs
Disclaimer: normally this question would get closed as a duplicate but because there is a bounty on it and the duplicate is over at SuperUser I've chosen to share that answer here. Full credit to the original author: https://superuser.com/users/108033/richard and https://superuser.com/users/132069/jamie-pate
I think what you want is a ViewPort.
Essentially you put a Control inside a PictureBox. The Control has a larger height than the PictureBox making it a ViewPort.
Before
You'll need to change the form designer code to get the control inside the PictureBox:
'
'PictureBox1
'
Me.PictureBox1.Location = New System.Drawing.Point(96, 87)
Me.PictureBox1.Name = "PictureBox1"
Me.PictureBox1.Size = New System.Drawing.Size(231, 195)
Me.PictureBox1.TabIndex = 0
Me.PictureBox1.TabStop = False
'
'VScrollBar1
'
Me.VScrollBar1.Location = New System.Drawing.Point(330, 88)
Me.VScrollBar1.Name = "VScrollBar1"
Me.VScrollBar1.Size = New System.Drawing.Size(34, 194)
Me.VScrollBar1.TabIndex = 2
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(0, 0)
Me.TextBox1.Multiline = True
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(211, 251)
Me.TextBox1.TabIndex = 3
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(522, 392)
Me.Controls.Add(Me.VScrollBar1)
Me.Controls.Add(Me.PictureBox1)
'======= THIS IS THE CRITICAL CHANGE =======
PictureBox1.Controls.Add(Me.TextBox1)
After
Then manually place a ScrollBar to the right of the PictureBox and facilitate the behaviour yourself, eg:
//set the VScroll the difference
VScroll.Max = Textbox.Height - PictureBox.Height;
In the VScroll event:
TextBox.Top = -VScroll.Value;
This will save you from mucking around with system settings in order to produce a QuickViewer custom control.
You can add smarts to it like programming PictureBox drag events to set the ScrollBar (and subsequently the inside controls Top). For most inside controls you'll just need to work out the Height which is easy using a for loop, eg:
foreach(var ctrl in PictureBox.Controls) {
// tally up the controls height
...
For inside Textbox controls you can work out the Height based on Fontsize and number of lines. There are plenty of examples online showing how to do that. Since you're doing Textbox's with graphics, eg e.Graphics.DrawString it should be easy enough having the inside control as a innerPictureBox.
To swap the scroll/swipe direction set the VScroll default starting Value to its Max value and set the inside controls Top = VScroll.Value (no minus sign needed)

MediaElement not always playing video in WPF application

we created a test application were users interact with it using gestures. Each user gets to interact with all gestures in a sequential manner. When the users first is introduced to a new gesture, a small instructional movie is played for the user showing him how to perform that gesture. The movie should first play on the main screen, and then after playing once should loop on the second monitor until the next gesture starts, when it should then close the secondary video screen and start the process over. This is where we are running into problems.
The movies all get loaded up fine, and actually most of the time play correctly. The problem is that sometimes, the movie does not actually start in the secondary monitor. They load up fine but never actually start. This is not something we can reliably reproduce, this happens sometimes at random.
This is the code that we have for the VideoPlayer window at the moment:
public partial class VideoWindow : Window {
static VideoWindow currentVideoWindow;
public VideoWindow(GestureDirection direction, GestureType type, bool reopen = false)
{
if(currentVideoWindow != null) {
currentVideoWindow.CloseWindow();
currentVideoWindow = this;
}
else {
currentVideoWindow = this;
}
GestureParser.Pause(!reopen);
InitializeComponent();
this.Title = type + " " + direction;
this.Show();
videoMediaElement.LoadedBehavior = MediaState.Manual;
videoMediaElement.UnloadedBehavior = MediaState.Manual;
string videoDirectory = #"techniques/";
string video = direction.ToString() + "_" + type.ToString() + ".mp4";
if (Screen.AllScreens.Length > 1) {
int secScreen = Screen.AllScreens.Length == 2 ? 0 : 2;
int mainScreen = Screen.AllScreens.Length == 2 ? 1 : 0;
Screen s = reopen ? Screen.AllScreens[secScreen] : Screen.AllScreens[mainScreen];
System.Drawing.Rectangle r = s.WorkingArea;
this.Top = r.Top;
this.Left = r.Left;
this.Topmost = true;
this.Show();
this.WindowStyle = WindowStyle.None;
this.WindowState = WindowState.Maximized;
}
else {
Screen s = Screen.AllScreens[0];
System.Drawing.Rectangle r = s.WorkingArea;
this.Top = r.Top;
this.Left = r.Left;
this.Show();
}
String videoPath = CreateAbsolutePathTo(videoDirectory + video);
if (File.Exists(videoPath)) {
Uri videoUri = new Uri(videoPath, UriKind.Relative);
videoMediaElement.Source = videoUri;
}
if (reopen) {
this.Activate();
canvasWindow.Activate();
videoMediaElement.MediaEnded += (sender, args) => {
videoMediaElement.Stop();
videoMediaElement.Position = TimeSpan.Zero;
};
} else {
videoMediaElement.MediaEnded += (sender, args) => {
this.CloseWindow();
var t = new VideoWindow(direction, type, true);
};
}
videoMediaElement.Play();
Task task = Task.Factory.StartNew(() =>
{
while(GetMediaState(videoMediaElement) != MediaState.Play)
{
videoMediaElement.Play();
}
});
}
private MediaState GetMediaState(MediaElement myMedia)
{
FieldInfo hlp = typeof(MediaElement).GetField("_helper", BindingFlags.NonPublic | BindingFlags.Instance);
object helperObject = hlp.GetValue(myMedia);
FieldInfo stateField = helperObject.GetType().GetField("_currentState", BindingFlags.NonPublic | BindingFlags.Instance);
MediaState state = (MediaState)stateField.GetValue(helperObject);
return state;
}
static CanvasWindow canvasWindow;
public static void SetCanvasWindow(CanvasWindow window) {
canvasWindow = window;
}
private static string CreateAbsolutePathTo(string mediaFile) {
return Path.Combine(new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName, mediaFile);
}
private void CloseWindow() {
videoMediaElement.Stop();
videoMediaElement.Close();
this.Close();
}
}
As you can see, we have tried creating a task that constantly checks to see if the video is playing, and if not it should play it. The thing is, the media state is always playing, even if the movie is stopped, and as such it does nothing.
We really don't know what is wrong, and would really appreciate some help.

Categories

Resources