|
Hi All,
Is it possible to get the address of an object reference
variable in C#?
Cheers
|
|
|
|
|
In my form application, I repeatedly obtain graphics from a sequence of images by using Graphics.FromImage(...). At first few calls, it is fine. But after a while, there will an exception: System.InvalidOperationException: The object is currently in use elsewhere.
I checked on the web, it seems this is related to a microsoft bug and can be solved by a hotfix. I updated my machine with several patches, but the problem is still there.
Any suggestion? Thanx.
|
|
|
|
|
Have you ever called Disposed on Graphics object?
Maqsood Ahmed
Kolachi Advanced Technologies
http://www.kolachi.net
|
|
|
|
|
Yes, I did. I tried both with dispose and no dispose. There is no difference.
|
|
|
|
|
how would i make a control that can save and edit bmps and have a grid like the following...
___________
| | | | | |
-----------
| | | | | |
-----------
| | | | | |
-----------
| | | | | |
-----------
| | | | | |
-----------
| | | | | |
-----------
|
|
|
|
|
Hi~
In C# compact framework, I would like to send a message to a window written using "SendMessage" method by p/Invoke.
How can I pass the string to p/invoke method so that the C++ window can get the message? If a pass string, How to convert the lparam into string in C++
windows message loop function? If pass the string as other type, then what is the type?
In compact framework, the key word "MarshalAs" is not supported. Then is there any other way to solve it?
[DllImport("coredll.dll",EntryPoint="SendMessage", CharSet=CharSet.Auto)]
private static extern void SendMessage(IntPtr hwnd, uint msg, int wparam, [MarshalAs(UnmanagedType.LPSTR)] string lparam);
Thanks
|
|
|
|
|
MarshalAs isn't a keyword - it's an attribute, as in MarshalAsAttribute . What you have isn't even correct on the full .NET Framework, though. Why do you set CharSet=CharSet.Auto , then try to marshal the string as an UnmanagedType.LPSTR ? An LPSTR is a char* . You should marshal as an LPTSTR (TCHAR* ), but setting the CharSet field to CharSet.Auto does that automatically.
The only reason overloading the SendMessage function like this would work is because by passing a TCHAR* you pass the address of the first character (rather, the first byte which is 1 character in ANSI and 2 Unicode (typically). Since both an WPARAM and LPARAM are just addresses (32 bits on a 32-bit system, and 64 bits on a 64-bit system, unless you're running under WOW64 to emulate a 32-bit processor for a 32-bit application, which is currently all that's available with .NET 1.x), the following signature should work for you:
[DllImport("user32.dll", CharSet=CharSet.Auto)]
extern static IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, string lParam); As you may have noticed, I've changed the signature a little more. The return value should be an IntPtr . By not defining the return value correctly you could corrupt the stack (a return value needs to be pushed back onto the stack whether or not you use it). And, as I said, both the WPARAM and LPARAM parameters are processor-dependent so you need to use an IntPtr (which is also a processor-dependent bit width). If you recompiled for 64-bit processors ever, your code would not work (you'd be trying to call the 32-bit SendMessage on the 64-bit implementation and should surely have an execution stack problem since your parameters wouldn't be correct and you'd end up passing something else (uninitialized data, etc. - definitely not your address and most likely ending up with an Access Violation (AV) exception).
PS: To pass 0 as the wParam that's now correctly defined as an IntPtr , use IntPtr.Zero .
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Then, I pass a string to the method "SendMessage". How can I turn the lparam to LPSTR or any other string pointer? It is simple that just cast the lparam to string pointer? Thanks
|
|
|
|
|
You really need to understand the difference between LPSTR , LPWSTR , and LPTSTR . Since CharSet.Auto is specified in the DllImportAttribute , the string (always Unicode in .NET) will be marshaled as ANSI strings on Win9x/Me and Unicode strings on Windows NT (includes 2K, XP, 2K3, and future versions of Windows).
If you need to marshal from an IntPtr to a string (assuming that memory address points to a string) then use the relevent Marshal class methods, like Marshal.PtrToStringAuto . Read more about the class in the .NET Framework SDK for more information.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Oh sorry,
How to let a IntPtr point to a string in C#?
Thanks
|
|
|
|
|
The only reason to get the start address of a string as an IntPtr would be to marshal it, and the Marshal class does just that, so I told you exactly how to do it in C# (remember, C# is just a language that targets the CLR; it's the .NET Framework that provides the language constructs).
You could also use GCHandle to pin the string in memory so that the garbage collector (GC) doesn't move it around after you've sent the address to unmanaged code (if the GC moves it, the unmanaged code won't know and will access the wrong data):
string s = "Hello, world!";
GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
SomeUnmanagedPInvokedFunction(ptr);
handle.Free(); In most cases you don't need to worry about this, though. Passing a string is actually passing the address of the string, so declaring your P/Invoke signatures correctly aleviates this problem.
Again, read the documentation for interop'ing with unmanaged DLL functions I posted before, and play close attention to the marshaling topics toward the end.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Hi~
I use these code to past string to a C++ window but still doesn't work.
[C#]<br />
string s = "Hello, world!";<br />
GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);<br />
IntPtr ptr = handle.AddrOfPinnedObject();<br />
PostMessage(hWnd, msg, IntPtr.Zero, ptr);<br />
handle.Free();<br />
<br />
[DllImport="Test.dll", CharSet=CharSet.Auto]<br />
private static extern IntPtr PostMessage(IntPtr hwnd, uint msg, IntPtr wparam, IntPtr lparam);<br />
<br />
<br />
[C++]<br />
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)<br />
{<br />
if (message == WM_TESTING)<br />
{<br />
TCHAR* StringPtr = (TCHAR*)LPARAM;<br />
MessageBox(0,StringPtr,_T("Caption"),MB_OK | MB_INFORMATION);<br />
}<br />
else<br />
{<br />
return DefWindowProc(hWnd, message, wParam, lParam);<br />
}<br />
return 0;<br />
}
The message box in C++ show null string. How can I solve it?
Thanks
|
|
|
|
|
As I said in my first reply, in such a case you can define the last parameter as string instead of an IntPtr . Either passes the address of the variable and in this case you don't need to pin the string if you use SendMessage instead of PostMessage . Besides, you don't need to set DllImportAttribute.CharSet unless you're passing a string.
If you're C++ code was compiled without UNICODE (or _UNICODE , depending on which macros and APIs you're using - always be sure to define both) and get the IntPtr of your managed string - which is always Unicode - the ANSI version of your call to MessageBox won't display the string right. You should've at least seen a single character.
So, just define SendMessage how I showed you in the first place. You really only need PostMessage if you need to return immediately and let the message be processed on the target window's thread. If you use SendMessage , the thread context is switched - blocking your execution - and the message is processed until finished.
If you use PostMessage , then you'll need to pin the string but don't free it right away. Remember, your message may still not be processed. To marshal the string as well as get the IntPtr , use Marshal.StringToHGlobalAuto and when you know your message has bee processed, call Marshal.FreeHGlobal with the IntPtr returned from the previous call. This will make sure your string is marshaled as the correct type (ANSI or Unicode) and copied into global memory.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
In compact framework, there is no Marshal.StringToHGloablAuto method.
Also if I use sendMessage,
[DllImport("User32.dll"), CharSet=CharSet.Auto]<br />
private static extern IntPtr SendMessage (IntPtr Hwnd, uint msg, IntPtr wparam, string lparam)
is that correct?
In C++ side
Is that just Cast the lparam to TCHAR * like this?
TCHAR* stringPtr = (TCHAR*)lparam;<br />
MessageBox(0, stringPtr, _T("Caption"), MB_OK);
Thanks
|
|
|
|
|
ting668 wrote:
In compact framework, there is no Marshal.StringToHGloablAuto method.
Yes, but you never said you were using the .NET CF. How was I to know?
ting668 wrote:
Is that just Cast the lparam to TCHAR * like this?
Yes.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
hi Gurus,
I'm using DataView to display a datagrid. The data source of the dataview is a data table.
The dataview should always be sorted by a specific column in the same order. The user can modify the row data, without the columns unchanged. The data grid (or data view?) is frozen so that the user can't sort the data when clicking on any column header of the datagrid, but it seems one Mission Impossible...
The codes are something like the follows, where
one column of the data table is defined as the "Sort" column of the dataview, and validate the "ApplyDefaultSort" property to be true.
DataTable myTable = createMyTable(); // define MyTable
myTable = refreshMyTable(myTable); // add rows to the table
DataView MyView = new DataView();
MyView.Table = myTable; MyView.RowStateFilter = DataViewRowState.CurrentRows ;
MyView.AllowEdit = true; MyView.ApplyDefaultSort = true;
m_myDataGrid.SetDataBinding(MyView,"");
...
However, now it seems the user gets a full control over sorting of the datagrid.
I'm expecting your help, many thanks in advance~~~
|
|
|
|
|
|
ok
I want to know
how to prevent sorting the order of datagrid items when clicking its column header?
The fact is,
a data view is bound to the datagrid.
a data table is the data view's data source.
so I can't add a DataTableStyle to the datagrid.
Thanks!
|
|
|
|
|
Set the value of datagrid's AllowSorting property to false.
Sreejith Nair
[ My Articles ]
|
|
|
|
|
oh yeah, it works!
Thank you ~~~
|
|
|
|
|
Hello all
i make a MDI form and there is a many forms inside it but when i try to max one form all forms turn max and when i min it all forms turn min can i seprate the form status
Regards
hoho
|
|
|
|
|
Maximizing one MDI form is supposed to maximize all MDI forms, and restoring (not minimizing - that's different) is supposed to restore them all. This has been the behavior since...well...forever.
Open any other MDI application (Adobe Photoshop, older versions of Office programs, the old MFC samples applications, etc.) and you'll see the same behavior.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Here is my problem I wasn't sure if I should put it here or in the C# board ot he GDI+ board
I have a 1 form that has 2 user controls on and both user controls use GDI+ (I need to draw my own custom bitmap).
In user control 1 (ucmain) i use GDI+ to draw my own customized calender(it shows the time of day and has columns for the different conference rooms). This user control so far no problem. In user control 2 (ucappts) I draw the the scheduled appts (with detaled info) this also works. Now how I execute it is as follows: from ucmain I first create the calender bitmap for that day and draw the image and it shows up on the form.Than within ucmain I get all the appts from the db for that day and within ucmain I create ucappt for each appt. from within ucappts, I position where ucappt should go on the image that is created by ucmain ((based on time and conferrence room). Than I add the ucappt controls to ucmain. so far so good this seems to work. ucappts also contains code to deal with mouseup, mousedown, mousemove events in which I am able to move the ucappt around somewhat, this is where my problem lies.
Moving ucappts is where I have my problem, when I move the appt (ucappts) around, the background behind it i.e. the image of the calender does not repaint until after I'll let the mouse up. (the appt (ucappts) acts like a eraser wiping the image of the calender clear and does repaint until after the mouseup event is fired(it than repaints and everything looks ok). Second problem is when I move the appt (ucappts) the ucappts image it shows a double image (1/2 inch apart sometimes more) of the ucappts (i.e. flickers) like it is jumping around. Can some on help me this?
I think with the first problem, I have to somehow call the ucmain OnPaint method from ucappts from within ucappts everytime the mousemove event is fired, any opinions , thoughts.
As far as the second problem I have no Idea? any help would be great
thanks for the help
|
|
|
|
|
Painting and other interaction with the control happens in the same thread (by default), and most likely your painting routines are far too slow to keep up (so you get the appearance on-screen bitmap staying place). While you're moving the control, you're blocking the thread so the painting isn't even performed (the reason the controls move is because they encapsulate the native Windows APIs - and in most cases the Windows Common Controls - which are programmed to paint correctly in a separate thread...which is exactly what you're going to do if you follow this advice.
In our defualt constructor, call the following:
SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true); Now you're responsible for all drawing (even the background), but it sounds like you're doing that already. Additionally, the .NET Framework - without any additional code on your part - is performing the paint routine in a separate thread and copying that secondary graphics buffer to the on-screen buffer when it can. This will elliminate the flicker (mostly; terribly inefficient paint routines may still cause flicker so honor the PaintEventArgs.ClipRectangle and only redraw what's necessary) and should provide a more consistent, contiquous painting experience while dragging your windows.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Heath thanks
It still didn't solve my problem, actually it causes more. I understand your points, but i'm still learning and as a result my coding is getting complicated.
I tried your solution but it appears that rather than stopping my flickering, when I have a mousedown event (in ucappts) i now get two seperate imagaes and when I move it around both images wipe out the background image and when the mouseup event fires does not repaint like it did before it. how do get the OnPaint event in ucmain to fire when I'm in ucappts?
thnaks for your insight and help
|
|
|
|
|