2

I was using the following pattern to record an enhanced meta-file for a later playback:

POINT pts[] = {
//.....
};

::SelectObject(hEnhDC, ::GetStockObject(LTGRAY_BRUSH));
::Polygon(hEnhDC, pts, _countof(pts));

Now I'm forced to use GDI+ to provide anti-aliasing, so I'm trying to convert that code sample:

Gdiplus::Point pts[] = {
//...
};

Gdiplus::Graphics grx(hEnhDC);
Gdiplus::Pen pen(Gdiplus::Color(255, GetRValue(clrPen), GetGValue(clrPen), GetBValue(clrPen)), PEN_THICKNESS);

grx.FillPolygon(&brush, pts, _countof(pts));
grx.DrawPolygon(&pen, pts, _countof(pts));

The issue is how do I convert a stock-object HBRUSH from ::GetStockObject(LTGRAY_BRUSH) to GDI+ Brush object?


EDIT: Guys, thank you for all your suggestions. And I apologize for not providing more details. This question is not about getting the RGB color triplet from the stock brush. I can do all that with the GetSysColor function, or with the LOGBRUSH like you showed below.

The trick lies in the first sentence above. I am recording an enhanced metafile that may be played on a separate computer, so I cannot hard-code colors into it.

Let me explain. Say, the first GDI example (let's simplify it down to a triangle with a gray fill):

POINT pts[] = {
    {100, 100,},
    {100, 120,},
    {120, 100,},
};

::SelectObject(hEnhDC, ::GetStockObject(LTGRAY_BRUSH));
::Polygon(hEnhDC, pts, _countof(pts));

If I then call GetEnhMetaFileBits on that meta-file, I'll get the following data:

enter image description here

So as you see the EMR_SELECTOBJECT object in that recorded meta-file specifies the LTGRAY_BRUSH = 0x80000001, which will be properly substituted for the color when that meta-file is played on the target system.

And that's what I'm trying to achieve here with GDI+. For some reason it only seems to support hard-coded color triplets in its Brush class. That's why I asked.

Otherwise, one solution is to parse the enhanced meta-file's raw data. (For GDI+ it is a much more complex structure though, that also involves parsing EMR_GDICOMMENT objects.) And then substitute the needed color on the target system before the GDI+ meta-file is played. But it involves writing a lot of code, which I was trying to avoid at this stage ...

c00000fd
  • 20,994
  • 29
  • 177
  • 400
  • Why do you specifically want to use a stock object? Why not just pick a light grey color and make a brush from it? – Jonathan Potter Jul 21 '19 at 03:10
  • 1
    @JonathanPotter: Because `GetStockObject(LTGRAY_BRUSH)` may be a "light grey color" on your computer, but it may be a bright yellow one on someone else's who picks `high contrast` color scheme. – c00000fd Jul 21 '19 at 04:14
  • 2
    `LOGBRUSH lb; GetObjectW(GetStockObject(LTGRAY_BRUSH), sizeof(lb), &lb); Color clr; clr.SetFromCOLORREF(lb.lbColor); Pen pen(&SolidBrush(clr));` – RbMm Jul 21 '19 at 09:02
  • @c00000fd Color scheme affects results of GetSysColor and GetSysColorBrush API calls. GetStockObject is different. – Soonts Jul 21 '19 at 14:07
  • yeah, sorry everyone. I guess I didn't explain it with more details. Posted an update above. – c00000fd Jul 21 '19 at 20:57
  • 1
    I think you’re over-engineering things. Unlike windows borders and other theme-dependent stuff, stock brushes don’t change. MS has them documented over there https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-emf/91c257d7-c39d-4a36-9b1f-63e3f73d30ca for decades now. The spec says `#C0C0C0`, and always did. It’s a data exchange format, after all. – Soonts Jul 21 '19 at 21:17
  • @Soonts: maybe. I just want the software to comply with the users' accessibility settings. – c00000fd Jul 21 '19 at 22:31

1 Answers1

1

I’m afraid you can’t easily convert.

A simple workaround is create GDI+ solid brush with the same color.

See this spec for color values of GDI stock objects, that particular brush has color #C0C0C0

Soonts
  • 20,079
  • 9
  • 57
  • 130