|
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.
|
|
|
|
|
No idea why I implemented loadlibrary, when I started working on this project first I tried to translate c code to vb code practically line by line, loadlibrary was the first thing on the way.
I didnt think it might wreak havoc when combined with pinvoking , I will be removing it to see what happens.
I have already tried your solution - it didnt work. I always get hPrinter returned as "0". I simply cant get the printer to return a valid handle. There is no way of finding out whether the dll communicates with the printer, therefore I cannot figure out what this 0 I get returned means, does it mean that no printer was found or something else?
With no way of knowing how (and if) the dll, in itself, communicates with the hardware, I cant troubleshoot this.
|
|
|
|
|
while there isn't much text in the manual, the way I understand the available information is:
1. you need to install your printer and its driver somehow; that should result in it being visible in the list of installed printers.
2. your program needs to start with a GetHandle, which returns success/failure and an error code on failure. Those should be self-explanatory.
The one thing .NET adds here is some uncertainty about the P/Invoke stuff, due to gaps in the doc, not shortcomings of .NET
Therefore:
1. do you see your printer in say MS Word?
2. could you try the C example?
Once those two work well, getting VB.NET up and printing should be simple.
|
|
|
|
|
USB interface - tested, can print, can use windows driver, cant use my app, cant use SDK app
Ethernet interface - tested, can print, can use win driver, cant use my app, cant use SDK app
This was tested on both win 7 and win Vista, I also tried it on VMWARE windows XP SP2 but it crashed immidiately, but possible due to virtualization itself.
Tomorrow I will try it on "pure" Windows XP, but I dont expect much.
|
|
|
|
|
from that information, I would focus on a real XP system, no virtualization, no UAC stuff.
Vista & 7 keep regular users away from protected data, you can't even get a disk's serial number as that requires an OpenFile(mydisk).
If that turns out to be the problem, the manufacturer will be bound to come up with a solution, as the Windows world is slowly moving to Vista/7 and they can't ignore that.
FWIW: and the error code(s) should be more informative!
|
|
|
|
|
Their SDK is from 2007, done in C, and their support people havent responded to my queries yet, I wont hold my breath
If we had known we would have gone with a different manufacturer.
|
|
|
|
|
|
It (SDK example) crashes with no relevant error code even on "pure" windows XP SP2 machine which normally accesses the printer.
I have (finally) been contacted by Zebra support, they have given me an email address, which unfortunately does not exist.
|
|
|
|
|
Hi,
I am new to Visual Basic 2005.
I need to create a vb project inside it there is a treeview at the left panel and right panel is empty. when user click the node in treeview, a form related to this node will be open in the right side panel. multiple forms launched by the tree nodes can be existed together, the latest one at the top of the stack.
I try to create a window application with MDI form, inside the MDI form, I create a splitContainer component, on the left panel I add a treeview node, if user click the node in the treeview, multiple child forms can co-exist, but how can I let the child forms opened only at the right panel, and attached to the right panel?
Is this the right way to design the project that satisfies my requirements?
do you have some samples about this?
Thanks!
|
|
|
|
|
Andraw Tang wrote: I try to create a window application with MDI form, inside the MDI form,
If you're saying that you're trying to create a form that is both an MDI Parent and an MDI Child at the same time, you can't. Windows doesn't support it.
Every MDIParent form has a control on it of type "MdiClient". You won't find this control in the ToolBox, so don't bother looking. This control occupies all available space on the MDIParent form that is not taken up by menu bars, command bars, status bars, ... and is managed automatically. You would need to get a reference to this control (you'll find it in the MDIParent form Controls collection), then manipulate the control just like any other. Once you create your split containers, you can move the MdiClient control to the right side split container quite easily.
Of course, you have to do all of this in code...
|
|
|
|
|
Dave,
Thank you for your reply.
I got the MDIClient control, but would you please tell me while we move the MDIClient control to the right panel of splitContainer? Since you said the MDIClient occupies all the available area except menu, status and tool bar, if we move it to the right panel, what area the right panel will occupy?
|
|
|
|
|
I should said that the MdiClient occupies all the remaining space of it's parent container by default. It has it's Dock property set to fill the container.
Andraw Tang wrote: what area the right panel will occupy?
All of it since there are no other controls in the Panel.
|
|
|
|
|
Dave,
Also is there any difference to display MDI child form on the splitcontainer right panel by using the following code
frmSimu.Parent = Me.SplitContainer1.Panel2 '-----------Method 1
or like you said move the MDIClient control to right panel, then I '---------- Method 2
display MDI child form??
I tried first way, the newly opened form is always hidden by previous opened form, even I set TOPMost flag to true.
Do you have any tutorial or sample code about this?
Thanks!
|
|
|
|
|
Andraw Tang wrote: Also is there any difference to display MDI child form on the splitcontainer right panel by using the following code
frmSimu.Parent = Me.SplitContainer1.Panel2 '-----------Method 1
Won't work since an MdiChild can only be shown in an MdiClient control...
Andraw Tang wrote: Do you have any tutorial or sample code about this?
Nope. But in playing with this for a little bit, you cannot do this with a split container. The parent container of the MdiClient must be a Form, not another control. You'd have to implement this in a pretty complex manner. Basically, I thikn you'd have to undock the MdiClient, add a Panel to where you want it in the forms Controls collection, then redock the MdiClient. I just don't have the time right now to code it up and test the theory.
|
|
|
|
|
Dave,
Thanks.
Since I will have a treeview on the left side and all the child forms launched by clicking treeview nodes are displayed on the right panel.
Splitcontainer make resize panel easy, but how can I display child form on the right panel? how to move the MDIClient control to the right panel?
Thanks again!
|
|
|
|
|
Andraw Tang wrote: but how can I display child form on the right panel? how to move the MDIClient control to the right panel?
Didn't I just get done telling you that I tested this and it won't work? As soon as the MdiClient leaves the Form's Controls collection, the Form stops being an MdiParent and MDI no longer works.
If you insist on using MDI, you have no choice but to skip the split container. If you implement this using a single form on the right side, then you can skip the MDI stuff and use the split container.
|
|
|
|
|
Dave,
ok now, I remove the splitcontainer control, just create MDIForm as parent, then add a treeview and dock on the left, add a splitter and also dock on the left, so the other space is belonged to MDIClient.
It works fine now, and the treeview can also be resized.
Thanks!
|
|
|
|
|
Hi, dear all,
I am alway confused by the terms of Visual Basic 2005 and VB.NET 2005, are they same? if not, what's the difference?
I installed Visual Studio 2005 in my compuer, when I create vb project from Visual Studio 2005, is it VB 2005 of VB.NET 2005?
Thanks!
|
|
|
|
|