I'm trying to scan A4 pages from a C# application using a flat bed scanner and Windows 10. To speed things up, I use the ScanWIA library found here: https://scanwia.codeplex.com/
However, I have huge problems configuring the page settings correctly.
Setting the page size (WIA ID 3097) to AUTO, gives me an "property not supported" exception.
Setting horizontal and vertical extend (WIA ID 6151, 6152) gives me either too small (cropped) results or an "value out of range" exception.
What is the correct way to set this up for A4 pages and variable DPI settings?
How do I set the size of the captured area correctly?
How do I control the size of the output image?
Which setting uses which unit? What are the maximum value ranges?
MSDN is not very helpful on these topics...
I have made a user control to scan the documents from attached scanner.
Here I can explain the details.
In the attached form image there are 2 picture boxes, a preview button, a save button, two labels for showing save path and a drop down to show available scanner devices. See the image above to get a clear picture about the form design.
There is a class file named WIAScanner.cs, see the the code below
using System;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using WIA;
namespace TESTSCAN
{
class WIAScanner
{
const string wiaFormatBMP = "{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}";
const string WIA_DEVICE_PROPERTY_PAGES_ID = "3096";
const string WIA_SCAN_BRIGHTNESS_PERCENTS = "6154";
const string WIA_SCAN_CONTRAST_PERCENTS = "6155";
const string WIA_SCAN_COLOR_MODE = "6146";
class WIA_DPS_DOCUMENT_HANDLING_SELECT
{
public const uint FEEDER = 0x00000001;
public const uint FLATBED = 0x00000002;
}
class WIA_DPS_DOCUMENT_HANDLING_STATUS
{
public const uint FEED_READY = 0x00000001;
}
class WIA_PROPERTIES
{
public const uint WIA_RESERVED_FOR_NEW_PROPS = 1024;
public const uint WIA_DIP_FIRST = 2;
public const uint WIA_DPA_FIRST = WIA_DIP_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
public const uint WIA_DPC_FIRST = WIA_DPA_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
//
// Scanner only device properties (DPS)
//
public const uint WIA_DPS_FIRST = WIA_DPC_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
public const uint WIA_DPS_DOCUMENT_HANDLING_STATUS = WIA_DPS_FIRST + 13;
public const uint WIA_DPS_DOCUMENT_HANDLING_SELECT = WIA_DPS_FIRST + 14;
}
//public void SetProperty(Property property, int value)
//{
// IProperty x = (IProperty)property;
// Object val = value;
// x.set_Value(ref val);
//}
/// <summary>
/// Use scanner to scan an image (with user selecting the scanner from a dialog).
/// </summary>
/// <returns>Scanned images.</returns>
public static List<Image> Scan()
{
WIA.ICommonDialog dialog = new WIA.CommonDialog();
WIA.Device device = dialog.ShowSelectDevice(WIA.WiaDeviceType.UnspecifiedDeviceType, true, false);
if (device != null)
{
return Scan(device.DeviceID,1);
}
else
{
throw new Exception("You must select a device for scanning.");
}
}
/// <summary>
/// Use scanner to scan an image (scanner is selected by its unique id).
/// </summary>
/// <param name="scannerName"></param>
/// <returns>Scanned images.</returns>
public static List<Image> Scan(string scannerId, int pages)
{
List<Image> images = new List<Image>();
bool hasMorePages = true;
int numbrPages = pages;
while (hasMorePages)
{
// select the correct scanner using the provided scannerId parameter
WIA.DeviceManager manager = new WIA.DeviceManager();
WIA.Device device = null;
foreach (WIA.DeviceInfo info in manager.DeviceInfos)
{
if (info.DeviceID == scannerId)
{
// connect to scanner
device = info.Connect();
break;
}
}
// device was not found
if (device == null)
{
// enumerate available devices
string availableDevices = "";
foreach (WIA.DeviceInfo info in manager.DeviceInfos)
{
availableDevices += info.DeviceID + "\n";
}
// show error with available devices
throw new Exception("The device with provided ID could not be found. Available Devices:\n" + availableDevices);
}
SetWIAProperty(device.Properties, WIA_DEVICE_PROPERTY_PAGES_ID, 1);
WIA.Item item = device.Items[1] as WIA.Item;
AdjustScannerSettings(item, 150, 0, 0, 1250, 1700, 0, 0, 1);
try
{
// scan image
WIA.ICommonDialog wiaCommonDialog = new WIA.CommonDialog();
WIA.ImageFile image = (WIA.ImageFile)wiaCommonDialog.ShowTransfer(item, wiaFormatBMP, false);
// save to temp file
string fileName = Path.GetTempFileName();
File.Delete(fileName);
image.SaveFile(fileName);
image = null;
// add file to output list
images.Add(Image.FromFile(fileName));
}
catch (Exception exc)
{
throw exc;
}
finally
{
item = null;
//determine if there are any more pages waiting
WIA.Property documentHandlingSelect = null;
WIA.Property documentHandlingStatus = null;
foreach (WIA.Property prop in device.Properties)
{
if (prop.PropertyID == WIA_PROPERTIES.WIA_DPS_DOCUMENT_HANDLING_SELECT)
documentHandlingSelect = prop;
if (prop.PropertyID == WIA_PROPERTIES.WIA_DPS_DOCUMENT_HANDLING_STATUS)
documentHandlingStatus = prop;
}
// assume there are no more pages
hasMorePages = false;
// may not exist on flatbed scanner but required for feeder
if (documentHandlingSelect != null)
{
// check for document feeder
if ((Convert.ToUInt32(documentHandlingSelect.get_Value()) & WIA_DPS_DOCUMENT_HANDLING_SELECT.FEEDER) != 0)
{
hasMorePages = ((Convert.ToUInt32(documentHandlingStatus.get_Value()) & WIA_DPS_DOCUMENT_HANDLING_STATUS.FEED_READY) != 0);
}
}
}
numbrPages -= 1;
if (numbrPages > 0)
hasMorePages = true;
else
hasMorePages = false;
}
return images;
}
/// <summary>
/// Gets the list of available WIA devices.
/// </summary>
/// <returns></returns>
public static List<string> GetDevices()
{
List<string> devices = new List<string>();
WIA.DeviceManager manager = new WIA.DeviceManager();
foreach (WIA.DeviceInfo info in manager.DeviceInfos)
{
devices.Add(info.DeviceID);
}
return devices;
}
private static void SetWIAProperty(WIA.IProperties properties,
object propName, object propValue)
{
WIA.Property prop = properties.get_Item(ref propName);
prop.set_Value(ref propValue);
}
private static void AdjustScannerSettings(IItem scannnerItem, int scanResolutionDPI, int scanStartLeftPixel, int scanStartTopPixel,
int scanWidthPixels, int scanHeightPixels, int brightnessPercents, int contrastPercents, int colorMode)
{
const string WIA_SCAN_COLOR_MODE = "6146";
const string WIA_HORIZONTAL_SCAN_RESOLUTION_DPI = "6147";
const string WIA_VERTICAL_SCAN_RESOLUTION_DPI = "6148";
const string WIA_HORIZONTAL_SCAN_START_PIXEL = "6149";
const string WIA_VERTICAL_SCAN_START_PIXEL = "6150";
const string WIA_HORIZONTAL_SCAN_SIZE_PIXELS = "6151";
const string WIA_VERTICAL_SCAN_SIZE_PIXELS = "6152";
const string WIA_SCAN_BRIGHTNESS_PERCENTS = "6154";
const string WIA_SCAN_CONTRAST_PERCENTS = "6155";
SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_RESOLUTION_DPI, scanResolutionDPI);
SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_RESOLUTION_DPI, scanResolutionDPI);
SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_START_PIXEL, scanStartLeftPixel);
SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_START_PIXEL, scanStartTopPixel);
SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_SIZE_PIXELS, scanWidthPixels);
SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_SIZE_PIXELS, scanHeightPixels);
SetWIAProperty(scannnerItem.Properties, WIA_SCAN_BRIGHTNESS_PERCENTS, brightnessPercents);
SetWIAProperty(scannnerItem.Properties, WIA_SCAN_CONTRAST_PERCENTS, contrastPercents);
SetWIAProperty(scannnerItem.Properties, WIA_SCAN_COLOR_MODE, colorMode);
}
}
}
Then see below the .cs file of the form named Form1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
namespace TESTSCAN
{
public partial class Form1 : Form
{
int cropX, cropY, cropWidth, cropHeight;
//here rectangle border pen color=red and size=2;
Pen borderpen = new Pen(Color.Red, 2);
Image _orgImage;
Bitmap crop;
List<string> devices;
//fill the rectangle color =white
SolidBrush rectbrush = new SolidBrush(Color.FromArgb(100, Color.White));
int pages;
int currentPage = 0;
public Form1()
{
InitializeComponent();
IsSaved = false;
}
List<Image> images;
private string f_path;
private string doc_no;
private bool savedOrNot = false;
private List<string> fNames;
public List<string> fileNames
{
get { return fNames; }
set { fNames = value; }
}
public String SavePath
{
get { return f_path; }
set { f_path = value; }
}
public String DocNo
{
get { return doc_no; }
set { doc_no = value; }
}
public bool IsSaved
{
get { return savedOrNot; }
set { savedOrNot = value; }
}
private void Form1_Load(object sender, EventArgs e)
{
lblPath.Text = SavePath;
lblDocNo.Text = DocNo;
//get list of devices available
devices = WIAScanner.GetDevices();
foreach (string device in devices)
{
lbDevices.Items.Add(device);
}
//check if device is not available
if (lbDevices.Items.Count != 0)
{
lbDevices.SelectedIndex = 0;
}
}
private void btnPreview_Click(object sender, EventArgs e)
{
try
{
//get list of devices available
if (lbDevices.Items.Count == 0)
{
MessageBox.Show("You do not have any WIA devices.");
}
else
{
//get images from scanner
pages =3;
images = WIAScanner.Scan((string)lbDevices.SelectedItem, pages);
pages = images.Count;
if (images != null)
{
foreach (Image image in images)
{
pic_scan.Image = images[0];
pic_scan.Show();
pic_scan.SizeMode = PictureBoxSizeMode.StretchImage;
_orgImage = images[0];
crop = new Bitmap(images[0]);
btnOriginal.Enabled = true;
btnSave.Enabled = true;
currentPage = 0;
//pic_scan.Image = image;
//pic_scan.Show();
//pic_scan.SizeMode = PictureBoxSizeMode.StretchImage;
//_orgImage = image;
//crop = new Bitmap(image);
//btnOriginal.Enabled = true;
//btnSave.Enabled = true;
}
}
}
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
}
}
List<string> sss = new List<string>();
private void btnSave_Click(object sender, EventArgs e)
{
try
{
if (crop != null)
{
SavePath = #"D:\NAJEEB\scanned images\";
DocNo = "4444";
string currentFName = DocNo + Convert.ToString(currentPage + 1) + ".jpeg";
crop.Save(SavePath + currentFName, ImageFormat.Jpeg);
sss.Add(currentFName);
MessageBox.Show("Document Saved Successfully");
IsSaved = true;
currentPage += 1;
if (currentPage < (pages))
{
pic_scan.Image = images[currentPage];
pic_scan.Show();
pic_scan.SizeMode = PictureBoxSizeMode.StretchImage;
_orgImage = images[currentPage];
crop = new Bitmap(images[currentPage]);
btnOriginal.Enabled = true;
btnSave.Enabled = true;
}
else
{ btnSave.Enabled =false;
fileNames = sss;
}
}
}
catch (Exception exc)
{
IsSaved = false;
MessageBox.Show(exc.Message);
}
}
private void btnOriginal_Click(object sender, EventArgs e)
{
if (_orgImage != null)
{
crop = new Bitmap(_orgImage);
pic_scan.Image = _orgImage;
pic_scan.SizeMode = PictureBoxSizeMode.StretchImage;
pic_scan.Refresh();
}
}
private void pic_scan_MouseDown(object sender, MouseEventArgs e)
{
try
{
if (e.Button == MouseButtons.Left)//here i have use mouse click left button only
{
pic_scan.Refresh();
cropX = e.X;
cropY = e.Y;
Cursor = Cursors.Cross;
}
pic_scan.Refresh();
}
catch { }
}
private void pic_scan_MouseMove(object sender, MouseEventArgs e)
{
try
{
if (pic_scan.Image == null)
return;
if (e.Button == MouseButtons.Left)//here i have use mouse click left button only
{
pic_scan.Refresh();
cropWidth = e.X - cropX;
cropHeight = e.Y - cropY;
}
pic_scan.Refresh();
}
catch { }
}
private void pic_scan_MouseUp(object sender, MouseEventArgs e)
{
try
{
Cursor = Cursors.Default;
if (cropWidth < 1)
{
return;
}
Rectangle rect = new Rectangle(cropX, cropY, cropWidth, cropHeight);
Bitmap bit = new Bitmap(pic_scan.Image, pic_scan.Width, pic_scan.Height);
crop = new Bitmap(cropWidth, cropHeight);
Graphics gfx = Graphics.FromImage(crop);
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;//here add System.Drawing.Drawing2D namespace;
gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;//here add System.Drawing.Drawing2D namespace;
gfx.CompositingQuality = CompositingQuality.HighQuality;//here add System.Drawing.Drawing2D namespace;
gfx.DrawImage(bit, 0, 0, rect, GraphicsUnit.Pixel);
}
catch { }
}
private void pic_scan_Paint(object sender, PaintEventArgs e)
{
Rectangle rect = new Rectangle(cropX, cropY, cropWidth, cropHeight);
Graphics gfx = e.Graphics;
gfx.DrawRectangle(borderpen, rect);
gfx.FillRectangle(rectbrush, rect);
}
}
}
Short description of the working flow:
On form load event the available scanner devices adding to drop down list.
The user can select any device from this drop down.
On Preview button click, the document is scanned to application and is shown in the picture box.
There is another picture box in the form for keeping the cropped image. If you select any area from the picture in the picture box then you will feel the cropping effect. The cropped image keep in the second picture box placed behind the first picture box.
On save button click the image save into the specified location in the disk.
This location we can configure from the application. See the code.
Related
The treeview control code :
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class AdvancedTreeView : TreeView
{
private const int TVM_SETEXTENDEDSTYLE = 0x1100 + 44;
private const int TVM_GETEXTENDEDSTYLE = 0x1100 + 45;
private const int TVS_EX_DOUBLEBUFFER = 0x0004;
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
private Bitmap openedIcon, closedIcon;
private List<TreeNode> rootNodes = new List<TreeNode>();
public AdvancedTreeView()
{
DrawMode = TreeViewDrawMode.OwnerDrawText;
ShowLines = false;
AlternateBackColor = BackColor;
ArrowColor = SystemColors.WindowText;
this.AllowDrop = true;
}
public Color AlternateBackColor { get; set; }
public Color ArrowColor { get; set; }
protected override void OnHandleCreated(EventArgs e)
{
SendMessage(this.Handle, TVM_SETEXTENDEDSTYLE, (IntPtr)TVS_EX_DOUBLEBUFFER, (IntPtr)TVS_EX_DOUBLEBUFFER);
base.OnHandleCreated(e);
}
protected override void OnDrawNode(DrawTreeNodeEventArgs e)
{
Color backColor = (GetTopNodeIndex(e.Node) & 1) == 0 ? BackColor : AlternateBackColor;
using (Brush b = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(b, new Rectangle(0, e.Bounds.Top, ClientSize.Width, e.Bounds.Height));
}
if ((e.State & TreeNodeStates.Selected) != 0)
{
e.Graphics.FillRectangle(Brushes.Green, e.Bounds);
}
// icon
if (e.Node.Nodes.Count > 0)
{
Image icon = GetIcon(e.Node.IsExpanded);
e.Graphics.DrawImage(icon, e.Bounds.Left - icon.Width - 3, e.Bounds.Top);
}
// text (due to OwnerDrawText mode, indenting of e.Bounds will be correct)
TextRenderer.DrawText(e.Graphics, e.Node.Text, Font, e.Bounds, ForeColor);
// indicate selection (if not by backColor):
if ((e.State & TreeNodeStates.Selected) != 0)
ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds);
}
protected override void OnItemDrag(ItemDragEventArgs e)
{
// Move the dragged node when the left mouse button is used.
if (e.Button == MouseButtons.Left)
{
DoDragDrop(e.Item, DragDropEffects.Move);
}
// Copy the dragged node when the right mouse button is used.
else if (e.Button == MouseButtons.Right)
{
DoDragDrop(e.Item, DragDropEffects.Copy);
}
}
protected override void OnDragOver(DragEventArgs e)
{
// Retrieve the client coordinates of the mouse position.
Point targetPoint = this.PointToClient(new Point(e.X, e.Y));
// Select the node at the mouse position.
this.SelectedNode = this.GetNodeAt(targetPoint);
}
protected override void OnDragDrop(DragEventArgs e)
{
Point targetPoint = PointToClient(new Point(e.X, e.Y));
TreeNode targetNode = GetNodeAt(targetPoint);
TreeNode draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
if (draggedNode == null || targetNode == null || draggedNode.Level != targetNode.Level)
{
return;
}
else
{
TreeNode parentNode = targetNode;
if (!draggedNode.Equals(targetNode) && targetNode != null)
{
bool canDrop = true;
while (canDrop && (parentNode != null))
{
canDrop = !Object.ReferenceEquals(draggedNode, parentNode);
parentNode = parentNode.Parent;
}
if (canDrop)
{
TreeNode treeNode = draggedNode.Parent;
if (treeNode != null)
{
int index = draggedNode.Index;
draggedNode.Remove();
treeNode.Nodes.Insert(targetNode.Index, draggedNode);
targetNode.Remove();
treeNode.Nodes.Insert(index, targetNode);
}
else
{
int draggedindex = draggedNode.Index;
int targetindex = targetNode.Index;
draggedNode.Remove();
targetNode.Remove();
this.Nodes.Insert(targetindex, draggedNode);
this.Nodes.Insert(draggedindex, targetNode);
}
}
}
}
SelectedNode = draggedNode;
}
private int GetTopNodeIndex(TreeNode node)
{
while (node.Parent != null)
node = node.Parent;
return Nodes.IndexOf(node);
}
// Determine whether one node is a parent
// or ancestor of a second node.
private bool ContainsNode(TreeNode node1, TreeNode node2)
{
// Check the parent node of the second node.
if (node2.Parent == null) return false;
if (node2.Parent.Equals(node1)) return true;
// If the parent node is not null or equal to the first node,
// call the ContainsNode method recursively using the parent of
// the second node.
return ContainsNode(node1, node2.Parent);
}
private Image GetIcon(bool nodeIsExpanded)
{
if (openedIcon == null)
InitIcons();
return nodeIsExpanded ? openedIcon : closedIcon;
}
private void InitIcons()
{
openedIcon = new Bitmap(16, 16);
closedIcon = new Bitmap(16, 16);
using (Brush b = new SolidBrush(ArrowColor))
{
using (Graphics g = Graphics.FromImage(openedIcon))
g.FillPolygon(b, new[] { new Point(0, 0), new Point(15, 0), new Point(8, 15), });
using (Graphics g = Graphics.FromImage(closedIcon))
g.FillPolygon(b, new[] { new Point(0, 0), new Point(15, 8), new Point(0, 15), });
}
}
}
And form1 where I'm adding the nodes and using the trackbar :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Treeview_Test
{
public partial class Form1 : Form
{
int numberofroots = 1000;
int childsnum = 50;
int childsnumperlevel = 5;
int leveldepth = 6;
public Form1()
{
InitializeComponent();
AddNodes();
for (int i = 0; i < 100; i++)
{
ComboboxItem boxitem = new ComboboxItem();
boxitem.Text = i.ToString();
comboBox1.Items.Add(boxitem);
}
comboBox1.SelectedIndex = 0;
}
private void AddNodes()
{
advancedTreeView1.Nodes.Clear();
for (int i = 0; i < numberofroots; i++)
{
TreeNode subnode = advancedTreeView1.Nodes.Add("New Node " + i);
if (allRootsWithChilds.Checked || i < childsnum)
{
for (int j = 0; j < leveldepth; j++)
{
// Add a new child node and set subnode to the new node we just added
subnode = subnode.Nodes.Add(subnode.Text);
for (int x = 0; x < childsnumperlevel; x++)
{
subnode.Nodes.Add("New Node " + x);
}
}
}
}
}
private void allRootsWithChilds_CheckedChanged(object sender, EventArgs e)
{
AddNodes();
}
private void advancedTreeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
textBox2.Text = e.Node.Text;
}
private void button1_Click(object sender, EventArgs e)
{
}
public class ComboboxItem
{
public string Text { get; set; }
public object Value { get; set; }
public override string ToString()
{
return Text;
}
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
advancedTreeView1.ItemHeight = 5;
advancedTreeView1.SelectedNode.NodeFont = new Font("Arial", 5);
// Get the font size from combobox.
string selectedString = trackBar1.Value.ToString();//comboBox1.SelectedItem.ToString();
int myNodeFontSize = Int32.Parse(selectedString);
// Set the font of root node.
advancedTreeView1.SelectedNode.NodeFont = new Font("Arial", myNodeFontSize);
for (int i = 0; i < advancedTreeView1.Nodes[0].Nodes.Count; i++)
{
// Set the font of child nodes.
advancedTreeView1.Nodes[0].Nodes[i].NodeFont =
new Font("Arial", myNodeFontSize);
}
// Get the bounds of the tree node.
Rectangle myRectangle = advancedTreeView1.SelectedNode.Bounds;
int myNodeHeight = myRectangle.Height;
if (myNodeHeight < myNodeFontSize)
{
myNodeHeight = myNodeFontSize;
}
advancedTreeView1.ItemHeight = myNodeHeight + 4;
}
}
}
The first problem is each time I'm changing the trackBar value from 1 to 2 it's taking time the treeview to redraw. I'm not sure if it's drawing the whole treeview over again or only the nodes. Maybe the problem is the OnDrawNode override method in the AdvancedTreeView control code since this method is being called all the time.
The second problem is that when the nodes are resizing getting bigger each time when moving the trackBar to a higher value the text of the nodes is keep staying the same size and not resizing with the nodes. How can I make that the text of the nodes will be resized automatic fitting the size of the nodes?
And the red arrow the icon in the AdvancedTreeView code is also not fitting the nodes sizes the arrow is getting in each node higher and higher.
Here is a screenshot of the treeview when the trackbar value is 1: Now it's all fitting :
And this screenshot is after I moved the trackBar to the right to about the middle about value 50 :
Now the text is in the middle of each node but the text is still too small and not being resized with the nodes.
And the red arrow the icon in each node seems to be on the top left corner instead like in the first screenshot.
The icon/red arrow should also resize with the nodes and stay in the centre pointing the text of the nodes.
Edit :
Tried to reduce the code in the trackBar1_Scroll event to test and it sitll drawing slow when changing the trackBar values :
private void trackBar1_Scroll(object sender, EventArgs e)
{
// Get the font size from combobox.
string selectedString = trackBar1.Value.ToString();
int myNodeFontSize = Int32.Parse(selectedString);
// Get the bounds of the tree node.
Rectangle myRectangle = advancedTreeView1.SelectedNode.Bounds;
int myNodeHeight = myRectangle.Height;
if (myNodeHeight < myNodeFontSize)
{
myNodeHeight = myNodeFontSize;
}
advancedTreeView1.ItemHeight = myNodeHeight + 4;
}
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)
I have a flag in the Form1 top level: addFrame wich is set to false in the constructor.
Then in the picnt event i check if its false let me draw if its true also let me draw. The problem here is that i want to be able to draw when im running the program first time !
But when im moving the trackBar to the right i dont want it to draw anything .
private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
moveCounter++;
label6.Text = moveCounter.ToString();
if (addFrame == false)
{
WireObjectGraphics.Draw(wireObject1, g);
}
else
{
addFrame = false;
WireObjectGraphics.Draw(wireObject1, g);
}
}
This is the button click event where im clicking to set the addFrame to true:
private void button16_Click(object sender, EventArgs e)
{
wireObjectAnimation1.AddFrame();
addFrame = true;
trackBar1.Select();
}
And the scroll bar event in this case i want to make that if i move the trackBar to the right and there are no any draws already then just show the image in the pictureBox dont draw anything ! But if i move it to the right and there are already draws then do show them.
If i move it to the left allways show the previous draws.
private void trackBar1_Scroll(object sender, EventArgs e)
{
if (addFrame == false)
{
}
else
{
currentFrameIndex = trackBar1.Value - 1;
textBox1.Text = "Frame Number : " + trackBar1.Value;
wireObject1.woc.Set(wireObjectAnimation1.GetFrame(currentFrameIndex));
trackBar1.Minimum = 0;
trackBar1.Maximum = fi.Length - 1;
if (checkBox1.Checked)
{
setpicture(trackBar1.Value);
Graphics g = Graphics.FromImage(pictureBox1.Image);
g.Clear(SystemColors.Control);
pictureBox1.Invalidate();
}
else
{
setpicture(trackBar1.Value);
}
pictureBox1.Refresh();
button1.Enabled = false;
button2.Enabled = false;
button3.Enabled = false;
button4.Enabled = false;
button8.Enabled = false;
SaveFormPicutreBoxToBitMapIncludingDrawings(currentFrameIndex);
return;
}
}
This is the draw function in the WireObjectGraphics class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace AnimationEditor
{
class WireObjectGraphics
{
static Point connectionPointStart;
static Point connectionPointEnd;
static SolidBrush brush;
static Pen p = null;
public WireObjectGraphics()
{
}
public static void Draw(WireObject wo, Graphics graphics)
{
brush = new SolidBrush(Color.Red);
p = new Pen(brush);
Graphics g = graphics;
WireObject wireObject1 = wo;
if (wireObject1 != null)
{
for (int idx = 0; idx < wireObject1.woc.Point_X.Count; ++idx)
{
Point dPoint = new Point((int)wireObject1.woc.Point_X[idx], (int)wireObject1.woc.Point_Y[idx]);
dPoint.X = dPoint.X - 5; // was - 2
dPoint.Y = dPoint.Y - 5; // was - 2
Rectangle rect = new Rectangle(dPoint, new Size(10, 10));
g.FillEllipse(brush, rect);
// bitmapGraphics.FillEllipse(brush, rect);
// g.FillEllipse(brush, rect);
}
for (int i = 0; i < wireObject1._connectionstart.Count; i++)
{
int startIndex = wireObject1._connectionstart[i];
int endIndex = wireObject1._connectionend[i];
connectionPointStart = new Point((int)wireObject1.woc.Point_X[startIndex], (int)wireObject1.woc.Point_Y[startIndex]);
connectionPointEnd = new Point((int)wireObject1.woc.Point_X[endIndex], (int)wireObject1.woc.Point_Y[endIndex]);
p.Width = 2;
g.DrawLine(p, connectionPointStart, connectionPointEnd);
// bitmapGraphics.DrawLine(p, connectionPointStart, connectionPointEnd);
}
}
}
}
}
What i need is that first time running the program to be able to draw !
Then when moving the trackBar to the righ to check if draws already exists show them if not exist show only the image and only when i click the button it will add the draws on the frame im on.
If i move to the left allways show the draws i did in the other frames.
WireObject class:
Constructor:
class WireObject
{
private string an;
private bool fnExt;
public string lockObject;
private int idx;
public WireObjectCoordinates woc;
private List<int> connectionStart = new List<int>();
private List<int> connectionEnd = new List<int>();
private const string version = "01.00";
string wo_name;
public WireObject( string name )
{
wo_name = name;
woc = new WireObjectCoordinates();
fnExt = false;
}
In the wireobject class i have some function like connecting points(pixels) like delete pixels like save and load...
WireObjectCoordinates class is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AnimationEditor
{
class WireObjectCoordinates
{
public List<float> Point_X = new List<float>();
public List<float> Point_Y = new List<float>();
public WireObjectCoordinates()
{
}
public WireObjectCoordinates(WireObjectCoordinates w)
{
Point_X.AddRange(w.Point_X);
Point_Y.AddRange(w.Point_Y);
}
public void Set(WireObjectCoordinates w)
{
if (w == null)
{
}
else
{
for (int i = 0; i < Point_X.Count; i++)
{
Point_X[i] = w.Point_X[i];
Point_Y[i] = w.Point_Y[i];
}
}
}
}
}
The problem is still in Form1 with the flag when to show the pixels i mean when and how to call the paint event like pictureBox1.Refresh(); but oncei t will use the Draw function inside and once it will not. When i run the program let me use the draw function once i moved the trackBar to the right dont use the draw function.
For a windows form control OnPaint is only called when a.) a window overlapping the current control is moved out of the way OR b.) you manually invalidate the control : http://msdn.microsoft.com/en-us/library/1e430ef4.aspx
So OnPaint should be getting called too often.
I've tried converting vb.net to C# but I keep getting error while compiling. I am new to .NET.
This is my version of converted image utilities class. Util.cs
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using Com.Griaule.IcaoFace;
using System.Windows.Forms;
namespace IcaoWF
{
public class Util
{
//Set if the mouth is important
public const bool USES_MOUTH = true;
//The number of supported pictures
const int SFile = 3;
//
public const int FEATURES_COLOR = (255 << 8);
public const int FEATURES_SIZE = 8;
//File Vector with spec ID
TFile[] VTFile = new TFile[SFile + 1];
//Pointers to the .NET classes
public FaceImage GrFaceImage = null;
public IcaoImage GrIcaoImage = null;
public CbeffImage GrCbeffImage = null;
public Cbeff GrCbeff = null;
ListBox log;
// raw image data type.
public struct TRawImage
{
// Image data.
public object img;
// Image width.
public int width;
// Image height.
public int height;
//Reduction Factor because stretch
public float frX;
public float frY;
//Eyes an mouth positions
public int lx;
public int ly;
public int rx;
public int ry;
public int mx;
public int my;
}
// File Enum Type
public enum EFile
{
BMP = 1,
JPEG2000 = 2,
CBEFF = 3,
NOTDEF = 0
}
//File Type
private struct TFile
{
//File Extension
public string fileExt;
//File Type
public EFile fileID;
}
//Class constructor
public Util(ListBox ltBox)
{
//Adding Supportted files
VTFile[1].fileExt = ".bmp";
VTFile[1].fileID = EFile.BMP;
VTFile[2].fileExt = ".jp2";
VTFile[2].fileID = EFile.JPEG2000;
VTFile[3].fileExt = ".cbeff";
VTFile[3].fileID = EFile.CBEFF;
log = ltBox;
}
public void WriteError(GriauleIcaoFaceException err)
{
WriteLog("Error: " + err.ToString());
}
// Write a message in box.
public void WriteLog(string message)
{
log.Items.Add(message);
log.SelectedIndex = log.Items.Count - 1;
log.ClearSelected();
}
//Get the ID File Type from file path name
public EFile GetFileType(string fileName)
{
EFile functionReturnValue = default(EFile);
int i = 0;
for (i = 0; i <= SFile; i++)
{
if (Strings.InStr(1, fileName, VTFile[i].fileExt) == Strings.Len(fileName) - Strings.Len(VTFile[i].fileExt) + 1)
{
functionReturnValue = VTFile[i].fileID;
return functionReturnValue;
}
}
functionReturnValue = EFile.NOTDEF;
return functionReturnValue;
}
//Loading an Image
public bool LoadImage(string fileName, PictureBox img)
{
// create face image from file
GrFaceImage = new FaceImage(fileName);
// display face image
DisplayFaceImage(img, false);
WriteLog("Image loaded successfully.");
return true;
}
//Process the raw Image to FaceImage Type and paint the points on pBox
public bool ProcessFaceImage(PictureBox pBox)
{
//Set mouth to be relevant to generate the ICAO
GrFaceImage.MouthDetectionEnabled = USES_MOUTH;
WriteLog("Finding the eyes and mouth positions. Please, wait...");
//Get the positions from mouth and eyes
if (GetPositionsFromFaceImage())
{
WriteLog("Eyes and mouth founded. Drawing their positions on the image.");
//Display Face Image with eyes and mouth drawn
DisplayFaceImage(pBox, true);
return true;
}
else
{
//Display Face Image
DisplayFaceImage(pBox, false);
return false;
}
}
//Display the ICAO Image
public void DisplayIcaoImg(PictureBox imgIcao)
{
if (GrFaceImage.LeftEye.X <= 0 | GrFaceImage.LeftEye.Y <= 0 | GrFaceImage.LeftEye.X > GrFaceImage.Width | GrFaceImage.LeftEye.Y > GrFaceImage.Height)
{
WriteLog("Left eye is out of bounds.");
return;
}
if (GrFaceImage.RightEye.X <= 0 | GrFaceImage.RightEye.Y <= 0 | GrFaceImage.RightEye.X > GrFaceImage.Width | GrFaceImage.RightEye.Y > GrFaceImage.Height)
{
WriteLog("Right eye is out of bounds.");
return;
}
if (GrFaceImage.Mouth.X <= 0 | GrFaceImage.Mouth.Y <= 0 | GrFaceImage.Mouth.X > GrFaceImage.Width | GrFaceImage.Mouth.Y > GrFaceImage.Height)
{
WriteLog("Mouth is out of bounds.");
return;
}
//Get the GrIcaoImage
try
{
GrIcaoImage = GrFaceImage.FullFrontalImage(imgIcao.Width, 3.0 / 4.0, IcaoImage.IcaoFullFrontalMode.FullFrontal);
}
catch (GriauleIcaoFaceException ex)
{
WriteError(ex);
return;
}
//Getting the eyes positons from icao
if (GetPositionsFromIcaoImage())
{
//Displaying the icao image
DisplayIcaoImage(imgIcao);
}
WriteLog("ICAO image generated.");
}
//Display Face Image
public void DisplayFaceImage(PictureBox pBox, bool withFeatures)
{
if (withFeatures)
{
pBox.Image = GrFaceImage.ImageWithFeatures(8, Color.Green);
}
else
{
pBox.Image = GrFaceImage.Image;
}
pBox.Update();
}
//Display Cbeff Image
public void DisplayCbeffImage(PictureBox pBox)
{
pBox.Image = GrCbeffImage.Image;
pBox.Update();
}
//Display Icao Image
public void DisplayIcaoImage(PictureBox pBox)
{
pBox.Image = GrIcaoImage.Image;
pBox.Update();
}
//Save ICAO in CBEFF file format
public void SaveIcaoIntoCBEFFImage(string fileName)
{
// Create a CBEFF from Icao
if (GetCbeffFromIcao())
{
//Get the CBEFF buffer
try
{
SaveBuffer(fileName, ref GrCbeff.CBEFF);
}
catch (GriauleIcaoFaceException ex)
{
WriteError(ex);
}
}
}
//Load an ICAO image from CBEFF file format
public void LoadIcaoFromCBEFFImage(string fileName, PictureBox pBox)
{
//Creating the cbeff from the buffer
try
{
GrCbeff = new Cbeff(LoadBuffer(fileName));
GrCbeffImage = GrCbeff.Image(0);
}
catch (GriauleIcaoFaceException ex)
{
WriteError(ex);
}
// Display icao image
DisplayCbeffImage(pBox);
}
//Save ICAO image in JPEG2000 file format
public void SaveIcaoIntoJP2Image(string fileName)
{
// Create a CBEFF from Icao
if (!GetCbeffFromIcao())
{
return;
}
//Get Jpeg2000 buffer from CBEFF and save it in a file
SaveBuffer(fileName, ref GrCbeffImage.BufferJPEG);
}
//Save Byte Buffer into a file
private void SaveBuffer(string fileName, ref byte[] buffer)
{
System.IO.FileStream oFileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
System.IO.BinaryWriter swb = new System.IO.BinaryWriter(oFileStream);
swb.Write(buffer);
swb.Close();
}
//Load stream from file
private byte[] LoadBuffer(string fileName)
{
// Open a file that is to be loaded into a byte array
FileInfo oFile = null;
oFile = new FileInfo(fileName);
System.IO.FileStream oFileStream = oFile.OpenRead();
long lBytes = oFileStream.Length;
byte[] fileData = new byte[lBytes + 1];
// Read the file into a byte array
oFileStream.Read(fileData, 0, lBytes);
oFileStream.Close();
return fileData;
}
//Get CBEFF image from an Icao image
private bool GetCbeffFromIcao()
{
//Create Cbeff Image Data pointer
GrCbeff = new Cbeff();
GrCbeffImage = GrCbeff.AddImage(GrIcaoImage, false, 0);
GrCbeffImage.Gender = CbeffImage.CbeffGender.Unknown;
GrCbeffImage.Eyes = CbeffImage.CbeffEyes.Unspecified;
GrCbeffImage.Hair = CbeffImage.CbeffHair.Unspecified;
GrCbeffImage.FeatureMask = 0;
GrCbeffImage.Expression = CbeffImage.CbeffExpression.Unspecified;
return true;
}
//Get eyes and mouth position from Face Image
public bool GetPositionsFromFaceImage()
{
float prob = 0;
//Get the eyes detection probabilty
prob = GrFaceImage.DetectionProbability;
if (prob == 0)
{
Interaction.MsgBox("There isn't any probability to find the eyes position.", Constants.vbCritical, "No probability");
return false;
}
return true;
}
//Get eyes and mouth position from ICAO Image
public bool GetPositionsFromIcaoImage()
{
//get the position from an icao image.
float prob = 0;
prob = GrIcaoImage.DetectionProbability;
if (prob <= 0)
{
WriteLog("There isn't any probability to find the eyes position.");
return false;
}
return true;
}
//Set left eye position on library
public void SetLeftEyePos(int x, int y)
{
GrFaceImage.LeftEye = new Point(x, y);
}
//Set right eye position on library
public void SetRightEyePos(int x, int y)
{
GrFaceImage.RightEye = new Point(x, y);
}
//Set mouth position on library
public void SetMouthPos(int x, int y)
{
if (x > 0 & x < GrFaceImage.Width & y > 0 & y < GrFaceImage.Height)
{
Point p = new Point(x, y);
GrFaceImage.Mouth = p;
}
}
//Marshal between library and VB .NET. Copy an Variant Array to Byte() vector
public byte[] ConvertArrayToVByte(Array buffer)
{
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
byte[] bytes = new byte[buffer.Length + 1];
Marshal.Copy(ptr, bytes, 0, bytes.Length);
return bytes;
}
// Show GriauleAfis version and type
public void MessageVersion()
{
int majorVersion = 0;
int minorVersion = 0;
GriauleIcaoFace.GetVersion(majorVersion, minorVersion);
MessageBox.Show("The GrIcaoFace DLL version is " + majorVersion + "." + minorVersion + ".", "GrIcaoFace Version", MessageBoxButtons.OK);
}
}
}
I keep get error with this error:
The type or namespace name 'ListBox' could not be found (are
you missing a using directive or an assembly reference?).
The type or namespace name 'PictureBox' could not be found (are you
missing a using directive or an assembly reference?).
And here is the formMain.cs
using Microsoft.VisualBasic;
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 IcaoWF
{
public partial class formMain : Form
{
public formMain(): base()
{
Load += formMain_Load;
InitializeComponent();
}
// raw image data type.
private struct TSetting
{
// Image data.
public Button button;
// Image width.
public Label x;
public Label y;
public bool setting;
}
TSetting CSetting = new TSetting();
Util myUtil = default(Util);
private void formMain_Load(Object sender, EventArgs e)
{
InitializeInterface();
//Setting file filters
ldImg.Filter = "JPEG Images (*.jpg,*.jpeg)|*.jpg;*.jpeg|Gif Images (*.gif)|*.gif|Bitmaps (*.bmp)|*.bmp";
ldIcaoImg.Filter = "CBEFF (*.cbeff)|*.cbeff";
svIcaoImg.Filter = "JPEG2000 (*.jp2)|*.jp2|CBEFF (*.cbeff)|*.cbeff";
myUtil = new Util(logBox);
//Verifieing if the mouth is important
gbMouth.Enabled = myUtil.USES_MOUTH;
}
//Unlock the interface and update the clicked iten
private void interfaceSetStop(int x, int y)
{
if (CSetting.setting) {
//Set the CSetting to false
CSetting.setting = false;
//Set positions from mouse to CSetting text selected
CSetting.x.Text = x.ToString();
CSetting.y.Text = y.ToString();
//Enable Set button again
CSetting.button.Enabled = true;
//Set the normal cursor above image
imgFace.Cursor = Cursors.Arrow;
//Enable all butons, disabled before
EnableButtons();
//Sets new position from image
myUtil.SetLeftEyePos(lbLeftEyeXPos.Text, lbLeftEyeYPos.Text);
myUtil.SetRightEyePos(lbRightEyeXPos.Text, lbRightEyeYPos.Text);
if (myUtil.USES_MOUTH) {
myUtil.SetMouthPos(lbMouthXPos.Text, lbMouthYPos.Text);
}
//Redraw img
myUtil.DisplayFaceImage(imgFace, true);
}
}
//Initialize the program interface
private void InitializeInterface()
{
//Disable butons
DisableButtons();
//Disbable image picture box
imgFace.Enabled = false;
//Current setting eye or mouth to false
CSetting.setting = false;
//Disable Save ICAO image
mnFileSaveIcaoImg.Enabled = false;
//Reset the logBox
logBox.ResetText();
}
//Enable all butons from interface
private void EnableButtons()
{
btGenIcaoImage.Enabled = true;
btLeftEyeSet.Enabled = true;
btMouthSet.Enabled = true;
btRightEyeSet.Enabled = true;
btProcess.Enabled = true;
imgFace.Enabled = true;
}
//Set the inteface to click on the image
private void btLeftEyeSet_Click(Object sender, EventArgs e)
{
interfaceSetStart(btLeftEyeSet, lbLeftEyeXPos, lbLeftEyeYPos);
}
//Set the inteface to click on the image
private void lbRightEyeSet_Click(Object sender, EventArgs e)
{
interfaceSetStart(btRightEyeSet, lbRightEyeXPos, lbRightEyeYPos);
}
//Set the inteface to click on the image
private void btMouthSet_Click(Object sender, EventArgs e)
{
interfaceSetStart(btMouthSet, lbMouthXPos, lbMouthYPos);
}
//Lock the interface to click on image
private void interfaceSetStart(Button button, Label x, Label y)
{
//Set the clicked button set
CSetting.button = button;
//set the label to update the position
CSetting.x = x;
CSetting.y = y;
//Enable set mode
CSetting.setting = true;
//Disable the button
button.Enabled = false;
//Enable Cross cursor on image
imgFace.Cursor = Cursors.Cross;
//Disable button to avoid user to click in another area
DisableButtons();
}
//Disable all buttons from interface
private void DisableButtons()
{
btGenIcaoImage.Enabled = false;
btLeftEyeSet.Enabled = false;
btMouthSet.Enabled = false;
btRightEyeSet.Enabled = false;
btProcess.Enabled = false;
}
//On click on the image, stop the interface and set the right position
private void imgFace_MouseDown(object sender, MouseEventArgs e)
{
interfaceSetStop(e.X / (imgFace.Width / myUtil.GrFaceImage.Width), e.Y / (imgFace.Height / myUtil.GrFaceImage.Height));
}
//Gen the ICAO image from FaceImage
private void btGenIcaoImage_Click(Object sender, EventArgs e)
{
//Display ICAO image captured
myUtil.DisplayIcaoImg(imgIcaoImg);
//Enabled
mnFileSaveIcaoImg.Enabled = true;
}
//Load Icao IMAGE From CBEFF or JPEG2000
private void mnFileLoadIcaoImg_Click(Object sender, EventArgs e)
{
Util.EFile fileType = default(Util.EFile);
ldIcaoImg.FileName = "";
//save the ICAO image
if (ldIcaoImg.ShowDialog == DialogResult.OK & !string.IsNullOrEmpty(ldIcaoImg.FileName))
{
fileType = myUtil.GetFileType(ldIcaoImg.FileName);
switch (fileType)
{
case Util.EFile.CBEFF:
//Save CBEFF image
myUtil.LoadIcaoFromCBEFFImage(ldIcaoImg.FileName, imgIcaoImg);
break;
//
default:
//Image type not found
myUtil.WriteLog("File type not supported.");
return;
}
}
}
//Save ICAO Image
private void mnFileSaveIcaoImg_Click(Object sender, EventArgs e)
{
Util.EFile fileType = default(Util.EFile);
svIcaoImg.FileName = "";
//save the ICAO image
if (svIcaoImg.ShowDialog == DialogResult.OK & !string.IsNullOrEmpty(svIcaoImg.FileName))
{
fileType = myUtil.GetFileType(svIcaoImg.FileName);
switch (fileType)
{
case Util.EFile.CBEFF:
//Save CBEFF image
myUtil.SaveIcaoIntoCBEFFImage(svIcaoImg.FileName);
break;
case Util.EFile.JPEG2000:
//Save JPEG200 image
myUtil.SaveIcaoIntoJP2Image(svIcaoImg.FileName);
break;
default:
//Image type not found
myUtil.WriteLog("File type not supported.");
break;
}
}
}
//Load Image
private void mnFileLoadImg_Click(Object sender, EventArgs e)
{
lbLeftEyeXPos.Text = "0";
lbLeftEyeYPos.Text = "0";
lbRightEyeXPos.Text = "0";
lbRightEyeYPos.Text = "0";
lbMouthXPos.Text = "0";
lbMouthYPos.Text = "0";
//Disable buttons
DisableButtons();
//Enable image
imgFace.Enabled = true;
//Set file name image to null
ldImg.FileName = "";
if (ldImg.ShowDialog == DialogResult.OK & !string.IsNullOrEmpty(ldImg.FileName))
{
//load image from FileName into imgFace Picture Box
if (myUtil.LoadImage(ldImg.FileName, imgFace))
{
//Set the icaoImage to null
imgIcaoImg.Image = null;
imgIcaoImg.Refresh();
//Disble mnFileSaveIcaoImg to save
mnFileSaveIcaoImg.Enabled = false;
//Disable buttons
DisableButtons();
//Enable find eyes and mouth button
btProcess.Enabled = true;
}
}
}
//Close the program
private void MenuItem5_Click(Object sender, EventArgs e)
{
this.Close();
}
//Process the Face Image
private void btProcess_Click(Object sender, EventArgs e)
{
//Enable buttons to set eyes and mouth
EnableButtons();
//Process face image
if (myUtil.ProcessFaceImage(imgFace))
{
//Get positions from face image
lbLeftEyeXPos.Text = myUtil.GrFaceImage.LeftEye.X.ToString();
lbLeftEyeYPos.Text = myUtil.GrFaceImage.LeftEye.Y.ToString();
lbRightEyeXPos.Text = myUtil.GrFaceImage.RightEye.X.ToString();
lbRightEyeYPos.Text = myUtil.GrFaceImage.RightEye.Y.ToString();
lbMouthXPos.Text = myUtil.GrFaceImage.Mouth.X.ToString();
lbMouthYPos.Text = myUtil.GrFaceImage.Mouth.Y.ToString();
}
}
//Print the DLL version
private void mnVersion_Click(Object sender, EventArgs e)
{
myUtil.MessageVersion();
}
}
}
I can post the vb.net version if needed.
EDITED: I have added refference(System.Windows.Forms.dll) to the project and all the other am using.
thanx
Nurcky
ListBox is defined in the assembly System.Windows.Forms.dll. Make sure you have a reference to that assembly.
Additionally you probably want
using System.Windows.Forms;
Both the ListBox and PictureBox controls are found in the System.Windows.Forms namespace. Add the following statement to the top of your code:
using System.Windows.Forms;
Then add a reference to System.Windows.Forms.dll
Use the System.Windows.Forms namespace. To use the System.Windows.Forms namespace, you have to add System.Windows.Forms.dll as a reference.
To add the reference,follow the following step:
In Solution Explorer, right-click on the project node and click Add Reference.
In the Add Reference dialog box, select the .NET tab and choose System.Windows.Forms and click OK.
I have made a bouncing screensaver in C#. When there is only a single monitor to display it works perfectly. However, when I have a dual monitor display the bounds do not work properly. The position of secondary monitor seems to have an effect and there does not seem to be a right bound (secondary screen is on the right side).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace LIUScreensaver
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (args.Length > 0)
{
string firstArg = args[0].ToLower().Trim();
string secondArg = null;
//handle cases where arguments are separated by colon
if (firstArg.Length > 2)
{
secondArg = firstArg.Substring(3).Trim();
firstArg = firstArg.Substring(0, 2);
}
else if (args.Length > 1)
{
secondArg = args[1];
}
if (firstArg == "/c")
{
MessageBox.Show("This screensaver does not allow configuration changes");
}
else if (firstArg == "/p")
{
if (secondArg == null)
{
MessageBox.Show("Sorry, but there was an error.", "Screensaver", MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
IntPtr preview = new IntPtr(long.Parse(secondArg));
Application.Run(new ScreensaverForm(preview));
}
else if (firstArg == "/s")
{
ShowScreenSaver();
Application.Run();
}
else
{
MessageBox.Show("Invalid command line argument. \"" + firstArg + "\" is not a valid ", "Screensaver",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
else
{
MessageBox.Show("There has been an error displaying the screensaver. Please report this issue.");
}
}
public static void ShowScreenSaver()
{
//creates form on each display
int i = 0;
Screen[] screen = Screen.AllScreens;
for (i = 0; i < screen.Length; i++)
{
ScreensaverForm screensaver = new ScreensaverForm(screen[i].Bounds);
screensaver.Show();
}
}
}
}
//Screensaver form
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 LIUScreensaver
{
public partial class ScreensaverForm : Form
{
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern bool GetClientRect(IntPtr hWnd, out Rectangle lpRect);
private Boolean previewMode = false;
private int mouseX = 0, mouseY = 0;
private int imgX = 0, imgY = 0;
private Boolean bot = true, left = true, right = false, top = false;
Point p;
//constructor with no arguments
public ScreensaverForm()
{
InitializeComponent();
}
//constructor with bound arguments
public ScreensaverForm(Rectangle Bounds)
{
InitializeComponent();
this.Bounds = Bounds;
}
//preview constructor
public ScreensaverForm(IntPtr preview)
{
InitializeComponent();
SetParent(this.Handle, preview);
SetWindowLong(this.Handle, -16, new IntPtr(GetWindowLong(this.Handle, -16) | 0x40000000));
Rectangle parentRec;
GetClientRect(preview, out parentRec);
Size = parentRec.Size;
Location = new Point(0, 0);
txtLabel.Font = new System.Drawing.Font("Arial", 6);
previewMode = true;
}
//form load
private void ScreensaverForm_Load(object sender, EventArgs e)
{
Cursor.Hide();
TopMost = true;
System.Drawing.Color background = System.Drawing.ColorTranslator.FromHtml("#002668");
this.BackColor = background;
moveTimer.Interval = 1;
moveTimer.Tick += new EventHandler(moveTimer_Tick);
moveTimer.Start();
}
//
//-----------------------------------------------------------------------------------------------------
//The following code ends the application and exits the screensaver
private void ScreensaverForm_KeyPress(object sender, KeyPressEventArgs e)
{
if (!previewMode)
{
Application.Exit();
}
}
private void ScreensaverForm_MouseMove(object sender, MouseEventArgs e)
{
if (!previewMode)
{
if (mouseX == 0)
{
mouseX = e.X;
mouseY = e.Y;
}
if ((mouseX - e.X) > 5 || (mouseY - e.Y) > 5)
{
Application.Exit();
}
}
}
private void ScreensaverForm_MouseClick(object sender, MouseEventArgs e)
{
if (!previewMode)
{
Application.Exit();
}
}
//
//
//timer to bounce the image across the screen
private void moveTimer_Tick(object sender, System.EventArgs e)
{
// Move text to new location
bounce();
}
//function that moves the image
private void bounce()
{
//Checks boundaries
if (txtLabel.Location.Y + txtLabel.Image.Height - this.Bounds.Bottom>= 0)
{
top = true;
bot = false;
}
if (txtLabel.Location.X + txtLabel.Image.Width - this.Bounds.Right >= 0)
{
right = false;
left = true;
}
if (txtLabel.Location.X <= this.Bounds.Left)
{
right = true;
left = false;
}
if (txtLabel.Location.Y <= this.Bounds.Top)
{
top = false;
bot = true;
}
//moves image
if (bot == true)
{
if (right == true)
{
++imgX;
++imgY;
p.X = imgX;
p.Y = imgY;
txtLabel.Location = p;
}
else if (left == true)
{
--imgX;
++imgY;
p.X = imgX;
p.Y = imgY;
txtLabel.Location = p;
}
}
if (top == true)
{
if (right == true)
{
++imgX;
--imgY;
p.X = imgX;
p.Y = imgY;
txtLabel.Location = p;
}
else if (left == true)
{
--imgX;
--imgY;
p.X = imgX;
p.Y = imgY;
txtLabel.Location = p;
}
}
Invalidate();
}
}
}
The problem is the label's Location is its position relative to the monitor that it's on while the bounds you are comparing it too are an absolute position across all monitors.
So if the bounds of the primary monitor are Top: 0, Bottom: 900, Left: 0, Right: 1600
the bounds of the secondary monitor might be something like Top: 0, Bottom: 900, Left: 1600, Right: 3200. While the Location of the label on the secondary monitor will returning its position relative to the secondary monitor so for example Location.X: 200, Location.Y: 300.
You need to change the bounce Method to make the comparsion use either only absolute coordinates or only relative coordinates.
Here is the comparison code modified to use relative position of the label on the monitor;
if (txtLabel.Location.Y + txtLabel.Image.Height - (this.Bounds.Bottom - this.Bounds.Top) >= 0)
{
top = true;
bot = false;
}
if (txtLabel.Location.X + txtLabel.Image.Width - (this.Bounds.Right - this.Bounds.Left) >= 0)
{
right = false;
left = true;
}
// in relative coordinates left is always 0
if (txtLabel.Location.X <= 0)
{
right = true;
left = false;
}
// in relative coordinates top is always 0
if (txtLabel.Location.Y <= 0)
{
top = false;
bot = true;
}