|
I'm trying to understand how to use the P/Invoke method SystemParametersInfo() to get some information from my mobile computer. I am ok with the following requirements:
using System.Runtime.InteropServices;
[DllImport("coredll.dll")]
private static extern int SystemParametersInfo(uint uiAction, uint uiParam, StringBuilder pvParam, uint fWiniIni);
with a question regarding the 'pvParam' parameter. I have seen it used as StringBuilder, string, int, etc. If I type it as a string, does that limit the types of uiActions and uiParams I can return? Do I have to re-construct it with a different type for the 'pvParam' for others? I apologize that this is a bit confusing, but the document on MSDN shows the constructor and the parameters, but it's difficult to figure out exactly how to use it from that. My final source of confusion, and this is the one I'm really hung up on, is why I have to perform the following:
private const uint SPI_GETPLATFORMTYPE = 257;
private const uint SPI_GETOEMINFO = 258;
I don't understand why I have to specify an int value, and does the value matter? I see that it happens to be the next two values after 256, which seems significant but I'm not sure why. I can't find any documentation that shows that this is what I must do in order to use something like SPI_GETOEMINFO, nor can I find an explanation for the use of '258'.
Regards,
Scott
|
|
|
|
|
The reason for the StringBuider is so that the called method can modify it - strings are immutable in .NET so when a change is to be made a new string is created. This is not the case with StringBuider. If you pass string to the P/Invoked method, it cannot change it.
pvParam just stands for "pointer to a void" parameter, which is the C++ version of a reference to an object - it is a parameter which can be in effect any type, depending on what function the method is to perform on it.
Why an int value? Because the constant is an integer! C# is strongly typed, so if you didn't specify the type when you declared it, it could cause confusion when you used it later.
Yes, the value does matter! It is the value that is passed through to the P/Invoked method, and which tells it what action it is to perform - not the name of the constant! If the value is wrong, the method will perform the wrong action. You don't need to declare these as constants - you could just use the numbers directly in the method call - but it is a lot, lot more readable and checkable to use the same names and values that the called method does. (We can't use the same definition file, because they are stored in a ".h" file for the C++ and C# cannot understand those. However, what most people do is to read the ".h" file in a text editor, and automaticlly replace
#define SPI_GETPLATFORMTYPE 257 with
private const uint SPI_GETPLATFORMTYPE = 257; to make sure they are the same throughout! I know I do...
Real men don't use instructions. They are only the manufacturers opinion on how to put the thing together.
Manfred R. Bihy: "Looks as if OP is learning resistant."
|
|
|
|
|
That helps a great deal! This is the kind of stuff that I just can't seem to find in books. I figured the integers had a specific meaning, and that they weren't just randomly chosen. Thanks for providing me with the insight as to where they come from. Where could I find the C++ header to review?
|
|
|
|
|
Sorry - in this case I can't help: I've never needed SPI_GETPLATFORMTYPE!
Real men don't use instructions. They are only the manufacturers opinion on how to put the thing together.
Manfred R. Bihy: "Looks as if OP is learning resistant."
|
|
|
|
|
According to the documentation[^], the header file is Winuser.h. It says to include Windows.h so there may be some things declared in there that you need also.
On my system (W7 64bit with Visual Studio 2010 Ultimate) they can both be found in
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\
|
|
|
|
|
Dave -
The documentation you refer to is for desktop, whereas I'm using this on a Windows Mobile platform. Not sure if that matters when it comes to the Winuser.h header. I'll take a look nonetheless. Thanks for the info.
Regards,
Scott
|
|
|
|
|
Not sure where this header will be on the system - I'll have a look. The documentation is here.
|
|
|
|
|
I have seen information on the web about how to access private methods and properties from outside of a PUBLIC class by using a public method that exposes only the specific property one is interested in. But how does one gain access outside of the class when the entire class is private?
Regards,
Scott
|
|
|
|
|
You don't. Private members are not available to consumers outside the class.
What are you trying to do?
|
|
|
|
|
Sure they are. You can use reflection, expression trees, etc. Thats not to say its recommended, but to flat out say you can't is incorrect.
|
|
|
|
|
Since reflection is excruciatingly slow, it would be nice to know what he's really trying to do with this. If speed is an issue, it's really not going to work very well.
If hyjaking someones work is the reason, well, you where I stand on that...
|
|
|
|
|
SledgeHammer01 wrote: Sure they are.
Cool, than it'd be very easy for you to write a code example. He's talking about a private class, which is not the thing below as you'd might expect;
namespace MyTest
{
private class Test
{
}
}
Try to compile that, and you'll get an error;
Compiler says: Elements defined in a namespace cannot be explicitly declared as private, protected, or protected internal.
This would be a private class;
static class Owner
{
private class SomeClass
{
private string SomeMethod()
{
return "Hello world";
}
}
}
Standard reflection would look like the two lines below, which would both return NULL , not the Type "SomeClass";
Type someClassType = Type.GetType("SomeClass");
Type someClassType = Type.GetType("Owner.SomeClass");
Bastard Programmer from Hell
|
|
|
|
|
Cool, how do you think .NET Reflector sees private classes? Or ILSpy? You just need the FULLY qualified name of the class including assembly information.
|
|
|
|
|
SledgeHammer01 wrote: Cool, how do you think .NET Reflector sees private classes? Or ILSpy?
Easy to find out by using ILSpy on Reflector
I know that they're accessible, just wanted to point out that it might be somewhat harder than it initially looks.
SledgeHammer01 wrote: You just need the FULLY qualified name of the class including assembly information.
Type someClassType = Type.GetType("ConsoleApplication7.Owner.SomeClass, ConsoleApplication7, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
someClassType remains null .
Bastard Programmer from Hell
|
|
|
|
|
using System;
using System.Diagnostics;
using System.Reflection;
namespace ConsoleApplication7
{
static class Owner
{
private class SomeClass
{
private string SomeMethod()
{ return "Hello world"; }
}
}
class Program
{
static int Main(string[] args)
{
Type ownerClassType = Type.GetType(
"ConsoleApplication7.Owner, ConsoleApplication7, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
Type someClassType = ownerClassType.GetNestedType(
"SomeClass",
BindingFlags.Instance | BindingFlags.NonPublic);
Object someObject = Activator.CreateInstance(someClassType);
MethodInfo mi = someClassType.GetMethod(
"SomeMethod",
BindingFlags.Instance | BindingFlags.NonPublic);
Object result = mi.Invoke(someObject, null);
Console.WriteLine(result);
Console.ReadKey();
return 0;
}
}
}
Yup, works
Bastard Programmer from Hell
|
|
|
|
|
Eddy Vluggen wrote:
namespace MyTest
{
private class Test
{
}
}
Try to compile that, and you'll get an error;
Hi Eddie,
Yes, but, you can have 'private classes' inside another class (nested) which is not private:
public class ContainsPrivateClassExample
{
private PrivateClass pcInstance;
public ContainsPrivateClassExample()
{
pcInstance = new PrivateClass();
}
private class PrivateClass
{
public int y = 200;
}
} Interesting that both these examples compile, and instances of them behave as if they are marked 'public:'
namespace MyTest
{
class Test
{
}
}
namespace MyTest
{
internal class Test
{
}
} For myself, I follow a discipline of marking all classes which are not nested as 'public.'
The issue of whether or not you should use a private, nested, class: well, I don't see any "one ring to bind them all" kind of rule there; I think that depends on program design, algorithm, context, etc.
best, Bill
"Beauty is in the eye of the beholder, and it may be necessary from time to time to give a stupid or misinformed beholder a black eye." Miss Piggy"
|
|
|
|
|
Dave -
I am reviewing someone else's code as part of my endeavor to learn more about C# and wondering why someone would type a class as private when it appears to be (in my opinion) not very useful when the methods and properties can't be accessed from outside of it.
Regards,
Scott
|
|
|
|
|
namelkcip wrote: why someone would type a class as private If you have a class marked as 'private,' and the code compiles, then you can be sure the class marked as 'private' is nested within another class.
Please see my detailed response to Eddy Vluggen above[^] for an example.
best, Bill
"Beauty is in the eye of the beholder, and it may be necessary from time to time to give a stupid or misinformed beholder a black eye." Miss Piggy"
|
|
|
|
|
They're private because they are used internally by the class. This is very common.
Not all methods and properties in a class are meant to be used by outside callers. Calling this stuff without knowing what it's for can cause the class to break completely or behave funny.
|
|
|
|
|
A private nested class is often useful within its enclosing parent class. I do this quite often to either store class-private data (as return types from internal methods, or storage elements in a hash map), or to implement interface objects that need to be returned outside as an interface (e.g. IEnumerable/IEnumerable<OuterClass>).
|
|
|
|
|
Bob -
I am looking at some code where a user wrote a class to get the device ID of a Windows Mobile computer, but put the method inside of a class that was private. There are other methods in another class that get the operating system version, and they are in a public class. The user then wrote a WinForm that updates the text of a label upon form_load to display the detected OS type. So I was really curious as to why the user might have chosen to make the device ID method live inside a private class? By doing so, I wouldn't be able to update a text label on the form with that information, correct? I have read about using a private method with a private set variable and a public get, but I don't know how I would make use of that device ID method when it lives in a class that is private.
Regards,
Scott
|
|
|
|
|
With Reflection. But it's not generally a good idea.
|
|
|
|
|
I'd like to use the asynchronous model with the Socket class to receive data.
The BeginReceive function must be told how many bytes you wish to receive:
public IAsyncResult BeginReceive(
byte[] buffer,
int offset,
int size,
SocketFlags socketFlags,
AsyncCallback callback,
Object state
)
Does this mean that if I pass size = 200 , and there are 199 bytes waiting for me, it won't complete the receive?
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
If you read the sample supplied with the document of Socket.BeginReceive Method[^] you will notice that the size specified is the size of the buffer passed to the function. So this size has no relation with the amount of bytes waiting to be received.
In the callback function you determine if all the data has been received or whether there is any more data. If there is more data you call BeginReceive again.
So to answer your question directly when 199 bytes are waiting and you pass a buffer of 200 bytes the receive will complete.
If you had used a buffer of 100 bytes you would have needed to perform two receives to get all the bytes. This means that you would have to put the two receives together in a larger buffer.
I hope I clarified it for you.
0100000101101110011001000111001011101001
|
|
|
|
|
Thank you, that clears it up.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|