Yes, but the sheet names must be known to hardcode a range.
Also, will there ever be any discontinuities (empty cells) is the column data. This is not a problem, it needs to be accounted for in computing the range to process.
Yes, but the sheet names must be known to hardcode a range.
Also, will there ever be any discontinuities (empty cells) is the column data. This is not a problem, it needs to be accounted for in computing the range to process.
Sorry, but I begin to use VBA and I want/need to learn more. I will be apreaciated for any clues.
I am going to assume that since you mentioned VBA that you are looking for Excel macro help.
If this is the case, this thread should be probably moved to the VB6 forum as that is the most appropriate one that I can think of.
TnTinMN,
Yes, it sounds like what I need.
Here is a basic macro with minimal error checking. It asks you to select two ranges and it compares the first column in each range to produce a result array. It then asks you for a place to copy the results to in a worksheet.
Private Sub CompareColumns()
Dim Col1 As Range
Dim Col2 As Range
On Error Resume Next
Set Col1 = Application.InputBox("Select 1st column", , ActiveCell.Address, _
, , , , vbString)
If Col1 Is Nothing Then Exit Sub
Set Col2 = Application.InputBox("Select 2nd column", , ActiveCell.Address, _
, , , , vbString)
If Col2 Is Nothing Then Exit Sub
On Error GoTo 0 ' cancel resume next
'Determine the longer list
Dim shortCol As Range
Dim LongCol As Range
If Col1.Rows.Count < Col2.Rows.Count Then
Set shortCol = Col1
Set LongCol = Col2
Else
Set shortCol = Col2
Set LongCol = Col1
End If
Dim LongColMatched() As Boolean ' Used to indicate matched value used if duplicates exist
ReDim LongColMatched(0 To LongCol.Rows.Count - 1)
' declare a result array …
I am going try to rephrase your question and ask that you confirm whether or not it matches your ultimate goal.
You have two lists of of numbers. One of the lists is longer than other and it contains all the values in the shorter list.
You need to create a side by side comparison of the two lists showing a blank cells in the column representing the shorter list where a number exists in the longer list but not in the shorter list.
Does this sound like what you are after?
The routine that I posted does not clone Children nor Content. It may be possible to write a generic cloner, but write know I do not see an easy way to do so.
It is be fairly easy to write a simple cloner for the pattern of ContentControl <- Grid <- Shape.
private void Button1_Click(object sender, RoutedEventArgs e)
{
ContentControl cc = ContentControlCloner(ContentControl1);
cc.Margin = new Thickness(100, 0, 0, 0);
Canvas1.Children.Add(cc);
}
private Shape ShapeCloneProperties(Shape source)
{
Shape clone = null;
switch (source.GetType().Name)
{
case "Ellipse":
clone = new Ellipse();
break;
case "Line":
clone = new Line();
break;
case "Path":
clone = new Path();
break;
case "Polygon":
clone = new Polygon();
break;
case "Polyline":
clone = new Polyline();
break;
case "Rectangle":
clone = new Rectangle();
break;
default:
throw new ArgumentException("Invalid shape");
}
foreach (System.Reflection.PropertyInfo pi in source.GetType().GetProperties())
{
if (pi.CanWrite && pi.CanRead)
{
pi.SetValue(clone, pi.GetValue(source, null), null);
}
}
return clone;
}
private ContentControl ContentControlCloner(ContentControl source)
{
ContentControl clone = new ContentControl();
clone.Name = "fred";
foreach (System.Reflection.PropertyInfo pi in typeof(ContentControl).GetProperties())
{
if (pi.Name == "Content")
{
Grid gr = (Grid)source.Content;
Grid gridclone = GridCloneProperties(gr);
gridclone.Children.Clear();
Shape sh = ShapeCloneProperties((Shape)gr.Children[0]);
gridclone.Children.Add(sh);
clone.Content = gridclone;
}
else
{
if (pi.CanWrite && pi.CanRead)
{
pi.SetValue(clone, pi.GetValue(source, null), null);
}
}
}
return clone;
}
private Grid GridCloneProperties(Grid source)
{
Grid clone = new Grid();
foreach (System.Reflection.PropertyInfo pi in typeof(Grid).GetProperties())
{
if (pi.CanWrite && pi.CanRead)
{
pi.SetValue(clone, pi.GetValue(source, null), null);
}
}
return clone;
}
}
Modify your code like this:
'Read each line after first seven lines
For I = 1 To 7
If inputFile.Peek >= 0 Then
strWeather = inputFile.ReadLine()
Stop
End If
Next
While inputFile.Peek >= 0
strWeather = inputFile.ReadLine()
Stop
key = CInt(strWeather.Substring(1, 3))
'store the entire line in the collection
colWeather.Add(strWeather, CStr(key))
End While
Then run it and inspect strWeather each time then code stops. Most likely you have an empty line if the text file that is being read.
Hit F5 to continue execution.
I still get my catch message box. At this point I'm not really sure what is happening anymore...
Comment out the Try-Catch statements and let the debugger show you where the error is occuring. Inspect the variables and see if they are what you would expect.
For some guidance on debugging, read : Debugging in Visual Basic .NET. It is old but still valid.
That was fast.
I was in the neighborhood and it was an easy question. :)
Please mark the thread as answered, if you don't have any more questions on the topic.
Thanks.
Your file is open with the filestream object when you try to open it via Proc.Start();
.
At a minimum, add FS.Flush();
after writing out the bytes to flush the buffer to disk. Preferably, close the file before calling Proc.Start();
.
Perhaps something like this, where "ellispse1" in the name of the ellipse you defined in XAML.
private void button1_Click(object sender, RoutedEventArgs e)
{
Ellipse copyel = EllipseCloneProperties(ellipse1);
// set your positioning properties
canvas1.Children.Add(copyel);
}
private Ellipse EllipseCloneProperties(Ellipse source)
{
Ellipse clone = new Ellipse();
foreach (System.Reflection.PropertyInfo pi in typeof(Ellipse).GetProperties())
{
if (pi.CanWrite && pi.CanRead)
{
pi.SetValue(clone, pi.GetValue(source, null), null);
}
}
return clone;
}
Here are two options:
This one whould update after you leave the first column.
private void dgv1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex == -1)
return;
if (sender is DataGridView && e.ColumnIndex == 0)
{
DataGridView dgv = (DataGridView)sender;
if (dgv1.Equals(dgv))
{
// set the value as needed
dgv.Rows[e.RowIndex].Cells[2].Value = "fred";
}
}
}
This one updates immediately.
private DataGridViewComboBoxEditingControl cboxEdit;
private void EditComboBox_SelectionChangeCommitted(object sender, System.EventArgs e)
{
// set the value as needed
dgv1.CurrentRow.Cells[2].Value = "wilma";
}
private void dgv1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (dgv1.CurrentCell.ColumnIndex == 0 && e.Control is DataGridViewComboBoxEditingControl)
{
if (cboxEdit != null)
{
cboxEdit.SelectionChangeCommitted -= EditComboBox_SelectionChangeCommitted;
}
cboxEdit = (DataGridViewComboBoxEditingControl)e.Control;
cboxEdit.SelectionChangeCommitted += EditComboBox_SelectionChangeCommitted;
}
}
when i try to delete a certain row it gives me the previous exception
What previous exception?
Is Bridge_Number a Text field? If not, get rid of the single qotes around it in the query. What column index does Bridge_Number represent in the listview? Your query indicates that it is the first column.
Here is an example that you can follow to read in the DBASE file. It is slightly different than the method you are using.
Dim ofd As New OpenFileDialog
With ofd
.Filter = "DBASE File (*.dbf)|*.dbf"
.Multiselect = False
.CheckFileExists = True
End With
If ofd.ShowDialog() = Windows.Forms.DialogResult.OK Then
Dim fi As New IO.FileInfo(ofd.FileName)
Dim cn As New OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=dBase IV;Data Source='" _
& fi.DirectoryName & "'")
Dim TableName As String = fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length)
Dim cmd As New OleDb.OleDbCommand(TableName, cn)
cmd.CommandType = CommandType.TableDirect
Dim dt As New DataTable
cn.Open()
Dim rdr As OleDb.OleDbDataReader = cmd.ExecuteReader
dt.Load(rdr)
DataGridView1.DataSource = dt
cn.Close()
cn.Dispose()
End If
In addition to rubberman's comment:
you are summing in "coursesCount:, but comparing "courses".
Is this the logic you intended?
You will likely get several techniques for doing this. Here are two that I find preferable.
Public Class Form1
Sub LaunchForm2()
Dim f2 As New Form2
f2.needVariable = 2 ' pass as property
f2.ShowDialog()
End Sub
Sub LaunchForm3()
Dim f3 As New Form3(3) ' pass in constructor
f3.ShowDialog()
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
LaunchForm2()
LaunchForm3()
End Sub
End Class
'Declare a property on the 2nd form
Public Class Form2
Inherits Form
Private _needVariable As Int32
Public Property needVariable() As Int32
Get
Return _needVariable
End Get
Set(ByVal value As Int32)
_needVariable = value
End Set
End Property 'needVariable
Private Sub Form2_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
MsgBox("F2: " & needVariable.ToString())
Me.Close()
End Sub
End Class
' pass the value in the form's constructor
Public Class Form3
Inherits Form
Private needVariable As Int32
Public Sub New(ByVal needVariable As Int32)
Me.needVariable = needVariable
End Sub
Private Sub Form2_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
MsgBox("F3: " & needVariable.ToString())
Me.Close()
End Sub
End Class
Scrap emmbedding the video files.
Bring up the Solution Explorer: View Menu - > Solution Explorer
Add New Folder: Project Menu -> New Folder (Let's Name it Video)
In the "Solution Explorer" window, Selected the "Video" folder and then right-click->Add->Existing Item
Now Select your video files to include in the project.
For each video you add, set it's properties like this:
Build the Application.
Set the Publishing Options:
Now Publish it.
You can then load the video like this:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
AxWindowsMediaPlayer1.currentMedia = AxWindowsMediaPlayer1.newMedia(ExecutionPath() & "\Video\Video1.avi")
End Sub
Public Function ExecutionPath() As String
Return System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
End Function
How are you doing the Deployment?
That's a new error message to me :/
Usually it's along the lines of cannot delete file blah blah...
Are you sure you do not have an instance of the program running? It may have crashed and did not fully unload from memory and release the file. Sometimes you will need to reboot to clear things up.
Tinnin,
Why are you going through all this work just to read in values from an Excel file? What does converting it to a CSV format gain you?
You could use the Excel interop to read the values directly.
Alternatively, you could use ADO.Net to read the files without any dependence on having Excel installed.
Use one of these forms of parsing:
i = Integer.Parse("1")
- will throw an exception if conversion is not possibleInteger.TryParse("1", i)
- will not throw exception, leaves i unchanged
I believe you are going to have to normalize and strip the diacritics from the string first.
see: http://stackoverflow.com/questions/249087/how-do-i-remove-diacritics-accents-from-a-string-in-net
You could add new column to your datatable with the processed string and then do the row filter against that processed string.
Or you could use LINQ to create a list of datarows and use that presumably as a datagridview.DataSource.
Something like this:
List<DataRow> rows = (from row in dt.AsEnumerable()
where System.Text.RegularExpressions.Regex.IsMatch(RemoveDiacritics(((DataRow) row)[0].ToString()), "Maria*")
select row).ToList();
Try using the CellClick event not CellContentClick event handler.
Private Sub DataGridView1_CellClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvEmployee.CellClick
TextBox1.Text = dgvEmployee.Rows(e.RowIndex).Cells(0).Value.ToString()
TextBox2.Text = dgvEmployee.Rows(e.RowIndex).Cells(1).Value.ToString()
TextBox3.Text = dgvEmployee.Rows(e.RowIndex).Cells(2).Value.ToString()
End Sub
Sure it is doable! You just have to code it. :))
Here is a crude implementation of a custom textbox with this capability. You have to double click on a item to select it. You could change that to single click if you want. You may need to change the "@" detection algorithm. It works with a standard US keyboard with "@" = shift-2.
There is no error checking; I leave that to you.
Public Class AutoCompleteDropDownTB
Inherits TextBox
Public WithEvents dropdown As New ListBox
Private frmDropDown As New Form
Public Sub New()
dropdown.Parent = frmDropDown
dropdown.SelectionMode = SelectionMode.One
With frmDropDown
.FormBorderStyle = FormBorderStyle.None
.Size = dropdown.Size
.Visible = False
.StartPosition = FormStartPosition.Manual
.TopLevel = True
.TopMost = True
End With
End Sub
Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
If e.Shift AndAlso e.KeyCode = Keys.D2 AndAlso Not Text.Contains("@"c) Then
ShowDropDown()
End If
MyBase.OnKeyDown(e)
End Sub
Private Sub ShowDropDown()
dropdown.SelectedIndex = 0 ' make sure 1st item is selected
Dim offset As Int32
If BorderStyle = Windows.Forms.BorderStyle.Fixed3D Then
offset = 2
Else
offset = 0
End If
With frmDropDown
.Location = PointToScreen(New Point(0, Size.Height - offset))
.Show()
End With
End Sub
Private Sub dropdown_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles dropdown.DoubleClick
frmDropDown.Hide()
Text &= dropdown.SelectedItem.ToString
SelectionStart = TextLength
End Sub
Private Sub dropdown_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles dropdown.LostFocus
frmDropDown.Hide()
End Sub
End Class
Just add this to your project and rebuild. It should show up at the top of your toolbox.
Example …
…so why do it the other way, ie ole I guess whatever that is
I’ll try to explain this to the best of my ability. I may get some of the facts and terminology mixed up though. I never was one for all the fancy computer science terminology.
ADO,Net is the basis for all .Net database interfacing. OleDB is layer above ADO that provides addition tools to manipulate the data and interface with the other .Net data classes such as a DataSet.
See: Overview of ADO.NET
. Is there any advantage of using one over the other?
The choice comes down to selecting the correct tool for the given task and whether or not you know how to use that tool.
For a case like appending a record to datatable, you could go either route. You could also have used OLEDBCommand with a SQL “Insert” statement to do the same thing directly as that convoluted code shown above that was crafted to prevent the need for you to generate the “Insert” SQL yourself (i.e. same destination, but a different path).
The biggest advantage is when you use the full design functionality of Visual Studio for creating a “Data Access Layer” in the graphical environment. Many people will create a dataset on the fly in their code just to make work with selected abstraction layer like OleDB or SQLClient without ever realizing that there is so much more that they can accomplish in they just …
Your welcome.
Please close this thread out if you don't have any more questions.
The form deactivate/Activate only seems to occur in you use the MonthCalendar dropdown to make the selection.
It probably has to do with the MonthCalendar control being displayed a Modal window (like a dialog box) and it taking focus (hence the deactivation of the form) when clicked on. The form is reactivated when the MonthCalendar closes.
I want to set the focus only the first time the form is loaded, from that point on I want the tab control to dictate the navigation.
Then use either the Form.Shown event or Form.Load event.
No. You did not do anything wrong.
A line of code got deleted when I was editing it while posting. :(
Add dt.Rows.Add(r)
somewhere before the statement: da.Update(New DataRow() {r})
I am a VB6 man at heart and it is so easy to do this on VB6
Then you are probably more comfortable with ADO. Use it then. I'm a bit rusty with ADO, but I believe that this should do the trick once you add the adodb reference. It worked on my quick test.
Remember to to make the needed changes to the connection string (in cn.open) and TableName (in the rs.Open).
' Add Project .Net Reference to adodb. see: http://support.microsoft.com/kb/318559
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
cn.Open(My.Settings.PlayConnectionString)
rs.Open(Source:="History", ActiveConnection:=cn, CursorType:=ADODB.CursorTypeEnum.adOpenDynamic, LockType:=ADODB.LockTypeEnum.adLockOptimistic)
rs.AddNew()
rs.Fields.Item("Datee").Value = Now
rs.Fields.Item("ContactID").Value = contactID
rs.Fields.Item("Userr").Value = username
rs.Save()
cn.Close()
UKnod,
That code is just plain nasty! :(
It appears that you want to add a new record to the History table in the database. You have created a dataset (ds5) elsewhere in your code.
Does your code need to access the dataset's History table elsewhere, or do you create it just for the purpose of adding a new row?
If you do not need to maintain records in memory, you could do something like this:
' Modify the following line to reflect your connection string
Dim cn As New OleDbConnection(My.Settings.PlayConnectionString)
'create command to use
Dim cmd As New OleDbCommand("History", cn)
cmd.CommandType = CommandType.TableDirect
' create a dataadapter and commandbuilder for it
Dim da As New OleDbDataAdapter(cmd)
Dim cb As New OleDbCommandBuilder(da)
' create a temporary table to hold History's schema
Dim dt As New DataTable
' Fill the schema so that we can get the row template NewRow
da.FillSchema(dt, SchemaType.Source)
Dim r As DataRow = dt.NewRow
r(6) = contactID
r(1) = Now()
r(3) = username
' process the new row
da.Update(New DataRow() {r})
' cleanup
cb.Dispose()
da.Dispose()
cmd.Dispose()
cn.Dispose()
This code could be shorter if you would post the History table's schema (field definition listing) and note the keyed fields. Knowing the schema would allow creating an insert command and the datatable code could be eliminated.
I like using datatables and a rowfilter for this type of stuff.
Here is a simple example. I manually loaded the DataTables, but you would do this with your file contents. You could also do your text files as xml and load the table directly with the xml definition. Most of the code is just creating some data to play with.
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 WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private DataTable dtGenre = new DataTable();
private DataTable dtMovies = new DataTable();
private void Form1_Load(object sender, EventArgs e)
{
DataRow r = default(DataRow);
// Build Movies Table
dtMovies.Columns.Add("Genre", typeof(string));
// add whatever columns you need
dtMovies.Columns.Add("Title", typeof(string));
dtMovies.Columns.Add("Description", typeof(string));
dtMovies.Columns.Add("Rating", typeof(string));
// just defining Genre and title for this example
r = dtMovies.NewRow(); r[0] = "Action"; r[1] = "Title1"; dtMovies.Rows.Add(r);
r = dtMovies.NewRow(); r[0] = "Action"; r[1] = "Title2"; dtMovies.Rows.Add(r);
r = dtMovies.NewRow();r[0] = "Action"; r[1] = "Title3"; dtMovies.Rows.Add(r);
r = dtMovies.NewRow(); r[0] = "Adventure"; r[1] = "Title4"; dtMovies.Rows.Add(r);
r = dtMovies.NewRow(); r[0] = "Comedy"; r[1] = "Title5"; dtMovies.Rows.Add(r);
r = dtMovies.NewRow(); r[0] = "Comedy"; r[1] = "Title6"; dtMovies.Rows.Add(r);
dtMovies.DefaultView.RowFilter = null;
// Build Genre Table
dtGenre.Columns.Add("Genre", typeof(string));
dtGenre.Columns.Add("Description", typeof(string));
r = dtGenre.NewRow(); r[0] = "Action";
r[1] = "Action: Usually include high energy, big-budget physical stunts and chases, possibly with rescues, battles, fights, escapes, destructive crises (floods, explosions, natural disasters, fires, etc.), non-stop motion, spectacular rhythm and …
My opinion excel is the worst choice. Access is nearly as bad.
I would go with either SQL Server Compact or Sql Server Client.
now the question is how can i get the that name to be used in my query?
using loop?
i will use it to be the name of my table i want to search.I hope you understand what i mean.
Nope!, I do not understand.
Do you mean that you want to retrieve a list of Table names from the DB and be able to substitute the Table name in the query?
This example is for a SQLClient connection, but should work for OleDb as well.
Dim cn As New SqlClient.SqlConnection(My.Settings.NorthwindConnectionString)
cn.Open()
For Each r As DataRow In cn.GetSchema("Tables").Rows
' Note that this will pull both Tables &" Views. You may need to filter out the Views.
Dim TableName As String = r("Table_Name").ToString
' do something with TableName
Next
cn.Close()
Since you state that you are using a VB Express Edition, this question should be moved to the VB.Net forum.
Depending on the volume of data and security needs, you could use any of the options you listed, but I would stay away from using Excel files since that option will provide very limited DB functionality. If you foresee a need to dump a set of data out for use in Excel, there are several options available for doing this.
For a simple DB structure and relatively small amount of data, you could use the .Net DataTable class to save/load your data to/from an XML file. Your DB would be held in memory once loaded.
MS Access can be a pain in regards to the driver bitness. You can not have both 32 and 64 bit versions of the driver installed.
Another option to consider is SQL CE that is very light weight and gives an easy upgrade path to SQL Server if that need would ever become necessary. You should have been given an option to install it when you installed VB express (at least with the more recent versions).
And as Jim already mentioned, you could always install SQL Server Express.
@ddanbe: You are welcome. :) VB has a few utility classes that they really should publicize better to the .Net world or better yet, move to generic Utility namespace.
You should calculate the monthly payment once based on the initial loan amount and not in your loop based on remaining balance.
Are you using the Financial Class from the VisualBasic Namespace? If so, then your usage is incorrect and you should review the documentation.
"Sender" typically is the control prompting the call to the event handler method. Cast it to the type of control you hope it is after a bit of chgecking first.
Private Sub Label_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
If sender IsNot Nothing AndAlso TypeOf sender Is Label Then
Dim lbl As Label = CType(sender, Label)
MsgBox(lbl.Text)
End If
End Sub
Don,
No offense intended, but you need to get more of the basics (no pun intended) under control first.
Learn to use the debugger. It is there for reason it and is your best friend.
Debugging User Interface Reference
Set a break-point in your code and inspect the variable's contents by hovering your mouse pointer over the variable name. This will allow you to see if the variables actually hold what you think they do.
You are using SQL Server, yet your code is using the OLEBD namespace data objects (connection, dataadapter, etc.). This in itself is not incorrect, but there is the SQLClient namespace that has versions of these objects specifically tailored to SQL Server.
Minor issue: you are hard coding your connection strings into your code. This will make it a pain later on when you want to distribute your application. You could define a string variable in Module or my preference is to use the My.Settings collection that VB provides. You can access this by going to Project Properties and selectioning the settings tab. When you define the setting, select "Connection string" for the type.
In the code you have shown, you are "opening" a connection. You should be close every connection you open. I believe the DataAdapter fill method does not require you top open the connection first. It will open and close the connection that you have provided it.
I also suggest that you consider using the DataSet designer to assist you in …
When you override OnMouseDown and do not call the base method, you prevent the OnClick method from being called. Therefore, move the code (this.Checked = !this.Checked;
) from OnClick to OnMouseDown.
protected override void OnMouseDown(MouseEventArgs mevent)
{
//base.OnMouseDown(mevent);
this.Checked = !this.Checked;
}
it seems like you have experience with listviews
Not really, I do not particularly like this control.
n vb 6 you could set the BackgroundImageAligment in .net thats not allowed
Yeh, if you do a search you will find that in the original .Net they had some issues with it. I did some snooping of the source code and for some reason they did not give you the option to set the x,y positioning eventhough there does not appear to be any reason for it. They just locked it into (0,0), the top-left corner. So as usual when the control does not do what you want, you need to create your own version. I had some issues with graphical artifacts when something dragged over the image, so I added some hacks. Its not perfect, but close. It does give you a bit more control on positioning. You set the (x,y) point as an integer percentage value for x and y. You will see the new properties in the property grid. Just add this to your project, build the project and it should show up at the top of your toolbox.
Public Class LV
Inherits ListView
<Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True, CharSet:=Runtime.InteropServices.CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, _
ByVal Msg As Int32, _
ByVal wParam As IntPtr, _
ByRef lParam As LVBKIMAGE) As IntPtr
End Function
Private Structure LVBKIMAGE
Public ulFlags As LVFlags
Public hbm As IntPtr
Public pszImage As String
Public cchImageMax As Int32
Public …
@TnTinMN: after working on your code to make it work another problem is noticed. you can't make a transparent button on the MouseEnter event :( :S.
so it will be noticed as a button and not as a checkbox
I can provide you with pictures it you want
Just override the OnMouseEnter method and do not call the base OnMouseEnter method.
protected override void OnMouseEnter(EventArgs e)
{
//base.OnMouseEnter(e);
}
Perhaps something like this will work for you.
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
With ListView1
.Alignment = ListViewAlignment.SnapToGrid
.AllowDrop = True
.AutoArrange = False
.Scrollable = False
.View = View.LargeIcon
End With
End Sub
Private Sub ListView1_ItemDrag(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemDragEventArgs) Handles ListView1.ItemDrag
Dim lvi As ListViewItem = CType(e.Item, ListViewItem)
ListView1.DoDragDrop(New DataObject("System.Windows.Forms.ListViewItem", lvi), DragDropEffects.Move)
End Sub
Private Sub ListView1_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListView1.DragEnter
If e.Data.GetDataPresent("System.Windows.Forms.ListViewItem") Then
e.Effect = DragDropEffects.Move
End If
End Sub
Private Sub ListView1_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListView1.DragOver
Dim lvi As ListViewItem = CType(e.Data.GetData("System.Windows.Forms.ListViewItem"), ListViewItem)
Dim Offset As Size = Size.Subtract(Cursor.Size, New Size(Cursor.HotSpot.X, Cursor.HotSpot.Y))
lvi.Position = Point.Subtract(ListView1.PointToClient(New Point(e.X, e.Y)), Offset)
e.Effect = DragDropEffects.Move
End Sub
End Class
Your main problem is that the checkbox is not very amenable to using an image to indicate the checked state. You are trying to paint over the box and that is always going to look strange.
Here is a custom control that I hammered out quickly based on a Button. It left aligns the button image and uses the ImageList property to contain a Checked and UnChecked Image. There are three added properties: CheckedImage, UnCheckedImage and ImageSize that control the images. If you don't like the looks, you can easy overide the style properties.
The code style my seem a bit strange as I originally did it in VB and converted to C#.
public class ImageCheckBox : Button
{
private Image _CheckedImage = new Bitmap(24, 24);
private Image _UnCheckedImage = new Bitmap(24, 24);
public ImageCheckBox()
{
_Checked = false;
this.ImageAlign = ContentAlignment.MiddleLeft;
base.ImageList = new ImageList();
this.FlatAppearance.BorderSize = 0;
this.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
Checked = false;
}
private void SetImages()
{
base.ImageList.Images.Clear();
base.ImageList.Images.Add(_UnCheckedImage);
base.ImageList.Images.Add(_CheckedImage);
Invalidate();
}
private bool _Checked;
public bool Checked
{
get { return _Checked; }
set
{
_Checked = value;
if (_Checked)
{
ImageIndex = 1;
}
else
{
ImageIndex = 0;
}
}
}
private Size _ImageSize = new Size(24,24);
public Size ImageSize
{
get { return _ImageSize; }
set
{
_ImageSize = value;
this.ImageList.ImageSize = value;
SetImages();
}
}
public Image CheckedImage
{
get { return _CheckedImage; }
set
{
_CheckedImage.Dispose();
_CheckedImage = value;
SetImages();
}
}
public Image UnCheckedImage
{
get { return _UnCheckedImage; …
vbBack is string value
try Asc(vbBack)
but one more question how can i make it something like 30,000,000 not like 29,482,410?
Change the rounding factor: Const Factor As Double = 5
If you want to round to the nearest 10,000,000, use that as the factor.
Also if your range always starts at zero, just set the Y axis minimum to zero as there is no need to compute a minimum value.
Please take the time to try and understand how to code works instead of just inserting it.
Probably due to me giving an example that I did not check properly. :(
ymax should be using FindMaxByMalue not FindMinByValue.
Dim ymax As Double = Math.Max(.Series(0).Points.FindMaxByValue("Y1").YValues(0), _
.Series(1).Points.FindMaxByValue("Y1").YValues(0))
the secondary axis i want it to be fixed in the line of the primary axis in the left side
Assuming that this means that you want both axes to have the same range, then something like this will work.
With Chart1
' Y1 = first Y Point, Y2 = Second Y point, etc.
Dim ymin As Double = Math.Min(.Series(0).Points.FindMinByValue("Y1").YValues(0), _
.Series(1).Points.FindMinByValue("Y1").YValues(0))
Dim ymax As Double = Math.Max(.Series(0).Points.FindMinByValue("Y1").YValues(0), _
.Series(1).Points.FindMinByValue("Y1").YValues(0))
'round values to the nearest "Factor"
Const Factor As Double = 5
ymin = Math.Floor(ymin / Factor) * Factor
ymax = Math.Ceiling(ymax / Factor) * Factor
.ChartAreas(0).AxisY.Minimum = ymin
.ChartAreas(0).AxisY.Maximum = ymax
.ChartAreas(0).AxisY2.Minimum = ymin
.ChartAreas(0).AxisY2.Maximum = ymax
End With
arr is a binary data file stored in a database
Assuming that this means that "arr" is a byte array that has been loaded from a database, then
change: Photograph1.Image = Photograph1.Image.FromStream(New IO.MemoryStream(arr))
to: Photograph1.Image = Image.FromStream(New IO.MemoryStream(arr))
FromStream is a shared method on the Image class. The IDE does not like you accessing a shared method/field/property on an instance eventhough as it works as you have found out. In this case, the instance is the Image property on Photograph (assuming Photograph is a PictureBox).
Try something like this:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim sorter As New lvMonthSorter
sorter.MonthColumn = 0 ' set the column that holds the month
sorter.Order = SortOrder.Ascending
ListView1.ListViewItemSorter = sorter
End Sub
End Class
Public Class lvMonthSorter
Implements System.Collections.IComparer
' array to get a month index from for sorting
Private Shared Months() As String = {"january", "february", "march", "april", "may", "june", _
"july", "august", "september", "october", "november", "december"}
Private _MonthColumn As Int32 = 0
Public Property MonthColumn() As Int32
Set(ByVal Value As Int32)
_MonthColumn = Value
End Set
Get
Return _MonthColumn
End Get
End Property
Private _Order As SortOrder = SortOrder.Ascending
Public Property Order() As SortOrder
Set(ByVal Value As SortOrder)
_Order = Value
End Set
Get
Return _Order
End Get
End Property
Public Function Compare(ByVal x As Object, ByVal y As Object) As Int32 Implements IComparer.Compare
Dim result As Int32
Dim xstr As String = CType(x, ListViewItem).SubItems(_MonthColumn).Text.ToLower
Dim ystr As String = CType(y, ListViewItem).SubItems(_MonthColumn).Text.ToLower
Dim xpos As Int32 = Array.FindIndex(Of String)(Months, Function(xs As String) xs = xstr)
Dim ypos As Int32 = Array.FindIndex(Of String)(Months, Function(ys As String) ys = ystr)
result = xpos.CompareTo(ypos)
Select Case Order
Case SortOrder.Ascending : Return result
Case SortOrder.Descending : Return -result
Case Else : Return 0
End Select
End Function
End Class
Great. Please close out this thread then by marking it answered.