tags:

views:

58

answers:

1

I need a little help in defining the following Windows GDI type in C#. I have the data in the form of a byte[] in C#, and I need to somehow marshal or cast it as the following in C#. Please see my other question, as I got the answer to the Polyline. This is the type:

NAME

META_CREATEPENINDIRECT

NEAREST API CALL

#include <windows.h>
HPEN32 CreatePenIndirect(const LOGPEN32 *pen);

typedef struct tagLOGPEN
{
    UINT        lopnStyle;
    POINT       lopnWidth;
    COLORREF    lopnColor;
} LOGPEN;

DESCRIPTION

U16     Value
0       lopnStyle
1       lopnWidth
2, 3    lopnColor

lopnColor is the color of the pen, lopnWidth is the width of the pen, if the pen's width is > 1 but the lopnStyle is not solid, then lopnStyle is ignored and set to solid anyway.

lopnStyle can be one of PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL, PS_INSIDEFRAME, PS_USERSTYLE, PS_ALTERNATE. Check out the source for that they actually mean.

Theres also a set of flags and masks that can be found in lopnStyle as well that set the end and join styles of lines drawn with a pen, they are PS_STYLE_MASK, PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE, PS_ENDCAP_FLAT, PS_ENDCAP_MASK, PS_JOIN_ROUND, PS_JOIN_BEVEL, PS_JOIN_MITER, PS_JOIN_MASK, PS_COSMETIC, PS_GEOMETRIC, PS_TYPE_MASK, again check out the source to figure these out.


Update: This is as close as I can get so far:

fixed (byte* b = dataArray)
{
    byte* ptr = (byte*)b;
    // Get style
    l_nStyle = (ushort)*(ptr);
    ++ptr;
    // Get width
    l_nWidth = (ushort)*(++ptr);
    ++ptr;
    // skip one ushort
    ++ptr; ++ptr;
    // Get RGB colors
    l_nColorR = (ushort)*(++ptr);
    l_nColorG = (ushort)*(++ptr);
    l_nColorB = (ushort)*(++ptr);
}
A: 
byte[] buffer;
int style = BitConverter.ToUInt16(buffer, 0);
int width = BitConverter.ToUInt16(buffer, 2);
var color = Color.FromArgb(buffer[4], buffer[5], buffer[6]);
var pen   = new Pen(color, width)
            {
                DashStyle = ..., // set style
                StartCap = ...,
                EndCap = ...
            };

(Untested)

dtb
That is very close. The raw data array contents look like this:[0] 0 byte [1] 0 byte [2] 0 byte [3] 255 byte [4] 255 byte [5] 0 byte [6] 0 byte [7] 0 byteSo I used: int l_nColorR = BitConverter.ToUInt16(dataArray, 2); int l_nColorG = BitConverter.ToUInt16(dataArray, 3); int l_nColorB = BitConverter.ToUInt16(dataArray, 4); Color color = Color.FromArgb(l_nColorR, l_nColorG, l_nColorB);Wich is not correct. How do I get an Int from a single Byte?
GdiHelp
If you have a byte array, just get the element at the index. It's already a byte, no need to convert it :-)
dtb
Are you sure it's just 8 bytes? The Java code you linked and the MSDN docs say different. http://msdn.microsoft.com/en-us/library/cc250423.aspx
dtb
Perfect. I did 10 more, and got stuck on PolyPolygon16 in EMF. Would you please take a look? http://stackoverflow.com/questions/1778938/how-do-i-parse-a-polypolygon16-metafile-record-out-of-a-byte-cThank you
GdiHelp