|
Hi Paolo,
The ActiveX is expecting a pointer to, presumably, an array of long values. But from C# you are only passing a single Int32. You need to use an IntPtr to pass the data back and forth, like so:
Int32[] buffer = new Int32[10];
buffer[5] = 1;
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Int32)) * 10);
Marshal.Copy(buffer, 0, ptr, 10);
buffer[5] = 2;
Marshal.Copy(ptr, buffer, 0, 10);
Marshal.FreeHGlobal(ptr);
Note: The Marshal class is in the System.Runtime.InteropServices namespace.
Take care,
Tom
-----------------------------------------------
Check out my blog at http://tjoe.wordpress.com
|
|
|
|
|
It doesn't work
Your code works, but it stops if I use different unmanaged memory areas when storing and when retrieving or if I change the data in the unmanaged memory.
For example, this code doesn't work:
<br />
Int32[] buffer = new Int32[10];<br />
buffer[5] = 1;<br />
<br />
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Int32)) * 10);<br />
Marshal.Copy(buffer, 0, ptr, 10);<br />
<br />
int bptr = (int)ptr;<br />
ocx.PutData(ref bptr, Marshal.SizeOf(typeof(Int32)) * 10);<br />
<br />
buffer[5] = 2;<br />
<br />
IntPtr ptr2 = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Int32)) * 10);<br />
int bptr2 = (int)ptr2;<br />
<br />
ocx.GetData(ref bptr2);<br />
<br />
Marshal.Copy(ptr2, buffer, 0, 10);<br />
<br />
Marshal.FreeHGlobal(ptr);<br />
Marshal.FreeHGlobal(ptr2);<br />
|
|
|
|
|
Do you have access to the ActiveX source code? Or is it publicly available? If you have access, could you post examples of PutData and GetData. If it's publicly available, could you please provide a link.
If GetData is updating bptr2 so that it has the same value as bptr, then I would assume that PutData simply stored the long* that was passed in (instead of copying it). Then GetData is simply passing out the same long*. If this is the case then you do not need to allocate ptr2, because GetData does not required you to pass in a pre-allocated buffer.
This really depends on how the OCX methods are written and you would need a full understanding of how they work to properly use them. For example, if the PutData does in fact save the long* that was passed in, then the code below would cause access violations:
Int32[] buffer = new Int32[10];
buffer[5] = 1;
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Int32)) * 10);
Marshal.Copy(buffer, 0, ptr, 10);
int bptr = (int)ptr;
ocx.PutData(ref bptr, Marshal.SizeOf(typeof(Int32)) * 10);
buffer[5] = 2;
Marshal.FreeHGlobal(ptr);
IntPtr ptr2 = IntPtr.Zero;
int bptr2 = (int)ptr2;
ocx.GetData(ref bptr2);
Marshal.Copy(ptr2, buffer, 0, 10);
In the code above, the long* that was cached is freed and then is accessed later. If you are only using the OCX in a serial fashion like your example, then it would be fine.
Let me know if this makes sense.
Take care,
Tom
-----------------------------------------------
Check out my blog at http://tjoe.wordpress.com
|
|
|
|
|
No, I haven't access to the activeX source code, but the activeX it is freely available at http://www.kolbasoft.com/
I put the test projects (c# and c++), the link to the activeX and a a few notes in www.vernazza.org/Vecad.zip
I agree with you, it seems that GetData is passing out the long* that I passed it before instead of the data pointed, but I can't understand why it works while I call that function from c++ , and it doesn't when I call it from c#!
|
|
|
|
|
You may want to use AllocCoTaskMem[^] instead (and it's associated free method), but I don't think that is your problem.
Looking at the put code:
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Int32)) * 10);
Marshal.Copy(buffer, 0, ptr, 10);
int bptr = (int)ptr;
axVecad1.PutExData(ref bptr, 10 * 4);
After the first line, ptr points to the allocated block of memory. The array is then copied to the allocated block. Next ptr is cast to an int, so bptr now holds the correct address to the buffer. Now, when passing in the address to the PutExData, the address of the bptr is passed in (ref bptr). What you really want to pass in is the value of bptr. So really you are passing in a pointer to bptr which has a pointer to the actual data (so a pointer to a pointer).
Basically, the signature for the PutExData should have the first parameter as an "IntPtr", not as a "ref Int32". I don't think there is a way to properly pass in the IntPtr address when the signature has the ref value there. Because you would need to create an Int32 value at the same location as the allocated buffer.
I realize that VS generated the signature of the method for you (more specifically, aximp.exe generates it). The best work-around (short of hand-writing all the code you need) I found was here[^]. Be sure to read the whole thread, he talks about activeX controls later in the thread.
Hopefully this helps.
UPDATE: Actually, it looks like aximp.exe can generate C# source code now, so that would probably be your best option.
Take care,
Tom
-----------------------------------------------
Check out my blog at http://tjoe.wordpress.com
|
|
|
|
|
I would like to create a sidebar type application that sits on the right side of the client area. This application will always be executing, and I want it to always be visible.
Is there any way of controlling _other_ windows so that the won't maximise or be resized over/under that application? Optimally I would like another window to maximize to the full screen _except_ for the right X pixels where my sidebar application is residing.
Always on top will fix the "always visible" parameter, but using this other windows will be hidden behind it..
Preferrably I would like to set a registry value or such setting max size, but the next best case is to do this programmatically in my app.
Would really appreciate an answer!
Best regards
// T
|
|
|
|
|
|
That hit the spot!
Thanks for the help!
Really appreciate it!
// T
|
|
|
|
|
I have an issue that hopefully has a quick answer (dont we always...)
I have some code that uses this as an identifying tag:
[:: ::]
So i would mark something as [::Text_In_Here::], and I would identify that there was a tag with this expression:
\[:: (.|\n)+?::\]
this works fantastically. But, in some cases, i need to be able to identify the tag, and replace the outer portion with another tag. SO what I need is to able to find [::Text_In_Here::] and turn it into <input type='hidden' value= 'Text_In_Here'/>
any ideas? i am using Regex.Replace in other areas, but it doesnt appear to have an overload that will do what I need.
______________________
Mr Griffin, eleventy billion is not a number...
|
|
|
|
|
You would need to modify your regex so that it captures the entire inner portion of the tag. Then when replacing you can reference the inner portion using $1.
Note: I added "?:" to the inner parenthesis so that the character matched by it is not captured. Instead, the entire inner portion is captured.
Regex regex = new Regex(@"\[: ?:.|\n)+?)::\]");
String output = regex.Replace("[::Testing::]",
"<intput type='hidden' value='$1'/>");
Take care,
Tom
-----------------------------------------------
Check out my blog at http://tjoe.wordpress.com
|
|
|
|
|
Hi
row adding (after adding + saving, reloading the form) is OK to 1 of my table but delete is not... Here's what I've done:
since DeleteCommand didn't exist to that table I defined a simple one (at dataset designer mode to the tableadapter):
DELETE FROM Felhaszn_Egyeb
WHERE (TetelArId = @TetelArId) AND (EgyebId = @EgyebId) AND (Mennyiseg = @Mennyiseg)
similarly UpdateCommand is defined as follows:
UPDATE Felhaszn_Egyeb
SET TetelArId = @TetelArId, EgyebId = @EgyebId, Mennyiseg = @Mennyiseg
WHERE (TetelArId = @Original_TetelArId) AND (EgyebId = @Original_EgyebId)
upon the user clicks the delete button, the bindingsource.removecurrent() & bindinsource.endedit()
& [dataset].acceptchanges() are invoked row is deleted from the datagridview
upon user clicks save the well known invoked (thistableadapter.update(thisdataset.thisdatatable)
upon reloading the form it still fills the table with 1 row, which shouldn't be there
thx for your thread...g
|
|
|
|
|
Hey
I like the way menus can be slid in and out of view in Visual Studio (such as solution explorer and the properties window) and would like to use something similar for a project I am working on.
I assume this is a control you can drag onto a form in visual studio that when the mouse moves over shows panels in a specific position. Does any one know which control I should use?
Also If i want to make the menus slightly transparent is it a case of inheriting from say a panel then overriding its draw command using GDI? I may be way off the mark with this one as I have not done this before (only made my own items using GDI)
Thanks
Dan
|
|
|
|
|
I don't think it's built in, but there is a free control (I haven't used it, but many folks here have): http://sourceforge.net/projects/dockpanelsuite[^]
Me: Can you see the "up" arrow?
User:Errr...ummm....no.
Me: Can you see an arrow that points upwards?
User: Oh yes, I see it now!
-Excerpt from a support call taken by me, 08/31/2007
|
|
|
|
|
I am new to C#the problem is this that i m making an employee database for a firm the informATION will be filled in three forms serial vise for example
1 Employee personal
2 Service history
3 Expertise
when i fill the first form then when i click next i want to fill the second service history form in the same window so how it could be possible i dont want a separate window to be opened as many softwares do the same procedure by pressing next and going on filling the information in same window in different criterias
SAS
|
|
|
|
|
One easy way to do this is to build your different views as controls and show/hide them on the form.
However, my overall advice would be that if you're new to C#, you should not be writing code that anyone is going to use for anything, unless you have a strong background in another language.
Christian Graus - Microsoft MVP - C++
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
The above suggestion is best but what about if i use MDI will it solve the problem and how to displaydifferentforms ibn window
SAS
|
|
|
|
|
Doesn't make any difference. You don't display different forms in a window, you display different controls. A form is a window.
Christian Graus - Microsoft MVP - C++
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
Hi
Please give me an idea how to change the layout of an excel file through c# coding.If i am opening the printer dialogue box the then change the layout, the printing layout is working fine but it doesnt the layout of the excel
Thanks in advance.
Regards
DilipRam
|
|
|
|
|
Hi all,
Ok, I have a datagrid, the user can input data. I want something which will prevent them to edit
previously created rows.
Can someone give me some suggestions.
Thanx in advance
|
|
|
|
|
Ok I figured out something which works, could someone let me know of any other ways??
<br />
private void table_RowChanged(object sender, DataRowChangeEventArgs e)<br />
{<br />
lastRow++;<br />
}<br />
private void datagrid_CurrentCellChanged(object sender, System.EventArgs e)<br />
{<br />
if( datagrid.CurrentCell.RowNumber != lastRow )<br />
{<br />
datagrid.CurrentRowIndex = lastRow;<br />
}<br />
}<br />
|
|
|
|
|
Hi,
Is there a way how to disable selecting mechanism of a DataGridView at all? It brings me a lot of workaround... Simply I don't want user to select anything, neither rows, columns or cells.
thank you
zilo
|
|
|
|
|
|
|
That would solve your problem. You can still see the data, but you can't select. Isn't that what you want?
|
|
|
|
|
I need to disable selecting anything, however I still need to use all controls (button's, checkboxes,etc...)
|
|
|
|
|