|
Hi All,
I have a userform (BinSheetForm) which I bind to a datasource as per the code below.
Private Sub BinSheetForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
BsCountIdLabel.Text = iCountId.ToString
Dim Conn As New SqlConnection(CntString)
conn.Open()
adapter = New SqlDataAdapter("select * from zz_ST_Binsheets", Conn)
adapter.FillSchema(dtset, SchemaType.Source, "zz_ST_Binsheets")
adapter.Fill(dtset, "zz_ST_Binsheets")
Conn.Close()
bind.DataSource = dtset
bind.DataMember = "zz_ST_Binsheets"
End Sub
On this userform I have a datagridview that I fill with the follwing code.
Private Sub FillBinDataGrid()
With Me.BsDataGridView
.DataSource = bind
.EditMode = DataGridViewEditMode.EditOnEnter
End With
End Sub
Up to this point it works fine, but now I want to do 2 more things.
First:
The database table zz_ST_Binsheets contains columns "iCountId" and "iBinNr". I have a label on the from that contains the value of "iCountId" and a textbox where the user can enter a value for "iBinNr". The user will then press a button and the datagridview must only be filled with the selection where "iCountId" = the label value and "iBinNr" = the textbox value.
Second:
I want the changes that the user make to be saved back to the database. The changes would include editing current data, adding new rows and deleting current rows.
I am using VS2005.
Thanks in advance.
|
|
|
|
|
To remove the need to go back and refilter the data to the selected iCountId and iBinNr values, you can use client side filter capabilities of the BindingSource . The binding source has a Filter property which acts like an additional where clause of the query, but does not requery the database.
Set the BindingSource.Filter to "Where iCountId=" & textBoxiCountId.text & " AND iBinNr= " & textBoxiBinNr.text
You can then Edit the data and save changes as you would do normally. When you are finished with the filter, it can be removed by BindingSouce.RemoveFilter()
[obviously change the names of the controls to match yours]
|
|
|
|
|
Thanks, that filter property had the desired effect. It is so simple if you how
I have one more problem which I think wil also have a simple solution.
I add a comboboxcolumn to the datagridview as follows:
Dim InvCode As New DataGridViewComboBoxColumn
and then add the details and further down
BsDataGridView.Columns.Insert(5, InvCode)
The problem is that it now adds a new column every time I run the query for a different bin nr.
|
|
|
|
|
At your form level, declare a reference to the InvCode object (without new);
Dim InvCode As DataGridViewComboBoxColumn
In your code you run at present, test this InvCode object for being Nothing and if it is create it and add it to the DGV, if it is not nothing, then you have already created it, so do not create it again.
if isnothing(InvCode) then
InvCode = new DataGridViewComboBoxColumn()
BsDataGRidView.Columns.Insert(5,InvCode)
else
end if
[Edit: wrong syntax initially]
Dave
Don't forget to rate messages!Find Me On: Web| Facebook| Twitter| LinkedInWaving? dave.m.auld[at]googlewave.com
modified on Tuesday, June 29, 2010 9:42 AM
|
|
|
|
|
That worked like a charm, thanks.
|
|
|
|
|
|
Thanks for the link - I will have a look.
|
|
|
|
|
I am having some problems getting a printer driver to work in Visual Basic.
I am stuck at not being able to get a printer handle from the printer dll.
This is what I got thus far;
Static dll_loaded As Boolean
If Not dll_loaded Then
Dim dll_handle = LoadLibrary("ZBRPrinter.dll")
If dll_handle = 0 Then
MsgBox("LoadLibrary failed")
Return
Else
dll_loaded = True
MsgBox("LoadLibrary success!")
End If
End If
Dim pName As StringBuilder = New StringBuilder("Zebra P330i USB Card Printer")
Dim hPrinter As IntPtr = 2
Dim printerType = 330
Dim err As Integer = 0
Dim ret = ZBRGetHandle(hPrinter, pName, printerType, err)
If err = 61 Then
MsgBox("Unable to open handle to Zebra printer driver")
End If
I am using the following pinvoke sig:
DllImport("ZBRPrinter.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Public Shared Function ZBRGetHandle(ByRef hPrinter As IntPtr, ByVal pName As StringBuilder, ByRef printerType As Integer, ByRef err As Integer) As IntPtr
End Function
I am getting the following data returned to me as I run this code;
hprinter gets changed from 2 (test number) to 0
pname is the stringbuilder (also tried it as a string)
printertype is 330
err is 61
It seems that I am getting "through" to the dll but I am unable to get a proper printer handle.
This is what I got in Zebra SDK:
HMODULE hModule = LoadLibrary(_T("ZBRGPMF.dll"));
if (hModule)
{
form1.StatusBox->Text = "The DLL has been successfully loaded.";
}
else
{
return FALSE;
}
zsdkGetHandle = (ZBRGetHandle)GetProcAddress(hModule, "ZBRGetHandle");
HANDLE hPrinter = NULL;
INT printerType = NULL;
INT err = 0,
ret = 0;
ret = getHandle(&hPrinter, "Zebra P330i USB Card Printer", &printerType, &err);
ret = getPrinterStatus(&err);
And by running that example I do get a handle returned (its 0x000000) and the thing works.
This is the typedef I got with the SDK:
typedef INT (CALLBACK *ZBRGetHandle)(LPHANDLE hPrinter, LPSTR pName, INT* printerType, LPINT err);
I am (quite obviously) new to adapting the code from C# to VB, I have managed to make several projects work (win32 API based) but I hit a wall on this one, please help if you can, any suggestions are most welcome, thanks in advance!
|
|
|
|
|
do you use VB6 oder .net ??
try the following pinvoke sig:
<br />
declare function ZBRGetHandle lib "ZBRPrinter.dll" (ByRef hPrinter As IntPtr, <System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)> byval szBuffer as String, byval printerType As IntPtr, ByRef err As Integer) As IntPtr<br />
does complile but i don't know if this would solve your problem
|
|
|
|
|
.Net, Studio 2008
By studying the SDK example, I deduce that the entries for printer type and name are irrelevant as they havent used those as well (value = 0).
I am getting the error code back as I should (61 or 63, error getting data from the printer) so it would seem that the pinvoke works at least partially, what I am still not getting is the proper handle for the printer itself.
|
|
|
|
|
Let us suppose that I am having problems marshalling a null terminated char array to the function I wish to call (GetHandle function as stated in the previous post(s)).
I guess I should "reserve" a specific size memory (malloc or something), fill it with chars taken from the string, make sure its null terminated and then pass this memory by reference to the dll. Additionally I think the pointer points only to the first element of the char array, dont know how this will reflect on the problem at hand.
I have no idea how to achieve the above mentioned Any help? sample code?
|
|
|
|
|
did you try my example code ???
i am marshalling the string into a LPSTR in the example.
greetz
|
|
|
|
|
I have, I also tries it as safearray, LParray, char array and other stuff, same end result, no go.
|
|
|
|
|
Its just wierd, the function does return a new value (changes the value before it runs through the function) and sets it to "0" which cant be right. The error code states that no data could be received from the printer.
The printer is an USB printer, and it is on, and it does indeed work (prints normally).
Why does it return an invalid handle?
|
|
|
|
|
Hi,
I'd try ByVal hPrinter As IntPtr
|
|
|
|
|
Still getting 63 ZBR_ERROR_GETPRINTERDATA_ERROR
The handle still = 0
|
|
|
|
|
hmm the lib returns an error code so every thing goes right for me.
if the function can't be called you will get an exception during the call! that means there will be no return value!
check what exactly ZBR_ERROR_GETPRINTERDATA_ERROR means. you may have other errors that cause to an ZBR_ERROR_GETPRINTERDATA_ERROR by calling your pinvoke sig...
blessssss it
|
|
|
|
|
I am having doubts that Zebra SDK dll doesnt communicate with the printer for some reason which I cannot discern as I did not make the dll itself.
I have no option but to contact Zebra, although I wont hold my breath, software programming support is usually abysmal. ;(
|
|
|
|
|
the SDK said INT printerType = NULL; yet you pass 330 ?
|
|
|
|
|
I tried both; 1) nothing, 2) 330, 1) byval and 2) byref, same result in all cases.
|
|
|
|
|
I looked deeper into the matter, here is my conclusion:
<DllImport("ZBRPrinter.dll")>
Public Shared Function ZBRGetHandle(ByVal hPrinter As IntPtr, ByVal pName As StringBuilder, ByRef printerType As Integer, ByRef err As Integer) As IntPtr
End Function
which means:
1. no SetLastError (where did you get that idea? there already is an error pointer)
2. no Charset.Auto (the native code expects ANSI, which is the default)
3. pointers normally get passed by value
reminder: printerType in the SDK example was zero, not 330.
|
|
|
|
|
In the meantime I also tried it without SetLastError and Charset.Auto, and I toyed around with byval/byref, nothing changed.
I also did try it with printerType set to both zero and 330 , with same result.
I have found someone with a similar problem, unfortuantely the said individual does his programming in delphi so I am still trying to understand what he said, heres the text:
I am attempting to access a function in a C-style DLL, written in Microsoft Visual C++ version 6.0.
The function is defined as follows:
INT __stdcall ZBRGetHandle(LPHANDLE hPrinter, LPSTR pName, LPINT printerType, LPINT err)
In my Delphi project, I prototype the function as:
function ZBRGetHandle(var handle: THandle; var drvName: Array of Byte; var prnType: Integer; var err: Integer) : Integer;
{$IFDEF WIN32} stdcall; {$ENDIF} external 'ZBRPrinter.dll' ;
I have a wrapper function within a class that calls this function. The class method is defined as:
function Open(var drvName: array of Byte; var errValue: Integer) : Integer; stdcall;
I call it as:
function TZBRPrinter.Open(var drvName: Array of Byte; var errValue: Integer) : Integer; stdcall;
begin
Result := ZBRGetHandle(_handle, drvName, _prnType, errValue);
end;
note: _handle & _prnType are defined within the class TZBRPrinter as:
private
_handle: THandle; // _handle to printer driver
_prnType: Integer;
I initialize both variables in the class constructor:
constructor TZBRPrinter.Create;
begin
// Execute the parent (TObject) constructor first
inherited; // Call the parent Create method
// Now set defaults
self._handle := 0;
self._prnType := 100;
end;
errValue is set to -1 prior to the call to TZBRPrinter.Open.
In an attempt to root-cause the problem, I used my delphi executable as the debugging application for my ZBRPrinter.dll project.
When the ZBRGetHandle is called via the Delphi application, what I find is puzzling:
With respect to ZBRGetHandle within the dll source code, I find that the 3rd parameter, LPINT printerType, is invalid, and
the 4th parameter, LPINT err is set to 100. The first 2 parameters are correct.
I have tried using a fixed array of bytes and chars as the second parameter, and a String, yet I find that I still encounter problems when passing all 4 parameters to this DLL function. I find that if the dll's second parameter only gets the first char of the string, then the 3rd parameter gets the value 100, and the 4th gets the value -1 as I intend. If the second parameter contains the entire string I am passing, then the 3rd parameter is corrupted and the 4th parameter contains the value 100, which is intended for the 3rd parameter.
Can someone explain to me how I pass a null-terminated string as the second parameter to my dll such that it doesn't cause the 3rd parameter to become corrupted and the 4th to be assigned the 3rd's intended value?
I had actually figured out the problem yesterday.
I was already making sure to null terminate the strings I am using. However, I did not realize that Delphi wouldn't pass the address of the byte array to the c-style function even when I specifically declared the function parameter as a reference.
What I did to solve the problem was to delcare a PChar and assign it the address of the dynamic byte array. I also changed my function to use a PChar instead of a reference to a byte array.
Once I made these changes, I was able to successfully pass the null terminated string to my c-style function and the function call succeeded.
|
|
|
|
|
sorry, that's too messy for me to understand.
you have an existing Delphi program that works? and your own VB.NET program that doesn't?
if .NET 4.0 calling conventions are checked more severely.
if Win64, pointers take 8-byte
|
|
|
|
|
I have SDkit provided by Zebra company, which features some C examples (which produce the same error as my VB.net code), I have my own code done in VB.net, the Delphi code was done by someone else on the internet (I do not have this code) and he stumbled into an extremely similar (maybe even identical) problem as I did.
My string (the name of the printer) is null terminated and I did try to pass that as LParray, safearray, char array and stringbuilder (same result = fail), one time I passed it as a pointer to the first character in the arrey (namely character "Z"), that time I didnt get the error code 63 nor 61 but the handle returned was still 0.
It is possible that I need to find a way to marshal this null terminated char array by the way of not sending only the pointer to the first element in the array but to the entire segment of memory, I do not know how to do this.
Even if I manage to do it, which I will certainly try to do, I might still get 0 as returned printer handle value.
No matter what I do, the returned printer handle always is "0", I think the dll is not able to communicate to the hardware hence errors 61 and 63 (no data from printer), hence invalid printer handle.
|
|
|
|
|
I looked in the manual (ZBRGetHandle defined on p12 , example p219), and I now see:
- the Handle is going to be returned, so it must be ByRef after all.
- passing the name should be no problem at all, a simple string is all it takes, not even a StringBuilder;
- strangely enough printerType is an int and needs being passed by reference (don't see why).
So I'll go for:
Dim hPrinter As IntPtr
Dim printerType As Integer = 330
Dim err As Integer = 0
Dim ret As IntPtr = ZBRGetHandle(hPrinter, "Zebra P330i USB Card Printer", printerType, err)
<DllImport("ZBRPrinter.dll")>
Public Shared Function ZBRGetHandle(ByRef hPrinter As IntPtr, ByVal pName As String, ByRef printerType As Integer, ByRef err As Integer) As IntPtr
End Function
What I do not understand is why you load the DLL first, see your LoadLibrary.
P/Invoke does not need (not even want?) that, and the DLL must be found by regular Windows PATH scanning.
|
|
|
|
|