|
add a popup menu to the form, so the user can minimize/maximize the form by right-clicking on the form and choosing the state.
~~~ From Milano to The Hague, easy as it goes ~~~
|
|
|
|
|
Thanks for your reply Rey9999,
Yes I could add a Context Menu to the form, but the user has no access to it when the form is minimized to the taskbar, it's this which is my main problem.
Thanks for your time,
Rob.
|
|
|
|
|
you could minimize the form to the system tray instead, through a NotifyIcon control, which you can add a context menu to.
~~~ From Milano to The Hague, easy as it goes ~~~
|
|
|
|
|
I'm a C++ programmer trying to find his feet in the C# world. One problem I'm particularly struggling with is this. In C++ I used to have a handy little technique for populating a buffer according to certain rules.
Say for instance I have something like unsigned char xmt_buf[200] . Now the first 4 bytes of this buffer will be header information (it's all part of a transmission protocol). So I define the header structure as follows:
struct MessageHeader_t
{
unsigned char MessageFormat;
unsigned char MessageLength;
unsigned char MessageType;
unsigned char HeaderLength;
} MSG_HDR;
So far so good, but now for the part that I like and which I just can't implement in C#. When I populate the buffer I do something like this:
MSG_HDR *msghdr;
msghdr = (MSG_HDR *)&xmt_buf[0];
msghdr->MessageFormat = 0x23;
msghdr->MessageLength = 0x3E;
msghdr->MessageType = 0x61;
msghdr->HeaderLength = 0x04;
Of course then I can populate the remainder of the buffer in a similar way.
TAG_CON *connect;
connect = (TAG_CON *)&xmt_buf[sizeof(MSG_HDR)];
connect->TagType = 0x65;
connect->Priority = 0x01;
.
.
.
Maybe I'm not ready for ths type of thing in C# yet but if anyone can help, I'd be thrilled.
|
|
|
|
|
Which part are you having problems with?
Keep in mind, you can use pointers if you like; they just have to be wrapped up in an unsafe block:
unsafe
{
msghdr = (MSG_HDR *)&mt_buff[0];
}
Or just put unsafe in the method declaration.
public unsafe void DoIt() {...}
That said, typically there isn't a need to use pointers directly; typically one can just make use of reference types. If you need to pass a value type like a struct by reference, one can use the ref or the out keyword:
public void ModifyThisInt(ref int i)
{
i = 10;
}
int i = 0;
ModifyThisInt(ref i);
Console.WriteLine(i);
But to answer your question, can you be specific about what piece you're having trouble with?
|
|
|
|
|
Thanks for the help so far.
Judah Himango wrote:
msghdr = (MSG_HDR *)&xmt_buf[0];
Right there is where I get stuck. The above line gives me a compile error that reads:
You can only take the address of an unfixed expression inside of a fixed statement initializer.
I also have another problem which probably belongs in another thread but I'll throw it in just in case there's a quick answer to it. The struct that I quoted in my original message is a simplified version of what I had in C++. The real struct is not just a struct of byte values. Some of the members were arrays. Here is a more realistic version of the struct.
struct MessageHeader_t
{
unsigned char MessageFormat;
unsigned char MessageLength;
unsigned char MessageType;
unsinged char MessageFlags[6];
unsigned char HeaderLength;
} MSG_HDR;
In other words, after msghdr = (MSG_HDR *)&xmt_buf[0]; I can populate the msghdr variable which as the effect of populating the first 10 bytes of xmt_buf.
Important to note is that I'm not using the .NET 2.0 framework as I'm developing for a device running the Windows CE.NET OS with the older framework.
Thanks mate.
BTW - I like your blog.
|
|
|
|
|
Dewald wrote: msghdr = (MSG_HDR *)&xmt_buf[0];
OK, I use pointers so rarely I forgot that in C# you have to use the fixed statement around something you're taking the address of; "fixed" is required to tell the garbage collector to pin (not move) the object in memory while you hold a pointer to it. Otherwise your pointer could end up pointing to something else. So it'd look like:
fixed ( MSG_HDR* msghdr = &xmt_buf )
{
}
Something like that. You can read more about using unsafe code like this in this article[^].
Again, one typically does not need to use unsafe code in C#. You certainly can, but it's rather irregular. If you haven't already, you might want to have a look at the C# FAQ for C++ programmers[^]; kind of clarifies some things when you're coming from a C++ background. I found it quite useful when moving to C# myself.
When you said you're having trouble with the struct itself, was it because you were having trouble with declaring arrays? In any event, if I were to write the equivalent of that struct in C#, it'd look something like this:
struct MessageHeader
{
byte MessageFormat;
byte MessageLength;
byte MessageType;
byte[] MessageFlags = new byte[6];
byte HeaderLength;
}
Let me stress again I normally wouldn't write such code in C#. This sounds more like a task for a class than a struct (C# structs are very different than C structs). So I'd probably put this stuff in a class unless there's a real need to have it in a C# struct. Also, when you've got stuff in classes, it's common to make fields private, and supply property accessors to the data. So if I really wanted to be all .NET warm and fuzzy, I'd write it something like this:
public class MessageHeader
{
private byte format;
private byte length;
private byte type;
private byte[] flags;
private byte headerLength;
public MessageHeader()
{
}
public MessageHeader(byte format, byte length, byte type, byte[] flags, byte headerLength)
{
if(flags == null)
{
throw new ArgumentNullException("flags");
}
if(flags.Length != 6)
{
throw new ArgumentException("Flags must be 6 elements in length.");
}
this.format = format;
this.length = length;
this.type = type;
this.flags = flags;
this.headerLength = headerLength;
}
public byte Format
{
get { return this.format; }
set { this.format = value; }
}
public byte Length
{
get { return this.length; }
set { this.length = value; }
}
public byte[] Flags
{
get { return this.flags; }
set
{
if(value == null)
{
throw new ArgumentNullException("flags");
}
if(value.Length != 6)
{
throw new ArgumentException("flags must be 6 elements in length.");
}
this.flags = value;
}
}
public byte HeaderLength
{
get { return this.headerLength; }
set { this.headerLength = value; }
}
}
And from calling code, if I wanted to fill up that Flags array with data, it'd look something like this:
MessageHeader header = new MessageHeader();
header.Flags = new byte[] { 5, 240, 6, 29, 60, 152 };
Dewald wrote: BTW - I like your blog.
Thanks.
|
|
|
|
|
Thanks again. You've been of great help so far. I've still not managed to achieve what I set out to do but I think I'm making progress at least. If you say that you use pointers so rarely then it gives me hope that I may be able to move away from it myself in due course.
Anyway, your code
fixed ( MSG_HDR* msghdr = &xmt_buf )
gives me the error message
Cannot take the address of, get the size of, or declare a pointer to a managed type ('byte[]')
But as I said, I'm quite keen to move away from pointers and I am not convinced that it really is neccessary for what I am achieving here. Using the class as you pointed out would indeed be a good sollution for me, at least up to a point. What remains is for me to populate a byte array with the contents of the class but that I can do with member functions.
What would help is if you could give me an example of a byte array being passed as a reference variable to a function. I've managed to do this with simple data types such as int, byte etc. but I'm missing something when it comes to arrays. In other words, I would like to pass an array of bytes to a function as a parameter, the function then populates certain elements of the array (not neccessarily all) and when done the array will hold the new values.
I hope I'm making sense. At times I find it hard expressing myself in English. But thanks for your help.
|
|
|
|
|
Dewald wrote: What would help is if you could give me an example of a byte array being passed as a reference variable to a function.
Aaah, never mind, I figured it out. Turns out to be a walk in the park really.
static void ProcessArr(ref byte[] paramArr)<br />
{<br />
for (int i=0; i<paramArr.Length; i++)<br />
{<br />
}<br />
}
And then call the function as follows:
<br />
byte[] byteArr = { 0, 1, 2, 3, 4 };<br />
ProcessArr(ref byteArr);<br />
I think I'm on my way to success now.
If yu have an answer to that error message I quoted above I'd still appreciate that though.
|
|
|
|
|
Yeah, to pass a reference of anything into a method, just use the ref keyword.
However, arrays are reference types themselves. When you pass it into a method, it's passing a pointer to the real data:
byte[] myBytes = { 5, 10, 15 };
FillItAllWith7s(myBytes);
...
void FillItAllWith7s(byte[] bytesToModify)
{
for(int i = 0; i < bytesToModify.Length; i++)
{
bytesToModify[i] = 7;
}
}
Notice how I didn't even need to use the ref keyword; passing any class type (AKA reference type) into a function simply passes a pointer to that object. Passing any struct type (AKA value type, including int, double, float, etc.) will pass a copy of the struct instance to the function. This is when the ref keyword really comes in handy.
However, you can certainly use the ref keyword for parameters that are classes/reference types, as you just did in your above example. This allows you to actually change the reference itself:
byte[] myBytes = {1, 2, 3};
SetToNull(ref myBytes);
...
void SetToNull(ref byte[] bytesToModify)
{
bytesToModify = null;
}
To summarize, if you're just changing the data of the class passed in as a parameter to a function, you don't need the ref keyword. In fact, I think I've used the ref keyword -- for reference type parameters -- on functions maybe 2 or 3 times in my 500k line project at work. I've used the ref keyword many times for value type parameters.
The only time you *need* the ref keyword on classes/reference types passed in as parameter is if you need to actually modify what the object points to. In your case, if you needed to change the byte[] to point to something else (that is, a new byte[], or a null), then you'd use the ref keyword. Otherwise, you can omit the ref keyword and pass in the array if you just want to manipulate that array (i.e. change the array's elements). Make sense?
|
|
|
|
|
Has anyone found a way to put hyperlinks to web pages in a help file? I have tried using <summary><see cref="http://www.codeproject.com">CodeProject</see></summary> but it doesn't work. I have tried <seealso> but this doesn't work either.
Chris
|
|
|
|
|
I'm not sure on Sandcastle, but it worked in NDoc so it probably works in Sandcastle is to use XHTML.
So your summary becomes:
<summary><a href="http://www.codeproject.com">CodeProject</a></summary>
|
|
|
|
|
<summary><a href="http://www.codeproject.com">CodeProject</a></summary> doesn't work. Thanks for the try. Anyone else have any possibilities?
Chris
|
|
|
|
|
Chris
I believe that you need to use <summary><see href="http://www.codeproject.com">CodeProject</see></summary>
cref refers to items that are in the docs that you are building, and anything that is external has to be href .
Arthur Dent - "That would explain it. All my life I've had this strange feeling that there's something big and sinister going on in the world."
Slartibartfast - "No. That's perfectly normal paranoia. Everybody in the universe gets that."
Deja View - the feeling that you've seen this post before.
|
|
|
|
|
I tried it with an h and no luck.
Chris
|
|
|
|
|
I need to read the extended/summary properties of an mp3 file. What class .net class would be used for this? I have been searching the internet trying to find examples but I have had no luck.
Thanks,
Patrick
|
|
|
|
|
|
This does not appear to be working and I can't figure out why
<br />
MemoryStream ms = new MemoryStream();<br />
string message;<br />
<br />
….some code here to fill the memory stream….<br />
<br />
Using (StreamReader sr = new StreamReader(ms))<br />
{<br />
message = sr.ReadToEnd();<br />
}<br />
<br />
ms.Position = 0;
Blog Have I http:\\www.frankkerrigan.com
|
|
|
|
|
Frank Kerrigan wrote: This does not appear to be working and I can't figure out why
What exactly do you mean by "not working"?
|
|
|
|
|
This code was taken from a live web service that had been running perfectly happily for nearly 3 months and then all of a sudden stopped working, throwing the ObjectDisposedException.
Blog Have I http:\\www.frankkerrigan.com
|
|
|
|
|
|
Alois Kraus wrote: http://geekswithblogs.net/akraus1/articles/81629.aspx
Sorry, that link doesn't work for me.
|
|
|
|
|
The reason is because the using block closes the StreamReader when you move out of the scope of the using block. When you close a StreamReader OR a StreamWriter , however, the underlying stream object is also closed and thus disposed. If your stream was a FileStream then that might make logical sense but it is not so obvious with a MemoryStream because you probably want to use it as temporary storage or pass to another method for further processing etc. Even if you did not use the using block the MemoryStream would still be closed the moment the StreamReader is disposed of or garbage collected.
I've no idea why it would just suddenly show up now after so many months - That is a curiosity.
|
|
|
|
|
Thanks guys
Blog Have I http:\\www.frankkerrigan.com
|
|
|
|
|
sr.ReadToEnd will read to the end from the current position. Make sure the position is 0 before reading to end. Also, don't touch the memory stream after it has been disposed. The using(...) block will dispose the object; it will actually compile down to this:
StreamReader sr = null;
try
{
sr = new StreamReader(ms);
message = sr.ReadToEnd();
}
finally
{
if(sr != null)
{
sr.Dispose();
}
}
Since it gets disposed when the using block leaves scope, callign ms.Position = 0 after the using scope is going to cause problems.
|
|
|
|
|