I have a win32 screen saver application that gets its device context from the HWND that's passed into ScreenSaverProc, using, for instance, BeginPaint.
Now I want to use the same code to create a video of the screen saver (ussing ffmpeg, but that's not relevant). What I'd like to do is put a wrapper around the code which calls ScreenSaverProc (instead of having libscrsave do it), and passing in some kind of virtual window, so that it can get the device context the same way as usual and paint on it, but then in the wrapper code I can get at the device context's bitmap and copy it into a frame of the video.
Is there a way to create such a virtual window? Would it work to just create a regular window and leave it hidden?
I would structure the screen saver into a thin wrapper function that just obtains a device context, then calls another function to do the drawing into the DC:
void On_WmPaint() {
HDC dc = BeginPaint();
// ...
do_draw(dc);
EndPaint();
}
void do_draw(HDC dc) {
// ...
}
Then when you want to create a frame for your video, you can use CreateCompatibleDC (for one possibility) to create a DC compatible with your screen. Then use CreateCompatibleBitmap to create a bitmap (also compatible with the screen). Select that bitmap into the DC, then call do_draw, passing it that DC. That will draw into the bitmap you selected into the DC, so afterwards you can do what you wish with the bitmap.
Related
While there are lots of variations of the question, there doesn't seem to be a specific answer to a simple case of wanting to use built-in common controls on a transparent window using Win32. I don't want the controls to be transparent, I just want the border around it to be transparent. I can't believe MS didn't update the .dll's to handle transparency when they added it, but I guess they forgot? Is there a specific method that works. A button can get close with WS_EX_TRANSPARENT, but flaky where it works most of the time but at times part of the border shows up. Edit controls, change depending on when get focus or not.
So the question is simply:
Is there a way to make common controls on transparent window so there is no white border around them?
If not, is there a good replacement library that does it via owner draw?
If some, which ones and what is the method?
Seems silly to reinvent the wheel just because of the area around the control.
TIA!!
If I am not mistaken, you can take the following steps to achieve this effect.
1.Create a GDI+ Bitmap object with the PixelFormat32bppPARGB pixel format.
2.Create a Graphics object to draw in this Bitmap object.
3.Do all your drawing into this object using GDI+.
4.Destroy the Graphics object created in step 2.
5.Call the GetHBITMAP method on the Bitmap object to get a Windows HBITMAP.
6.Destroy the Bitmap object.
7.Create a memory DC using CreateCompatibleDC and select the HBITMAP from step 5 into it.
8.Call UpdateLayeredWindow using the memory DC as a source.
9.Select previous bitmap and delete the memory DC.
10.Destroy the HBITMAP created in step 5.
This method should allow you to control the alpha channel of everything that is drawn: transparent for the background, opaque for the button.
A similar discussion: Transparent window containing opaque text and buttons
In Win32 or Direct2D, is it possible to read the screen that would be under the window that is being drawn? (in OnPaint() or wherever) Is it necessary to generate the screen data in back of the current window's rectangle and blit it into a memory buffer, and is this possible?
So, I am working on a text editor. I use double buffering to paint on to the screen. So basically I have an offscreen bitmap, which I paint on, and then copy it to the screen. Now, when the window for the text editor resizes, I need to resize the offscreen bitmap as well. So what would be a good way to resize the bitmap? I was thinking to maybe delete the old object and create a new bitmap using CreateCompatibleBitmap, but I'm wondering if it's the correct way to do it.
Language : C++ using Win32 API
Using CreateCompatibleBitmap will work, and then you'll want to call BitBlt on it to copy the contents of your existing backbuffer to the resized buffer. I don't think there is a more efficient way to do it using GDI.
If are thinking about using CreateCompatibleBitmap with BitBlt, you might like to look at StretchBlt instead. StretchBlt works like BitBlt but resizes the source image to fit into the destination area.
I have subclassed a graphics control that takes a device context handle, HDC, as an input and uses that for drawing. My new control is just the original control centered on top of a larger image. I would like to be able to call the original control's Draw() method for code re-use, but I'm unsure how to proceed.
Here's the idea:
void CCheckBox::DrawCtrl( HDC hdc, HDC hdcTmp, LPSIZE pCtlSize, BYTE alpha ) {
// original method draws a checkbox
}
void CBorderedCheckBox::DrawCtrl( HDC hdc, HDC hdcTmp, LPSIZE pCtlSize, BYTE alpha ) {
// Draw my image here
// Create new hdc2 and hdcTemp2 which are just some portion of hdc and hdcTemp
// For example, hdc2 may just be a rectangle inside of hdc that is 20 pixels
// indented on all sides.
// Call CCheckBox::DrawCtrl() with hdc2 and hdcTemp2
}
I think you may be confused of what a device context is. A device context is a place in memory that you can draw to, be it the screen buffer or a bitmap or something else. Since I imagine you only want to draw on the screen, you only need one DC. To accomplish what you want, I would recommend passing a rectangle to the function that tells it where to draw. Optionally, and with poorer performance, you could create a new Bitmap for the smaller area, and give the function the Bitmap's DC to draw on. Now that I think about it, that might have been what you meant in the first place :P Good luck!
While not foolproof, you can fake a DC as a subsection of a DC by using a combination of SetViewportOrgEx and SelectObject with a region clipped to the sub area in question.
The problem with this approach is if drawing code already uses these APIs it needs to rewritten to be aware that it needs to combine its masking and offsetting with the existing offsets and clipping regions.
I use GDI to create some custom textwidget. I draw directly to the screen, unbuffered.
now i'd like to implement some fast scrolling, that simply pixelshifts the respective part of the framebuffer (and only redraws the newly visible lines).
I noticed that for example the rich text controls does it like this. If i use some GDI drawing functions to directly draw to the framebuffer, over a rich text control, and then scroll the rich text, it will also scroll my drawing along with the text. so i assume the rich text simply pixelshifts it's part of the framebuffer.
I'd like to do the same, but don't know how to do so.
Can someone help? (independant of programming language))
thanks!
The ScrollWindowEx() API function is optimized to do this.
See BitBlt function:
The BitBlt function performs a
bit-block transfer of the color data
corresponding to a rectangle of pixels
from the specified source device
context into a destination device
context.
and the example at the end of its documentation: Capturing an Image:
You can use a bitmap to capture an
image, and you can store the captured
image in memory, display it at a
different location in your
application's window. [...]
In some cases, you may want your
application to capture images and
store them only temporarily. [...] To
store an image temporarily, your
application must call
CreateCompatibleDC to create a DC that
is compatible with the current window
DC. After you create a compatible DC,
you create a bitmap with the
appropriate dimensions by calling the
CreateCompatibleBitmap function and
then select it into this device
context by calling the SelectObject
function.
After the compatible device context is
created and the appropriate bitmap has
been selected into it, you can capture
the image. The BitBlt function
captures images. This function
performs a bit block transfer that is,
it copies data from a source bitmap
into a destination bitmap. [...]
To redisplay the image, call BitBlt a
second time, specifying the compatible
DC as the source DC and a window DC as
the target DC.