VB6 Shape control BorderWidth >1 with Dash style? - vb6

When you set a Shape's BorderWidth > 1 in VB6, the Style is forced to be a plain line.
I'd like a DASHED (or Dotted) border with a thicker (say borderwidth=3) size.
any way to do that without drawing it manually?

Unfortunately not, under the hood a GDI Pen is used to draw the shape and the 1 twip limit is imposed there.
PS_DASH
The pen is dashed. This style is valid only when the pen width
is one or less in device units.
This of course also means you cannot use the GDI API to do it directly for you either.
Perhaps draw a series of lines offset by 1 twip.

Related

Windows GDI - FillRect vs MoveToEx & LineTo?

When reading source code which draws lines in Windows using GDI it is relatively common to see FillRect() being used despite the only purpose being to draw a line. But the end product of drawing a line with a width value and a filled rectangle are quite similar aren't they?
FillRect() is 1 function call, Using MoveToEx & LineTo requires 2
Which is more efficient when needing to draw a line, using FillRect() or MoveToEx() and LineTo()?
In the most common cases, FillRect will do the same thing as MoveToEx and LineTo for perfectly horizontal and vertical rectangles. Nowadays, there are so many layers of indirection between GDI and the screen that the performance difference is almost certainly not relevant.
Drawing operations in GDI typically depend on the current "state" of the device context (DC). Lines are drawn with whichever pen is currently selected into the DC. The pen determines the color, style (solid, dashed, etc.), thickness, end caps, etc.
FillRect, however, doesn't depend on much of the DC state. All drawing primitives depend on the mapping mode and clipping region, but, unlike lines, FillRect doesn't even depend on the selected brush, since you get to provide one right in the call.
Changing state (which objects are selected into the DC) can be a lot of work. If you know you want a horizontal line, 2 pixels thick, in blue, it's a tad easier to use FillRect than to first create a pen, select it into the DC, draw your line, select the pen back out, and then decide how to manage the lifetime of that pen (when do you delete it?). If the rest of the drawing is a bunch of dashed yellow lines with round endcaps, not having to keep switching state can make the code simpler.

DwmEnableBlurBehindWindow makes the entire client area transparent

Aero glass causes alot of people problems trying to draw on it. Anything with an alpha value of 255 seems to be treated as transparent with DWM using an additive blur to draw it. I want a part of client area to use Aero glass with the rest of it treated as opaque, so I don't have to deal with the headache of common controls not rendering properly.
MSDN lists a function DwmEnableBlurBehindWindow which lets you mark part of the client area as blurred by DWM. It takes a DWM_BLURBEHIND pointer which which has an HRGN handle to the region of the window. When I use this function, the entire window becomes transparent with an additive blend, but only the region of the window I passed to DwmEnableBlurBehindWindow gets blurred. Is there a way I can keep the rest of the window from becoming transparent?
What I have looks a bit like:
blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
blur.hRgnBlur = CreateRectRgn(0, 0, 90, 90);
blur.fEnable = true;
DwmEnableBlurBehindWindow(hwnd, &blur);
RECT rect;
GetClientArea(&rect);
FillRect(hdc, &rect, CreateSolidBrush(0));
From the MSDN Library article:
The alpha values in the window are honored and the rendering atop the blur will use these alpha values. It is the applications responsiblity for ensuring that the alpha values of all pixels in the window are correct. Some GDI operations do not perserve alpha values so care must be taken when presenting child windows as the alpha values they contribute are unpredicitable.
Make that most GDI operations, like FillRect(). The brush you created is drawn with 24-bit colors, the alpha will be 0. Which makes the window transparent. You'll need to switch to, say, GDI+. Text is particularly troublesome. As well as legacy Windows controls, like EDIT and LISTBOX which draw with GDI.

Using Win32 TextOut to draw text at an angle

I'm using GDI to draw text onto a device context, and I noticed that the kerning or character placement is different if the angle is exactly 0, 90, 180, or 270. As soon as I increase the angle by 1, the character placement differs noticeably.
Rather than creating an HFONT with the angle, I am using ModifyWorldTransform to transform the device context's world coordinates, and then I use TextOut to draw the text onto the device context.
I think that GDI is using font hints or some other special technique when the text is being drawn at exact multiples of 90 degrees, but not for any other angle.
Is there a way to disable this hinting, so that text rendered at 0 degrees does not differ significantly from text rendered at 1 degree?
Here's an example of what I mean (Monotype Corsiva font):
0 degrees:
1 degree:
For some fonts, such as Arial or Tahoma, it is not as noticeable, but I would like to get rid of the difference entirely, even if it means the text is not rendered as best it can.
I think this is due to anti-aliasing rather than font hints. You could try the following:
Disable (font) AA, but this will not yield acceptable results.
Create font handles for every possible angle and see if the problem persists. I assume it doesn't, but it's not a pretty solution.
Render the text to a bitmap (e.g. using CreateCompatibleBitmap() ) render the text to it and then render the rotated bitmap. This depends on how often you need different rotations / different text.
Play with fdwOutputPrecision and fdwQuality in CreateFont(). This could be the easiest solution, but you'd have to experiment a little bit I guess.
hth

Transparency to text in GDI

i have created a Bitmap using GDI+.I am drawing text on to that bitmap using GDI Drawtext.Using Drawtext i am unable to apply tranparency.
Any help or code will be appreciated.
If you want to draw text without a background fill, SetBkMode(hdc,TRANSPARENT) will tell GDI to leave the background when drawing text.
To actually render the foreground color of the text with alpha... is going to be more complicated. GDI does not actually support alpha channels all that widely in its APIs. Outside of AlphaBlend actually all it does is preserve the channel. Its actually not valid to set the upper bits of a COLOREF to alpha values as the high byte is actually used for flags to indicate whether the COLOREF is (rather than an RGB value) a palette entry.
So, unfortunately, your only real way forward is to:
Create a 32bit DIBSection. (CreateDIBSection). This gives you an HBITMAP that is guaranteed to be able to hold alpha information. If you create a bitmap via one of the other bitmap creation functions its going to be at the device colordepth that might not be 32bpp.
DrawText onto the DIBSection.
When you created the DIBSection you got a pointer to the actual memory. At this point you need to go through the memory and set the alpha values. I don't think that DrawText is going to do anything to the alpha channel by itself at all. Im thinking a simple check of the RGB components of each DWORD of the bitmap - if theyre the forground color, rewrite the DWORD with a 50% (or whatever) alpha in the alpha byte, if theyre the background color, rewrite with a 100% alpha in the alpha byte. *
AlphaBlend the bitmap onto the final destination. AlphaBlend requires the alpha channel in the source to be pre-multiplied.
*
It might be sufficient to simply memset the DIBSection with a 50% alpha before doing the DrawText, and ensure that the BKColor is black. I don't know what DrawText might do to the alpha channel though. Some experimentation is called for.
SIMPLE and EASY solution:)
Had this problem, i tried to change alpha values and premultiply, but there was another problem - antialiased and cleartype fonts where not shown correctly (ugly edges). So what i did...
Compose your scene (bitmaps, graphics, etc.)
BitBlt required rectangle from this scene (same as your text rectangle, from the place where you want your text to be) to memory DC with compatible bitmap selected at 0,0 destination coordinates
Draw Your text to that rectangle in memory DC.
Now AlphaBlend that rectangle without AC_SRC_ALPHA in the BLENDFUNCTION and with desired SourceConstantAlpha from this memory DC back to your scene DC.
I think You got it :)
Hmmmm - trying to do same here - wondering - I see that when you create a dib section youi specify the "masks" that is a R,G,B (and alpha) mask.
IF and thats a big if it really does not alter the alpha chhannel, then you might specify the mask differently for two bitmap headers. ONe specifies thr RGB in the proper places, the other makes them all have their bits assigned to the alpha channel. (set the text color to white in this case) then render in two passes, one to load the color values, the other to load the alpha values.
???? anyway just musing :)
While this question is about making text semi-transparent, I had the opposite problem.
DrawText was making the text in my layered window (UpdateLayeredWindow) semi-transparent ... and I didn't want it to be.
Take a look at this other question ... since in the other question I post some code that you could easily modify ... and is almost exactly what Chris Becke suggests in his answer.
A limited answer for a specific situation:
If you have a graphic with alpha channel and you want to draw opaque text over a locally opaque background, first prepare your 32 bit bitmap with 32 bit brushes created with CreateDIBPatternBrushPt. Then scan through the bitmap bits inverting the alpha channel, draw your text as you normally would (including SetBkMode to TRANSPARENT), then invert the alpha in the bitmap again. You can skip the first inversion if you invert the alpha of your brushes.

Window border width and height

I'm writing a direct3d application and after noticing strange bugs such as anti-aliasing occurring even when it was turned off and the mouse pointer not lining up to things with the same coordinates as itself I discovered that when creating a window the width and height parameters include the border. The program was rendering a 800x600 graphics output to a window of the same size, but because of the borders it was squished into 792x566 rectangle. I've increased the size of the window to compensate, but this does not work if the system uses a border style other the standard XP style. (Classic style, for example)
Is there a way to tell what the border width and heights will be before I create the window?
Another option would be to make sure the D3D surface is the same size as the client rectangle size (GetClientRect()). Then you know you'll render to the appropriate size and not have to worry at all about the width of menus, borders, etc.
It sounds like you are looking for the GetSystemMetrics function. For example, the border width in pixels is returned by
GetSystemMetrics(SM_CXBORDER)
ADDED: For the total size you will need to add together the various "pieces" of the non-client area: border, frame sizes, title bars, etc.

Resources