Drawn in full screen

I am trying to make a simple little tool that will allow the user to switch from normal operation to the mode when all messages of the application are turned off, and they can use the mouse to make some free-hand drawing, and then switch the modes again to save their drawing on the screen, in while they do any other normal things they want. It could, if I decided, turn into a nice thing that you could use to use the decorated screen, preserving the scenery you are doing, and download it later.

When I started this (which was more than six months ago, shortly after the discovery of the Windows API), I just did a global mouse tracking and drew a circle wherever it was with hdc GetDC (NULL). Of course, the problems were that it would disappear when something under it was updated and the mouse messages still displayed, so if I clicked a button on the desktop, for example, it would resize the rectangle to the whole a picture.

Today, finally, after some free time since the last major work on this most of this 6 months ago, I decided to redo it and see if I can achieve what I want. I made a transparent, uppermost, WS_CHILD, multi-level, maximized window (basically the screen does not change, but there is a window on top of everything that passes messages). Then I made it so that when he was in drawing mode, he set the alpha-1 value to 1 and let the user draw. What I did not understand until I did this was that, since the alpha window value was 1, none of the pictures would be visible.

Next, I tried to use GetDC (NULL), but remembered that it is deleted when something is updated.

Now I just thought about using bitmaps and dcs to save the screen multiple times in dc, draw on another dc, and then copy it back to the one that is stored on the screen with transparency for parts that are not drawn, and copy it back to the screen, but I'm losing a little heart. Here is my source code for this (the mask function is taken from this tutorial ). Please tell me if this is not necessary. I used bitmaps for double buffering, but I'm not so sure where I need them.

//Global mask since it takes longer to make HBITMAP mask; //Window Procedure Start HDC screenDC; //hdc for entire screen screenDC = GetDC (NULL); //get DC for screen HDC memDC = CreateCompatibleDC (screenDC); //create DC for holding the screen+paint HBITMAP bm = CreateCompatibleBitmap (screenDC, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN)); //create bitmap for memDC HDC paintDC = CreateCompatibleDC (screenDC); //create DC to paint on HBITMAP paintBM = CreateCompatibleBitmap (screenDC, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN)); //create bitmap for paintDC SelectObject (memDC, bm); //select bitmap into memDC SelectObject (paintDC, paintBM); //select painting bitmap into paintDC BitBlt (memDC, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), screenDC, 0, 0, SRCCOPY); //copy screen to memDC SetBkColor (paintDC, RGB(0,0,0)); //set background of paintDC to black so it all transparent to start //WM_CREATE mask = CreateBitmapMask (bm, RGB(0,0,0)); //create black mask (paint colours are limited 1-255 now) //painting is done into paintDC //at end of Window Procedure SelectObject (paintDC, mask); //select mask into paintDC BitBlt (memDC, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), paintDC, 0, 0, SRCAND); //this in combination with the next should make it bitblt with all of the black taken out I thought SelectObject (paintDC, paintBM); //select bitmaps into DCs SelectObject (memDC, bm); BitBlt (memDC, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), paintDC, 0, 0, SRCPAINT); //second part of transparent bitblt BitBlt (screenDC, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), paintDC, 0, 0, SRCCOPY); //copy memDC back to screen DeleteObject (paintBM); //delete stuff DeleteObject (mask); DeleteDC (memDC); DeleteDC (paintDC); ReleaseDC (hwnd, screenDC); //CreateBitmapMask() (taken directly from http://www.winprog.org/tutorial/transparency.html HBITMAP CreateBitmapMask(HBITMAP hbmColour, COLORREF crTransparent) { HDC hdcMem, hdcMem2; HBITMAP hbmMask; BITMAP bm; // Create monochrome (1 bit) mask bitmap. GetObject(hbmColour, sizeof(BITMAP), &bm); hbmMask = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL); // Get some HDCs that are compatible with the display driver hdcMem = CreateCompatibleDC(0); hdcMem2 = CreateCompatibleDC(0); SelectObject(hdcMem, hbmColour); SelectObject(hdcMem2, hbmMask); // Set the background colour of the colour image to the colour // you want to be transparent. SetBkColor(hdcMem, crTransparent); // Copy the bits from the colour image to the B+W mask... everything // with the background colour ends up white while everythig else ends up // black...Just what we wanted. BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); // Take our new mask and use it to turn the transparent colour in our // original colour image to black so the transparency effect will // work right. BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem2, 0, 0, SRCINVERT); // Clean up. DeleteDC(hdcMem); DeleteDC(hdcMem2); return hbmMask; } 

I know the code can be horrible. I take into account all the proposals, I just donโ€™t understand this topic too much and I donโ€™t get everything that happens, which makes it difficult to fix it. This code works for me, pretty much putting a fullscreen black rectangle so often.

My main question is: is there a way to draw on the screen without erasing it when the windows are under updating? The only real thing I can think of right now is to store all the locations of the tiny line segments that the user draws and continue to redraw them on top of the screen. At first glance, this seems very inefficient and wasteful for memory.

In addition, I was pretty sure, writing this, that I did not need code examples for theoretical materials in front of the delivered code segments. Most of them are now gone, but this is more of a theory problem.

EDIT: I just found out about the TransparentBlt function, which seemed perfect for the situation, so I tried to use it instead of SRCPAINT and SRCAND BitBlts, and this led to the same result: a black rectangle covering the screen, sometimes having parts disappearing when the mouse moves things .

+4
source share
2 answers

The simplest way is possible:

In non-drawing mode, use SetLayeredWindowAttributes to set the transparency color for the transparent window. Make the alpha window completely opaque, but fill the window (FillRect or the like) with this key color and it will all become transparent. Then everything that you paint in a non-key color will look solid, on top of all windows under a transparent multilayer window.

To switch to the drawing mode, one approach is to create a new window with the captured raster image of the desktop right below your transparent layer. Or avoid the bitmap, and make it slightly opaque and all solid color - for example, it looks like the desktop is "greyed out". The main thing is that this window is not completely transparent, so it can receive mouse input, which can then be used to draw on a real transparent layer.

+3
source

I think that itโ€™s best for you to take a snapshot of the screen and save it as a bitmap (as a DC memory). Before you show a window that displays the contents of DC memory in full screen mode. This way you really get messages caused by clicks, etc. In your own window, and process them as usual.

  • Capture Screen Contents
  • Create a window (full screen) and use the captured content
  • Make some drawings
  • Save the content (as BMP or something interesting)
  • Close the window and return to the normal desktop.

A good idea?

0
source

All Articles